Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx
Warning:line 1213, column 1
Potential leak of memory pointed to by 'pLn'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name untbl.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx
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 <UndoTable.hxx>
21#include <UndoRedline.hxx>
22#include <UndoDelete.hxx>
23#include <UndoSplitMove.hxx>
24#include <UndoCore.hxx>
25#include <fesh.hxx>
26#include <hintids.hxx>
27#include <hints.hxx>
28#include <doc.hxx>
29#include <docredln.hxx>
30#include <IDocumentUndoRedo.hxx>
31#include <IDocumentChartDataProviderAccess.hxx>
32#include <IDocumentRedlineAccess.hxx>
33#include <IDocumentFieldsAccess.hxx>
34#include <IDocumentStylePoolAccess.hxx>
35#include <editsh.hxx>
36#include <docary.hxx>
37#include <ndtxt.hxx>
38#include <swtable.hxx>
39#include <pam.hxx>
40#include <tblsel.hxx>
41#include <swundo.hxx>
42#include <rolbck.hxx>
43#include <ddefld.hxx>
44#include <tabfrm.hxx>
45#include <rowfrm.hxx>
46#include <cellfrm.hxx>
47#include <swcache.hxx>
48#include <tblafmt.hxx>
49#include <poolfmt.hxx>
50#include <mvsave.hxx>
51#include <cellatr.hxx>
52#include <swtblfmt.hxx>
53#include <swddetbl.hxx>
54#include <redline.hxx>
55#include <node2lay.hxx>
56#include <tblrwcl.hxx>
57#include <fmtanchr.hxx>
58#include <strings.hrc>
59#include <unochart.hxx>
60#include <calbck.hxx>
61#include <frameformats.hxx>
62
63#include <memory>
64#include <utility>
65#include <vector>
66
67#ifdef DBG_UTIL
68#define CHECK_TABLE(t) (t).CheckConsistency();
69#else
70#define CHECK_TABLE(t)
71#endif
72
73#ifdef DBG_UTIL
74 #define DEBUG_REDLINE( pDoc ) sw_DebugRedline( pDoc );
75#else
76 #define DEBUG_REDLINE( pDoc )
77#endif
78
79typedef std::vector<std::shared_ptr<SfxItemSet> > SfxItemSets;
80
81struct UndoTableCpyTable_Entry
82{
83 sal_uLong nBoxIdx, nOffset;
84 std::unique_ptr<SfxItemSet> pBoxNumAttr;
85 std::unique_ptr<SwUndo> pUndo;
86
87 // Was the last paragraph of the new and the first paragraph of the old content joined?
88 bool bJoin; // For redlining only
89
90 explicit UndoTableCpyTable_Entry( const SwTableBox& rBox );
91};
92
93namespace {
94
95class SaveBox;
96class SaveLine;
97
98}
99
100class SaveTable
101{
102 friend SaveBox;
103 friend SaveLine;
104 SfxItemSet m_aTableSet;
105 std::unique_ptr<SaveLine> m_pLine;
106 const SwTable* m_pSwTable;
107 SfxItemSets m_aSets;
108 SwFrameFormatsV m_aFrameFormats;
109 sal_uInt16 m_nLineCount;
110 bool m_bModifyBox : 1;
111 bool m_bSaveFormula : 1;
112 bool m_bNewModel : 1;
113
114 SaveTable(const SaveTable&) = delete;
115 SaveTable& operator=(const SaveTable&) = delete;
116
117public:
118 SaveTable( const SwTable& rTable, sal_uInt16 nLnCnt = USHRT_MAX(32767 *2 +1),
119 bool bSaveFormula = true );
120
121 sal_uInt16 AddFormat( SwFrameFormat* pFormat, bool bIsLine );
122 void NewFrameFormat( const SwTableLine* , const SwTableBox*, sal_uInt16 nFormatPos,
123 SwFrameFormat* pOldFormat );
124
125 void RestoreAttr( SwTable& rTable, bool bModifyBox = false );
126 void SaveContentAttrs( SwDoc* pDoc );
127 void CreateNew( SwTable& rTable, bool bCreateFrames = true,
128 bool bRestoreChart = true );
129 bool IsNewModel() const { return m_bNewModel; }
130};
131
132namespace {
133
134class SaveLine
135{
136 friend SaveTable;
137 friend class SaveBox;
138
139 SaveLine* pNext;
140 SaveBox* pBox;
141 sal_uInt16 nItemSet;
142
143 SaveLine(const SaveLine&) = delete;
144 SaveLine& operator=(const SaveLine&) = delete;
145
146public:
147 SaveLine( SaveLine* pPrev, const SwTableLine& rLine, SaveTable& rSTable );
148 ~SaveLine();
149
150 void RestoreAttr( SwTableLine& rLine, SaveTable& rSTable );
151 void SaveContentAttrs( SwDoc* pDoc );
152
153 void CreateNew( SwTable& rTable, SwTableBox& rParent, SaveTable& rSTable );
154};
155
156class SaveBox
157{
158 friend class SaveLine;
159
160 SaveBox* pNext;
161 sal_uLong nSttNode;
162 long nRowSpan;
163 sal_uInt16 nItemSet;
164 union
165 {
166 SfxItemSets* pContentAttrs;
167 SaveLine* pLine;
168 } Ptrs;
169
170public:
171 SaveBox( SaveBox* pPrev, const SwTableBox& rBox, SaveTable& rSTable );
172 ~SaveBox();
173
174 void RestoreAttr( SwTableBox& rBox, SaveTable& rSTable );
175 void SaveContentAttrs( SwDoc* pDoc );
176
177 void CreateNew( SwTable& rTable, SwTableLine& rParent, SaveTable& rSTable );
178};
179
180}
181
182#if OSL_DEBUG_LEVEL1 > 0
183static void CheckTable( const SwTable& );
184#define CHECKTABLE(t)CheckTable( t ); CheckTable( t );
185#else
186#define CHECKTABLE(t)CheckTable( t );
187#endif
188
189/* #130880: Crash in undo of table to text when the table has (freshly) merged cells
190The order of cell content nodes in the nodes array is not given by the recursive table structure.
191The algorithm must not rely on this even it holds for a fresh loaded table in odt file format.
192So we need to remember not only the start node position but the end node position as well.
193*/
194
195struct SwTableToTextSave
196{
197 sal_uLong m_nSttNd;
198 sal_uLong m_nEndNd;
199 sal_Int32 m_nContent;
200 std::unique_ptr<SwHistory> m_pHstry;
201 // metadata references for first and last paragraph in cell
202 std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
203 std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
204
205 SwTableToTextSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, sal_Int32 nContent );
206
207private:
208 SwTableToTextSave(const SwTableToTextSave&) = delete;
209 SwTableToTextSave& operator=(const SwTableToTextSave&) = delete;
210
211};
212
213sal_uInt16 const aSave_BoxContentSet[] = {
214 RES_CHRATR_COLOR, RES_CHRATR_CROSSEDOUT,
215 RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
216 RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
217 RES_CHRATR_SHADOWED, RES_CHRATR_WEIGHT,
218 RES_PARATR_ADJUST, RES_PARATR_ADJUST,
219 0 };
220
221SwUndoInsTable::SwUndoInsTable( const SwPosition& rPos, sal_uInt16 nCl, sal_uInt16 nRw,
222 sal_uInt16 nAdj, const SwInsertTableOptions& rInsTableOpts,
223 const SwTableAutoFormat* pTAFormat,
224 const std::vector<sal_uInt16> *pColArr,
225 const OUString & rName)
226 : SwUndo( SwUndoId::INSTABLE, &rPos.GetDoc() ),
227 m_aInsTableOptions( rInsTableOpts ),
228 m_nStartNode( rPos.nNode.GetIndex() ), m_nRows( nRw ), m_nColumns( nCl ), m_nAdjust( nAdj )
229{
230 if( pColArr )
231 {
232 m_pColumnWidth.reset( new std::vector<sal_uInt16>(*pColArr) );
233 }
234 if( pTAFormat )
235 m_pAutoFormat.reset( new SwTableAutoFormat( *pTAFormat ) );
236
237 // consider redline
238 SwDoc& rDoc = rPos.nNode.GetNode().GetDoc();
239 if( rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
240 {
241 m_pRedlineData.reset( new SwRedlineData( RedlineType::Insert, rDoc.getIDocumentRedlineAccess().GetRedlineAuthor() ) );
242 SetRedlineFlags( rDoc.getIDocumentRedlineAccess().GetRedlineFlags() );
243 }
244
245 m_sTableName = rName;
246}
247
248SwUndoInsTable::~SwUndoInsTable()
249{
250 m_pDDEFieldType.reset();
251 m_pColumnWidth.reset();
252 m_pRedlineData.reset();
253 m_pAutoFormat.reset();
254}
255
256void SwUndoInsTable::UndoImpl(::sw::UndoRedoContext & rContext)
257{
258 SwDoc & rDoc = rContext.GetDoc();
259 SwNodeIndex aIdx( rDoc.GetNodes(), m_nStartNode );
260
261 SwTableNode* pTableNd = aIdx.GetNode().GetTableNode();
262 OSL_ENSURE( pTableNd, "no TableNode" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "262" ": "), "%s", "no TableNode"); } } while (false)
;
263 pTableNd->DelFrames();
264
265 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
266 rDoc.getIDocumentRedlineAccess().DeleteRedline( *pTableNd, true, RedlineType::Any );
267 RemoveIdxFromSection( rDoc, m_nStartNode );
268
269 // move hard page breaks into next node
270 SwContentNode* pNextNd = rDoc.GetNodes()[ pTableNd->EndOfSectionIndex()+1 ]->GetContentNode();
271 if( pNextNd )
272 {
273 SwFrameFormat* pTableFormat = pTableNd->GetTable().GetFrameFormat();
274 const SfxPoolItem *pItem;
275
276 if( SfxItemState::SET == pTableFormat->GetItemState( RES_PAGEDESC,
277 false, &pItem ) )
278 pNextNd->SetAttr( *pItem );
279
280 if( SfxItemState::SET == pTableFormat->GetItemState( RES_BREAK,
281 false, &pItem ) )
282 pNextNd->SetAttr( *pItem );
283 }
284
285 m_sTableName = pTableNd->GetTable().GetFrameFormat()->GetName();
286 if( auto pDDETable = dynamic_cast<const SwDDETable *>(&pTableNd->GetTable()) )
287 m_pDDEFieldType.reset(static_cast<SwDDEFieldType*>(pDDETable->GetDDEFieldType()->Copy().release()));
288
289 rDoc.GetNodes().Delete( aIdx, pTableNd->EndOfSectionIndex() -
290 aIdx.GetIndex() + 1 );
291
292 SwPaM & rPam( rContext.GetCursorSupplier().CreateNewShellCursor() );
293 rPam.DeleteMark();
294 rPam.GetPoint()->nNode = aIdx;
295 rPam.GetPoint()->nContent.Assign( rPam.GetContentNode(), 0 );
296}
297
298void SwUndoInsTable::RedoImpl(::sw::UndoRedoContext & rContext)
299{
300 SwDoc & rDoc = rContext.GetDoc();
301
302 SwPosition const aPos(SwNodeIndex(rDoc.GetNodes(), m_nStartNode));
303 const SwTable* pTable = rDoc.InsertTable( m_aInsTableOptions, aPos, m_nRows, m_nColumns,
304 m_nAdjust,
305 m_pAutoFormat.get(), m_pColumnWidth.get() );
306 rDoc.GetEditShell()->MoveTable( GotoPrevTable, fnTableStart );
307 static_cast<SwFrameFormat*>(pTable->GetFrameFormat())->SetName( m_sTableName );
308 SwTableNode* pTableNode = rDoc.GetNodes()[m_nStartNode]->GetTableNode();
309
310 if( m_pDDEFieldType )
311 {
312 SwDDEFieldType* pNewType = static_cast<SwDDEFieldType*>(rDoc.getIDocumentFieldsAccess().InsertFieldType(
313 *m_pDDEFieldType));
314 std::unique_ptr<SwDDETable> pDDETable(new SwDDETable( pTableNode->GetTable(), pNewType ));
315 pTableNode->SetNewTable( std::move(pDDETable) );
316 m_pDDEFieldType.reset();
317 }
318
319 if( !((m_pRedlineData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() )) ||
320 ( !( RedlineFlags::Ignore & GetRedlineFlags() ) &&
321 !rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() )))
322 return;
323
324 SwPaM aPam( *pTableNode->EndOfSectionNode(), *pTableNode, 1 );
325 SwContentNode* pCNd = aPam.GetContentNode( false );
326 if( pCNd )
327 aPam.GetMark()->nContent.Assign( pCNd, 0 );
328
329 if( m_pRedlineData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) )
330 {
331 RedlineFlags eOld = rDoc.getIDocumentRedlineAccess().GetRedlineFlags();
332 rDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern(eOld & ~RedlineFlags::Ignore);
333
334 rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlineData, aPam ), true);
335 rDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
336 }
337 else
338 rDoc.getIDocumentRedlineAccess().SplitRedline( aPam );
339}
340
341void SwUndoInsTable::RepeatImpl(::sw::RepeatContext & rContext)
342{
343 rContext.GetDoc().InsertTable(
344 m_aInsTableOptions, *rContext.GetRepeatPaM().GetPoint(),
345 m_nRows, m_nColumns, m_nAdjust, m_pAutoFormat.get(), m_pColumnWidth.get() );
346}
347
348SwRewriter SwUndoInsTable::GetRewriter() const
349{
350 SwRewriter aRewriter;
351
352 aRewriter.AddRule(UndoArg1, SwResId(STR_START_QUOTEreinterpret_cast<char const *>("STR_START_QUOTE" "\004"
u8"“")
));
353 aRewriter.AddRule(UndoArg2, m_sTableName);
354 aRewriter.AddRule(UndoArg3, SwResId(STR_END_QUOTEreinterpret_cast<char const *>("STR_END_QUOTE" "\004" u8"”"
)
));
355
356 return aRewriter;
357}
358
359SwTableToTextSave::SwTableToTextSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, sal_Int32 nCnt )
360 : m_nSttNd( nNd ), m_nEndNd( nEndIdx), m_nContent( nCnt )
361{
362 // keep attributes of the joined node
363 SwTextNode* pNd = rDoc.GetNodes()[ nNd ]->GetTextNode();
364 if( pNd )
365 {
366 m_pHstry.reset( new SwHistory );
367
368 m_pHstry->Add( pNd->GetTextColl(), nNd, SwNodeType::Text );
369 if ( pNd->GetpSwpHints() )
370 {
371 m_pHstry->CopyAttr( pNd->GetpSwpHints(), nNd, 0,
372 pNd->GetText().getLength(), false );
373 }
374 if( pNd->HasSwAttrSet() )
375 m_pHstry->CopyFormatAttr( *pNd->GetpSwAttrSet(), nNd );
376
377 if( !m_pHstry->Count() )
378 {
379 m_pHstry.reset();
380 }
381
382 // METADATA: store
383 m_pMetadataUndoStart = pNd->CreateUndo();
384 }
385
386 // we also need to store the metadata reference of the _last_ paragraph
387 // we subtract 1 to account for the removed cell start/end node pair
388 // (after SectionUp, the end of the range points to the node after the cell)
389 if ( nEndIdx - 1 > nNd )
390 {
391 SwTextNode* pLastNode( rDoc.GetNodes()[ nEndIdx - 1 ]->GetTextNode() );
392 if( pLastNode )
393 {
394 // METADATA: store
395 m_pMetadataUndoEnd = pLastNode->CreateUndo();
396 }
397 }
398}
399
400SwUndoTableToText::SwUndoTableToText( const SwTable& rTable, sal_Unicode cCh )
401 : SwUndo( SwUndoId::TABLETOTEXT, rTable.GetFrameFormat()->GetDoc() ),
402 m_sTableName( rTable.GetFrameFormat()->GetName() ),
403 m_nStartNode( 0 ), m_nEndNode( 0 ),
404 m_cSeparator( cCh ), m_nHeadlineRepeat( rTable.GetRowsToRepeat() )
405{
406 m_pTableSave.reset( new SaveTable( rTable ) );
407 m_vBoxSaves.reserve(rTable.GetTabSortBoxes().size());
408
409 if( auto pDDETable = dynamic_cast<const SwDDETable *>(&rTable) )
410 m_pDDEFieldType.reset(static_cast<SwDDEFieldType*>(pDDETable->GetDDEFieldType()->Copy().release()));
411
412 m_bCheckNumFormat = rTable.GetFrameFormat()->GetDoc()->IsInsTableFormatNum();
413
414 m_pHistory.reset(new SwHistory);
415 const SwTableNode* pTableNd = rTable.GetTableNode();
416 sal_uLong nTableStt = pTableNd->GetIndex(), nTableEnd = pTableNd->EndOfSectionIndex();
417
418 const SwFrameFormats& rFrameFormatTable = *pTableNd->GetDoc().GetSpzFrameFormats();
419 for( size_t n = 0; n < rFrameFormatTable.size(); ++n )
420 {
421 SwFrameFormat* pFormat = rFrameFormatTable[ n ];
422 SwFormatAnchor const*const pAnchor = &pFormat->GetAnchor();
423 SwPosition const*const pAPos = pAnchor->GetContentAnchor();
424 if (pAPos &&
425 ((RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
426 (RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId())) &&
427 nTableStt <= pAPos->nNode.GetIndex() &&
428 pAPos->nNode.GetIndex() < nTableEnd )
429 {
430 m_pHistory->AddChangeFlyAnchor(*pFormat);
431 }
432 }
433
434 if( !m_pHistory->Count() )
435 {
436 m_pHistory.reset();
437 }
438}
439
440SwUndoTableToText::~SwUndoTableToText()
441{
442 m_pDDEFieldType.reset();
443 m_pTableSave.reset();
444 m_vBoxSaves.clear();
445 m_pHistory.reset();
446}
447
448void SwUndoTableToText::UndoImpl(::sw::UndoRedoContext & rContext)
449{
450 SwDoc & rDoc = rContext.GetDoc();
451 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
452
453 SwNodeIndex aFrameIdx( rDoc.GetNodes(), m_nStartNode );
454 SwNodeIndex aEndIdx( rDoc.GetNodes(), m_nEndNode );
455
456 pPam->GetPoint()->nNode = aFrameIdx;
457 pPam->SetMark();
458 pPam->GetPoint()->nNode = aEndIdx;
459 rDoc.DelNumRules( *pPam );
460 pPam->DeleteMark();
461
462 // now collect all Uppers
463 SwNode2LayoutSaveUpperFrames aNode2Layout(aFrameIdx.GetNode());
464
465 // create TableNode structure
466 SwTableNode* pTableNd = rDoc.GetNodes().UndoTableToText( m_nStartNode, m_nEndNode, m_vBoxSaves );
467 pTableNd->GetTable().SetTableModel( m_pTableSave->IsNewModel() );
468 SwTableFormat* pTableFormat = rDoc.MakeTableFrameFormat( m_sTableName, rDoc.GetDfltFrameFormat() );
469 pTableNd->GetTable().RegisterToFormat( *pTableFormat );
470 pTableNd->GetTable().SetRowsToRepeat( m_nHeadlineRepeat );
471
472 // create old table structure
473 m_pTableSave->CreateNew( pTableNd->GetTable() );
474
475 if( m_pDDEFieldType )
476 {
477 SwDDEFieldType* pNewType = static_cast<SwDDEFieldType*>(rDoc.getIDocumentFieldsAccess().InsertFieldType(
478 *m_pDDEFieldType));
479 std::unique_ptr<SwDDETable> pDDETable( new SwDDETable( pTableNd->GetTable(), pNewType ) );
480 pTableNd->SetNewTable( std::move(pDDETable), false );
481 m_pDDEFieldType.reset();
482 }
483
484 if( m_bCheckNumFormat )
485 {
486 SwTableSortBoxes& rBxs = pTableNd->GetTable().GetTabSortBoxes();
487 for (size_t nBoxes = rBxs.size(); nBoxes; )
488 {
489 rDoc.ChkBoxNumFormat( *rBxs[ --nBoxes ], false );
490 }
491 }
492
493 if( m_pHistory )
494 {
495 sal_uInt16 nTmpEnd = m_pHistory->GetTmpEnd();
496 m_pHistory->TmpRollback( &rDoc, 0 );
497 m_pHistory->SetTmpEnd( nTmpEnd );
498 }
499
500 aNode2Layout.RestoreUpperFrames( rDoc.GetNodes(),
501 pTableNd->GetIndex(), pTableNd->GetIndex()+1 );
502
503 // Is a table selection requested?
504 pPam->DeleteMark();
505 pPam->GetPoint()->nNode = *pTableNd->EndOfSectionNode();
506 pPam->SetMark();
507 pPam->GetPoint()->nNode = *pPam->GetNode().StartOfSectionNode();
508 pPam->Move( fnMoveForward, GoInContent );
509 pPam->Exchange();
510 pPam->Move( fnMoveBackward, GoInContent );
511
512 ClearFEShellTabCols(rDoc, nullptr);
513}
514
515// located in untbl.cxx and only an Undo object is allowed to call it
516SwTableNode* SwNodes::UndoTableToText( sal_uLong nSttNd, sal_uLong nEndNd,
517 const SwTableToTextSaves& rSavedData )
518{
519 SwNodeIndex aSttIdx( *this, nSttNd );
520 SwNodeIndex aEndIdx( *this, nEndNd+1 );
521
522 SwTableNode * pTableNd = new SwTableNode( aSttIdx );
523 SwEndNode* pEndNd = new SwEndNode( aEndIdx, *pTableNd );
524
525 aEndIdx = *pEndNd;
526
527 /* Set pTableNd as start of section for all nodes in [nSttNd, nEndNd].
528 Delete all Frames attached to the nodes in that range. */
529 SwNode* pNd;
530 {
531 sal_uLong n, nTmpEnd = aEndIdx.GetIndex();
532 for( n = pTableNd->GetIndex() + 1; n < nTmpEnd; ++n )
533 {
534 if( ( pNd = (*this)[ n ] )->IsContentNode() )
535 static_cast<SwContentNode*>(pNd)->DelFrames(nullptr);
536 pNd->m_pStartOfSection = pTableNd;
537 }
538 }
539
540 // than create table structure partially. First a single line that contains
541 // all boxes. The correct structure is then taken from SaveStruct.
542 SwTableBoxFormat* pBoxFormat = GetDoc().MakeTableBoxFormat();
543 SwTableLineFormat* pLineFormat = GetDoc().MakeTableLineFormat();
544 SwTableLine* pLine = new SwTableLine( pLineFormat, rSavedData.size(), nullptr );
545 pTableNd->GetTable().GetTabLines().insert( pTableNd->GetTable().GetTabLines().begin(), pLine );
546
547 const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
548 for( size_t n = rSavedData.size(); n; )
549 {
550 const SwTableToTextSave *const pSave = rSavedData[ --n ].get();
551 // if the start node was merged with last from prev. cell,
552 // subtract 1 from index to get the merged paragraph, and split that
553 aSttIdx = pSave->m_nSttNd - ( ( SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF) != pSave->m_nContent ) ? 1 : 0);
554 SwTextNode* pTextNd = aSttIdx.GetNode().GetTextNode();
555
556 if( SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF) != pSave->m_nContent )
557 {
558 // split at ContentPosition, delete previous char (= separator)
559 OSL_ENSURE( pTextNd, "Where is my TextNode?" )do { if (true && (!(pTextNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "559" ": "), "%s", "Where is my TextNode?"); } } while (
false)
;
560 SwIndex aCntPos( pTextNd, pSave->m_nContent - 1 );
561
562 pTextNd->EraseText( aCntPos, 1 );
563
564 std::function<void (SwTextNode *, sw::mark::RestoreMode)> restoreFunc(
565 [&](SwTextNode *const pNewNode, sw::mark::RestoreMode const eMode)
566 {
567 if (!pContentStore->Empty())
568 {
569 pContentStore->Restore(*pNewNode, pSave->m_nContent, pSave->m_nContent + 1, eMode);
570 }
571 });
572 pTextNd->SplitContentNode(
573 SwPosition(aSttIdx, aCntPos), &restoreFunc);
574 }
575 else
576 {
577 pContentStore->Clear();
578 if( pTextNd )
579 {
580 pContentStore->Save(GetDoc(), aSttIdx.GetIndex(), SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF));
581 }
582 }
583
584 if( pTextNd )
585 {
586 // METADATA: restore
587 pTextNd->GetTextNode()->RestoreMetadata(pSave->m_pMetadataUndoStart);
588 if( pTextNd->HasSwAttrSet() )
589 pTextNd->ResetAllAttr();
590
591 if( pTextNd->GetpSwpHints() )
592 pTextNd->ClearSwpHintsArr( false );
593 }
594
595 if( pSave->m_pHstry )
596 {
597 sal_uInt16 nTmpEnd = pSave->m_pHstry->GetTmpEnd();
598 pSave->m_pHstry->TmpRollback( &GetDoc(), 0 );
599 pSave->m_pHstry->SetTmpEnd( nTmpEnd );
600 }
601
602 // METADATA: restore
603 // end points to node after cell
604 if ( pSave->m_nEndNd - 1 > pSave->m_nSttNd )
605 {
606 SwTextNode* pLastNode = (*this)[ pSave->m_nEndNd - 1 ]->GetTextNode();
607 if (pLastNode)
608 {
609 pLastNode->RestoreMetadata(pSave->m_pMetadataUndoEnd);
610 }
611 }
612
613 aEndIdx = pSave->m_nEndNd;
614 SwStartNode* pSttNd = new SwStartNode( aSttIdx, SwNodeType::Start,
615 SwTableBoxStartNode );
616 pSttNd->m_pStartOfSection = pTableNd;
617 new SwEndNode( aEndIdx, *pSttNd );
618
619 for( sal_uLong i = aSttIdx.GetIndex(); i < aEndIdx.GetIndex()-1; ++i )
620 {
621 pNd = (*this)[ i ];
622 pNd->m_pStartOfSection = pSttNd;
623 if( pNd->IsStartNode() )
624 i = pNd->EndOfSectionIndex();
625 }
626
627 SwTableBox* pBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
628 pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin(), pBox );
629 }
630 return pTableNd;
631}
632
633void SwUndoTableToText::RedoImpl(::sw::UndoRedoContext & rContext)
634{
635 SwDoc & rDoc = rContext.GetDoc();
636 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
637
638 pPam->GetPoint()->nNode = m_nStartNode;
639 pPam->GetPoint()->nContent.Assign( nullptr, 0 );
640 SwNodeIndex aSaveIdx( pPam->GetPoint()->nNode, -1 );
641
642 pPam->SetMark(); // log off all indices
643 pPam->DeleteMark();
644
645 SwTableNode* pTableNd = pPam->GetNode().GetTableNode();
646 OSL_ENSURE( pTableNd, "Could not find any TableNode" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "646" ": "), "%s", "Could not find any TableNode"); } } while
(false)
;
647
648 if( auto pDDETable = dynamic_cast<const SwDDETable *>(&pTableNd->GetTable()) )
649 m_pDDEFieldType.reset(static_cast<SwDDEFieldType*>(pDDETable->GetDDEFieldType()->Copy().release()));
650
651 rDoc.TableToText( pTableNd, m_cSeparator );
652
653 ++aSaveIdx;
654 SwContentNode* pCNd = aSaveIdx.GetNode().GetContentNode();
655 if( !pCNd && nullptr == ( pCNd = rDoc.GetNodes().GoNext( &aSaveIdx ) ) &&
656 nullptr == ( pCNd = SwNodes::GoPrevious( &aSaveIdx )) )
657 {
658 OSL_FAIL( "Where is the TextNode now?" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "658" ": "), "%s", "Where is the TextNode now?"); } } while
(false)
;
659 }
660
661 pPam->GetPoint()->nNode = aSaveIdx;
662 pPam->GetPoint()->nContent.Assign( pCNd, 0 );
663
664 pPam->SetMark(); // log off all indices
665 pPam->DeleteMark();
666}
667
668void SwUndoTableToText::RepeatImpl(::sw::RepeatContext & rContext)
669{
670 SwPaM *const pPam = & rContext.GetRepeatPaM();
671 SwTableNode *const pTableNd = pPam->GetNode().FindTableNode();
672 if( pTableNd )
673 {
674 // move cursor out of table
675 pPam->GetPoint()->nNode = *pTableNd->EndOfSectionNode();
676 pPam->Move( fnMoveForward, GoInContent );
677 pPam->SetMark();
678 pPam->DeleteMark();
679
680 rContext.GetDoc().TableToText( pTableNd, m_cSeparator );
681 }
682}
683
684void SwUndoTableToText::SetRange( const SwNodeRange& rRg )
685{
686 m_nStartNode = rRg.aStart.GetIndex();
687 m_nEndNode = rRg.aEnd.GetIndex();
688}
689
690void SwUndoTableToText::AddBoxPos( SwDoc& rDoc, sal_uLong nNdIdx, sal_uLong nEndIdx, sal_Int32 nContentIdx )
691{
692 m_vBoxSaves.push_back(std::make_unique<SwTableToTextSave>(rDoc, nNdIdx, nEndIdx, nContentIdx));
693}
694
695SwUndoTextToTable::SwUndoTextToTable( const SwPaM& rRg,
696 const SwInsertTableOptions& rInsTableOpts,
697 sal_Unicode cCh, sal_uInt16 nAdj,
698 const SwTableAutoFormat* pAFormat )
699 : SwUndo( SwUndoId::TEXTTOTABLE, &rRg.GetDoc() ), SwUndRng( rRg ), m_aInsertTableOpts( rInsTableOpts ),
700 m_pHistory( nullptr ), m_cSeparator( cCh ), m_nAdjust( nAdj )
701{
702 if( pAFormat )
703 m_pAutoFormat.reset( new SwTableAutoFormat( *pAFormat ) );
704
705 const SwPosition* pEnd = rRg.End();
706 SwNodes& rNds = rRg.GetDoc().GetNodes();
707 m_bSplitEnd = pEnd->nContent.GetIndex() && ( pEnd->nContent.GetIndex()
708 != pEnd->nNode.GetNode().GetContentNode()->Len() ||
709 pEnd->nNode.GetIndex() >= rNds.GetEndOfContent().GetIndex()-1 );
710}
711
712SwUndoTextToTable::~SwUndoTextToTable()
713{
714 m_pAutoFormat.reset();
715}
716
717void SwUndoTextToTable::UndoImpl(::sw::UndoRedoContext & rContext)
718{
719 SwDoc & rDoc = rContext.GetDoc();
720
721 sal_uLong nTableNd = m_nSttNode;
722 if( m_nSttContent )
723 ++nTableNd; // Node was split previously
724 SwNodeIndex aIdx( rDoc.GetNodes(), nTableNd );
725 SwTableNode *const pTNd = aIdx.GetNode().GetTableNode();
726 OSL_ENSURE( pTNd, "Could not find a TableNode" )do { if (true && (!(pTNd))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "726" ": "), "%s", "Could not find a TableNode"); } } while
(false)
;
727
728 RemoveIdxFromSection( rDoc, nTableNd );
729
730 m_sTableName = pTNd->GetTable().GetFrameFormat()->GetName();
731
732 if( m_pHistory )
733 {
734 m_pHistory->TmpRollback( &rDoc, 0 );
735 m_pHistory->SetTmpEnd( m_pHistory->Count() );
736 }
737
738 if( !mvDelBoxes.empty() )
739 {
740 pTNd->DelFrames();
741 SwTable& rTable = pTNd->GetTable();
742 for( size_t n = mvDelBoxes.size(); n; )
743 {
744 SwTableBox* pBox = rTable.GetTableBox( mvDelBoxes[ --n ] );
745 if( pBox )
746 ::DeleteBox_( rTable, pBox, nullptr, false, false );
747 else {
748 OSL_ENSURE( false, "Where is my box?" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "748" ": "), "%s", "Where is my box?"); } } while (false
)
;
749 }
750 }
751 }
752
753 rDoc.TableToText( pTNd, 0x0b == m_cSeparator ? 0x09 : m_cSeparator );
754
755 // join again at start?
756 SwPaM aPam(rDoc.GetNodes().GetEndOfContent());
757 SwPosition *const pPos = aPam.GetPoint();
758 if( m_nSttContent )
759 {
760 pPos->nNode = nTableNd;
761 pPos->nContent.Assign(pPos->nNode.GetNode().GetContentNode(), 0);
762 if (aPam.Move(fnMoveBackward, GoInContent))
763 {
764 SwNodeIndex & rIdx = aPam.GetPoint()->nNode;
765
766 // than move, relatively, the Cursor/etc. again
767 RemoveIdxRel( rIdx.GetIndex()+1, *pPos );
768
769 rIdx.GetNode().GetContentNode()->JoinNext();
770 }
771 }
772
773 // join again at end?
774 if( m_bSplitEnd )
775 {
776 SwNodeIndex& rIdx = pPos->nNode;
777 rIdx = m_nEndNode;
778 SwTextNode* pTextNd = rIdx.GetNode().GetTextNode();
779 if( pTextNd && pTextNd->CanJoinNext() )
780 {
781 aPam.GetMark()->nContent.Assign( nullptr, 0 );
782 aPam.GetPoint()->nContent.Assign( nullptr, 0 );
783
784 // than move, relatively, the Cursor/etc. again
785 pPos->nContent.Assign(pTextNd, pTextNd->GetText().getLength());
786 RemoveIdxRel( m_nEndNode + 1, *pPos );
787
788 pTextNd->JoinNext();
789 }
790 }
791
792 AddUndoRedoPaM(rContext);
793}
794
795void SwUndoTextToTable::RedoImpl(::sw::UndoRedoContext & rContext)
796{
797 SwPaM & rPam( AddUndoRedoPaM(rContext) );
798 RemoveIdxFromRange(rPam, false);
799 SetPaM(rPam);
800
801 SwTable const*const pTable = rContext.GetDoc().TextToTable(
802 m_aInsertTableOpts, rPam, m_cSeparator, m_nAdjust, m_pAutoFormat.get() );
803 static_cast<SwFrameFormat*>(pTable->GetFrameFormat())->SetName( m_sTableName );
804}
805
806void SwUndoTextToTable::RepeatImpl(::sw::RepeatContext & rContext)
807{
808 // no Table In Table
809 if (!rContext.GetRepeatPaM().GetNode().FindTableNode())
810 {
811 rContext.GetDoc().TextToTable( m_aInsertTableOpts, rContext.GetRepeatPaM(),
812 m_cSeparator, m_nAdjust,
813 m_pAutoFormat.get() );
814 }
815}
816
817void SwUndoTextToTable::AddFillBox( const SwTableBox& rBox )
818{
819 mvDelBoxes.push_back( rBox.GetSttIdx() );
820}
821
822SwHistory& SwUndoTextToTable::GetHistory()
823{
824 if( !m_pHistory )
825 m_pHistory = new SwHistory;
826 return *m_pHistory;
827}
828
829SwUndoTableHeadline::SwUndoTableHeadline( const SwTable& rTable, sal_uInt16 nOldHdl,
830 sal_uInt16 nNewHdl )
831 : SwUndo( SwUndoId::TABLEHEADLINE, rTable.GetFrameFormat()->GetDoc() ),
832 m_nOldHeadline( nOldHdl ),
833 m_nNewHeadline( nNewHdl )
834{
835 OSL_ENSURE( !rTable.GetTabSortBoxes().empty(), "Table without content" )do { if (true && (!(!rTable.GetTabSortBoxes().empty()
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "835" ": "), "%s", "Table without content"); } } while (
false)
;
836 const SwStartNode *pSttNd = rTable.GetTabSortBoxes()[ 0 ]->GetSttNd();
837 OSL_ENSURE( pSttNd, "Box without content" )do { if (true && (!(pSttNd))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "837" ": "), "%s", "Box without content"); } } while (false
)
;
838
839 m_nTableNode = pSttNd->StartOfSectionIndex();
840}
841
842void SwUndoTableHeadline::UndoImpl(::sw::UndoRedoContext & rContext)
843{
844 SwDoc & rDoc = rContext.GetDoc();
845 SwTableNode* pTNd = rDoc.GetNodes()[ m_nTableNode ]->GetTableNode();
846 OSL_ENSURE( pTNd, "could not find any TableNode" )do { if (true && (!(pTNd))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "846" ": "), "%s", "could not find any TableNode"); } } while
(false)
;
847
848 rDoc.SetRowsToRepeat( pTNd->GetTable(), m_nOldHeadline );
849}
850
851void SwUndoTableHeadline::RedoImpl(::sw::UndoRedoContext & rContext)
852{
853 SwDoc & rDoc = rContext.GetDoc();
854
855 SwTableNode* pTNd = rDoc.GetNodes()[ m_nTableNode ]->GetTableNode();
856 OSL_ENSURE( pTNd, "could not find any TableNode" )do { if (true && (!(pTNd))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "856" ": "), "%s", "could not find any TableNode"); } } while
(false)
;
857
858 rDoc.SetRowsToRepeat( pTNd->GetTable(), m_nNewHeadline );
859}
860
861void SwUndoTableHeadline::RepeatImpl(::sw::RepeatContext & rContext)
862{
863 SwTableNode *const pTableNd =
864 rContext.GetRepeatPaM().GetNode().FindTableNode();
865 if( pTableNd )
866 {
867 rContext.GetDoc().SetRowsToRepeat( pTableNd->GetTable(), m_nNewHeadline );
868 }
869}
870
871SaveTable::SaveTable( const SwTable& rTable, sal_uInt16 nLnCnt, bool bSaveFormula )
872 : m_aTableSet(*rTable.GetFrameFormat()->GetAttrSet().GetPool(), aTableSetRange),
873 m_pSwTable(&rTable), m_nLineCount(nLnCnt), m_bSaveFormula(bSaveFormula)
874{
875 m_bModifyBox = false;
876 m_bNewModel = rTable.IsNewModel();
877 m_aTableSet.Put(rTable.GetFrameFormat()->GetAttrSet());
878 m_pLine.reset( new SaveLine( nullptr, *rTable.GetTabLines()[ 0 ], *this ) );
4
Calling constructor for 'SaveLine'
879
880 SaveLine* pLn = m_pLine.get();
881 if( USHRT_MAX(32767 *2 +1) == nLnCnt )
882 nLnCnt = rTable.GetTabLines().size();
883 for( sal_uInt16 n = 1; n < nLnCnt; ++n )
884 pLn = new SaveLine( pLn, *rTable.GetTabLines()[ n ], *this );
885
886 m_aFrameFormats.clear();
887 m_pSwTable = nullptr;
888}
889
890sal_uInt16 SaveTable::AddFormat( SwFrameFormat* pFormat, bool bIsLine )
891{
892 size_t nRet = m_aFrameFormats.GetPos(pFormat);
893 if( SIZE_MAX(18446744073709551615UL) == nRet )
894 {
895 // Create copy of ItemSet
896 auto pSet = std::make_shared<SfxItemSet>( *pFormat->GetAttrSet().GetPool(),
897 bIsLine ? aTableLineSetRange : aTableBoxSetRange );
898 pSet->Put( pFormat->GetAttrSet() );
899 // When a formula is set, never save the value. It possibly must be
900 // recalculated.
901 // Save formulas always in plain text.
902 const SfxPoolItem* pItem;
903 if( SfxItemState::SET == pSet->GetItemState( RES_BOXATR_FORMULA, true, &pItem ))
904 {
905 pSet->ClearItem( RES_BOXATR_VALUE );
906 if (m_pSwTable && m_bSaveFormula)
907 {
908 SwTableFormulaUpdate aMsgHint(m_pSwTable);
909 aMsgHint.m_eFlags = TBL_BOXNAME;
910 SwTableBoxFormula* pFormulaItem = const_cast<SwTableBoxFormula*>(static_cast<const SwTableBoxFormula*>(pItem));
911 pFormulaItem->ChgDefinedIn( pFormat );
912 pFormulaItem->ChangeState( &aMsgHint );
913 pFormulaItem->ChgDefinedIn( nullptr );
914 }
915 }
916 nRet = m_aSets.size();
917 m_aSets.push_back(pSet);
918 m_aFrameFormats.insert(m_aFrameFormats.begin() + nRet, pFormat);
919 }
920 return static_cast<sal_uInt16>(nRet);
921}
922
923void SaveTable::RestoreAttr( SwTable& rTable, bool bMdfyBox )
924{
925 m_bModifyBox = bMdfyBox;
926
927 // first, get back attributes of TableFrameFormat
928 SwFrameFormat* pFormat = rTable.GetFrameFormat();
929 SfxItemSet& rFormatSet = const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pFormat->GetAttrSet()));
930 rFormatSet.ClearItem();
931 rFormatSet.Put(m_aTableSet);
932
933 if( pFormat->IsInCache() )
934 {
935 SwFrame::GetCache().Delete( pFormat );
936 pFormat->SetInCache( false );
937 }
938
939 // for safety, invalidate all TableFrames
940 SwIterator<SwTabFrame,SwFormat> aIter( *pFormat );
941 for( SwTabFrame* pLast = aIter.First(); pLast; pLast = aIter.Next() )
942 if( pLast->GetTable() == &rTable )
943 {
944 pLast->InvalidateAll();
945 pLast->SetCompletePaint();
946 }
947
948 // fill FrameFormats with defaults (0)
949 pFormat = nullptr;
950 for (size_t n = m_aSets.size(); n; --n)
951 m_aFrameFormats.push_back(pFormat);
952
953 const size_t nLnCnt = (USHRT_MAX(32767 *2 +1) == m_nLineCount)
954 ? rTable.GetTabLines().size()
955 : m_nLineCount;
956
957 SaveLine* pLn = m_pLine.get();
958 for( size_t n = 0; n < nLnCnt; ++n, pLn = pLn->pNext )
959 {
960 if( !pLn )
961 {
962 OSL_ENSURE( false, "Number of lines changed" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "962" ": "), "%s", "Number of lines changed"); } } while
(false)
;
963 break;
964 }
965
966 pLn->RestoreAttr( *rTable.GetTabLines()[ n ], *this );
967 }
968
969 m_aFrameFormats.clear();
970 m_bModifyBox = false;
971}
972
973void SaveTable::SaveContentAttrs( SwDoc* pDoc )
974{
975 m_pLine->SaveContentAttrs(pDoc);
976}
977
978void SaveTable::CreateNew( SwTable& rTable, bool bCreateFrames,
979 bool bRestoreChart )
980{
981 FndBox_ aTmpBox( nullptr, nullptr );
982 aTmpBox.DelFrames( rTable );
983
984 // first, get back attributes of TableFrameFormat
985 SwFrameFormat* pFormat = rTable.GetFrameFormat();
986 SfxItemSet& rFormatSet = const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pFormat->GetAttrSet()));
987 rFormatSet.ClearItem();
988 rFormatSet.Put(m_aTableSet);
989
990 if( pFormat->IsInCache() )
991 {
992 SwFrame::GetCache().Delete( pFormat );
993 pFormat->SetInCache( false );
994 }
995
996 // SwTableBox must have a format - the SwTableBox takes ownership of it
997 SwTableBoxFormat *const pNewFormat(pFormat->GetDoc()->MakeTableBoxFormat());
998 SwTableBox aParent(pNewFormat, rTable.GetTabLines().size(), nullptr);
999
1000 // fill FrameFormats with defaults (0)
1001 pFormat = nullptr;
1002 for( size_t n = m_aSets.size(); n; --n )
1003 m_aFrameFormats.push_back(pFormat);
1004
1005 m_pLine->CreateNew(rTable, aParent, *this);
1006 m_aFrameFormats.clear();
1007
1008 // add new lines, delete old ones
1009 const size_t nOldLines = (USHRT_MAX(32767 *2 +1) == m_nLineCount)
1010 ? rTable.GetTabLines().size()
1011 : m_nLineCount;
1012
1013 SwDoc *pDoc = rTable.GetFrameFormat()->GetDoc();
1014 SwChartDataProvider *pPCD = pDoc->getIDocumentChartDataProviderAccess().GetChartDataProvider();
1015 size_t n = 0;
1016 for( ; n < aParent.GetTabLines().size(); ++n )
1017 {
1018 SwTableLine* pLn = aParent.GetTabLines()[ n ];
1019 pLn->SetUpper( nullptr );
1020 if( n < nOldLines )
1021 {
1022 SwTableLine* pOld = rTable.GetTabLines()[ n ];
1023
1024 // TL_CHART2: notify chart about boxes to be removed
1025 const SwTableBoxes &rBoxes = pOld->GetTabBoxes();
1026 const size_t nBoxes = rBoxes.size();
1027 for (size_t k = 0; k < nBoxes; ++k)
1028 {
1029 SwTableBox *pBox = rBoxes[k];
1030 if (pPCD)
1031 pPCD->DeleteBox( &rTable, *pBox );
1032 }
1033
1034 rTable.GetTabLines()[n] = pLn;
1035 delete pOld;
1036 }
1037 else
1038 rTable.GetTabLines().insert( rTable.GetTabLines().begin() + n, pLn );
1039 }
1040
1041 if( n < nOldLines )
1042 {
1043 // remove remaining lines...
1044 for (size_t k1 = 0; k1 < nOldLines - n; ++k1)
1045 {
1046 const SwTableBoxes &rBoxes = rTable.GetTabLines()[n + k1]->GetTabBoxes();
1047 const size_t nBoxes = rBoxes.size();
1048 for (size_t k2 = 0; k2 < nBoxes; ++k2)
1049 {
1050 SwTableBox *pBox = rBoxes[k2];
1051 // TL_CHART2: notify chart about boxes to be removed
1052 if (pPCD)
1053 pPCD->DeleteBox( &rTable, *pBox );
1054 }
1055 }
1056
1057 for( SwTableLines::const_iterator it = rTable.GetTabLines().begin() + n;
1058 it != rTable.GetTabLines().begin() + nOldLines; ++it )
1059 delete *it;
1060 rTable.GetTabLines().erase( rTable.GetTabLines().begin() + n, rTable.GetTabLines().begin() + nOldLines );
1061 }
1062
1063 aParent.GetTabLines().erase( aParent.GetTabLines().begin(), aParent.GetTabLines().begin() + n );
1064 assert(aParent.GetTabLines().empty())(static_cast <bool> (aParent.GetTabLines().empty()) ? void
(0) : __assert_fail ("aParent.GetTabLines().empty()", "/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
, 1064, __extension__ __PRETTY_FUNCTION__))
;
1065
1066 if( bCreateFrames )
1067 aTmpBox.MakeFrames( rTable );
1068 if( bRestoreChart )
1069 {
1070 // TL_CHART2: need to inform chart of probably changed cell names
1071 pDoc->UpdateCharts( rTable.GetFrameFormat()->GetName() );
1072 }
1073}
1074
1075void SaveTable::NewFrameFormat( const SwTableLine* pTableLn, const SwTableBox* pTableBx,
1076 sal_uInt16 nFormatPos, SwFrameFormat* pOldFormat )
1077{
1078 SwDoc* pDoc = pOldFormat->GetDoc();
1079
1080 SwFrameFormat* pFormat = m_aFrameFormats[ nFormatPos ];
1081 if( !pFormat )
1082 {
1083 if( pTableLn )
1084 pFormat = pDoc->MakeTableLineFormat();
1085 else
1086 pFormat = pDoc->MakeTableBoxFormat();
1087 pFormat->SetFormatAttr(*m_aSets[nFormatPos]);
1088 m_aFrameFormats[nFormatPos] = pFormat;
1089 }
1090
1091 // first re-assign Frames
1092 SwIterator<SwLayoutFrame,SwFormat> aIter( *pOldFormat );
1093 for( SwFrame* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1094 {
1095 if( pTableLn ? static_cast<SwRowFrame*>(pLast)->GetTabLine() == pTableLn
1096 : static_cast<SwCellFrame*>(pLast)->GetTabBox() == pTableBx )
1097 {
1098 pLast->RegisterToFormat(*pFormat);
1099 pLast->InvalidateAll();
1100 pLast->ReinitializeFrameSizeAttrFlags();
1101 if ( !pTableLn )
1102 {
1103 static_cast<SwCellFrame*>(pLast)->SetDerivedVert( false );
1104 static_cast<SwCellFrame*>(pLast)->CheckDirChange();
1105 }
1106 }
1107 }
1108
1109 // than re-assign myself
1110 if ( pTableLn )
1111 const_cast<SwTableLine*>(pTableLn)->RegisterToFormat( *pFormat );
1112 else if ( pTableBx )
1113 const_cast<SwTableBox*>(pTableBx)->RegisterToFormat( *pFormat );
1114
1115 if (m_bModifyBox && !pTableLn)
1116 {
1117 const SfxPoolItem& rOld = pOldFormat->GetFormatAttr( RES_BOXATR_FORMAT ),
1118 & rNew = pFormat->GetFormatAttr( RES_BOXATR_FORMAT );
1119 if( rOld != rNew )
1120 pFormat->ModifyNotification( &rOld, &rNew );
1121 }
1122
1123 if( !pOldFormat->HasWriterListeners() )
1124 delete pOldFormat;
1125}
1126
1127SaveLine::SaveLine( SaveLine* pPrev, const SwTableLine& rLine, SaveTable& rSTable )
1128 : pNext( nullptr )
1129{
1130 if( pPrev
4.1
'pPrev' is null
)
5
Taking false branch
1131 pPrev->pNext = this;
1132
1133 nItemSet = rSTable.AddFormat( rLine.GetFrameFormat(), true );
1134
1135 pBox = new SaveBox( nullptr, *rLine.GetTabBoxes()[ 0 ], rSTable );
6
Calling constructor for 'SaveBox'
1136 SaveBox* pBx = pBox;
1137 for( size_t n = 1; n < rLine.GetTabBoxes().size(); ++n )
1138 pBx = new SaveBox( pBx, *rLine.GetTabBoxes()[ n ], rSTable );
1139}
1140
1141SaveLine::~SaveLine()
1142{
1143 delete pBox;
1144 delete pNext;
1145}
1146
1147void SaveLine::RestoreAttr( SwTableLine& rLine, SaveTable& rSTable )
1148{
1149 rSTable.NewFrameFormat( &rLine, nullptr, nItemSet, rLine.GetFrameFormat() );
1150
1151 SaveBox* pBx = pBox;
1152 for( size_t n = 0; n < rLine.GetTabBoxes().size(); ++n, pBx = pBx->pNext )
1153 {
1154 if( !pBx )
1155 {
1156 OSL_ENSURE( false, "Number of boxes changed" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1156" ": "), "%s", "Number of boxes changed"); } } while
(false)
;
1157 break;
1158 }
1159 pBx->RestoreAttr( *rLine.GetTabBoxes()[ n ], rSTable );
1160 }
1161}
1162
1163void SaveLine::SaveContentAttrs( SwDoc* pDoc )
1164{
1165 pBox->SaveContentAttrs( pDoc );
1166 if( pNext )
1167 pNext->SaveContentAttrs( pDoc );
1168}
1169
1170void SaveLine::CreateNew( SwTable& rTable, SwTableBox& rParent, SaveTable& rSTable )
1171{
1172 SwTableLineFormat* pFormat = static_cast<SwTableLineFormat*>(rSTable.m_aFrameFormats[ nItemSet ]);
1173 if( !pFormat )
1174 {
1175 SwDoc* pDoc = rTable.GetFrameFormat()->GetDoc();
1176 pFormat = pDoc->MakeTableLineFormat();
1177 pFormat->SetFormatAttr(*rSTable.m_aSets[nItemSet]);
1178 rSTable.m_aFrameFormats[nItemSet] = pFormat;
1179 }
1180 SwTableLine* pNew = new SwTableLine( pFormat, 1, &rParent );
1181
1182 rParent.GetTabLines().push_back( pNew );
1183
1184 pBox->CreateNew( rTable, *pNew, rSTable );
1185
1186 if( pNext )
1187 pNext->CreateNew( rTable, rParent, rSTable );
1188}
1189
1190SaveBox::SaveBox( SaveBox* pPrev, const SwTableBox& rBox, SaveTable& rSTable )
1191 : pNext( nullptr ), nSttNode( ULONG_MAX(9223372036854775807L *2UL+1UL) ), nRowSpan(0)
1192{
1193 Ptrs.pLine = nullptr;
1194
1195 if( pPrev
6.1
'pPrev' is null
)
7
Taking false branch
1196 pPrev->pNext = this;
1197
1198 nItemSet = rSTable.AddFormat( rBox.GetFrameFormat(), false );
1199
1200 if( rBox.GetSttNd() )
8
Assuming the condition is false
9
Taking false branch
1201 {
1202 nSttNode = rBox.GetSttIdx();
1203 nRowSpan = rBox.getRowSpan();
1204 }
1205 else
1206 {
1207 Ptrs.pLine = new SaveLine( nullptr, *rBox.GetTabLines()[ 0 ], rSTable );
1208
1209 SaveLine* pLn = Ptrs.pLine;
1210 for( size_t n = 1; n < rBox.GetTabLines().size(); ++n )
10
Assuming the condition is true
11
Loop condition is true. Entering loop body
13
Assuming the condition is false
14
Loop condition is false. Execution continues on line 1210
1211 pLn = new SaveLine( pLn, *rBox.GetTabLines()[ n ], rSTable );
12
Memory is allocated
1212 }
1213}
15
Potential leak of memory pointed to by 'pLn'
1214
1215SaveBox::~SaveBox()
1216{
1217 if( ULONG_MAX(9223372036854775807L *2UL+1UL) == nSttNode ) // no EndBox
1218 delete Ptrs.pLine;
1219 else
1220 delete Ptrs.pContentAttrs;
1221 delete pNext;
1222}
1223
1224void SaveBox::RestoreAttr( SwTableBox& rBox, SaveTable& rSTable )
1225{
1226 rSTable.NewFrameFormat( nullptr, &rBox, nItemSet, rBox.GetFrameFormat() );
1227
1228 if( ULONG_MAX(9223372036854775807L *2UL+1UL) == nSttNode ) // no EndBox
1229 {
1230 if( rBox.GetTabLines().empty() )
1231 {
1232 OSL_ENSURE( false, "Number of lines changed" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1232" ": "), "%s", "Number of lines changed"); } } while
(false)
;
1233 }
1234 else
1235 {
1236 SaveLine* pLn = Ptrs.pLine;
1237 for( size_t n = 0; n < rBox.GetTabLines().size(); ++n, pLn = pLn->pNext )
1238 {
1239 if( !pLn )
1240 {
1241 OSL_ENSURE( false, "Number of lines changed" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1241" ": "), "%s", "Number of lines changed"); } } while
(false)
;
1242 break;
1243 }
1244
1245 pLn->RestoreAttr( *rBox.GetTabLines()[ n ], rSTable );
1246 }
1247 }
1248 }
1249 else if( rBox.GetSttNd() && rBox.GetSttIdx() == nSttNode )
1250 {
1251 if( Ptrs.pContentAttrs )
1252 {
1253 SwNodes& rNds = rBox.GetFrameFormat()->GetDoc()->GetNodes();
1254 sal_uInt16 nSet = 0;
1255 sal_uLong nEnd = rBox.GetSttNd()->EndOfSectionIndex();
1256 for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
1257 {
1258 SwContentNode* pCNd = rNds[ n ]->GetContentNode();
1259 if( pCNd )
1260 {
1261 std::shared_ptr<SfxItemSet> pSet( (*Ptrs.pContentAttrs)[ nSet++ ] );
1262 if( pSet )
1263 {
1264 sal_uInt16 const *pRstAttr = aSave_BoxContentSet;
1265 while( *pRstAttr )
1266 {
1267 pCNd->ResetAttr( *pRstAttr, *(pRstAttr+1) );
1268 pRstAttr += 2;
1269 }
1270 pCNd->SetAttr( *pSet );
1271 }
1272 else
1273 pCNd->ResetAllAttr();
1274 }
1275 }
1276 }
1277 }
1278 else
1279 {
1280 OSL_ENSURE( false, "Box not anymore at the same node" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1280" ": "), "%s", "Box not anymore at the same node");
} } while (false)
;
1281 }
1282}
1283
1284void SaveBox::SaveContentAttrs( SwDoc* pDoc )
1285{
1286 if( ULONG_MAX(9223372036854775807L *2UL+1UL) == nSttNode ) // no EndBox
1287 {
1288 // continue in current line
1289 Ptrs.pLine->SaveContentAttrs( pDoc );
1290 }
1291 else
1292 {
1293 sal_uLong nEnd = pDoc->GetNodes()[ nSttNode ]->EndOfSectionIndex();
1294 Ptrs.pContentAttrs = new SfxItemSets;
1295 for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
1296 {
1297 SwContentNode* pCNd = pDoc->GetNodes()[ n ]->GetContentNode();
1298 if( pCNd )
1299 {
1300 std::shared_ptr<SfxItemSet> pSet;
1301 if( pCNd->HasSwAttrSet() )
1302 {
1303 pSet = std::make_shared<SfxItemSet>( pDoc->GetAttrPool(),
1304 aSave_BoxContentSet );
1305 pSet->Put( *pCNd->GetpSwAttrSet() );
1306 }
1307
1308 Ptrs.pContentAttrs->push_back( pSet );
1309 }
1310 }
1311 }
1312 if( pNext )
1313 pNext->SaveContentAttrs( pDoc );
1314}
1315
1316void SaveBox::CreateNew( SwTable& rTable, SwTableLine& rParent, SaveTable& rSTable )
1317{
1318 SwTableBoxFormat* pFormat = static_cast<SwTableBoxFormat*>(rSTable.m_aFrameFormats[ nItemSet ]);
1319 if( !pFormat )
1320 {
1321 SwDoc* pDoc = rTable.GetFrameFormat()->GetDoc();
1322 pFormat = pDoc->MakeTableBoxFormat();
1323 pFormat->SetFormatAttr(*rSTable.m_aSets[nItemSet]);
1324 rSTable.m_aFrameFormats[nItemSet] = pFormat;
1325 }
1326
1327 if( ULONG_MAX(9223372036854775807L *2UL+1UL) == nSttNode ) // no EndBox
1328 {
1329 SwTableBox* pNew = new SwTableBox( pFormat, 1, &rParent );
1330 rParent.GetTabBoxes().push_back( pNew );
1331
1332 Ptrs.pLine->CreateNew( rTable, *pNew, rSTable );
1333 }
1334 else
1335 {
1336 // search box for StartNode in old table
1337 SwTableBox* pBox = rTable.GetTableBox( nSttNode );
1338 if (pBox)
1339 {
1340 SwFrameFormat* pOld = pBox->GetFrameFormat();
1341 pBox->RegisterToFormat( *pFormat );
1342 if( !pOld->HasWriterListeners() )
1343 delete pOld;
1344
1345 pBox->setRowSpan( nRowSpan );
1346
1347 SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
1348 pTBoxes->erase( std::find( pTBoxes->begin(), pTBoxes->end(), pBox ) );
1349
1350 pBox->SetUpper( &rParent );
1351 pTBoxes = &rParent.GetTabBoxes();
1352 pTBoxes->push_back( pBox );
1353 }
1354 }
1355
1356 if( pNext )
1357 pNext->CreateNew( rTable, rParent, rSTable );
1358}
1359
1360// UndoObject for attribute changes on table
1361SwUndoAttrTable::SwUndoAttrTable( const SwTableNode& rTableNd, bool bClearTabCols )
1362 : SwUndo( SwUndoId::TABLE_ATTR, &rTableNd.GetDoc() ),
1363 m_nStartNode( rTableNd.GetIndex() )
1364{
1365 m_bClearTableCol = bClearTabCols;
1366 m_pSaveTable.reset( new SaveTable( rTableNd.GetTable() ) );
1367}
1368
1369SwUndoAttrTable::~SwUndoAttrTable()
1370{
1371}
1372
1373void SwUndoAttrTable::UndoImpl(::sw::UndoRedoContext & rContext)
1374{
1375 SwDoc & rDoc = rContext.GetDoc();
1376 SwTableNode* pTableNd = rDoc.GetNodes()[ m_nStartNode ]->GetTableNode();
1377 OSL_ENSURE( pTableNd, "no TableNode" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1377" ": "), "%s", "no TableNode"); } } while (false)
;
1378
1379 if (pTableNd)
1380 {
1381 SaveTable* pOrig = new SaveTable( pTableNd->GetTable() );
1382 m_pSaveTable->RestoreAttr( pTableNd->GetTable() );
1383 m_pSaveTable.reset( pOrig );
1384 }
1385
1386 if( m_bClearTableCol )
1387 {
1388 ClearFEShellTabCols(rDoc, nullptr);
1389 }
1390}
1391
1392void SwUndoAttrTable::RedoImpl(::sw::UndoRedoContext & rContext)
1393{
1394 UndoImpl(rContext);
1395}
1396
1397// UndoObject for AutoFormat on Table
1398SwUndoTableAutoFormat::SwUndoTableAutoFormat( const SwTableNode& rTableNd,
1399 const SwTableAutoFormat& rAFormat )
1400 : SwUndo( SwUndoId::TABLE_AUTOFMT, &rTableNd.GetDoc() )
1401 , m_TableStyleName(rTableNd.GetTable().GetTableStyleName())
1402 , m_nStartNode( rTableNd.GetIndex() )
1403 , m_bSaveContentAttr( false )
1404 , m_nRepeatHeading(rTableNd.GetTable().GetRowsToRepeat())
1405{
1406 m_pSaveTable.reset( new SaveTable( rTableNd.GetTable() ) );
1407
1408 if( rAFormat.IsFont() || rAFormat.IsJustify() )
1409 {
1410 // then also go over the ContentNodes of the EndBoxes and collect
1411 // all paragraph attributes
1412 m_pSaveTable->SaveContentAttrs( &const_cast<SwDoc&>(rTableNd.GetDoc()) );
1413 m_bSaveContentAttr = true;
1414 }
1415}
1416
1417SwUndoTableAutoFormat::~SwUndoTableAutoFormat()
1418{
1419}
1420
1421void SwUndoTableAutoFormat::SaveBoxContent( const SwTableBox& rBox )
1422{
1423 m_Undos.push_back(std::make_shared<SwUndoTableNumFormat>(rBox));
1424}
1425
1426void
1427SwUndoTableAutoFormat::UndoRedo(bool const bUndo, ::sw::UndoRedoContext & rContext)
1428{
1429 SwDoc & rDoc = rContext.GetDoc();
1430 SwTableNode* pTableNd = rDoc.GetNodes()[ m_nStartNode ]->GetTableNode();
1431 OSL_ENSURE( pTableNd, "no TableNode" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1431" ": "), "%s", "no TableNode"); } } while (false)
;
1432
1433 SwTable& table = pTableNd->GetTable();
1434 if (table.GetTableStyleName() != m_TableStyleName)
1435 {
1436 OUString const temp(table.GetTableStyleName());
1437 table.SetTableStyleName(m_TableStyleName);
1438 m_TableStyleName = temp;
1439 }
1440 SaveTable* pOrig = new SaveTable( table );
1441 // then go also over the ContentNodes of the EndBoxes and collect
1442 // all paragraph attributes
1443 if( m_bSaveContentAttr )
1444 pOrig->SaveContentAttrs( &rDoc );
1445
1446 if (bUndo)
1447 {
1448 for (size_t n = m_Undos.size(); 0 < n; --n)
1449 {
1450 m_Undos.at(n-1)->UndoImpl(rContext);
1451 }
1452
1453 table.SetRowsToRepeat(m_nRepeatHeading);
1454 }
1455
1456 m_pSaveTable->RestoreAttr( pTableNd->GetTable(), !bUndo );
1457 m_pSaveTable.reset( pOrig );
1458}
1459
1460void SwUndoTableAutoFormat::UndoImpl(::sw::UndoRedoContext & rContext)
1461{
1462 UndoRedo(true, rContext);
1463}
1464
1465void SwUndoTableAutoFormat::RedoImpl(::sw::UndoRedoContext & rContext)
1466{
1467 UndoRedo(false, rContext);
1468}
1469
1470SwUndoTableNdsChg::SwUndoTableNdsChg( SwUndoId nAction,
1471 const SwSelBoxes& rBoxes,
1472 const SwTableNode& rTableNd,
1473 long nMn, long nMx,
1474 sal_uInt16 nCnt, bool bFlg, bool bSmHght )
1475 : SwUndo( nAction, &rTableNd.GetDoc() ),
1476 m_nMin( nMn ), m_nMax( nMx ),
1477 m_nSttNode( rTableNd.GetIndex() ),
1478 m_nCount( nCnt ),
1479 m_bFlag( bFlg ),
1480 m_bSameHeight( bSmHght )
1481{
1482 const SwTable& rTable = rTableNd.GetTable();
1483 m_pSaveTable.reset( new SaveTable( rTable ) );
1484
1485 // and remember selection
1486 ReNewBoxes( rBoxes );
1487}
1488
1489void SwUndoTableNdsChg::ReNewBoxes( const SwSelBoxes& rBoxes )
1490{
1491 if (rBoxes.size() != m_Boxes.size())
1492 {
1493 m_Boxes.clear();
1494 for (size_t n = 0; n < rBoxes.size(); ++n)
1495 {
1496 m_Boxes.insert( rBoxes[n]->GetSttIdx() );
1497 }
1498 }
1499}
1500
1501SwUndoTableNdsChg::~SwUndoTableNdsChg()
1502{
1503}
1504
1505void SwUndoTableNdsChg::SaveNewBoxes( const SwTableNode& rTableNd,
1506 const SwTableSortBoxes& rOld )
1507{
1508 const SwTable& rTable = rTableNd.GetTable();
1509 const SwTableSortBoxes& rTableBoxes = rTable.GetTabSortBoxes();
1510
1511 OSL_ENSURE( ! IsDelBox(), "wrong Action" )do { if (true && (!(! IsDelBox()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1511" ": "), "%s", "wrong Action"); } } while (false)
;
1512 m_pNewSttNds.reset( new std::set<BoxMove> );
1513
1514 size_t i = 0;
1515 for (size_t n = 0; n < rOld.size(); ++i)
1516 {
1517 if( rOld[ n ] == rTableBoxes[ i ] )
1518 ++n;
1519 else
1520 // new box: insert sorted
1521 m_pNewSttNds->insert( BoxMove(rTableBoxes[ i ]->GetSttIdx()) );
1522 }
1523
1524 for( ; i < rTableBoxes.size(); ++i )
1525 // new box: insert sorted
1526 m_pNewSttNds->insert( BoxMove(rTableBoxes[ i ]->GetSttIdx()) );
1527}
1528
1529static SwTableLine* lcl_FindTableLine( const SwTable& rTable,
1530 const SwTableBox& rBox )
1531{
1532 SwTableLine* pRet = nullptr;
1533 // i63949: For nested cells we have to take nLineNo - 1, too, not 0!
1534 const SwTableLines &rTableLines = ( rBox.GetUpper()->GetUpper() != nullptr ) ?
1535 rBox.GetUpper()->GetUpper()->GetTabLines()
1536 : rTable.GetTabLines();
1537 const SwTableLine* pLine = rBox.GetUpper();
1538 sal_uInt16 nLineNo = rTableLines.GetPos( pLine );
1539 pRet = rTableLines[nLineNo - 1];
1540
1541 return pRet;
1542}
1543
1544static const SwTableLines& lcl_FindParentLines( const SwTable& rTable,
1545 const SwTableBox& rBox )
1546{
1547 const SwTableLines& rRet =
1548 ( rBox.GetUpper()->GetUpper() != nullptr ) ?
1549 rBox.GetUpper()->GetUpper()->GetTabLines() :
1550 rTable.GetTabLines();
1551
1552 return rRet;
1553}
1554
1555void SwUndoTableNdsChg::SaveNewBoxes( const SwTableNode& rTableNd,
1556 const SwTableSortBoxes& rOld,
1557 const SwSelBoxes& rBoxes,
1558 const std::vector<sal_uLong> &rNodeCnts )
1559{
1560 const SwTable& rTable = rTableNd.GetTable();
1561 const SwTableSortBoxes& rTableBoxes = rTable.GetTabSortBoxes();
1562
1563 OSL_ENSURE( ! IsDelBox(), "wrong Action" )do { if (true && (!(! IsDelBox()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1563" ": "), "%s", "wrong Action"); } } while (false)
;
1564 m_pNewSttNds.reset( new std::set<BoxMove> );
1565
1566 OSL_ENSURE( rTable.IsNewModel() || rOld.size() + m_nCount * rBoxes.size() == rTableBoxes.size(),do { if (true && (!(rTable.IsNewModel() || rOld.size(
) + m_nCount * rBoxes.size() == rTableBoxes.size()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1567" ": "), "%s", "unexpected boxes"); } } while (false
)
1567 "unexpected boxes" )do { if (true && (!(rTable.IsNewModel() || rOld.size(
) + m_nCount * rBoxes.size() == rTableBoxes.size()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1567" ": "), "%s", "unexpected boxes"); } } while (false
)
;
1568 OSL_ENSURE( rOld.size() <= rTableBoxes.size(), "more unexpected boxes" )do { if (true && (!(rOld.size() <= rTableBoxes.size
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1568" ": "), "%s", "more unexpected boxes"); } } while (
false)
;
1569 for (size_t n = 0, i = 0; i < rTableBoxes.size(); ++i)
1570 {
1571 if( ( n < rOld.size() ) &&
1572 ( rOld[ n ] == rTableBoxes[ i ] ) )
1573 {
1574 // box already known? Then nothing to be done.
1575 ++n;
1576 }
1577 else
1578 {
1579 // new box found: insert (obey sort order)
1580 const SwTableBox* pBox = rTableBoxes[ i ];
1581
1582 // find the source box. It must be one in rBoxes.
1583 // We found the right one if it's in the same column as pBox.
1584 // No, if more than one selected cell in the same column has been split,
1585 // we have to look for the nearest one (i65201)!
1586 const SwTableBox* pSourceBox = nullptr;
1587 const SwTableBox* pCheckBox = nullptr;
1588 const SwTableLine* pBoxLine = pBox->GetUpper();
1589 sal_uInt16 nLineDiff = lcl_FindParentLines(rTable,*pBox).GetPos(pBoxLine);
1590 sal_uInt16 nLineNo = 0;
1591 for (size_t j = 0; j < rBoxes.size(); ++j)
1592 {
1593 pCheckBox = rBoxes[j];
1594 if( pCheckBox->GetUpper()->GetUpper() == pBox->GetUpper()->GetUpper() )
1595 {
1596 const SwTableLine* pCheckLine = pCheckBox->GetUpper();
1597 sal_uInt16 nCheckLine = lcl_FindParentLines( rTable, *pCheckBox ).
1598 GetPos( pCheckLine );
1599 if( ( !pSourceBox || nCheckLine > nLineNo ) && nCheckLine < nLineDiff )
1600 {
1601 nLineNo = nCheckLine;
1602 pSourceBox = pCheckBox;
1603 }
1604 }
1605 }
1606
1607 // find the line number difference
1608 // (to help determine bNodesMoved flag below)
1609 nLineDiff = nLineDiff - nLineNo;
1610 OSL_ENSURE( pSourceBox, "Split source box not found!" )do { if (true && (!(pSourceBox))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1610" ": "), "%s", "Split source box not found!"); } } while
(false)
;
1611 // find out how many nodes the source box used to have
1612 // (to help determine bNodesMoved flag below)
1613 size_t nNdsPos = 0;
1614 while( rBoxes[ nNdsPos ] != pSourceBox )
1615 ++nNdsPos;
1616 sal_uLong nNodes = rNodeCnts[ nNdsPos ];
1617
1618 // When a new table cell is created, it either gets a new
1619 // node, or it gets node(s) from elsewhere. The undo must
1620 // know, of course, and thus we must determine here just
1621 // where pBox's nodes are from:
1622 // If 1) the source box has lost nodes, and
1623 // 2) we're in the node range that got nodes
1624 // then pBox received nodes from elsewhere.
1625 // If bNodesMoved is set for pBox the undo must move the
1626 // boxes back, otherwise it must delete them.
1627 bool bNodesMoved = pSourceBox &&
1628 ( nNodes != ( pSourceBox->GetSttNd()->EndOfSectionIndex() -
1629 pSourceBox->GetSttIdx() ) )
1630 && ( nNodes - 1 > nLineDiff );
1631 m_pNewSttNds->insert( BoxMove(pBox->GetSttIdx(), bNodesMoved) );
1632 }
1633 }
1634}
1635
1636void SwUndoTableNdsChg::SaveSection( SwStartNode* pSttNd )
1637{
1638 OSL_ENSURE( IsDelBox(), "wrong Action" )do { if (true && (!(IsDelBox()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1638" ": "), "%s", "wrong Action"); } } while (false)
;
1639 if (m_pDelSects == nullptr)
1640 m_pDelSects.reset(new SwUndoSaveSections);
1641
1642 SwTableNode* pTableNd = pSttNd->FindTableNode();
1643 std::unique_ptr<SwUndoSaveSection, o3tl::default_delete<SwUndoSaveSection>> pSave(new SwUndoSaveSection);
1644 pSave->SaveSection( SwNodeIndex( *pSttNd ));
1645
1646 m_pDelSects->push_back(std::move(pSave));
1647 m_nSttNode = pTableNd->GetIndex();
1648}
1649
1650void SwUndoTableNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
1651{
1652 SwDoc & rDoc = rContext.GetDoc();
1653 SwNodeIndex aIdx( rDoc.GetNodes(), m_nSttNode );
1654
1655 SwTableNode *const pTableNd = aIdx.GetNode().GetTableNode();
1656 OSL_ENSURE( pTableNd, "no TableNode" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1656" ": "), "%s", "no TableNode"); } } while (false)
;
1657
1658 SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
1659 aMsgHint.m_eFlags = TBL_BOXPTR;
1660 rDoc.getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
1661
1662 CHECK_TABLE( pTableNd->GetTable() )
1663
1664 FndBox_ aTmpBox( nullptr, nullptr );
1665 // ? TL_CHART2: notification or locking of controller required ?
1666
1667 SwChartDataProvider *pPCD = rDoc.getIDocumentChartDataProviderAccess().GetChartDataProvider();
1668 SwSelBoxes aDelBoxes;
1669 std::vector< std::pair<SwTableBox *, sal_uLong> > aDelNodes;
1670 if( IsDelBox() )
1671 {
1672 // Trick: add missing boxes in any line, they will be connected
1673 // correctly when calling CreateNew
1674 SwTableBox* pCpyBox = pTableNd->GetTable().GetTabSortBoxes()[0];
1675 SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
1676
1677 // restore sections
1678 for (size_t n = m_pDelSects->size(); n; )
1679 {
1680 SwUndoSaveSection *const pSave = (*m_pDelSects)[ --n ].get();
1681 pSave->RestoreSection( &rDoc, &aIdx, SwTableBoxStartNode );
1682 if( pSave->GetHistory() )
1683 pSave->GetHistory()->Rollback( &rDoc );
1684 SwTableBox* pBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pCpyBox->GetFrameFormat()), aIdx,
1685 pCpyBox->GetUpper() );
1686 rLnBoxes.push_back( pBox );
1687 }
1688 m_pDelSects->clear();
1689 }
1690 else if( !m_pNewSttNds->empty() )
1691 {
1692 // Then the nodes have be moved and not deleted!
1693 // But for that we need a temp array.
1694 std::vector<BoxMove> aTmp( m_pNewSttNds->begin(), m_pNewSttNds->end() );
1695
1696 // backwards
1697 for (size_t n = aTmp.size(); n > 0 ; )
1698 {
1699 --n;
1700 // delete box from table structure
1701 sal_uLong nIdx = aTmp[n].index;
1702 SwTableBox* pBox = pTableNd->GetTable().GetTableBox( nIdx );
1703 OSL_ENSURE( pBox, "Where is my TableBox?" )do { if (true && (!(pBox))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1703" ": "), "%s", "Where is my TableBox?"); } } while (
false)
;
1704
1705 // TL_CHART2: notify chart about box to be removed
1706 if (pPCD)
1707 pPCD->DeleteBox( &pTableNd->GetTable(), *pBox );
1708
1709 // insert _before_ deleting the section - otherwise the box
1710 // has no start node so all boxes sort equal in SwSelBoxes
1711 aDelBoxes.insert(pBox);
1712
1713 if( aTmp[n].hasMoved )
1714 {
1715 SwNodeRange aRg( *pBox->GetSttNd(), 1,
1716 *pBox->GetSttNd()->EndOfSectionNode() );
1717
1718 SwTableLine* pLine = lcl_FindTableLine( pTableNd->GetTable(), *pBox );
1719 SwNodeIndex aInsPos( *(pLine->GetTabBoxes()[0]->GetSttNd()), 2 );
1720
1721 // adjust all StartNode indices
1722 size_t i = n;
1723 sal_uLong nSttIdx = aInsPos.GetIndex() - 2,
1724 nNdCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
1725 while( i && aTmp[ --i ].index > nSttIdx )
1726 aTmp[ i ].index += nNdCnt;
1727
1728 // first delete box
1729 delete pBox;
1730 // than move nodes
1731 rDoc.GetNodes().MoveNodes( aRg, rDoc.GetNodes(), aInsPos, false );
1732 }
1733 else
1734 {
1735 aDelNodes.emplace_back(pBox, nIdx);
1736 }
1737 }
1738 }
1739 else
1740 {
1741 // Remove nodes from nodes array (backwards!)
1742 std::set<BoxMove>::reverse_iterator it;
1743 for( it = m_pNewSttNds->rbegin(); it != m_pNewSttNds->rend(); ++it )
1744 {
1745 sal_uLong nIdx = (*it).index;
1746 SwTableBox* pBox = pTableNd->GetTable().GetTableBox( nIdx );
1747 OSL_ENSURE( pBox, "Where's my table box?" )do { if (true && (!(pBox))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1747" ": "), "%s", "Where's my table box?"); } } while (
false)
;
1748 // TL_CHART2: notify chart about box to be removed
1749 if (pPCD)
1750 pPCD->DeleteBox( &pTableNd->GetTable(), *pBox );
1751 aDelBoxes.insert(pBox);
1752 aDelNodes.emplace_back(pBox, nIdx);
1753 }
1754 }
1755
1756 // fdo#57197: before deleting the SwTableBoxes, delete the SwTabFrames
1757 aTmpBox.SetTableLines(aDelBoxes, pTableNd->GetTable());
1758 aTmpBox.DelFrames(pTableNd->GetTable());
1759
1760 // do this _after_ deleting Frames because disposing SwAccessible requires
1761 // connection to the nodes, see SwAccessibleChild::IsAccessible()
1762 for (const std::pair<SwTableBox *, sal_uLong> & rDelNode : aDelNodes)
1763 {
1764 // first disconnect box from node, otherwise ~SwTableBox would
1765 // access pBox->pSttNd, deleted by DeleteSection
1766 rDelNode.first->RemoveFromTable();
1767 rDoc.getIDocumentContentOperations().DeleteSection(rDoc.GetNodes()[ rDelNode.second ]);
1768 }
1769
1770 // Remove boxes from table structure
1771 for( size_t n = 0; n < aDelBoxes.size(); ++n )
1772 {
1773 SwTableBox* pCurrBox = aDelBoxes[n];
1774 SwTableBoxes* pTBoxes = &pCurrBox->GetUpper()->GetTabBoxes();
1775 pTBoxes->erase( std::find( pTBoxes->begin(), pTBoxes->end(), pCurrBox ) );
1776 delete pCurrBox;
1777 }
1778
1779 m_pSaveTable->CreateNew( pTableNd->GetTable(), true, false );
1780
1781 // TL_CHART2: need to inform chart of probably changed cell names
1782 rDoc.UpdateCharts( pTableNd->GetTable().GetFrameFormat()->GetName() );
1783
1784 if( IsDelBox() )
1785 m_nSttNode = pTableNd->GetIndex();
1786 ClearFEShellTabCols(rDoc, nullptr);
1787 CHECK_TABLE( pTableNd->GetTable() )
1788}
1789
1790void SwUndoTableNdsChg::RedoImpl(::sw::UndoRedoContext & rContext)
1791{
1792 SwDoc & rDoc = rContext.GetDoc();
1793
1794 SwTableNode* pTableNd = rDoc.GetNodes()[ m_nSttNode ]->GetTableNode();
1795 OSL_ENSURE( pTableNd, "no TableNode" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1795" ": "), "%s", "no TableNode"); } } while (false)
;
1796 CHECK_TABLE( pTableNd->GetTable() )
1797
1798 SwSelBoxes aSelBoxes;
1799 for (const auto& rBox : m_Boxes)
1800 {
1801 SwTableBox* pBox = pTableNd->GetTable().GetTableBox( rBox );
1802 aSelBoxes.insert( pBox );
1803 }
1804
1805 // create SelBoxes and call InsertCell/-Row/SplitTable
1806 switch( GetId() )
1807 {
1808 case SwUndoId::TABLE_INSCOL:
1809 rDoc.InsertCol( aSelBoxes, m_nCount, m_bFlag );
1810 break;
1811
1812 case SwUndoId::TABLE_INSROW:
1813 rDoc.InsertRow( aSelBoxes, m_nCount, m_bFlag );
1814 break;
1815
1816 case SwUndoId::TABLE_SPLIT:
1817 rDoc.SplitTable( aSelBoxes, m_bFlag, m_nCount, m_bSameHeight );
1818 break;
1819 case SwUndoId::TABLE_DELBOX:
1820 case SwUndoId::ROW_DELETE:
1821 case SwUndoId::COL_DELETE:
1822 {
1823 SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
1824 aMsgHint.m_eFlags = TBL_BOXPTR;
1825 rDoc.getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
1826 SwTable &rTable = pTableNd->GetTable();
1827 if( m_nMax > m_nMin && rTable.IsNewModel() )
1828 rTable.PrepareDeleteCol( m_nMin, m_nMax );
1829 rTable.DeleteSel( &rDoc, aSelBoxes, nullptr, this, true, true );
1830 m_nSttNode = pTableNd->GetIndex();
1831 }
1832 break;
1833 default:
1834 ;
1835 }
1836 ClearFEShellTabCols(rDoc, nullptr);
1837 CHECK_TABLE( pTableNd->GetTable() )
1838}
1839
1840SwUndoTableMerge::SwUndoTableMerge( const SwPaM& rTableSel )
1841 : SwUndo( SwUndoId::TABLE_MERGE, &rTableSel.GetDoc() ), SwUndRng( rTableSel )
1842{
1843 const SwTableNode* pTableNd = rTableSel.GetNode().FindTableNode();
1844 OSL_ENSURE( pTableNd, "Where is the TableNode?" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1844" ": "), "%s", "Where is the TableNode?"); } } while
(false)
;
1845 m_pSaveTable.reset( new SaveTable( pTableNd->GetTable() ) );
1846 m_nTableNode = pTableNd->GetIndex();
1847}
1848
1849SwUndoTableMerge::~SwUndoTableMerge()
1850{
1851 m_pSaveTable.reset();
1852 m_vMoves.clear();
1853 m_pHistory.reset();
1854}
1855
1856void SwUndoTableMerge::UndoImpl(::sw::UndoRedoContext & rContext)
1857{
1858 SwDoc & rDoc = rContext.GetDoc();
1859 SwNodeIndex aIdx( rDoc.GetNodes(), m_nTableNode );
1860
1861 SwTableNode *const pTableNd = aIdx.GetNode().GetTableNode();
1862 OSL_ENSURE( pTableNd, "no TableNode" )do { if (true && (!(pTableNd))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1862" ": "), "%s", "no TableNode"); } } while (false)
;
1863
1864 SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
1865 aMsgHint.m_eFlags = TBL_BOXPTR;
1866 rDoc.getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
1867
1868 // ? TL_CHART2: notification or locking of controller required ?
1869
1870 // 1. restore deleted boxes:
1871 // Trick: add missing boxes in any line, they will be connected
1872 // correctly when calling CreateNew
1873 SwTableBox *pBox, *pCpyBox = pTableNd->GetTable().GetTabSortBoxes()[0];
1874 SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
1875
1876 CHECKTABLE(pTableNd->GetTable())CheckTable( pTableNd->GetTable() );
1877
1878 SwSelBoxes aSelBoxes;
1879 SwTextFormatColl* pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD );
1880
1881 for (const auto& rBox : m_Boxes)
1882 {
1883 aIdx = rBox;
1884 SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection( aIdx,
1885 SwTableBoxStartNode, pColl );
1886 pBox = new SwTableBox( static_cast<SwTableBoxFormat*>(pCpyBox->GetFrameFormat()), *pSttNd,
1887 pCpyBox->GetUpper() );
1888 rLnBoxes.push_back( pBox );
1889
1890 aSelBoxes.insert( pBox );
1891 }
1892
1893 CHECKTABLE(pTableNd->GetTable())CheckTable( pTableNd->GetTable() );
1894
1895 SwChartDataProvider *pPCD = rDoc.getIDocumentChartDataProviderAccess().GetChartDataProvider();
1896 // 2. deleted the inserted boxes
1897 // delete nodes (from last to first)
1898 for( size_t n = m_aNewStartNodes.size(); n; )
1899 {
1900 // remove box from table structure
1901 sal_uLong nIdx = m_aNewStartNodes[ --n ];
1902
1903 if( !nIdx && n )
1904 {
1905 nIdx = m_aNewStartNodes[ --n ];
1906 pBox = pTableNd->GetTable().GetTableBox( nIdx );
1907 OSL_ENSURE( pBox, "Where is my TableBox?" )do { if (true && (!(pBox))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "1907" ": "), "%s", "Where is my TableBox?"); } } while (
false)
;
1908
1909 if( !m_pSaveTable->IsNewModel() )
1910 rDoc.GetNodes().MakeTextNode( SwNodeIndex(
1911 *pBox->GetSttNd()->EndOfSectionNode() ), pColl );
1912
1913 // this was the separator -> restore moved ones
1914 for (size_t i = m_vMoves.size(); i; )
1915 {
1916 SwTextNode* pTextNd = nullptr;
1917 sal_Int32 nDelPos = 0;
1918 SwUndoMove *const pUndo = m_vMoves[ --i ].get();
1919 if( !pUndo->IsMoveRange() )
1920 {
1921 pTextNd = rDoc.GetNodes()[ pUndo->GetDestSttNode() ]->GetTextNode();
1922 nDelPos = pUndo->GetDestSttContent() - 1;
1923 }
1924 pUndo->UndoImpl(rContext);
1925 if( pUndo->IsMoveRange() )
1926 {
1927 // delete the unnecessary node
1928 aIdx = pUndo->GetEndNode();
1929 SwContentNode *pCNd = aIdx.GetNode().GetContentNode();
1930 if( pCNd )
1931 {
1932 SwNodeIndex aTmp( aIdx, -1 );
1933 SwContentNode *pMove = aTmp.GetNode().GetContentNode();
1934 if( pMove )
1935 pCNd->MoveTo( *pMove );
1936 }
1937 rDoc.GetNodes().Delete( aIdx );
1938 }
1939 else if( pTextNd )
1940 {
1941 // also delete not needed attributes
1942 SwIndex aTmpIdx( pTextNd, nDelPos );
1943 if( pTextNd->GetpSwpHints() && pTextNd->GetpSwpHints()->Count() )
1944 pTextNd->RstTextAttr( aTmpIdx, pTextNd->GetText().getLength() - nDelPos + 1 );
1945 // delete separator
1946 pTextNd->EraseText( aTmpIdx, 1 );
1947 }
1948 }
1949 nIdx = pBox->GetSttIdx();
1950 }
1951 else
1952 pBox = pTableNd->GetTable().GetTableBox( nIdx );
1953
1954 if( !m_pSaveTable->IsNewModel() )
1955 {
1956 // TL_CHART2: notify chart about box to be removed
1957 if (pPCD)
1958 pPCD->DeleteBox( &pTableNd->GetTable(), *pBox );
1959
1960 SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
1961 pTBoxes->erase( std::find(pTBoxes->begin(), pTBoxes->end(), pBox ) );
1962
1963 // delete indices from section
1964 {
1965 SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
1966 SwDoc::CorrAbs( SwNodeIndex( aTmpIdx, 1 ),
1967 SwNodeIndex( *aTmpIdx.GetNode().EndOfSectionNode() ),
1968 SwPosition( aTmpIdx, SwIndex( nullptr, 0 )), true );
1969 }
1970
1971 delete pBox;
1972 rDoc.getIDocumentContentOperations().DeleteSection( rDoc.GetNodes()[ nIdx ] );
1973 }
1974 }
1975 CHECKTABLE(pTableNd->GetTable())CheckTable( pTableNd->GetTable() );
1976
1977 m_pSaveTable->CreateNew( pTableNd->GetTable(), true, false );
1978
1979 // TL_CHART2: need to inform chart of probably changed cell names
1980 rDoc.UpdateCharts( pTableNd->GetTable().GetFrameFormat()->GetName() );
1981
1982 if( m_pHistory )
1983 {
1984 m_pHistory->TmpRollback( &rDoc, 0 );
1985 m_pHistory->SetTmpEnd( m_pHistory->Count() );
1986 }
1987 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
1988 pPam->DeleteMark();
1989 pPam->GetPoint()->nNode = m_nSttNode;
1990 pPam->GetPoint()->nContent.Assign( pPam->GetContentNode(), m_nSttContent );
1991 pPam->SetMark();
1992 pPam->DeleteMark();
1993
1994 CHECKTABLE(pTableNd->GetTable())CheckTable( pTableNd->GetTable() );
1995 ClearFEShellTabCols(rDoc, nullptr);
1996}
1997
1998void SwUndoTableMerge::RedoImpl(::sw::UndoRedoContext & rContext)
1999{
2000 SwDoc & rDoc = rContext.GetDoc();
2001 SwPaM & rPam( AddUndoRedoPaM(rContext) );
2002 rDoc.MergeTable(rPam);
2003}
2004
2005void SwUndoTableMerge::MoveBoxContent( SwDoc& rDoc, SwNodeRange& rRg, SwNodeIndex& rPos )
2006{
2007 SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 );
2008 std::unique_ptr<SwUndoMove> pUndo(new SwUndoMove( rDoc, rRg, rPos ));
2009 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
2010 rDoc.getIDocumentContentOperations().MoveNodeRange( rRg, rPos, m_pSaveTable->IsNewModel() ?
2011 SwMoveFlags::NO_DELFRMS :
2012 SwMoveFlags::DEFAULT );
2013 ++aTmp;
2014 ++aTmp2;
2015 pUndo->SetDestRange( aTmp2, rPos, aTmp );
2016
2017 m_vMoves.push_back(std::move(pUndo));
2018}
2019
2020void SwUndoTableMerge::SetSelBoxes( const SwSelBoxes& rBoxes )
2021{
2022 // memorize selection
2023 for (size_t n = 0; n < rBoxes.size(); ++n)
2024 {
2025 m_Boxes.insert(rBoxes[n]->GetSttIdx());
2026 }
2027
2028 // as separator for inserts of new boxes after shifting
2029 m_aNewStartNodes.push_back( sal_uLong(0) );
2030
2031 // The new table model does not delete overlapped cells (by row span),
2032 // so the rBoxes array might be empty even some cells have been merged.
2033 if( !rBoxes.empty() )
2034 m_nTableNode = rBoxes[ 0 ]->GetSttNd()->FindTableNode()->GetIndex();
2035}
2036
2037void SwUndoTableMerge::SaveCollection( const SwTableBox& rBox )
2038{
2039 if( !m_pHistory )
2040 m_pHistory.reset(new SwHistory);
2041
2042 SwNodeIndex aIdx( *rBox.GetSttNd(), 1 );
2043 SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
2044 if( !pCNd )
2045 pCNd = aIdx.GetNodes().GoNext( &aIdx );
2046
2047 m_pHistory->Add( pCNd->GetFormatColl(), aIdx.GetIndex(), pCNd->GetNodeType());
2048 if( pCNd->HasSwAttrSet() )
2049 m_pHistory->CopyFormatAttr( *pCNd->GetpSwAttrSet(), aIdx.GetIndex() );
2050}
2051
2052SwUndoTableNumFormat::SwUndoTableNumFormat( const SwTableBox& rBox,
2053 const SfxItemSet* pNewSet )
2054 : SwUndo(SwUndoId::TBLNUMFMT, rBox.GetFrameFormat()->GetDoc())
2055 , m_nFormatIdx(getSwDefaultTextFormat())
2056 , m_nNewFormatIdx(0)
2057 , m_fNum(0.0)
2058 , m_fNewNum(0.0)
2059 , m_bNewFormat(false)
2060 , m_bNewFormula(false)
2061 , m_bNewValue(false)
2062{
2063 m_nNode = rBox.GetSttIdx();
2064
2065 m_nNodePos = rBox.IsValidNumTextNd( nullptr == pNewSet );
2066 SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
2067
2068 if( ULONG_MAX(9223372036854775807L *2UL+1UL) != m_nNodePos )
2069 {
2070 SwTextNode* pTNd = pDoc->GetNodes()[ m_nNodePos ]->GetTextNode();
2071
2072 m_pHistory.reset(new SwHistory);
2073 SwRegHistory aRHst( *rBox.GetSttNd(), m_pHistory.get() );
2074 // always save all text atttibutes because of possibly overlapping
2075 // areas of on/off
2076 m_pHistory->CopyAttr( pTNd->GetpSwpHints(), m_nNodePos, 0,
2077 pTNd->GetText().getLength(), true );
2078
2079 if( pTNd->HasSwAttrSet() )
2080 m_pHistory->CopyFormatAttr( *pTNd->GetpSwAttrSet(), m_nNodePos );
2081
2082 m_aStr = pTNd->GetText();
2083 if( pTNd->GetpSwpHints() )
2084 pTNd->GetpSwpHints()->DeRegister();
2085 }
2086
2087 m_pBoxSet.reset( new SfxItemSet( pDoc->GetAttrPool(), aTableBoxSetRange ) );
2088 m_pBoxSet->Put( rBox.GetFrameFormat()->GetAttrSet() );
2089
2090 if( pNewSet )
2091 {
2092 const SfxPoolItem* pItem;
2093 if( SfxItemState::SET == pNewSet->GetItemState( RES_BOXATR_FORMAT,
2094 false, &pItem ))
2095 {
2096 m_bNewFormat = true;
2097 m_nNewFormatIdx = static_cast<const SwTableBoxNumFormat*>(pItem)->GetValue();
2098 }
2099 if( SfxItemState::SET == pNewSet->GetItemState( RES_BOXATR_FORMULA,
2100 false, &pItem ))
2101 {
2102 m_bNewFormula = true;
2103 m_aNewFormula = static_cast<const SwTableBoxFormula*>(pItem)->GetFormula();
2104 }
2105 if( SfxItemState::SET == pNewSet->GetItemState( RES_BOXATR_VALUE,
2106 false, &pItem ))
2107 {
2108 m_bNewValue = true;
2109 m_fNewNum = static_cast<const SwTableBoxValue*>(pItem)->GetValue();
2110 }
2111 }
2112
2113 // is a history needed at all?
2114 if (m_pHistory && !m_pHistory->Count())
2115 {
2116 m_pHistory.reset();
2117 }
2118}
2119
2120SwUndoTableNumFormat::~SwUndoTableNumFormat()
2121{
2122 m_pHistory.reset();
2123 m_pBoxSet.reset();
2124}
2125
2126void SwUndoTableNumFormat::UndoImpl(::sw::UndoRedoContext & rContext)
2127{
2128 OSL_ENSURE( m_pBoxSet, "Where's the stored item set?" )do { if (true && (!(m_pBoxSet))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "2128" ": "), "%s", "Where's the stored item set?"); } }
while (false)
;
2129
2130 SwDoc & rDoc = rContext.GetDoc();
2131 SwStartNode* pSttNd = rDoc.GetNodes()[ m_nNode ]->
2132 FindSttNodeByType( SwTableBoxStartNode );
2133 OSL_ENSURE( pSttNd, "without StartNode no TableBox" )do { if (true && (!(pSttNd))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "2133" ": "), "%s", "without StartNode no TableBox"); } }
while (false)
;
2134 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTableBox(
2135 pSttNd->GetIndex() );
2136 OSL_ENSURE( pBox, "found no TableBox" )do { if (true && (!(pBox))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "2136" ": "), "%s", "found no TableBox"); } } while (false
)
;
2137
2138 SwTableBoxFormat* pFormat = rDoc.MakeTableBoxFormat();
2139 pFormat->SetFormatAttr( *m_pBoxSet );
2140 pBox->ChgFrameFormat( pFormat );
2141
2142 if( ULONG_MAX(9223372036854775807L *2UL+1UL) == m_nNodePos )
2143 return;
2144
2145 SwTextNode* pTextNd = rDoc.GetNodes()[ m_nNodePos ]->GetTextNode();
2146 // If more than one node was deleted then all "node" attributes were also
2147 // saved
2148 if( pTextNd->HasSwAttrSet() )
2149 pTextNd->ResetAllAttr();
2150
2151 if( pTextNd->GetpSwpHints() && !m_aStr.isEmpty() )
2152 pTextNd->ClearSwpHintsArr( true );
2153
2154 // ChgTextToNum(..) only acts when the strings are different. We need to do
2155 // the same here.
2156 if( pTextNd->GetText() != m_aStr )
2157 {
2158 rDoc.getIDocumentRedlineAccess().DeleteRedline( *( pBox->GetSttNd() ), false, RedlineType::Any );
2159
2160 SwIndex aIdx( pTextNd, 0 );
2161 if( !m_aStr.isEmpty() )
2162 {
2163 pTextNd->EraseText( aIdx );
2164 pTextNd->InsertText( m_aStr, aIdx,
2165 SwInsertFlags::NOHINTEXPAND );
2166 }
2167 }
2168
2169 if( m_pHistory )
2170 {
2171 sal_uInt16 nTmpEnd = m_pHistory->GetTmpEnd();
2172 m_pHistory->TmpRollback( &rDoc, 0 );
2173 m_pHistory->SetTmpEnd( nTmpEnd );
2174 }
2175
2176 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2177 pPam->DeleteMark();
2178 pPam->GetPoint()->nNode = m_nNode + 1;
2179 pPam->GetPoint()->nContent.Assign( pTextNd, 0 );
2180}
2181
2182namespace {
2183
2184/** switch the RedlineFlags on the given document, using
2185 * SetRedlineFlags_intern. This class set the mode in the constructor,
2186 * and changes it back in the destructor, i.e. it uses the
2187 * initialization-is-resource-acquisition idiom.
2188 */
2189class RedlineFlagsInternGuard
2190{
2191 SwDoc& mrDoc;
2192 RedlineFlags meOldRedlineFlags;
2193
2194public:
2195 RedlineFlagsInternGuard(
2196 SwDoc& rDoc, // change mode of this document
2197 RedlineFlags eNewRedlineFlags, // new redline mode
2198 RedlineFlags eRedlineFlagsMask /*change only bits set in this mask*/);
2199
2200 ~RedlineFlagsInternGuard();
2201};
2202
2203}
2204
2205RedlineFlagsInternGuard::RedlineFlagsInternGuard(
2206 SwDoc& rDoc,
2207 RedlineFlags eNewRedlineFlags,
2208 RedlineFlags eRedlineFlagsMask )
2209 : mrDoc( rDoc ),
2210 meOldRedlineFlags( rDoc.getIDocumentRedlineAccess().GetRedlineFlags() )
2211{
2212 mrDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( ( meOldRedlineFlags & ~eRedlineFlagsMask ) |
2213 ( eNewRedlineFlags & eRedlineFlagsMask ) );
2214}
2215
2216RedlineFlagsInternGuard::~RedlineFlagsInternGuard()
2217{
2218 mrDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( meOldRedlineFlags );
2219}
2220
2221void SwUndoTableNumFormat::RedoImpl(::sw::UndoRedoContext & rContext)
2222{
2223 // Could the box be changed?
2224 if( !m_pBoxSet )
2225 return ;
2226
2227 SwDoc & rDoc = rContext.GetDoc();
2228 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2229
2230 pPam->DeleteMark();
2231 pPam->GetPoint()->nNode = m_nNode;
2232
2233 SwNode * pNd = & pPam->GetPoint()->nNode.GetNode();
2234 SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode );
2235 assert(pSttNd && "without StartNode no TableBox")(static_cast <bool> (pSttNd && "without StartNode no TableBox"
) ? void (0) : __assert_fail ("pSttNd && \"without StartNode no TableBox\""
, "/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
, 2235, __extension__ __PRETTY_FUNCTION__))
;
2236 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTableBox(
2237 pSttNd->GetIndex() );
2238 OSL_ENSURE( pBox, "found no TableBox" )do { if (true && (!(pBox))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "2238" ": "), "%s", "found no TableBox"); } } while (false
)
;
2239
2240 SwFrameFormat* pBoxFormat = pBox->ClaimFrameFormat();
2241 if( m_bNewFormat || m_bNewFormula || m_bNewValue )
2242 {
2243 SfxItemSet aBoxSet( rDoc.GetAttrPool(),
2244 svl::Items<RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{} );
2245
2246 // Resetting attributes is not enough. In addition, take care that the
2247 // text will be also formatted correctly.
2248 pBoxFormat->LockModify();
2249
2250 if( m_bNewFormula )
2251 aBoxSet.Put( SwTableBoxFormula( m_aNewFormula ));
2252 else
2253 pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMULA );
2254 if( m_bNewFormat )
2255 aBoxSet.Put( SwTableBoxNumFormat( m_nNewFormatIdx ));
2256 else
2257 pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMAT );
2258 if( m_bNewValue )
2259 aBoxSet.Put( SwTableBoxValue( m_fNewNum ));
2260 else
2261 pBoxFormat->ResetFormatAttr( RES_BOXATR_VALUE );
2262 pBoxFormat->UnlockModify();
2263
2264 // dvo: When redlining is (was) enabled, setting the attribute
2265 // will also change the cell content. To allow this, the
2266 // RedlineFlags::Ignore flag must be removed during Redo. #108450#
2267 RedlineFlagsInternGuard aGuard( rDoc, RedlineFlags::NONE, RedlineFlags::Ignore );
2268 pBoxFormat->SetFormatAttr( aBoxSet );
2269 }
2270 else if( getSwDefaultTextFormat() != m_nFormatIdx )
2271 {
2272 SfxItemSet aBoxSet( rDoc.GetAttrPool(),
2273 svl::Items<RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{} );
2274
2275 aBoxSet.Put( SwTableBoxNumFormat( m_nFormatIdx ));
2276 aBoxSet.Put( SwTableBoxValue( m_fNum ));
2277
2278 // Resetting attributes is not enough. In addition, take care that the
2279 // text will be also formatted correctly.
2280 pBoxFormat->LockModify();
2281 pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMULA );
2282 pBoxFormat->UnlockModify();
2283
2284 // dvo: When redlining is (was) enabled, setting the attribute
2285 // will also change the cell content. To allow this, the
2286 // RedlineFlags::Ignore flag must be removed during Redo. #108450#
2287 RedlineFlagsInternGuard aGuard( rDoc, RedlineFlags::NONE, RedlineFlags::Ignore );
2288 pBoxFormat->SetFormatAttr( aBoxSet );
2289 }
2290 else
2291 {
2292 // it's no number
2293
2294 // Resetting attributes is not enough. In addition, take care that the
2295 // text will be also formatted correctly.
2296 pBoxFormat->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
2297
2298 pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2299 }
2300
2301 if( m_bNewFormula )
2302 {
2303 // No matter what was set, an update of the table is always a good idea
2304 SwTableFormulaUpdate aTableUpdate( &pSttNd->FindTableNode()->GetTable() );
2305 rDoc.getIDocumentFieldsAccess().UpdateTableFields( &aTableUpdate );
2306 }
2307
2308 if( !pNd->IsContentNode() )
2309 pNd = rDoc.GetNodes().GoNext( &pPam->GetPoint()->nNode );
2310 pPam->GetPoint()->nContent.Assign( static_cast<SwContentNode*>(pNd), 0 );
2311}
2312
2313void SwUndoTableNumFormat::SetBox( const SwTableBox& rBox )
2314{
2315 m_nNode = rBox.GetSttIdx();
2316}
2317
2318UndoTableCpyTable_Entry::UndoTableCpyTable_Entry( const SwTableBox& rBox )
2319 : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ),
2320 bJoin( false )
2321{
2322}
2323
2324SwUndoTableCpyTable::SwUndoTableCpyTable(const SwDoc& rDoc)
2325 : SwUndo( SwUndoId::TBLCPYTBL, &rDoc )
2326{
2327}
2328
2329SwUndoTableCpyTable::~SwUndoTableCpyTable()
2330{
2331 m_vArr.clear();
2332 m_pInsRowUndo.reset();
2333}
2334
2335void SwUndoTableCpyTable::UndoImpl(::sw::UndoRedoContext & rContext)
2336{
2337 SwDoc & rDoc = rContext.GetDoc();
2338 DEBUG_REDLINE( &rDoc )
2339
2340 SwTableNode* pTableNd = nullptr;
2341 for (size_t n = m_vArr.size(); n; )
2342 {
2343 UndoTableCpyTable_Entry *const pEntry = m_vArr[ --n ].get();
2344 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
2345 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
2346 if( !pTableNd )
2347 pTableNd = pSNd->FindTableNode();
2348
2349 SwTableBox& rBox = *pTableNd->GetTable().GetTableBox( nSttPos );
2350
2351 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
2352 rDoc.GetNodes().MakeTextNode( aInsIdx, rDoc.GetDfltTextFormatColl() );
2353
2354 // b62341295: Redline for copying tables
2355 const SwNode *pEndNode = rBox.GetSttNd()->EndOfSectionNode();
2356 SwPaM aPam( aInsIdx.GetNode(), *pEndNode );
2357 std::unique_ptr<SwUndoDelete> pUndo;
2358
2359 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) )
2360 {
2361 bool bDeleteCompleteParagraph = false;
2362 bool bShiftPam = false;
2363 // There are a couple of different situations to consider during redlining
2364 if( pEntry->pUndo )
2365 {
2366 SwUndoDelete *const pUndoDelete =
2367 dynamic_cast<SwUndoDelete*>(pEntry->pUndo.get());
2368 SwUndoRedlineDelete *const pUndoRedlineDelete =
2369 dynamic_cast<SwUndoRedlineDelete*>(pEntry->pUndo.get());
2370 assert(pUndoDelete || pUndoRedlineDelete)(static_cast <bool> (pUndoDelete || pUndoRedlineDelete)
? void (0) : __assert_fail ("pUndoDelete || pUndoRedlineDelete"
, "/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
, 2370, __extension__ __PRETTY_FUNCTION__))
;
2371 if (pUndoRedlineDelete)
2372 {
2373 // The old content was not empty or he has been merged with the new content
2374 bDeleteCompleteParagraph = !pEntry->bJoin; // bJoin is set when merged
2375 // Set aTmpIdx to the beginning of the old content
2376 SwNodeIndex aTmpIdx( *pEndNode,
2377 pUndoRedlineDelete->NodeDiff()-1 );
2378 SwTextNode *pText = aTmpIdx.GetNode().GetTextNode();
2379 if( pText )
2380 {
2381 aPam.GetPoint()->nNode = *pText;
2382 aPam.GetPoint()->nContent.Assign( pText,
2383 pUndoRedlineDelete->ContentStart() );
2384 }
2385 else
2386 *aPam.GetPoint() = SwPosition( aTmpIdx );
2387 }
2388 else if (pUndoDelete && pUndoDelete->IsDelFullPara())
2389 {
2390 // When the old content was an empty paragraph, but could not be joined
2391 // with the new content (e.g. because of a section or table)
2392 // We "save" the aPam.Point, we go one step backwards (because later on the
2393 // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag
2394 // for step forward later on.
2395 bDeleteCompleteParagraph = true;
2396 bShiftPam = true;
2397 SwNodeIndex aTmpIdx( *pEndNode, -1 );
2398 SwTextNode *pText = aTmpIdx.GetNode().GetTextNode();
2399 if( pText )
2400 {
2401 aPam.GetPoint()->nNode = *pText;
2402 aPam.GetPoint()->nContent.Assign( pText, 0 );
2403 }
2404 else
2405 *aPam.GetPoint() = SwPosition( aTmpIdx );
2406 }
2407 }
2408 rDoc.getIDocumentRedlineAccess().DeleteRedline( aPam, true, RedlineType::Any );
2409
2410 if( pEntry->pUndo )
2411 {
2412 pEntry->pUndo->UndoImpl(rContext);
2413 pEntry->pUndo.reset();
2414 }
2415 if( bShiftPam )
2416 {
2417 // The aPam.Point is at the moment at the last position of the new content and has to be
2418 // moved to the first position of the old content for the SwUndoDelete operation
2419 SwNodeIndex aTmpIdx( aPam.GetPoint()->nNode, 1 );
2420 SwTextNode *pText = aTmpIdx.GetNode().GetTextNode();
2421 if( pText )
2422 {
2423 aPam.GetPoint()->nNode = *pText;
2424 aPam.GetPoint()->nContent.Assign( pText, 0 );
2425 }
2426 else
2427 *aPam.GetPoint() = SwPosition( aTmpIdx );
2428 }
2429 pUndo = std::make_unique<SwUndoDelete>( aPam, bDeleteCompleteParagraph, true );
2430 }
2431 else
2432 {
2433 pUndo = std::make_unique<SwUndoDelete>( aPam, true );
2434 if( pEntry->pUndo )
2435 {
2436 pEntry->pUndo->UndoImpl(rContext);
2437 pEntry->pUndo.reset();
2438 }
2439 }
2440 pEntry->pUndo = std::move(pUndo);
2441
2442 aInsIdx = rBox.GetSttIdx() + 1;
2443 rDoc.GetNodes().Delete( aInsIdx );
2444
2445 SfxItemSet aTmpSet(
2446 rDoc.GetAttrPool(),
2447 svl::Items<
2448 RES_VERT_ORIENT, RES_VERT_ORIENT,
2449 RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{});
2450 aTmpSet.Put( rBox.GetFrameFormat()->GetAttrSet() );
2451 if( aTmpSet.Count() )
2452 {
2453 SwFrameFormat* pBoxFormat = rBox.ClaimFrameFormat();
2454 pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2455 pBoxFormat->ResetFormatAttr( RES_VERT_ORIENT );
2456 }
2457
2458 if( pEntry->pBoxNumAttr )
2459 {
2460 rBox.ClaimFrameFormat()->SetFormatAttr( *pEntry->pBoxNumAttr );
2461 pEntry->pBoxNumAttr.reset();
2462 }
2463
2464 if( aTmpSet.Count() )
2465 {
2466 pEntry->pBoxNumAttr = std::make_unique<SfxItemSet>(
2467 rDoc.GetAttrPool(),
2468 svl::Items<
2469 RES_VERT_ORIENT, RES_VERT_ORIENT,
2470 RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{});
2471 pEntry->pBoxNumAttr->Put( aTmpSet );
2472 }
2473
2474 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
2475 }
2476
2477 if( m_pInsRowUndo )
2478 {
2479 m_pInsRowUndo->UndoImpl(rContext);
2480 }
2481 DEBUG_REDLINE( &rDoc )
2482}
2483
2484void SwUndoTableCpyTable::RedoImpl(::sw::UndoRedoContext & rContext)
2485{
2486 SwDoc & rDoc = rContext.GetDoc();
2487 DEBUG_REDLINE( &rDoc )
2488
2489 if( m_pInsRowUndo )
2490 {
2491 m_pInsRowUndo->RedoImpl(rContext);
2492 }
2493
2494 SwTableNode* pTableNd = nullptr;
2495 for (size_t n = 0; n < m_vArr.size(); ++n)
2496 {
2497 UndoTableCpyTable_Entry *const pEntry = m_vArr[ n ].get();
2498 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
2499 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
2500 if( !pTableNd )
2501 pTableNd = pSNd->FindTableNode();
2502
2503 SwTableBox& rBox = *pTableNd->GetTable().GetTableBox( nSttPos );
2504
2505 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
2506
2507 // b62341295: Redline for copying tables - Start.
2508 rDoc.GetNodes().MakeTextNode( aInsIdx, rDoc.GetDfltTextFormatColl() );
2509 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode());
2510 std::unique_ptr<SwUndo> pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) ? nullptr : std::make_unique<SwUndoDelete>( aPam, true );
2511 if( pEntry->pUndo )
2512 {
2513 pEntry->pUndo->UndoImpl(rContext);
2514 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) )
2515 {
2516 // PrepareRedline has to be called with the beginning of the old content
2517 // When new and old content has been joined, the rIter.pAktPam has been set
2518 // by the Undo operation to this point.
2519 // Otherwise aInsIdx has been moved during the Undo operation
2520 if( pEntry->bJoin )
2521 {
2522 SwPaM const& rLastPam =
2523 rContext.GetCursorSupplier().GetCurrentShellCursor();
2524 pUndo = PrepareRedline( &rDoc, rBox, *rLastPam.GetPoint(),
2525 pEntry->bJoin, true );
2526 }
2527 else
2528 {
2529 SwPosition aTmpPos( aInsIdx );
2530 pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true );
2531 }
2532 }
2533 pEntry->pUndo.reset();
2534 }
2535 pEntry->pUndo = std::move(pUndo);
2536 // b62341295: Redline for copying tables - End.
2537
2538 aInsIdx = rBox.GetSttIdx() + 1;
2539 rDoc.GetNodes().Delete( aInsIdx );
2540
2541 SfxItemSet aTmpSet(
2542 rDoc.GetAttrPool(),
2543 svl::Items<
2544 RES_VERT_ORIENT, RES_VERT_ORIENT,
2545 RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{});
2546 aTmpSet.Put( rBox.GetFrameFormat()->GetAttrSet() );
2547 if( aTmpSet.Count() )
2548 {
2549 SwFrameFormat* pBoxFormat = rBox.ClaimFrameFormat();
2550 pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2551 pBoxFormat->ResetFormatAttr( RES_VERT_ORIENT );
2552 }
2553 if( pEntry->pBoxNumAttr )
2554 {
2555 rBox.ClaimFrameFormat()->SetFormatAttr( *pEntry->pBoxNumAttr );
2556 pEntry->pBoxNumAttr.reset();
2557 }
2558
2559 if( aTmpSet.Count() )
2560 {
2561 pEntry->pBoxNumAttr = std::make_unique<SfxItemSet>(
2562 rDoc.GetAttrPool(),
2563 svl::Items<
2564 RES_VERT_ORIENT, RES_VERT_ORIENT,
2565 RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{});
2566 pEntry->pBoxNumAttr->Put( aTmpSet );
2567 }
2568
2569 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
2570 }
2571 DEBUG_REDLINE( &rDoc )
2572}
2573
2574void SwUndoTableCpyTable::AddBoxBefore( const SwTableBox& rBox, bool bDelContent )
2575{
2576 if (!m_vArr.empty() && !bDelContent)
2577 return;
2578
2579 UndoTableCpyTable_Entry* pEntry = new UndoTableCpyTable_Entry( rBox );
2580 m_vArr.push_back(std::unique_ptr<UndoTableCpyTable_Entry>(pEntry));
2581
2582 SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
2583 DEBUG_REDLINE( pDoc )
2584 if( bDelContent )
2585 {
2586 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
2587 pDoc->GetNodes().MakeTextNode( aInsIdx, pDoc->GetDfltTextFormatColl() );
2588 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
2589
2590 if( !pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
2591 pEntry->pUndo = std::make_unique<SwUndoDelete>( aPam, true );
2592 }
2593
2594 pEntry->pBoxNumAttr = std::make_unique<SfxItemSet>(
2595 pDoc->GetAttrPool(),
2596 svl::Items<
2597 RES_VERT_ORIENT, RES_VERT_ORIENT,
2598 RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{});
2599 pEntry->pBoxNumAttr->Put( rBox.GetFrameFormat()->GetAttrSet() );
2600 if( !pEntry->pBoxNumAttr->Count() )
2601 {
2602 pEntry->pBoxNumAttr.reset();
2603 }
2604 DEBUG_REDLINE( pDoc )
2605}
2606
2607void SwUndoTableCpyTable::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, bool bDelContent )
2608{
2609 UndoTableCpyTable_Entry *const pEntry = m_vArr.back().get();
2610
2611 // If the content was deleted then remove also the temporarily created node
2612 if( bDelContent )
2613 {
2614 SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
2615 DEBUG_REDLINE( pDoc )
2616
2617 if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
2618 {
2619 SwPosition aTmpPos( rIdx );
2620 pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false );
2621 }
2622 SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 );
2623 rBox.GetFrameFormat()->GetDoc()->GetNodes().Delete( aDelIdx );
2624 DEBUG_REDLINE( pDoc )
2625 }
2626
2627 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
2628}
2629
2630// PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations.
2631// bRedo is set by calling from Redo()
2632// rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has
2633// been merged.
2634// rJoin is true if Redo() is calling and the content has already been merged
2635
2636std::unique_ptr<SwUndo> SwUndoTableCpyTable::PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox,
2637 const SwPosition& rPos, bool& rJoin, bool bRedo )
2638{
2639 std::unique_ptr<SwUndo> pUndo;
2640 // b62341295: Redline for copying tables
2641 // What's to do?
2642 // Mark the cell content before rIdx as insertion,
2643 // mark the cell content behind rIdx as deletion
2644 // merge text nodes at rIdx if possible
2645 RedlineFlags eOld = pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
2646 pDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( ( eOld | RedlineFlags::DontCombineRedlines ) & ~RedlineFlags::Ignore );
2647 SwPosition aInsertEnd( rPos );
2648 SwTextNode* pText;
2649 if( !rJoin )
2650 {
2651 // If the content is not merged, the end of the insertion is at the end of the node
2652 // _before_ the given position rPos
2653 --aInsertEnd.nNode;
2654 pText = aInsertEnd.nNode.GetNode().GetTextNode();
2655 if( pText )
2656 {
2657 aInsertEnd.nContent.Assign(pText, pText->GetText().getLength());
2658 if( !bRedo && rPos.nNode.GetNode().GetTextNode() )
2659 { // Try to merge, if not called by Redo()
2660 rJoin = true;
2661 pText->JoinNext();
2662 }
2663 }
2664 else
2665 aInsertEnd.nContent.Assign(nullptr, 0);
2666 }
2667 // For joined (merged) contents the start of deletion and end of insertion are identical
2668 // otherwise adjacent nodes.
2669 SwPosition aDeleteStart( rJoin ? aInsertEnd : rPos );
2670 if( !rJoin )
2671 {
2672 pText = aDeleteStart.nNode.GetNode().GetTextNode();
2673 if( pText )
2674 aDeleteStart.nContent.Assign( pText, 0 );
2675 }
2676 SwPosition aCellEnd( SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode(), -1 ) );
2677 pText = aCellEnd.nNode.GetNode().GetTextNode();
2678 if( pText )
2679 aCellEnd.nContent.Assign(pText, pText->GetText().getLength());
2680 if( aDeleteStart != aCellEnd )
2681 { // If the old (deleted) part is not empty, here we are...
2682 SwPaM aDeletePam( aDeleteStart, aCellEnd );
2683 pUndo = std::make_unique<SwUndoRedlineDelete>( aDeletePam, SwUndoId::DELETE );
2684 pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Delete, aDeletePam ), true );
2685 }
2686 else if( !rJoin ) // If the old part is empty and joined, we are finished
2687 { // if it is not joined, we have to delete this empty paragraph
2688 aCellEnd = SwPosition(
2689 SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() ));
2690 SwPaM aTmpPam( aDeleteStart, aCellEnd );
2691 pUndo = std::make_unique<SwUndoDelete>( aTmpPam, true );
2692 }
2693 SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) );
2694 pText = aCellStart.nNode.GetNode().GetTextNode();
2695 if( pText )
2696 aCellStart.nContent.Assign( pText, 0 );
2697 if( aCellStart != aInsertEnd ) // An empty insertion will not been marked
2698 {
2699 SwPaM aTmpPam( aCellStart, aInsertEnd );
2700 pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Insert, aTmpPam ), true );
2701 }
2702
2703 pDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
2704 return pUndo;
2705}
2706
2707bool SwUndoTableCpyTable::InsertRow( SwTable& rTable, const SwSelBoxes& rBoxes,
2708 sal_uInt16 nCnt )
2709{
2710 SwTableNode* pTableNd = const_cast<SwTableNode*>(rTable.GetTabSortBoxes()[0]->
2711 GetSttNd()->FindTableNode());
2712
2713 m_pInsRowUndo.reset( new SwUndoTableNdsChg( SwUndoId::TABLE_INSROW, rBoxes, *pTableNd,
2714 0, 0, nCnt, true, false ) );
2715 SwTableSortBoxes aTmpLst( rTable.GetTabSortBoxes() );
2716
2717 bool bRet = rTable.InsertRow( rTable.GetFrameFormat()->GetDoc(), rBoxes, nCnt, /*bBehind*/true );
2718 if( bRet )
2719 m_pInsRowUndo->SaveNewBoxes( *pTableNd, aTmpLst );
2720 else
2721 {
2722 m_pInsRowUndo.reset();
2723 }
2724 return bRet;
2725}
2726
2727bool SwUndoTableCpyTable::IsEmpty() const
2728{
2729 return !m_pInsRowUndo && m_vArr.empty();
2730}
2731
2732SwUndoCpyTable::SwUndoCpyTable(const SwDoc& rDoc)
2733 : SwUndo( SwUndoId::CPYTBL, &rDoc ), m_nTableNode( 0 )
2734{
2735}
2736
2737SwUndoCpyTable::~SwUndoCpyTable()
2738{
2739}
2740
2741void SwUndoCpyTable::UndoImpl(::sw::UndoRedoContext & rContext)
2742{
2743 SwDoc & rDoc = rContext.GetDoc();
2744 SwTableNode* pTNd = rDoc.GetNodes()[ m_nTableNode ]->GetTableNode();
2745
2746 // move hard page breaks into next node
2747 SwContentNode* pNextNd = rDoc.GetNodes()[ pTNd->EndOfSectionIndex()+1 ]->GetContentNode();
2748 if( pNextNd )
2749 {
2750 SwFrameFormat* pTableFormat = pTNd->GetTable().GetFrameFormat();
2751 const SfxPoolItem *pItem;
2752
2753 if( SfxItemState::SET == pTableFormat->GetItemState( RES_PAGEDESC,
2754 false, &pItem ) )
2755 pNextNd->SetAttr( *pItem );
2756
2757 if( SfxItemState::SET == pTableFormat->GetItemState( RES_BREAK,
2758 false, &pItem ) )
2759 pNextNd->SetAttr( *pItem );
2760 }
2761
2762 SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 );
2763 m_pDelete.reset( new SwUndoDelete( aPam, true ) );
2764}
2765
2766void SwUndoCpyTable::RedoImpl(::sw::UndoRedoContext & rContext)
2767{
2768 m_pDelete->UndoImpl(rContext);
2769 m_pDelete.reset();
2770}
2771
2772SwUndoSplitTable::SwUndoSplitTable( const SwTableNode& rTableNd,
2773 std::unique_ptr<SwSaveRowSpan> pRowSp, SplitTable_HeadlineOption eMode, bool bNewSize )
2774 : SwUndo( SwUndoId::SPLIT_TABLE, &rTableNd.GetDoc() ),
2775 m_nTableNode( rTableNd.GetIndex() ), m_nOffset( 0 ), mpSaveRowSpan( std::move(pRowSp) ),
2776 m_nMode( eMode ), m_nFormulaEnd( 0 ), m_bCalcNewSize( bNewSize )
2777{
2778 switch( m_nMode )
2779 {
2780 case SplitTable_HeadlineOption::BoxAttrAllCopy:
2781 m_pHistory.reset(new SwHistory);
2782 [[fallthrough]];
2783 case SplitTable_HeadlineOption::BorderCopy:
2784 case SplitTable_HeadlineOption::BoxAttrCopy:
2785 m_pSavedTable.reset(new SaveTable( rTableNd.GetTable(), 1, false ));
2786 break;
2787 default: break;
2788 }
2789}
2790
2791SwUndoSplitTable::~SwUndoSplitTable()
2792{
2793 m_pSavedTable.reset();
2794 m_pHistory.reset();
2795 mpSaveRowSpan.reset();
2796}
2797
2798void SwUndoSplitTable::UndoImpl(::sw::UndoRedoContext & rContext)
2799{
2800 SwDoc *const pDoc = & rContext.GetDoc();
2801 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2802
2803 SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
2804 rIdx = m_nTableNode + m_nOffset;
2805 pPam->GetPoint()->nContent.Assign(rIdx.GetNode().GetContentNode(), 0);
2806 assert(rIdx.GetNode().GetContentNode()->Len() == 0)(static_cast <bool> (rIdx.GetNode().GetContentNode()->
Len() == 0) ? void (0) : __assert_fail ("rIdx.GetNode().GetContentNode()->Len() == 0"
, "/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
, 2806, __extension__ __PRETTY_FUNCTION__))
; // empty para inserted
2807
2808 {
2809 // avoid asserts from ~SwIndexReg
2810 SwNodeIndex const idx(pDoc->GetNodes(), m_nTableNode + m_nOffset);
2811 {
2812 SwPaM pam(idx);
2813 pam.Move(fnMoveBackward, GoInContent);
2814 ::PaMCorrAbs(*pPam, *pam.GetPoint());
2815 }
2816
2817 // remove implicitly created paragraph again
2818 pDoc->GetNodes().Delete( idx );
2819 }
2820
2821 rIdx = m_nTableNode + m_nOffset;
2822 SwTableNode* pTableNd = rIdx.GetNode().GetTableNode();
2823 SwTable& rTable = pTableNd->GetTable();
2824
2825 SwTableFormulaUpdate aMsgHint( &rTable );
2826 aMsgHint.m_eFlags = TBL_BOXPTR;
2827 pDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2828
2829 switch( m_nMode )
2830 {
2831 case SplitTable_HeadlineOption::BoxAttrAllCopy:
2832 if( m_pHistory )
2833 m_pHistory->TmpRollback( pDoc, m_nFormulaEnd );
2834 [[fallthrough]];
2835 case SplitTable_HeadlineOption::BoxAttrCopy:
2836 case SplitTable_HeadlineOption::BorderCopy:
2837 {
2838 m_pSavedTable->CreateNew( rTable, false );
2839 m_pSavedTable->RestoreAttr( rTable );
2840 }
2841 break;
2842
2843 case SplitTable_HeadlineOption::ContentCopy:
2844 // the created first line has to be removed again
2845 {
2846 SwSelBoxes aSelBoxes;
2847 SwTableBox* pBox = rTable.GetTableBox( m_nTableNode + m_nOffset + 1 );
2848 SwTable::SelLineFromBox( pBox, aSelBoxes );
2849 FndBox_ aTmpBox( nullptr, nullptr );
2850 aTmpBox.SetTableLines( aSelBoxes, rTable );
2851 aTmpBox.DelFrames( rTable );
2852 rTable.DeleteSel( pDoc, aSelBoxes, nullptr, nullptr, false, false );
2853 }
2854 break;
2855 default: break;
2856 }
2857
2858 pDoc->GetNodes().MergeTable( rIdx );
2859
2860 if( m_pHistory )
2861 {
2862 m_pHistory->TmpRollback( pDoc, 0 );
2863 m_pHistory->SetTmpEnd( m_pHistory->Count() );
2864 }
2865 if( mpSaveRowSpan )
2866 {
2867 pTableNd = rIdx.GetNode().FindTableNode();
2868 if( pTableNd )
2869 pTableNd->GetTable().RestoreRowSpan( *mpSaveRowSpan );
2870 }
2871 ClearFEShellTabCols(*pDoc, nullptr);
2872}
2873
2874void SwUndoSplitTable::RedoImpl(::sw::UndoRedoContext & rContext)
2875{
2876 SwDoc *const pDoc = & rContext.GetDoc();
2877 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2878
2879 pPam->DeleteMark();
2880 pPam->GetPoint()->nNode = m_nTableNode;
2881 pDoc->SplitTable( *pPam->GetPoint(), m_nMode, m_bCalcNewSize );
2882
2883 ClearFEShellTabCols(*pDoc, nullptr);
2884}
2885
2886void SwUndoSplitTable::RepeatImpl(::sw::RepeatContext & rContext)
2887{
2888 SwPaM *const pPam = & rContext.GetRepeatPaM();
2889 SwDoc *const pDoc = & rContext.GetDoc();
2890
2891 pDoc->SplitTable( *pPam->GetPoint(), m_nMode, m_bCalcNewSize );
2892 ClearFEShellTabCols(*pDoc, nullptr);
2893}
2894
2895void SwUndoSplitTable::SaveFormula( SwHistory& rHistory )
2896{
2897 if( !m_pHistory )
2898 m_pHistory.reset(new SwHistory);
2899
2900 m_nFormulaEnd = rHistory.Count();
2901 m_pHistory->Move( 0, &rHistory );
2902}
2903
2904SwUndoMergeTable::SwUndoMergeTable( const SwTableNode& rTableNd,
2905 const SwTableNode& rDelTableNd,
2906 bool bWithPrv, sal_uInt16 nMd )
2907 : SwUndo( SwUndoId::MERGE_TABLE, &rTableNd.GetDoc() ),
2908 m_nMode( nMd ), m_bWithPrev( bWithPrv )
2909{
2910 // memorize end node of the last table cell that'll stay in position
2911 if( m_bWithPrev )
1
Assuming field 'm_bWithPrev' is false
2
Taking false branch
2912 m_nTableNode = rDelTableNd.EndOfSectionIndex() - 1;
2913 else
2914 m_nTableNode = rTableNd.EndOfSectionIndex() - 1;
2915
2916 m_aName = rDelTableNd.GetTable().GetFrameFormat()->GetName();
2917 m_pSaveTable.reset(new SaveTable( rDelTableNd.GetTable() ));
3
Calling constructor for 'SaveTable'
2918
2919 if (m_bWithPrev)
2920 m_pSaveHdl.reset( new SaveTable( rTableNd.GetTable(), 1 ) );
2921}
2922
2923SwUndoMergeTable::~SwUndoMergeTable()
2924{
2925 m_pSaveTable.reset();
2926 m_pSaveHdl.reset();
2927 m_pHistory.reset();
2928}
2929
2930void SwUndoMergeTable::UndoImpl(::sw::UndoRedoContext & rContext)
2931{
2932 SwDoc *const pDoc = & rContext.GetDoc();
2933 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2934
2935 pPam->DeleteMark();
2936 SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
2937 rIdx = m_nTableNode;
2938
2939 SwTableNode* pTableNd = rIdx.GetNode().FindTableNode();
2940 SwTable* pTable = &pTableNd->GetTable();
2941
2942 SwTableFormulaUpdate aMsgHint( pTable );
2943 aMsgHint.m_eFlags = TBL_BOXPTR;
2944 pDoc->getIDocumentFieldsAccess().UpdateTableFields( &aMsgHint );
2945
2946 // get lines for layout update
2947 FndBox_ aFndBox( nullptr, nullptr );
2948 aFndBox.SetTableLines( *pTable );
2949 aFndBox.DelFrames( *pTable );
2950 // ? TL_CHART2: notification or locking of controller required ?
2951
2952 SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx );
2953
2954 // update layout
2955 aFndBox.MakeFrames( *pTable );
2956 // ? TL_CHART2: notification or locking of controller required ?
2957
2958 if( m_bWithPrev )
2959 {
2960 // move name
2961 pNew->GetTable().GetFrameFormat()->SetName( pTable->GetFrameFormat()->GetName() );
2962 m_pSaveHdl->RestoreAttr( pNew->GetTable() );
2963 }
2964 else
2965 pTable = &pNew->GetTable();
2966
2967 pTable->GetFrameFormat()->SetName( m_aName );
2968 m_pSaveTable->RestoreAttr( *pTable );
2969
2970 if( m_pHistory )
2971 {
2972 m_pHistory->TmpRollback( pDoc, 0 );
2973 m_pHistory->SetTmpEnd( m_pHistory->Count() );
2974 }
2975
2976 // create frames for the new table
2977 SwNodeIndex aTmpIdx( *pNew );
2978 pNew->MakeOwnFrames(&aTmpIdx);
2979
2980 // position cursor somewhere in content
2981 SwContentNode* pCNd = pDoc->GetNodes().GoNext( &rIdx );
2982 pPam->GetPoint()->nContent.Assign( pCNd, 0 );
2983
2984 ClearFEShellTabCols(*pDoc, nullptr);
2985
2986 // TL_CHART2: need to inform chart of probably changed cell names
2987 SwChartDataProvider *pPCD = pDoc->getIDocumentChartDataProviderAccess().GetChartDataProvider();
2988 if (pPCD)
2989 {
2990 pDoc->UpdateCharts( pTable->GetFrameFormat()->GetName() );
2991 pDoc->UpdateCharts( pNew->GetTable().GetFrameFormat()->GetName() );
2992 }
2993}
2994
2995void SwUndoMergeTable::RedoImpl(::sw::UndoRedoContext & rContext)
2996{
2997 SwDoc *const pDoc = & rContext.GetDoc();
2998 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2999
3000 pPam->DeleteMark();
3001 pPam->GetPoint()->nNode = m_nTableNode;
3002 if( m_bWithPrev )
3003 pPam->GetPoint()->nNode = m_nTableNode + 3;
3004 else
3005 pPam->GetPoint()->nNode = m_nTableNode;
3006
3007 pDoc->MergeTable( *pPam->GetPoint(), m_bWithPrev, m_nMode );
3008
3009 ClearFEShellTabCols(*pDoc, nullptr);
3010}
3011
3012void SwUndoMergeTable::RepeatImpl(::sw::RepeatContext & rContext)
3013{
3014 SwDoc *const pDoc = & rContext.GetDoc();
3015 SwPaM *const pPam = & rContext.GetRepeatPaM();
3016
3017 pDoc->MergeTable( *pPam->GetPoint(), m_bWithPrev, m_nMode );
3018 ClearFEShellTabCols(*pDoc, nullptr);
3019}
3020
3021void SwUndoMergeTable::SaveFormula( SwHistory& rHistory )
3022{
3023 if( !m_pHistory )
3024 m_pHistory.reset( new SwHistory );
3025 m_pHistory->Move( 0, &rHistory );
3026}
3027
3028void InsertSort( std::vector<sal_uInt16>& rArr, sal_uInt16 nIdx )
3029{
3030 size_t nO = rArr.size();
3031 size_t nU = 0;
3032 if( nO > 0 )
3033 {
3034 nO--;
3035 while( nU <= nO )
3036 {
3037 const size_t nM = nU + ( nO - nU ) / 2;
3038 if ( rArr[nM] == nIdx )
3039 {
3040 OSL_FAIL( "Index already exists. This should never happen." )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "3040" ": "), "%s", "Index already exists. This should never happen."
); } } while (false)
;
3041 return;
3042 }
3043 if( rArr[nM] < nIdx )
3044 nU = nM + 1;
3045 else if( nM == 0 )
3046 break;
3047 else
3048 nO = nM - 1;
3049 }
3050 }
3051 rArr.insert( rArr.begin() + nU, nIdx );
3052}
3053
3054#if OSL_DEBUG_LEVEL1 > 0
3055void CheckTable( const SwTable& rTable )
3056{
3057 const SwNodes& rNds = rTable.GetFrameFormat()->GetDoc()->GetNodes();
3058 const SwTableSortBoxes& rSrtArr = rTable.GetTabSortBoxes();
3059 for (size_t n = 0; n < rSrtArr.size(); ++n)
3060 {
3061 const SwTableBox* pBox = rSrtArr[ n ];
3062 const SwNode* pNd = pBox->GetSttNd();
3063 OSL_ENSURE( rNds[ pBox->GetSttIdx() ] == pNd, "Box with wrong StartNode" )do { if (true && (!(rNds[ pBox->GetSttIdx() ] == pNd
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/undo/untbl.cxx"
":" "3063" ": "), "%s", "Box with wrong StartNode"); } } while
(false)
;
3064 }
3065}
3066#endif
3067
3068SwUndoTableStyleMake::SwUndoTableStyleMake(const OUString& rName, const SwDoc& rDoc)
3069 : SwUndo(SwUndoId::TBLSTYLE_CREATE, &rDoc),
3070 m_sName(rName)
3071{ }
3072
3073SwUndoTableStyleMake::~SwUndoTableStyleMake()
3074{ }
3075
3076void SwUndoTableStyleMake::UndoImpl(::sw::UndoRedoContext & rContext)
3077{
3078 m_pAutoFormat = rContext.GetDoc().DelTableStyle(m_sName, true);
3079}
3080
3081void SwUndoTableStyleMake::RedoImpl(::sw::UndoRedoContext & rContext)
3082{
3083 if (m_pAutoFormat)
3084 {
3085 SwTableAutoFormat* pFormat = rContext.GetDoc().MakeTableStyle(m_sName, true);
3086 if (pFormat)
3087 {
3088 *pFormat = *m_pAutoFormat;
3089 m_pAutoFormat.reset();
3090 }
3091 }
3092}
3093
3094SwRewriter SwUndoTableStyleMake::GetRewriter() const
3095{
3096 SwRewriter aResult;
3097 aResult.AddRule(UndoArg1, m_sName);
3098 return aResult;
3099}
3100
3101SwUndoTableStyleDelete::SwUndoTableStyleDelete(std::unique_ptr<SwTableAutoFormat> pAutoFormat, const std::vector<SwTable*>& rAffectedTables, const SwDoc& rDoc)
3102 : SwUndo(SwUndoId::TBLSTYLE_DELETE, &rDoc),
3103 m_pAutoFormat(std::move(pAutoFormat)),
3104 m_rAffectedTables(rAffectedTables)
3105{ }
3106
3107SwUndoTableStyleDelete::~SwUndoTableStyleDelete()
3108{ }
3109
3110void SwUndoTableStyleDelete::UndoImpl(::sw::UndoRedoContext & rContext)
3111{
3112 SwTableAutoFormat* pNewFormat = rContext.GetDoc().MakeTableStyle(m_pAutoFormat->GetName(), true);
3113 *pNewFormat = *m_pAutoFormat;
3114 for (size_t i=0; i < m_rAffectedTables.size(); i++)
3115 m_rAffectedTables[i]->SetTableStyleName(m_pAutoFormat->GetName());
3116}
3117
3118void SwUndoTableStyleDelete::RedoImpl(::sw::UndoRedoContext & rContext)
3119{
3120 // Don't need to remember deleted table style nor affected tables, because they must be the same as these already known.
3121 rContext.GetDoc().DelTableStyle(m_pAutoFormat->GetName());
3122}
3123
3124SwRewriter SwUndoTableStyleDelete::GetRewriter() const
3125{
3126 SwRewriter aResult;
3127 aResult.AddRule(UndoArg1, m_pAutoFormat->GetName());
3128 return aResult;
3129}
3130
3131SwUndoTableStyleUpdate::SwUndoTableStyleUpdate(const SwTableAutoFormat& rNewFormat, const SwTableAutoFormat& rOldFormat, const SwDoc& rDoc)
3132 : SwUndo(SwUndoId::TBLSTYLE_UPDATE, &rDoc)
3133 , m_pOldFormat(new SwTableAutoFormat(rOldFormat))
3134 , m_pNewFormat(new SwTableAutoFormat(rNewFormat))
3135{ }
3136
3137SwUndoTableStyleUpdate::~SwUndoTableStyleUpdate()
3138{ }
3139
3140void SwUndoTableStyleUpdate::UndoImpl(::sw::UndoRedoContext & rContext)
3141{
3142 rContext.GetDoc().ChgTableStyle(m_pNewFormat->GetName(), *m_pOldFormat);
3143}
3144
3145void SwUndoTableStyleUpdate::RedoImpl(::sw::UndoRedoContext & rContext)
3146{
3147 rContext.GetDoc().ChgTableStyle(m_pNewFormat->GetName(), *m_pNewFormat);
3148}
3149
3150SwRewriter SwUndoTableStyleUpdate::GetRewriter() const
3151{
3152 SwRewriter aResult;
3153 aResult.AddRule(UndoArg1, m_pNewFormat->GetName());
3154 return aResult;
3155}
3156
3157/* vim:set shiftwidth=4 softtabstop=4 expandtab: */