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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
79 | typedef std::vector<std::shared_ptr<SfxItemSet> > SfxItemSets; | |||
80 | ||||
81 | struct 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 | ||||
93 | namespace { | |||
94 | ||||
95 | class SaveBox; | |||
96 | class SaveLine; | |||
97 | ||||
98 | } | |||
99 | ||||
100 | class 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 | ||||
117 | public: | |||
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 | ||||
132 | namespace { | |||
133 | ||||
134 | class 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 | ||||
146 | public: | |||
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 | ||||
156 | class 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 | ||||
170 | public: | |||
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 | |||
183 | static 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 | |||
190 | The order of cell content nodes in the nodes array is not given by the recursive table structure. | |||
191 | The algorithm must not rely on this even it holds for a fresh loaded table in odt file format. | |||
192 | So we need to remember not only the start node position but the end node position as well. | |||
193 | */ | |||
194 | ||||
195 | struct 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 | ||||
207 | private: | |||
208 | SwTableToTextSave(const SwTableToTextSave&) = delete; | |||
209 | SwTableToTextSave& operator=(const SwTableToTextSave&) = delete; | |||
210 | ||||
211 | }; | |||
212 | ||||
213 | sal_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 | ||||
221 | SwUndoInsTable::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 | ||||
248 | SwUndoInsTable::~SwUndoInsTable() | |||
249 | { | |||
250 | m_pDDEFieldType.reset(); | |||
251 | m_pColumnWidth.reset(); | |||
252 | m_pRedlineData.reset(); | |||
253 | m_pAutoFormat.reset(); | |||
254 | } | |||
255 | ||||
256 | void 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 | ||||
298 | void 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 | ||||
341 | void 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 | ||||
348 | SwRewriter 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 | ||||
359 | SwTableToTextSave::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 | ||||
400 | SwUndoTableToText::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 | ||||
440 | SwUndoTableToText::~SwUndoTableToText() | |||
441 | { | |||
442 | m_pDDEFieldType.reset(); | |||
443 | m_pTableSave.reset(); | |||
444 | m_vBoxSaves.clear(); | |||
445 | m_pHistory.reset(); | |||
446 | } | |||
447 | ||||
448 | void 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 | |||
516 | SwTableNode* 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 | ||||
633 | void 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 | ||||
668 | void 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 | ||||
684 | void SwUndoTableToText::SetRange( const SwNodeRange& rRg ) | |||
685 | { | |||
686 | m_nStartNode = rRg.aStart.GetIndex(); | |||
687 | m_nEndNode = rRg.aEnd.GetIndex(); | |||
688 | } | |||
689 | ||||
690 | void 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 | ||||
695 | SwUndoTextToTable::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 | ||||
712 | SwUndoTextToTable::~SwUndoTextToTable() | |||
713 | { | |||
714 | m_pAutoFormat.reset(); | |||
715 | } | |||
716 | ||||
717 | void 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 | ||||
795 | void 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 | ||||
806 | void 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 | ||||
817 | void SwUndoTextToTable::AddFillBox( const SwTableBox& rBox ) | |||
818 | { | |||
819 | mvDelBoxes.push_back( rBox.GetSttIdx() ); | |||
820 | } | |||
821 | ||||
822 | SwHistory& SwUndoTextToTable::GetHistory() | |||
823 | { | |||
824 | if( !m_pHistory ) | |||
825 | m_pHistory = new SwHistory; | |||
826 | return *m_pHistory; | |||
827 | } | |||
828 | ||||
829 | SwUndoTableHeadline::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 | ||||
842 | void 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 | ||||
851 | void 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 | ||||
861 | void 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 | ||||
871 | SaveTable::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 ) ); | |||
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 | ||||
890 | sal_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 | ||||
923 | void 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 | ||||
973 | void SaveTable::SaveContentAttrs( SwDoc* pDoc ) | |||
974 | { | |||
975 | m_pLine->SaveContentAttrs(pDoc); | |||
976 | } | |||
977 | ||||
978 | void 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 | ||||
1075 | void 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 | ||||
1127 | SaveLine::SaveLine( SaveLine* pPrev, const SwTableLine& rLine, SaveTable& rSTable ) | |||
1128 | : pNext( nullptr ) | |||
1129 | { | |||
1130 | if( pPrev
| |||
1131 | pPrev->pNext = this; | |||
1132 | ||||
1133 | nItemSet = rSTable.AddFormat( rLine.GetFrameFormat(), true ); | |||
1134 | ||||
1135 | pBox = new SaveBox( nullptr, *rLine.GetTabBoxes()[ 0 ], rSTable ); | |||
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 | ||||
1141 | SaveLine::~SaveLine() | |||
1142 | { | |||
1143 | delete pBox; | |||
1144 | delete pNext; | |||
1145 | } | |||
1146 | ||||
1147 | void 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 | ||||
1163 | void SaveLine::SaveContentAttrs( SwDoc* pDoc ) | |||
1164 | { | |||
1165 | pBox->SaveContentAttrs( pDoc ); | |||
1166 | if( pNext ) | |||
1167 | pNext->SaveContentAttrs( pDoc ); | |||
1168 | } | |||
1169 | ||||
1170 | void 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 | ||||
1190 | SaveBox::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
| |||
1196 | pPrev->pNext = this; | |||
1197 | ||||
1198 | nItemSet = rSTable.AddFormat( rBox.GetFrameFormat(), false ); | |||
1199 | ||||
1200 | if( rBox.GetSttNd() ) | |||
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 ) | |||
1211 | pLn = new SaveLine( pLn, *rBox.GetTabLines()[ n ], rSTable ); | |||
1212 | } | |||
1213 | } | |||
| ||||
1214 | ||||
1215 | SaveBox::~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 | ||||
1224 | void 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 | ||||
1284 | void 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 | ||||
1316 | void 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 | |||
1361 | SwUndoAttrTable::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 | ||||
1369 | SwUndoAttrTable::~SwUndoAttrTable() | |||
1370 | { | |||
1371 | } | |||
1372 | ||||
1373 | void 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 | ||||
1392 | void SwUndoAttrTable::RedoImpl(::sw::UndoRedoContext & rContext) | |||
1393 | { | |||
1394 | UndoImpl(rContext); | |||
1395 | } | |||
1396 | ||||
1397 | // UndoObject for AutoFormat on Table | |||
1398 | SwUndoTableAutoFormat::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 | ||||
1417 | SwUndoTableAutoFormat::~SwUndoTableAutoFormat() | |||
1418 | { | |||
1419 | } | |||
1420 | ||||
1421 | void SwUndoTableAutoFormat::SaveBoxContent( const SwTableBox& rBox ) | |||
1422 | { | |||
1423 | m_Undos.push_back(std::make_shared<SwUndoTableNumFormat>(rBox)); | |||
1424 | } | |||
1425 | ||||
1426 | void | |||
1427 | SwUndoTableAutoFormat::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 | ||||
1460 | void SwUndoTableAutoFormat::UndoImpl(::sw::UndoRedoContext & rContext) | |||
1461 | { | |||
1462 | UndoRedo(true, rContext); | |||
1463 | } | |||
1464 | ||||
1465 | void SwUndoTableAutoFormat::RedoImpl(::sw::UndoRedoContext & rContext) | |||
1466 | { | |||
1467 | UndoRedo(false, rContext); | |||
1468 | } | |||
1469 | ||||
1470 | SwUndoTableNdsChg::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 | ||||
1489 | void 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 | ||||
1501 | SwUndoTableNdsChg::~SwUndoTableNdsChg() | |||
1502 | { | |||
1503 | } | |||
1504 | ||||
1505 | void 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 | ||||
1529 | static 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 | ||||
1544 | static 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 | ||||
1555 | void 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 | ||||
1636 | void 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 | ||||
1650 | void 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 | ||||
1790 | void 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 | ||||
1840 | SwUndoTableMerge::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 | ||||
1849 | SwUndoTableMerge::~SwUndoTableMerge() | |||
1850 | { | |||
1851 | m_pSaveTable.reset(); | |||
1852 | m_vMoves.clear(); | |||
1853 | m_pHistory.reset(); | |||
1854 | } | |||
1855 | ||||
1856 | void 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 | ||||
1998 | void SwUndoTableMerge::RedoImpl(::sw::UndoRedoContext & rContext) | |||
1999 | { | |||
2000 | SwDoc & rDoc = rContext.GetDoc(); | |||
2001 | SwPaM & rPam( AddUndoRedoPaM(rContext) ); | |||
2002 | rDoc.MergeTable(rPam); | |||
2003 | } | |||
2004 | ||||
2005 | void 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 | ||||
2020 | void 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 | ||||
2037 | void 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 | ||||
2052 | SwUndoTableNumFormat::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 | ||||
2120 | SwUndoTableNumFormat::~SwUndoTableNumFormat() | |||
2121 | { | |||
2122 | m_pHistory.reset(); | |||
2123 | m_pBoxSet.reset(); | |||
2124 | } | |||
2125 | ||||
2126 | void 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 | ||||
2182 | namespace { | |||
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 | */ | |||
2189 | class RedlineFlagsInternGuard | |||
2190 | { | |||
2191 | SwDoc& mrDoc; | |||
2192 | RedlineFlags meOldRedlineFlags; | |||
2193 | ||||
2194 | public: | |||
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 | ||||
2205 | RedlineFlagsInternGuard::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 | ||||
2216 | RedlineFlagsInternGuard::~RedlineFlagsInternGuard() | |||
2217 | { | |||
2218 | mrDoc.getIDocumentRedlineAccess().SetRedlineFlags_intern( meOldRedlineFlags ); | |||
2219 | } | |||
2220 | ||||
2221 | void 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 | ||||
2313 | void SwUndoTableNumFormat::SetBox( const SwTableBox& rBox ) | |||
2314 | { | |||
2315 | m_nNode = rBox.GetSttIdx(); | |||
2316 | } | |||
2317 | ||||
2318 | UndoTableCpyTable_Entry::UndoTableCpyTable_Entry( const SwTableBox& rBox ) | |||
2319 | : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ), | |||
2320 | bJoin( false ) | |||
2321 | { | |||
2322 | } | |||
2323 | ||||
2324 | SwUndoTableCpyTable::SwUndoTableCpyTable(const SwDoc& rDoc) | |||
2325 | : SwUndo( SwUndoId::TBLCPYTBL, &rDoc ) | |||
2326 | { | |||
2327 | } | |||
2328 | ||||
2329 | SwUndoTableCpyTable::~SwUndoTableCpyTable() | |||
2330 | { | |||
2331 | m_vArr.clear(); | |||
2332 | m_pInsRowUndo.reset(); | |||
2333 | } | |||
2334 | ||||
2335 | void 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 | ||||
2484 | void 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 | ||||
2574 | void 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 | ||||
2607 | void 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 | ||||
2636 | std::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 | ||||
2707 | bool 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 | ||||
2727 | bool SwUndoTableCpyTable::IsEmpty() const | |||
2728 | { | |||
2729 | return !m_pInsRowUndo && m_vArr.empty(); | |||
2730 | } | |||
2731 | ||||
2732 | SwUndoCpyTable::SwUndoCpyTable(const SwDoc& rDoc) | |||
2733 | : SwUndo( SwUndoId::CPYTBL, &rDoc ), m_nTableNode( 0 ) | |||
2734 | { | |||
2735 | } | |||
2736 | ||||
2737 | SwUndoCpyTable::~SwUndoCpyTable() | |||
2738 | { | |||
2739 | } | |||
2740 | ||||
2741 | void 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 | ||||
2766 | void SwUndoCpyTable::RedoImpl(::sw::UndoRedoContext & rContext) | |||
2767 | { | |||
2768 | m_pDelete->UndoImpl(rContext); | |||
2769 | m_pDelete.reset(); | |||
2770 | } | |||
2771 | ||||
2772 | SwUndoSplitTable::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 | ||||
2791 | SwUndoSplitTable::~SwUndoSplitTable() | |||
2792 | { | |||
2793 | m_pSavedTable.reset(); | |||
2794 | m_pHistory.reset(); | |||
2795 | mpSaveRowSpan.reset(); | |||
2796 | } | |||
2797 | ||||
2798 | void 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 | ||||
2874 | void 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 | ||||
2886 | void 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 | ||||
2895 | void 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 | ||||
2904 | SwUndoMergeTable::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 ) | |||
| ||||
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() )); | |||
2918 | ||||
2919 | if (m_bWithPrev) | |||
2920 | m_pSaveHdl.reset( new SaveTable( rTableNd.GetTable(), 1 ) ); | |||
2921 | } | |||
2922 | ||||
2923 | SwUndoMergeTable::~SwUndoMergeTable() | |||
2924 | { | |||
2925 | m_pSaveTable.reset(); | |||
2926 | m_pSaveHdl.reset(); | |||
2927 | m_pHistory.reset(); | |||
2928 | } | |||
2929 | ||||
2930 | void 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 | ||||
2995 | void 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 | ||||
3012 | void 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 | ||||
3021 | void SwUndoMergeTable::SaveFormula( SwHistory& rHistory ) | |||
3022 | { | |||
3023 | if( !m_pHistory ) | |||
3024 | m_pHistory.reset( new SwHistory ); | |||
3025 | m_pHistory->Move( 0, &rHistory ); | |||
3026 | } | |||
3027 | ||||
3028 | void 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 | |||
3055 | void 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 | ||||
3068 | SwUndoTableStyleMake::SwUndoTableStyleMake(const OUString& rName, const SwDoc& rDoc) | |||
3069 | : SwUndo(SwUndoId::TBLSTYLE_CREATE, &rDoc), | |||
3070 | m_sName(rName) | |||
3071 | { } | |||
3072 | ||||
3073 | SwUndoTableStyleMake::~SwUndoTableStyleMake() | |||
3074 | { } | |||
3075 | ||||
3076 | void SwUndoTableStyleMake::UndoImpl(::sw::UndoRedoContext & rContext) | |||
3077 | { | |||
3078 | m_pAutoFormat = rContext.GetDoc().DelTableStyle(m_sName, true); | |||
3079 | } | |||
3080 | ||||
3081 | void 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 | ||||
3094 | SwRewriter SwUndoTableStyleMake::GetRewriter() const | |||
3095 | { | |||
3096 | SwRewriter aResult; | |||
3097 | aResult.AddRule(UndoArg1, m_sName); | |||
3098 | return aResult; | |||
3099 | } | |||
3100 | ||||
3101 | SwUndoTableStyleDelete::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 | ||||
3107 | SwUndoTableStyleDelete::~SwUndoTableStyleDelete() | |||
3108 | { } | |||
3109 | ||||
3110 | void 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 | ||||
3118 | void 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 | ||||
3124 | SwRewriter SwUndoTableStyleDelete::GetRewriter() const | |||
3125 | { | |||
3126 | SwRewriter aResult; | |||
3127 | aResult.AddRule(UndoArg1, m_pAutoFormat->GetName()); | |||
3128 | return aResult; | |||
3129 | } | |||
3130 | ||||
3131 | SwUndoTableStyleUpdate::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 | ||||
3137 | SwUndoTableStyleUpdate::~SwUndoTableStyleUpdate() | |||
3138 | { } | |||
3139 | ||||
3140 | void SwUndoTableStyleUpdate::UndoImpl(::sw::UndoRedoContext & rContext) | |||
3141 | { | |||
3142 | rContext.GetDoc().ChgTableStyle(m_pNewFormat->GetName(), *m_pOldFormat); | |||
3143 | } | |||
3144 | ||||
3145 | void SwUndoTableStyleUpdate::RedoImpl(::sw::UndoRedoContext & rContext) | |||
3146 | { | |||
3147 | rContext.GetDoc().ChgTableStyle(m_pNewFormat->GetName(), *m_pNewFormat); | |||
3148 | } | |||
3149 | ||||
3150 | SwRewriter 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: */ |