LibreOffice Module sw (master) 1
swtable.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <libxml/xmlwriter.h>
21
22#include <hintids.hxx>
23#include <hints.hxx>
24#include <editeng/lrspitem.hxx>
25#include <editeng/shaditem.hxx>
27#include <editeng/colritem.hxx>
28#include <osl/diagnose.h>
29#include <sfx2/linkmgr.hxx>
30#include <fmtfsize.hxx>
31#include <fmtornt.hxx>
32#include <fmtpdsc.hxx>
33#include <fldbas.hxx>
34#include <fmtfld.hxx>
35#include <frmatr.hxx>
36#include <doc.hxx>
40#include <docary.hxx>
41#include <frame.hxx>
42#include <swtable.hxx>
43#include <ndtxt.hxx>
44#include <tabcol.hxx>
45#include <tabfrm.hxx>
46#include <cellfrm.hxx>
47#include <rowfrm.hxx>
48#include <swserv.hxx>
49#include <expfld.hxx>
50#include <mdiexp.hxx>
51#include <cellatr.hxx>
52#include <txatbase.hxx>
53#include <htmltbl.hxx>
54#include <swtblfmt.hxx>
55#include <ndindex.hxx>
56#include <tblrwcl.hxx>
57#include <shellres.hxx>
58#include <viewsh.hxx>
59#include <redline.hxx>
60#include <vector>
61#include <calbck.hxx>
62#include <o3tl/string_view.hxx>
63#include <svl/numformat.hxx>
64#include <txtfld.hxx>
65
66#ifdef DBG_UTIL
67#define CHECK_TABLE(t) (t).CheckConsistency();
68#else
69#define CHECK_TABLE(t)
70#endif
71
72using namespace com::sun::star;
73
74
75#define COLFUZZY 20
76
77static void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
78 bool bChgAlign, SwNodeOffset nNdPos );
79
80void SwTableBox::setRowSpan( sal_Int32 nNewRowSpan )
81{
82 mnRowSpan = nNewRowSpan;
83}
84
86{
87 return mbDummyFlag;
88}
89
90void SwTableBox::setDummyFlag( bool bDummy )
91{
92 mbDummyFlag = bDummy;
93}
94
95//JP 15.09.98: Bug 55741 - Keep tabs (front and rear)
96static OUString& lcl_TabToBlankAtSttEnd( OUString& rText )
97{
99 sal_Int32 n;
100
101 for( n = 0; n < rText.getLength() && ' ' >= ( c = rText[n] ); ++n )
102 if( '\x9' == c )
103 rText = rText.replaceAt( n, 1, u" " );
104 for( n = rText.getLength(); n && ' ' >= ( c = rText[--n] ); )
105 if( '\x9' == c )
106 rText = rText.replaceAt( n, 1, u" " );
107 return rText;
108}
109
110static OUString& lcl_DelTabsAtSttEnd( OUString& rText )
111{
112 sal_Unicode c;
113 sal_Int32 n;
114 OUStringBuffer sBuff(rText);
115
116 for( n = 0; n < sBuff.getLength() && ' ' >= ( c = sBuff[ n ]); ++n )
117 {
118 if( '\x9' == c )
119 sBuff.remove( n--, 1 );
120 }
121 for( n = sBuff.getLength(); n && ' ' >= ( c = sBuff[ --n ]); )
122 {
123 if( '\x9' == c )
124 sBuff.remove( n, 1 );
125 }
126 rText = sBuff.makeStringAndClear();
127 return rText;
128}
129
130void InsTableBox( SwDoc& rDoc, SwTableNode* pTableNd,
131 SwTableLine* pLine, SwTableBoxFormat* pBoxFrameFormat,
132 SwTableBox* pBox,
133 sal_uInt16 nInsPos, sal_uInt16 nCnt )
134{
135 OSL_ENSURE( pBox->GetSttNd(), "Box with no start node" );
136 SwNodeIndex aIdx( *pBox->GetSttNd(), +1 );
137 SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
138 if( !pCNd )
139 pCNd = rDoc.GetNodes().GoNext( &aIdx );
140 OSL_ENSURE( pCNd, "Box with no content node" );
141
142 if( pCNd->IsTextNode() )
143 {
144 if( pCNd->GetpSwAttrSet() )
145 {
146 SwAttrSet aAttrSet( *pCNd->GetpSwAttrSet() );
148 {
150 const std::shared_ptr<SfxItemSet>& handle = format.GetStyleHandle();
151 aAttrSet.Put(*handle);
152 }
153 if( pBox->GetSaveNumFormatColor() )
154 {
155 if( pBox->GetSaveUserColor() )
156 aAttrSet.Put( SvxColorItem( *pBox->GetSaveUserColor(), RES_CHRATR_COLOR ));
157 else
158 aAttrSet.ClearItem( RES_CHRATR_COLOR );
159 }
160 rDoc.GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
161 static_cast<SwTextNode*>(pCNd)->GetTextColl(),
162 &aAttrSet, nInsPos, nCnt );
163 }
164 else
165 rDoc.GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
166 static_cast<SwTextNode*>(pCNd)->GetTextColl(),
167 pCNd->GetpSwAttrSet(), nInsPos, nCnt );
168 }
169 else
170 rDoc.GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
171 rDoc.GetDfltTextFormatColl(), nullptr,
172 nInsPos, nCnt );
173
174 sal_Int32 nRowSpan = pBox->getRowSpan();
175 if( nRowSpan != 1 )
176 {
177 SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
178 for( sal_uInt16 i = 0; i < nCnt; ++i )
179 {
180 pBox = rTableBoxes[ i + nInsPos ];
181 pBox->setRowSpan( nRowSpan );
182 }
183 }
184}
185
187 : SwClient( nullptr ),
188 m_pTableNode( nullptr ),
189 m_nGraphicsThatResize( 0 ),
190 m_nRowsToRepeat( 1 ),
191 m_bModifyLocked( false ),
192 m_bNewModel( true )
193{
194 // default value set in the options
196}
197
198SwTable::SwTable( const SwTable& rTable )
199 : SwClient( rTable.GetFrameFormat() ),
200 m_pTableNode( nullptr ),
201 m_eTableChgMode( rTable.m_eTableChgMode ),
202 m_nGraphicsThatResize( 0 ),
203 m_nRowsToRepeat( rTable.GetRowsToRepeat() ),
204 maTableStyleName(rTable.maTableStyleName),
205 m_bModifyLocked( false ),
206 m_bNewModel( rTable.m_bNewModel )
207{
208}
209
210void DelBoxNode( SwTableSortBoxes const & rSortCntBoxes )
211{
212 for (size_t n = 0; n < rSortCntBoxes.size(); ++n)
213 {
214 rSortCntBoxes[ n ]->m_pStartNode = nullptr;
215 }
216}
217
219{
220 if( m_xRefObj.is() )
221 {
222 SwDoc* pDoc = GetFrameFormat()->GetDoc();
223 if( !pDoc->IsInDtor() ) // then remove from the list
225
226 m_xRefObj->Closed();
227 }
228
229 // the table can be deleted if it's the last client of the FrameFormat
230 SwTableFormat* pFormat = GetFrameFormat();
231 pFormat->Remove( this ); // remove
232
233 if( !pFormat->HasWriterListeners() )
234 pFormat->GetDoc()->DelTableFrameFormat( pFormat ); // and delete
235
236 // Delete the pointers from the SortArray of the boxes. The objects
237 // are preserved and are deleted by the lines/boxes arrays dtor.
238 // Note: unfortunately not enough, pointers to the StartNode of the
239 // section need deletion.
242}
243
244namespace
245{
246
247template<class T>
248T lcl_MulDiv64(sal_uInt64 nA, sal_uInt64 nM, sal_uInt64 nD)
249{
250 assert(nD != 0);
251 return nD == 0 ? static_cast<T>(nA*nM) : static_cast<T>((nA*nM)/nD);
252}
253
254}
255
256static void FormatInArr( std::vector<SwFormat*>& rFormatArr, SwFormat* pBoxFormat )
257{
258 std::vector<SwFormat*>::const_iterator it = std::find( rFormatArr.begin(), rFormatArr.end(), pBoxFormat );
259 if ( it == rFormatArr.end() )
260 rFormatArr.push_back( pBoxFormat );
261}
262
263static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const tools::Long nOld,
264 const tools::Long nNew, std::vector<SwFormat*>& rFormatArr );
265
266static void lcl_ModifyLines( SwTableLines &rLines, const tools::Long nOld,
267 const tools::Long nNew, std::vector<SwFormat*>& rFormatArr, const bool bCheckSum )
268{
269 for ( auto &rLine : rLines)
270 ::lcl_ModifyBoxes( rLine->GetTabBoxes(), nOld, nNew, rFormatArr );
271 if( bCheckSum )
272 {
273 for(SwFormat* pFormat : rFormatArr)
274 {
275 const SwTwips nBox = lcl_MulDiv64<SwTwips>(pFormat->GetFrameSize().GetWidth(), nNew, nOld);
276 SwFormatFrameSize aNewBox( SwFrameSize::Variable, nBox, 0 );
277 pFormat->LockModify();
278 pFormat->SetFormatAttr( aNewBox );
279 pFormat->UnlockModify();
280 }
281 }
282}
283
284static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const tools::Long nOld,
285 const tools::Long nNew, std::vector<SwFormat*>& rFormatArr )
286{
287 sal_uInt64 nSum = 0; // To avoid rounding errors we summarize all box widths
288 sal_uInt64 nOriginalSum = 0; // Sum of original widths
289 for ( size_t i = 0; i < rBoxes.size(); ++i )
290 {
291 SwTableBox &rBox = *rBoxes[i];
292 if ( !rBox.GetTabLines().empty() )
293 {
294 // For SubTables the rounding problem will not be solved :-(
295 ::lcl_ModifyLines( rBox.GetTabLines(), nOld, nNew, rFormatArr, false );
296 }
297 // Adjust the box
298 SwFrameFormat *pFormat = rBox.GetFrameFormat();
299 sal_uInt64 nBox = pFormat->GetFrameSize().GetWidth();
300 nOriginalSum += nBox;
301 nBox = lcl_MulDiv64<sal_uInt64>(nBox, nNew, nOld);
302 const sal_uInt64 nWishedSum = lcl_MulDiv64<sal_uInt64>(nOriginalSum, nNew, nOld) - nSum;
303 if( nWishedSum > 0 )
304 {
305 if( nBox == nWishedSum )
306 FormatInArr( rFormatArr, pFormat );
307 else
308 {
309 nBox = nWishedSum;
310 pFormat = rBox.ClaimFrameFormat();
311 SwFormatFrameSize aNewBox( SwFrameSize::Variable, static_cast< SwTwips >(nBox), 0 );
312 pFormat->LockModify();
313 pFormat->SetFormatAttr( aNewBox );
314 pFormat->UnlockModify();
315 }
316 }
317 else {
318 OSL_FAIL( "Rounding error" );
319 }
320 nSum += nBox;
321 }
322}
323
324void SwTable::SwClientNotify(const SwModify&, const SfxHint& rHint)
325{
326 if (rHint.GetId() != SfxHintId::SwLegacyModify)
327 return;
328 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
329 // catch SSize changes, to adjust the lines/boxes
330 const sal_uInt16 nWhich = pLegacy->GetWhich();
331 const SwFormatFrameSize* pNewSize = nullptr, *pOldSize = nullptr;
332 switch(nWhich)
333 {
334 case RES_ATTRSET_CHG:
335 {
336 if (pLegacy->m_pOld && pLegacy->m_pNew
337 && (pNewSize = static_cast<const SwAttrSetChg*>(pLegacy->m_pNew)->GetChgSet()->GetItemIfSet(
339 false)))
340 {
341 pOldSize = &static_cast<const SwAttrSetChg*>(pLegacy->m_pOld)->GetChgSet()->GetFrameSize();
342 }
343 }
344 break;
345 case RES_FRM_SIZE:
346 {
347 pOldSize = static_cast<const SwFormatFrameSize*>(pLegacy->m_pOld);
348 pNewSize = static_cast<const SwFormatFrameSize*>(pLegacy->m_pNew);
349 }
350 break;
351 default:
352 CheckRegistration(pLegacy->m_pOld);
353 }
354 if (pOldSize && pNewSize && !m_bModifyLocked)
355 AdjustWidths(pOldSize->GetWidth(), pNewSize->GetWidth());
356}
357
358void SwTable::AdjustWidths( const tools::Long nOld, const tools::Long nNew )
359{
360 std::vector<SwFormat*> aFormatArr;
361 aFormatArr.reserve( m_aLines[0]->GetTabBoxes().size() );
362 ::lcl_ModifyLines( m_aLines, nOld, nNew, aFormatArr, true );
363}
364
365static void lcl_RefreshHidden( SwTabCols &rToFill, size_t nPos )
366{
367 for ( size_t i = 0; i < rToFill.Count(); ++i )
368 {
369 if ( std::abs(static_cast<tools::Long>(nPos) - rToFill[i]) <= COLFUZZY )
370 {
371 rToFill.SetHidden( i, false );
372 break;
373 }
374 }
375}
376
377static void lcl_SortedTabColInsert( SwTabCols &rToFill, const SwTableBox *pBox,
378 const SwFrameFormat *pTabFormat, const bool bHidden,
379 const bool bRefreshHidden )
380{
381 const tools::Long nWish = pTabFormat->GetFrameSize().GetWidth();
382 OSL_ENSURE(nWish, "weird <= 0 width frmfrm");
383
384 // The value for the left edge of the box is calculated from the
385 // widths of the previous boxes.
386 tools::Long nPos = 0;
387 tools::Long nLeftMin = 0;
388 tools::Long nRightMax = 0;
389 if (nWish != 0) //fdo#33012 0 width frmfmt
390 {
391 SwTwips nSum = 0;
392 const SwTableBox *pCur = pBox;
393 const SwTableLine *pLine = pBox->GetUpper();
394 const tools::Long nAct = rToFill.GetRight() - rToFill.GetLeft(); // +1 why?
395
396 while ( pLine )
397 {
398 const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
399 for ( size_t i = 0; i < rBoxes.size(); ++i )
400 {
401 const SwTwips nWidth = rBoxes[i]->GetFrameFormat()->GetFrameSize().GetWidth();
402 nSum += nWidth;
403 const tools::Long nTmp = lcl_MulDiv64<tools::Long>(nSum, nAct, nWish);
404
405 if (rBoxes[i] != pCur)
406 {
407 if ( pLine == pBox->GetUpper() || 0 == nLeftMin )
408 nLeftMin = nTmp - nPos;
409 nPos = nTmp;
410 }
411 else
412 {
413 nSum -= nWidth;
414 if ( 0 == nRightMax )
415 nRightMax = nTmp - nPos;
416 break;
417 }
418 }
419 pCur = pLine->GetUpper();
420 pLine = pCur ? pCur->GetUpper() : nullptr;
421 }
422 }
423
424 bool bInsert = !bRefreshHidden;
425 for ( size_t j = 0; bInsert && (j < rToFill.Count()); ++j )
426 {
427 tools::Long nCmp = rToFill[j];
428 if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
429 (nPos <= (nCmp + COLFUZZY)) )
430 {
431 bInsert = false; // Already has it.
432 }
433 else if ( nPos < nCmp )
434 {
435 bInsert = false;
436 rToFill.Insert( nPos, bHidden, j );
437 }
438 }
439 if ( bInsert )
440 rToFill.Insert( nPos, bHidden, rToFill.Count() );
441 else if ( bRefreshHidden )
442 ::lcl_RefreshHidden( rToFill, nPos );
443
444 if ( !bHidden || bRefreshHidden )
445 return;
446
447 // calculate minimum/maximum values for the existing entries:
448 nLeftMin = nPos - nLeftMin;
449 nRightMax = nPos + nRightMax;
450
451 // check if nPos is entry:
452 bool bFoundPos = false;
453 bool bFoundMax = false;
454 for ( size_t j = 0; !(bFoundPos && bFoundMax ) && j < rToFill.Count(); ++j )
455 {
456 SwTabColsEntry& rEntry = rToFill.GetEntry( j );
457 tools::Long nCmp = rToFill[j];
458
459 if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
460 (nPos <= (nCmp + COLFUZZY)) )
461 {
462 // check if nLeftMin is > old minimum for entry nPos:
463 const tools::Long nOldMin = rEntry.nMin;
464 if ( nLeftMin > nOldMin )
465 rEntry.nMin = nLeftMin;
466 // check if nRightMin is < old maximum for entry nPos:
467 const tools::Long nOldMax = rEntry.nMax;
468 if ( nRightMax < nOldMax )
469 rEntry.nMax = nRightMax;
470
471 bFoundPos = true;
472 }
473 else if ( (nRightMax >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
474 (nRightMax <= (nCmp + COLFUZZY)) )
475 {
476 // check if nPos is > old minimum for entry nRightMax:
477 const tools::Long nOldMin = rEntry.nMin;
478 if ( nPos > nOldMin )
479 rEntry.nMin = nPos;
480
481 bFoundMax = true;
482 }
483 }
484}
485
486static void lcl_ProcessBoxGet( const SwTableBox *pBox, SwTabCols &rToFill,
487 const SwFrameFormat *pTabFormat, bool bRefreshHidden )
488{
489 if ( !pBox->GetTabLines().empty() )
490 {
491 const SwTableLines &rLines = pBox->GetTabLines();
492 for ( size_t i = 0; i < rLines.size(); ++i )
493 {
494 const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
495 for ( size_t j = 0; j < rBoxes.size(); ++j )
496 ::lcl_ProcessBoxGet( rBoxes[j], rToFill, pTabFormat, bRefreshHidden);
497 }
498 }
499 else
500 ::lcl_SortedTabColInsert( rToFill, pBox, pTabFormat, false, bRefreshHidden );
501}
502
503static void lcl_ProcessLineGet( const SwTableLine *pLine, SwTabCols &rToFill,
504 const SwFrameFormat *pTabFormat )
505{
506 for ( size_t i = 0; i < pLine->GetTabBoxes().size(); ++i )
507 {
508 const SwTableBox *pBox = pLine->GetTabBoxes()[i];
509 if ( pBox->GetSttNd() )
510 ::lcl_SortedTabColInsert( rToFill, pBox, pTabFormat, true, false );
511 else
512 for ( size_t j = 0; j < pBox->GetTabLines().size(); ++j )
513 ::lcl_ProcessLineGet( pBox->GetTabLines()[j], rToFill, pTabFormat );
514 }
515}
516
517void SwTable::GetTabCols( SwTabCols &rToFill, const SwTableBox *pStart,
518 bool bRefreshHidden, bool bCurRowOnly ) const
519{
520 // Optimization: if bHidden is set, we only update the Hidden Array.
521 if ( bRefreshHidden )
522 {
523 // remove corrections
524 for ( size_t i = 0; i < rToFill.Count(); ++i )
525 {
526 SwTabColsEntry& rEntry = rToFill.GetEntry( i );
527 rEntry.nPos -= rToFill.GetLeft();
528 rEntry.nMin -= rToFill.GetLeft();
529 rEntry.nMax -= rToFill.GetLeft();
530 }
531
532 // All are hidden, so add the visible ones.
533 for ( size_t i = 0; i < rToFill.Count(); ++i )
534 rToFill.SetHidden( i, true );
535 }
536 else
537 {
538 rToFill.Remove( 0, rToFill.Count() );
539 }
540
541 // Insertion cases:
542 // 1. All boxes which are inferior to Line which is superior to the Start,
543 // as well as their inferior boxes if present.
544 // 2. Starting from the Line, the superior box plus its neighbours; but no inferiors.
545 // 3. Apply 2. to the Line superior to the chain of boxes,
546 // until the Line's superior is not a box but the table.
547 // Only those boxes are inserted that don't contain further rows. The insertion
548 // function takes care to avoid duplicates. In order to achieve this, we work
549 // with some degree of fuzzyness (to avoid rounding errors).
550 // Only the left edge of the boxes are inserted.
551 // Finally, the first entry is removed again, because it's already
552 // covered by the border.
553 // 4. Scan the table again and insert _all_ boxes, this time as hidden.
554
555 const SwFrameFormat *pTabFormat = GetFrameFormat();
556
557 // 1.
558 const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
559
560 for ( size_t i = 0; i < rBoxes.size(); ++i )
561 ::lcl_ProcessBoxGet( rBoxes[i], rToFill, pTabFormat, bRefreshHidden );
562
563 // 2. and 3.
564 const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
565 pStart->GetUpper()->GetUpper()->GetUpper() : nullptr;
566 while ( pLine )
567 {
568 const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
569 for ( size_t k = 0; k < rBoxes2.size(); ++k )
570 ::lcl_SortedTabColInsert( rToFill, rBoxes2[k],
571 pTabFormat, false, bRefreshHidden );
572 pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : nullptr;
573 }
574
575 if ( !bRefreshHidden )
576 {
577 // 4.
578 if ( !bCurRowOnly )
579 {
580 for ( size_t i = 0; i < m_aLines.size(); ++i )
581 ::lcl_ProcessLineGet( m_aLines[i], rToFill, pTabFormat );
582 }
583
584 rToFill.Remove( 0 );
585 }
586
587 // Now the coordinates are relative to the left table border - i.e.
588 // relative to SwTabCols.nLeft. However, they are expected
589 // relative to the left document border, i.e. SwTabCols.nLeftMin.
590 // So all values need to be extended by nLeft.
591 for ( size_t i = 0; i < rToFill.Count(); ++i )
592 {
593 SwTabColsEntry& rEntry = rToFill.GetEntry( i );
594 rEntry.nPos += rToFill.GetLeft();
595 rEntry.nMin += rToFill.GetLeft();
596 rEntry.nMax += rToFill.GetLeft();
597 }
598}
599
600// Structure for parameter passing
601struct Parm
602{
607 std::deque<SwTableBox*> aBoxArr;
609
610 Parm( const SwTabCols &rN, const SwTabCols &rO )
611 : rNew( rN ), rOld( rO ), nNewWish(0), nOldWish(0)
612 {}
613};
614
615static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm );
616
617static void lcl_ProcessLine( SwTableLine *pLine, Parm &rParm )
618{
619 SwTableBoxes &rBoxes = pLine->GetTabBoxes();
620 for ( size_t i = rBoxes.size(); i > 0; )
621 {
622 --i;
623 ::lcl_ProcessBoxSet( rBoxes[i], rParm );
624 }
625}
626
627static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm )
628{
629 if ( !pBox->GetTabLines().empty() )
630 {
631 SwTableLines &rLines = pBox->GetTabLines();
632 for ( size_t i = rLines.size(); i > 0; )
633 {
634 --i;
635 lcl_ProcessLine( rLines[i], rParm );
636 }
637 }
638 else
639 {
640 // Search the old TabCols for the current position (calculate from
641 // left and right edge). Adjust the box if the values differ from
642 // the new TabCols. If the adjusted edge has no neighbour we also
643 // adjust all superior boxes.
644
645 const tools::Long nOldAct = rParm.rOld.GetRight() -
646 rParm.rOld.GetLeft(); // +1 why?
647
648 // The value for the left edge of the box is calculated from the
649 // widths of the previous boxes plus the left edge.
650 tools::Long nLeft = rParm.rOld.GetLeft();
651 const SwTableBox *pCur = pBox;
652 const SwTableLine *pLine = pBox->GetUpper();
653
654 while ( pLine )
655 {
656 const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
657 for ( size_t i = 0; (i < rBoxes.size()) && (rBoxes[i] != pCur); ++i)
658 {
659 nLeft += lcl_MulDiv64<tools::Long>(
660 rBoxes[i]->GetFrameFormat()->GetFrameSize().GetWidth(),
661 nOldAct, rParm.nOldWish);
662 }
663 pCur = pLine->GetUpper();
664 pLine = pCur ? pCur->GetUpper() : nullptr;
665 }
666 tools::Long nLeftDiff = 0;
667 tools::Long nRightDiff = 0;
668 if ( nLeft != rParm.rOld.GetLeft() ) // There are still boxes before this.
669 {
670 // Right edge is left edge plus width.
671 const tools::Long nWidth = lcl_MulDiv64<tools::Long>(
673 nOldAct, rParm.nOldWish);
674 const tools::Long nRight = nLeft + nWidth;
675 size_t nLeftPos = 0;
676 size_t nRightPos = 0;
677 bool bFoundLeftPos = false;
678 bool bFoundRightPos = false;
679 for ( size_t i = 0; i < rParm.rOld.Count(); ++i )
680 {
681 if ( nLeft >= (rParm.rOld[i] - COLFUZZY) &&
682 nLeft <= (rParm.rOld[i] + COLFUZZY) )
683 {
684 nLeftPos = i;
685 bFoundLeftPos = true;
686 }
687 else if ( nRight >= (rParm.rOld[i] - COLFUZZY) &&
688 nRight <= (rParm.rOld[i] + COLFUZZY) )
689 {
690 nRightPos = i;
691 bFoundRightPos = true;
692 }
693 }
694 nLeftDiff = bFoundLeftPos ?
695 rParm.rOld[nLeftPos] - rParm.rNew[nLeftPos] : 0;
696 nRightDiff= bFoundRightPos ?
697 rParm.rNew[nRightPos] - rParm.rOld[nRightPos] : 0;
698 }
699 else // The first box.
700 {
701 nLeftDiff = rParm.rOld.GetLeft() - rParm.rNew.GetLeft();
702 if ( rParm.rOld.Count() )
703 {
704 // Calculate the difference to the edge touching the first box.
705 const tools::Long nWidth = lcl_MulDiv64<tools::Long>(
707 nOldAct, rParm.nOldWish);
708 const tools::Long nTmp = nWidth + rParm.rOld.GetLeft();
709 for ( size_t i = 0; i < rParm.rOld.Count(); ++i )
710 {
711 if ( nTmp >= (rParm.rOld[i] - COLFUZZY) &&
712 nTmp <= (rParm.rOld[i] + COLFUZZY) )
713 {
714 nRightDiff = rParm.rNew[i] - rParm.rOld[i];
715 break;
716 }
717 }
718 }
719 }
720
721 if( pBox->getRowSpan() == 1 )
722 {
723 const sal_uInt16 nPos = pBox->GetUpper()->GetBoxPos( pBox );
724 SwTableBoxes& rTableBoxes = pBox->GetUpper()->GetTabBoxes();
725 if( nPos && rTableBoxes[ nPos - 1 ]->getRowSpan() != 1 )
726 nLeftDiff = 0;
727 if( nPos + 1 < o3tl::narrowing<sal_uInt16>(rTableBoxes.size()) &&
728 rTableBoxes[ nPos + 1 ]->getRowSpan() != 1 )
729 nRightDiff = 0;
730 }
731 else
732 nLeftDiff = nRightDiff = 0;
733
734 if ( nLeftDiff || nRightDiff )
735 {
736 // The difference is the actual difference amount. For stretched
737 // tables, it does not make sense to adjust the attributes of the
738 // boxes by this amount. The difference amount needs to be converted
739 // accordingly.
740 tools::Long nTmp = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); // +1 why?
741 nLeftDiff *= rParm.nNewWish;
742 nLeftDiff /= nTmp;
743 nRightDiff *= rParm.nNewWish;
744 nRightDiff /= nTmp;
745 tools::Long nDiff = nLeftDiff + nRightDiff;
746
747 // Adjust the box and all superiors by the difference amount.
748 while ( pBox )
749 {
750 SwFormatFrameSize aFormatFrameSize( pBox->GetFrameFormat()->GetFrameSize() );
751 aFormatFrameSize.SetWidth( aFormatFrameSize.GetWidth() + nDiff );
752 if ( aFormatFrameSize.GetWidth() < 0 )
753 aFormatFrameSize.SetWidth( -aFormatFrameSize.GetWidth() );
754 rParm.aShareFormats.SetSize( *pBox, aFormatFrameSize );
755
756 // The outer cells of the last row are responsible to adjust a surrounding cell.
757 // Last line check:
758 if ( pBox->GetUpper()->GetUpper() &&
759 pBox->GetUpper() != pBox->GetUpper()->GetUpper()->GetTabLines().back())
760 {
761 pBox = nullptr;
762 }
763 else
764 {
765 // Middle cell check:
766 if ( pBox != pBox->GetUpper()->GetTabBoxes().front() )
767 nDiff = nRightDiff;
768
769 if ( pBox != pBox->GetUpper()->GetTabBoxes().back() )
770 nDiff -= nRightDiff;
771
772 pBox = nDiff ? pBox->GetUpper()->GetUpper() : nullptr;
773 }
774 }
775 }
776 }
777}
778
779static void lcl_ProcessBoxPtr( SwTableBox *pBox, std::deque<SwTableBox*> &rBoxArr,
780 bool bBefore )
781{
782 if ( !pBox->GetTabLines().empty() )
783 {
784 const SwTableLines &rLines = pBox->GetTabLines();
785 for ( size_t i = 0; i < rLines.size(); ++i )
786 {
787 const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
788 for ( size_t j = 0; j < rBoxes.size(); ++j )
789 ::lcl_ProcessBoxPtr( rBoxes[j], rBoxArr, bBefore );
790 }
791 }
792 else if ( bBefore )
793 rBoxArr.push_front( pBox );
794 else
795 rBoxArr.push_back( pBox );
796}
797
798static void lcl_AdjustBox( SwTableBox *pBox, const tools::Long nDiff, Parm &rParm );
799
800static void lcl_AdjustLines( SwTableLines &rLines, const tools::Long nDiff, Parm &rParm )
801{
802 for ( size_t i = 0; i < rLines.size(); ++i )
803 {
804 SwTableBox *pBox = rLines[i]->GetTabBoxes()
805 [rLines[i]->GetTabBoxes().size()-1];
806 lcl_AdjustBox( pBox, nDiff, rParm );
807 }
808}
809
810static void lcl_AdjustBox( SwTableBox *pBox, const tools::Long nDiff, Parm &rParm )
811{
812 if ( !pBox->GetTabLines().empty() )
813 ::lcl_AdjustLines( pBox->GetTabLines(), nDiff, rParm );
814
815 // Adjust the size of the box.
816 SwFormatFrameSize aFormatFrameSize( pBox->GetFrameFormat()->GetFrameSize() );
817 aFormatFrameSize.SetWidth( aFormatFrameSize.GetWidth() + nDiff );
818
819 rParm.aShareFormats.SetSize( *pBox, aFormatFrameSize );
820}
821
822void SwTable::SetTabCols( const SwTabCols &rNew, const SwTabCols &rOld,
823 const SwTableBox *pStart, bool bCurRowOnly )
824{
825 CHECK_TABLE( *this )
826
827 SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // delete HTML-Layout
828
829 // FME: Made rOld const. The caller is responsible for passing correct
830 // values of rOld. Therefore we do not have to call GetTabCols anymore:
831 //GetTabCols( rOld, pStart );
832
833 Parm aParm( rNew, rOld );
834
835 OSL_ENSURE( rOld.Count() == rNew.Count(), "Number of columns changed.");
836
837 // Convert the edges. We need to adjust the size of the table and some boxes.
838 // For the size adjustment, we must not make use of the Modify, since that'd
839 // adjust all boxes, which we really don't want.
840 SwFrameFormat *pFormat = GetFrameFormat();
841 aParm.nOldWish = aParm.nNewWish = pFormat->GetFrameSize().GetWidth();
842 if ( (rOld.GetLeft() != rNew.GetLeft()) ||
843 (rOld.GetRight()!= rNew.GetRight()) )
844 {
845 LockModify();
846 {
847 SvxLRSpaceItem aLR( pFormat->GetLRSpace() );
848 SvxShadowItem aSh( pFormat->GetShadow() );
849
850 SwTwips nShRight = aSh.CalcShadowSpace( SvxShadowItemSide::RIGHT );
851 SwTwips nShLeft = aSh.CalcShadowSpace( SvxShadowItemSide::LEFT );
852
853 aLR.SetLeft ( rNew.GetLeft() - nShLeft );
854 aLR.SetRight( rNew.GetRightMax() - rNew.GetRight() - nShRight );
855 pFormat->SetFormatAttr( aLR );
856
857 // The alignment of the table needs to be adjusted accordingly.
858 // This is done by preserving the exact positions that have been
859 // set by the user.
860 SwFormatHoriOrient aOri( pFormat->GetHoriOrient() );
862 text::HoriOrientation::CENTER != aOri.GetHoriOrient() )
863 {
864 const bool bLeftDist = rNew.GetLeft() != nShLeft;
865 const bool bRightDist = rNew.GetRight() + nShRight != rNew.GetRightMax();
866 if(!bLeftDist && !bRightDist)
867 aOri.SetHoriOrient( text::HoriOrientation::FULL );
868 else if(!bRightDist && rNew.GetLeft() > nShLeft )
869 aOri.SetHoriOrient( text::HoriOrientation::RIGHT );
870 else if(!bLeftDist && rNew.GetRight() + nShRight < rNew.GetRightMax())
871 aOri.SetHoriOrient( text::HoriOrientation::LEFT );
872 else
873 {
874 // if an automatic table hasn't (really) changed size, then leave it as auto.
875 const tools::Long nOldWidth = rOld.GetRight() - rOld.GetLeft();
876 const tools::Long nNewWidth = rNew.GetRight() - rNew.GetLeft();
877 if (aOri.GetHoriOrient() != text::HoriOrientation::FULL
878 || std::abs(nOldWidth - nNewWidth) > COLFUZZY)
879 {
880 aOri.SetHoriOrient(text::HoriOrientation::LEFT_AND_WIDTH);
881 }
882 }
883 }
884 pFormat->SetFormatAttr( aOri );
885 }
886 const tools::Long nAct = rOld.GetRight() - rOld.GetLeft(); // +1 why?
887 tools::Long nTabDiff = 0;
888
889 if ( rOld.GetLeft() != rNew.GetLeft() )
890 {
891 nTabDiff = rOld.GetLeft() - rNew.GetLeft();
892 nTabDiff *= aParm.nOldWish;
893 nTabDiff /= nAct;
894 }
895 if ( rOld.GetRight() != rNew.GetRight() )
896 {
897 tools::Long nDiff = rNew.GetRight() - rOld.GetRight();
898 nDiff *= aParm.nOldWish;
899 nDiff /= nAct;
900 nTabDiff += nDiff;
901 if( !IsNewModel() )
902 ::lcl_AdjustLines( GetTabLines(), nDiff, aParm );
903 }
904
905 // Adjust the size of the table, watch out for stretched tables.
906 if ( nTabDiff )
907 {
908 aParm.nNewWish += nTabDiff;
909 if ( aParm.nNewWish < 0 )
910 aParm.nNewWish = USHRT_MAX; // Oops! Have to roll back.
911 SwFormatFrameSize aSz( pFormat->GetFrameSize() );
912 if ( aSz.GetWidth() != aParm.nNewWish )
913 {
914 aSz.SetWidth( aParm.nNewWish );
915 aSz.SetWidthPercent( 0 );
916 pFormat->SetFormatAttr( aSz );
917 }
918 }
919 UnlockModify();
920 }
921
922 if( IsNewModel() )
923 NewSetTabCols( aParm, rNew, rOld, pStart, bCurRowOnly );
924 else
925 {
926 if ( bCurRowOnly )
927 {
928 // To adjust the current row, we need to process all its boxes,
929 // similar to the filling of the TabCols (see GetTabCols()).
930 // Unfortunately we again have to take care to adjust the boxes
931 // from back to front, respectively from outer to inner.
932 // The best way to achieve this is probably to track the boxes
933 // in a PtrArray.
934 const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
935 for ( size_t i = 0; i < rBoxes.size(); ++i )
936 ::lcl_ProcessBoxPtr( rBoxes[i], aParm.aBoxArr, false );
937
938 const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
939 pStart->GetUpper()->GetUpper()->GetUpper() : nullptr;
940 const SwTableBox *pExcl = pStart->GetUpper()->GetUpper();
941 while ( pLine )
942 {
943 const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
944 bool bBefore = true;
945 for ( size_t i = 0; i < rBoxes2.size(); ++i )
946 {
947 if ( rBoxes2[i] != pExcl )
948 ::lcl_ProcessBoxPtr( rBoxes2[i], aParm.aBoxArr, bBefore );
949 else
950 bBefore = false;
951 }
952 pExcl = pLine->GetUpper();
953 pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : nullptr;
954 }
955 // After we've inserted a bunch of boxes (hopefully all and in
956 // correct order), we just need to process them in reverse order.
957 for ( int j = aParm.aBoxArr.size()-1; j >= 0; --j )
958 {
959 SwTableBox *pBox = aParm.aBoxArr[j];
960 ::lcl_ProcessBoxSet( pBox, aParm );
961 }
962 }
963 else
964 {
965 // Adjusting the entire table is 'easy'. All boxes without lines are
966 // adjusted, as are their superiors. Of course we need to process
967 // in reverse order to prevent fooling ourselves!
968 SwTableLines &rLines = GetTabLines();
969 for ( size_t i = rLines.size(); i > 0; )
970 {
971 --i;
972 ::lcl_ProcessLine( rLines[i], aParm );
973 }
974 }
975 }
976
977#ifdef DBG_UTIL
978 {
979 // do some checking for correct table widths
981 for (size_t n = 0; n < m_aLines.size(); ++n)
982 {
983 CheckBoxWidth( *m_aLines[ n ], nSize );
984 }
985 }
986#endif
987}
988
989typedef std::pair<sal_uInt16, sal_uInt16> ColChange;
990typedef std::list< ColChange > ChangeList;
991
992static void lcl_AdjustWidthsInLine( SwTableLine* pLine, ChangeList& rOldNew,
993 Parm& rParm, sal_uInt16 nColFuzzy )
994{
995 ChangeList::iterator pCurr = rOldNew.begin();
996 if( pCurr == rOldNew.end() )
997 return;
998 const size_t nCount = pLine->GetTabBoxes().size();
999 SwTwips nBorder = 0;
1000 SwTwips nRest = 0;
1001 for( size_t i = 0; i < nCount; ++i )
1002 {
1003 SwTableBox* pBox = pLine->GetTabBoxes()[i];
1004 SwTwips nWidth = pBox->GetFrameFormat()->GetFrameSize().GetWidth();
1005 SwTwips nNewWidth = nWidth - nRest;
1006 nRest = 0;
1007 nBorder += nWidth;
1008 if( pCurr != rOldNew.end() && nBorder + nColFuzzy >= pCurr->first )
1009 {
1010 nBorder -= nColFuzzy;
1011 while( pCurr != rOldNew.end() && nBorder > pCurr->first )
1012 ++pCurr;
1013 if( pCurr != rOldNew.end() )
1014 {
1015 nBorder += nColFuzzy;
1016 if( nBorder + nColFuzzy >= pCurr->first )
1017 {
1018 if( pCurr->second == pCurr->first )
1019 nRest = 0;
1020 else
1021 nRest = pCurr->second - nBorder;
1022 nNewWidth += nRest;
1023 ++pCurr;
1024 }
1025 }
1026 }
1027 if( nNewWidth != nWidth )
1028 {
1029 if( nNewWidth < 0 )
1030 {
1031 nRest += 1 - nNewWidth;
1032 nNewWidth = 1;
1033 }
1034 SwFormatFrameSize aFormatFrameSize( pBox->GetFrameFormat()->GetFrameSize() );
1035 aFormatFrameSize.SetWidth( nNewWidth );
1036 rParm.aShareFormats.SetSize( *pBox, aFormatFrameSize );
1037 }
1038 }
1039}
1040
1041static void lcl_CalcNewWidths( std::vector<sal_uInt16> &rSpanPos, ChangeList& rChanges,
1042 SwTableLine* pLine, tools::Long nWish, tools::Long nWidth, bool bTop )
1043{
1044 if( rChanges.empty() )
1045 {
1046 rSpanPos.clear();
1047 return;
1048 }
1049 if( rSpanPos.empty() )
1050 {
1051 rChanges.clear();
1052 return;
1053 }
1054 std::vector<sal_uInt16> aNewSpanPos;
1055 ChangeList::iterator pCurr = rChanges.begin();
1056 ChangeList aNewChanges { *pCurr }; // Nullposition
1057 std::vector<sal_uInt16>::iterator pSpan = rSpanPos.begin();
1058 sal_uInt16 nCurr = 0;
1059 SwTwips nOrgSum = 0;
1060 bool bRowSpan = false;
1061 sal_uInt16 nRowSpanCount = 0;
1062 const size_t nCount = pLine->GetTabBoxes().size();
1063 for( size_t nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
1064 {
1065 SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
1066 SwTwips nCurrWidth = pBox->GetFrameFormat()->GetFrameSize().GetWidth();
1067 const sal_Int32 nRowSpan = pBox->getRowSpan();
1068 const bool bCurrRowSpan = bTop ? nRowSpan < 0 :
1069 ( nRowSpan > 1 || nRowSpan < -1 );
1070 if( bRowSpan || bCurrRowSpan )
1071 aNewSpanPos.push_back( nRowSpanCount );
1072 bRowSpan = bCurrRowSpan;
1073 nOrgSum += nCurrWidth;
1074 const sal_uInt16 nPos = lcl_MulDiv64<sal_uInt16>(
1075 lcl_MulDiv64<sal_uInt64>(nOrgSum, nWidth, nWish),
1076 nWish, nWidth);
1077 while( pCurr != rChanges.end() && pCurr->first < nPos )
1078 {
1079 ++nCurr;
1080 ++pCurr;
1081 }
1082 bool bNew = true;
1083 if( pCurr != rChanges.end() && pCurr->first <= nPos &&
1084 pCurr->first != pCurr->second )
1085 {
1086 pSpan = std::find_if(pSpan, rSpanPos.end(),
1087 [nCurr](const sal_uInt16 nSpan) { return nSpan >= nCurr; });
1088 if( pSpan != rSpanPos.end() && *pSpan == nCurr )
1089 {
1090 aNewChanges.push_back( *pCurr );
1091 ++nRowSpanCount;
1092 bNew = false;
1093 }
1094 }
1095 if( bNew )
1096 {
1097 ColChange aTmp( nPos, nPos );
1098 aNewChanges.push_back( aTmp );
1099 ++nRowSpanCount;
1100 }
1101 }
1102
1103 pCurr = aNewChanges.begin();
1104 ChangeList::iterator pLast = pCurr;
1105 ChangeList::iterator pLeftMove = pCurr;
1106 while( pCurr != aNewChanges.end() )
1107 {
1108 if( pLeftMove == pCurr )
1109 {
1110 while( ++pLeftMove != aNewChanges.end() && pLeftMove->first <= pLeftMove->second )
1111 ;
1112 }
1113 if( pCurr->second == pCurr->first )
1114 {
1115 if( pLeftMove != aNewChanges.end() && pCurr->second > pLeftMove->second )
1116 {
1117 if( pLeftMove->first == pLast->first )
1118 pCurr->second = pLeftMove->second;
1119 else
1120 {
1121 pCurr->second = lcl_MulDiv64<sal_uInt16>(
1122 pCurr->first - pLast->first,
1123 pLeftMove->second - pLast->second,
1124 pLeftMove->first - pLast->first) + pLast->second;
1125 }
1126 }
1127 pLast = pCurr;
1128 ++pCurr;
1129 }
1130 else if( pCurr->second > pCurr->first )
1131 {
1132 pLast = pCurr;
1133 ++pCurr;
1134 ChangeList::iterator pNext = pCurr;
1135 while( pNext != pLeftMove && pNext->second == pNext->first &&
1136 pNext->second < pLast->second )
1137 ++pNext;
1138 while( pCurr != pNext )
1139 {
1140 if( pNext == aNewChanges.end() || pNext->first == pLast->first )
1141 pCurr->second = pLast->second;
1142 else
1143 {
1144 pCurr->second = lcl_MulDiv64<sal_uInt16>(
1145 pCurr->first - pLast->first,
1146 pNext->second - pLast->second,
1147 pNext->first - pLast->first) + pLast->second;
1148 }
1149 ++pCurr;
1150 }
1151 pLast = pCurr;
1152 }
1153 else
1154 {
1155 pLast = pCurr;
1156 ++pCurr;
1157 }
1158 }
1159
1160 rChanges.swap(aNewChanges);
1161 rSpanPos.swap(aNewSpanPos);
1162}
1163
1164void SwTable::NewSetTabCols( Parm &rParm, const SwTabCols &rNew,
1165 const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly )
1166{
1167#if OSL_DEBUG_LEVEL > 1
1168 static int nCallCount = 0;
1169 ++nCallCount;
1170#endif
1171 // First step: evaluate which lines have been moved/which widths changed
1172 ChangeList aOldNew;
1173 const tools::Long nNewWidth = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1174 const tools::Long nOldWidth = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1175 if( nNewWidth < 1 || nOldWidth < 1 )
1176 return;
1177 for( size_t i = 0; i <= rOld.Count(); ++i )
1178 {
1179 tools::Long nNewPos;
1180 tools::Long nOldPos;
1181 if( i == rOld.Count() )
1182 {
1183 nOldPos = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
1184 nNewPos = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
1185 }
1186 else
1187 {
1188 nOldPos = rOld[i] - rParm.rOld.GetLeft();
1189 nNewPos = rNew[i] - rParm.rNew.GetLeft();
1190 }
1191 nNewPos = lcl_MulDiv64<tools::Long>(nNewPos, rParm.nNewWish, nNewWidth);
1192 nOldPos = lcl_MulDiv64<tools::Long>(nOldPos, rParm.nOldWish, nOldWidth);
1193 if( nOldPos != nNewPos && nNewPos > 0 && nOldPos > 0 )
1194 {
1195 ColChange aChg( o3tl::narrowing<sal_uInt16>(nOldPos), o3tl::narrowing<sal_uInt16>(nNewPos) );
1196 aOldNew.push_back( aChg );
1197 }
1198 }
1199 // Finished first step
1200 int nCount = aOldNew.size();
1201 if( !nCount )
1202 return; // no change, nothing to do
1203 SwTableLines &rLines = GetTabLines();
1204 if( bCurRowOnly )
1205 {
1206 const SwTableLine* pCurrLine = pStart->GetUpper();
1207 sal_uInt16 nCurr = rLines.GetPos( pCurrLine );
1208 if( nCurr >= USHRT_MAX )
1209 return;
1210
1211 ColChange aChg( 0, 0 );
1212 aOldNew.push_front( aChg );
1213 std::vector<sal_uInt16> aRowSpanPos;
1214 if( nCurr )
1215 {
1216 ChangeList aCopy;
1217 sal_uInt16 nPos = 0;
1218 for( const auto& rCop : aOldNew )
1219 {
1220 aCopy.push_back( rCop );
1221 aRowSpanPos.push_back( nPos++ );
1222 }
1223 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1224 rParm.nOldWish, nOldWidth, true );
1225 bool bGoOn = !aRowSpanPos.empty();
1226 sal_uInt16 j = nCurr;
1227 while( bGoOn )
1228 {
1229 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[--j],
1230 rParm.nOldWish, nOldWidth, true );
1231 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1232 bGoOn = !aRowSpanPos.empty() && j > 0;
1233 }
1234 aRowSpanPos.clear();
1235 }
1236 if( nCurr+1 < o3tl::narrowing<sal_uInt16>(rLines.size()) )
1237 {
1238 ChangeList aCopy;
1239 sal_uInt16 nPos = 0;
1240 for( const auto& rCop : aOldNew )
1241 {
1242 aCopy.push_back( rCop );
1243 aRowSpanPos.push_back( nPos++ );
1244 }
1245 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
1246 rParm.nOldWish, nOldWidth, false );
1247 bool bGoOn = !aRowSpanPos.empty();
1248 sal_uInt16 j = nCurr;
1249 while( bGoOn )
1250 {
1251 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[++j],
1252 rParm.nOldWish, nOldWidth, false );
1253 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
1254 bGoOn = !aRowSpanPos.empty() && j+1 < o3tl::narrowing<sal_uInt16>(rLines.size());
1255 }
1256 }
1257 ::lcl_AdjustWidthsInLine( rLines[nCurr], aOldNew, rParm, COLFUZZY );
1258 }
1259 else
1260 {
1261 for( size_t i = 0; i < rLines.size(); ++i )
1262 ::lcl_AdjustWidthsInLine( rLines[i], aOldNew, rParm, COLFUZZY );
1263 }
1264 CHECK_TABLE( *this )
1265}
1266
1267// return the pointer of the box specified.
1268static bool lcl_IsValidRowName( std::u16string_view rStr )
1269{
1270 bool bIsValid = true;
1271 size_t nLen = rStr.size();
1272 for( size_t i = 0; i < nLen && bIsValid; ++i )
1273 {
1274 const sal_Unicode cChar = rStr[i];
1275 if (cChar < '0' || cChar > '9')
1276 bIsValid = false;
1277 }
1278 return bIsValid;
1279}
1280
1281// #i80314#
1282// add 3rd parameter and its handling
1283sal_uInt16 SwTable::GetBoxNum( OUString& rStr, bool bFirstPart,
1284 const bool bPerformValidCheck )
1285{
1286 sal_uInt16 nRet = 0;
1287 if( bFirstPart ) // true == column; false == row
1288 {
1289 sal_Int32 nPos = 0;
1290 // the first one uses letters for addressing!
1291 bool bFirst = true;
1292 sal_uInt32 num = 0;
1293 bool overflow = false;
1294 while (nPos<rStr.getLength())
1295 {
1296 sal_Unicode cChar = rStr[nPos];
1297 if ((cChar<'A' || cChar>'Z') && (cChar<'a' || cChar>'z'))
1298 break;
1299 cChar -= 'A';
1300 if( cChar >= 26 )
1301 cChar -= 'a' - '[';
1302 if( bFirst )
1303 bFirst = false;
1304 else
1305 ++num;
1306 num = num * 52 + cChar;
1307 if (num > SAL_MAX_UINT16) {
1308 overflow = true;
1309 }
1310 ++nPos;
1311 }
1312 nRet = overflow ? SAL_MAX_UINT16 : num;
1313 rStr = rStr.copy( nPos ); // Remove char from String
1314 }
1315 else
1316 {
1317 const sal_Int32 nPos = rStr.indexOf( "." );
1318 if ( nPos<0 )
1319 {
1320 nRet = 0;
1321 if ( !bPerformValidCheck || lcl_IsValidRowName( rStr ) )
1322 {
1323 nRet = o3tl::narrowing<sal_uInt16>(rStr.toInt32());
1324 }
1325 rStr.clear();
1326 }
1327 else
1328 {
1329 nRet = 0;
1330 const std::u16string_view aText( rStr.subView( 0, nPos ) );
1331 if ( !bPerformValidCheck || lcl_IsValidRowName( aText ) )
1332 {
1333 nRet = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(aText));
1334 }
1335 rStr = rStr.copy( nPos+1 );
1336 }
1337 }
1338 return nRet;
1339}
1340
1341// #i80314#
1342// add 2nd parameter and its handling
1343const SwTableBox* SwTable::GetTableBox( const OUString& rName,
1344 const bool bPerformValidCheck ) const
1345{
1346 const SwTableBox* pBox = nullptr;
1347 const SwTableLine* pLine;
1348 const SwTableLines* pLines;
1349
1350 sal_uInt16 nLine, nBox;
1351 OUString aNm( rName );
1352 while( !aNm.isEmpty() )
1353 {
1354 nBox = SwTable::GetBoxNum( aNm, nullptr == pBox, bPerformValidCheck );
1355 // first box ?
1356 if( !pBox )
1357 pLines = &GetTabLines();
1358 else
1359 {
1360 pLines = &pBox->GetTabLines();
1361 if( nBox )
1362 --nBox;
1363 }
1364
1365 nLine = SwTable::GetBoxNum( aNm, false, bPerformValidCheck );
1366
1367 // determine line
1368 if( !nLine || nLine > pLines->size() )
1369 return nullptr;
1370 pLine = (*pLines)[ nLine-1 ];
1371
1372 // determine box
1373 const SwTableBoxes* pBoxes = &pLine->GetTabBoxes();
1374 if( nBox >= pBoxes->size() )
1375 return nullptr;
1376 pBox = (*pBoxes)[ nBox ];
1377 }
1378
1379 // check if the box found has any contents
1380 if( pBox && !pBox->GetSttNd() )
1381 {
1382 OSL_FAIL( "Box without content, looking for the next one!" );
1383 // "drop this" until the first box
1384 while( !pBox->GetTabLines().empty() )
1385 pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
1386 }
1387 return pBox;
1388}
1389
1391{
1392 // For optimizations, don't always process the entire SortArray.
1393 // Converting text to table, tries certain conditions
1394 // to ask for a table box of a table that is not yet having a format
1395 if(!GetFrameFormat())
1396 return nullptr;
1397 SwTableBox* pRet = nullptr;
1398 SwNodes& rNds = GetFrameFormat()->GetDoc()->GetNodes();
1399 SwNodeOffset nIndex = nSttIdx + 1;
1400 SwContentNode* pCNd = nullptr;
1401 SwTableNode* pTableNd = nullptr;
1402
1403 while ( nIndex < rNds.Count() )
1404 {
1405 pTableNd = rNds[ nIndex ]->GetTableNode();
1406 if ( pTableNd )
1407 break;
1408
1409 pCNd = rNds[ nIndex ]->GetContentNode();
1410 if ( pCNd )
1411 break;
1412
1413 ++nIndex;
1414 }
1415
1416 if ( pCNd || pTableNd )
1417 {
1418 sw::BroadcastingModify* pModify = pCNd;
1419 // #144862# Better handling of table in table
1420 if ( pTableNd && pTableNd->GetTable().GetFrameFormat() )
1421 pModify = pTableNd->GetTable().GetFrameFormat();
1422
1423 SwFrame* pFrame = pModify ? SwIterator<SwFrame,sw::BroadcastingModify>(*pModify).First() : nullptr;
1424 while ( pFrame && !pFrame->IsCellFrame() )
1425 pFrame = pFrame->GetUpper();
1426 if ( pFrame )
1427 pRet = const_cast<SwTableBox*>(static_cast<SwCellFrame*>(pFrame)->GetTabBox());
1428 }
1429
1430 // In case the layout doesn't exist yet or anything else goes wrong.
1431 if ( !pRet )
1432 {
1433 for (size_t n = m_TabSortContentBoxes.size(); n; )
1434 {
1435 if (m_TabSortContentBoxes[ --n ]->GetSttIdx() == nSttIdx)
1436 {
1437 return m_TabSortContentBoxes[ n ];
1438 }
1439 }
1440 }
1441 return pRet;
1442}
1443
1445{
1446 // Returns true for complex tables, i.e. tables that contain nestings,
1447 // like containing boxes not part of the first line, e.g. results of
1448 // splits/merges which lead to more complex structures.
1449 for (size_t n = 0; n < m_TabSortContentBoxes.size(); ++n)
1450 {
1451 if (m_TabSortContentBoxes[ n ]->GetUpper()->GetUpper())
1452 {
1453 return true;
1454 }
1455 }
1456 return false;
1457}
1458
1459SwTableLine::SwTableLine( SwTableLineFormat *pFormat, sal_uInt16 nBoxes,
1460 SwTableBox *pUp )
1461 : SwClient( pFormat )
1462 , m_pUpper( pUp )
1463 , m_eRedlineType( RedlineType::None )
1464{
1465 m_aBoxes.reserve( nBoxes );
1466}
1467
1469{
1470 for (size_t i = 0; i < m_aBoxes.size(); ++i)
1471 {
1472 delete m_aBoxes[i];
1473 }
1474 // the TabelleLine can be deleted if it's the last client of the FrameFormat
1475 sw::BroadcastingModify* pMod = GetFrameFormat();
1476 pMod->Remove( this ); // remove,
1477 if( !pMod->HasWriterListeners() )
1478 delete pMod; // and delete
1479}
1480
1482{
1483 // This method makes sure that this object is an exclusive SwTableLine client
1484 // of an SwTableLineFormat object
1485 // If other SwTableLine objects currently listen to the same SwTableLineFormat as
1486 // this one, something needs to be done
1487 SwTableLineFormat *pRet = static_cast<SwTableLineFormat*>(GetFrameFormat());
1488 SwIterator<SwTableLine,SwFormat> aIter( *pRet );
1489 for( SwTableLine* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1490 {
1491 if ( pLast != this )
1492 {
1493 // found another SwTableLine that is a client of the current Format
1494 // create a new Format as a copy and use it for this object
1495 SwTableLineFormat *pNewFormat = pRet->GetDoc()->MakeTableLineFormat();
1496 *pNewFormat = *pRet;
1497
1498 // register SwRowFrames that know me as clients at the new Format
1499 SwIterator<SwRowFrame,SwFormat> aFrameIter( *pRet );
1500 for( SwRowFrame* pFrame = aFrameIter.First(); pFrame; pFrame = aFrameIter.Next() )
1501 if( pFrame->GetTabLine() == this )
1502 pFrame->RegisterToFormat( *pNewFormat );
1503
1504 // register myself
1505 pNewFormat->Add( this );
1506 pRet = pNewFormat;
1507 break;
1508 }
1509 }
1510
1511 return pRet;
1512}
1513
1515{
1516 auto pOld = GetFrameFormat();
1517 pOld->CallSwClientNotify(sw::TableLineFormatChanged(*pNewFormat, *this));
1518 // Now, re-register self.
1519 pNewFormat->Add(this);
1520 if(!pOld->HasWriterListeners())
1521 delete pOld;
1522}
1523
1524SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const
1525{
1526 SwTwips nRet = 0;
1527 bLayoutAvailable = false;
1529 // A row could appear several times in headers/footers so only one chain of master/follow tables
1530 // will be accepted...
1531 const SwTabFrame* pChain = nullptr; // My chain
1532 for( SwRowFrame* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1533 {
1534 if (pLast->GetTabLine() != this)
1535 continue;
1536
1537 const SwTabFrame* pTab = pLast->FindTabFrame();
1538 if (!pTab)
1539 continue;
1540
1541 bLayoutAvailable = ( pTab->IsVertical() ) ?
1542 ( 0 < pTab->getFrameArea().Height() ) :
1543 ( 0 < pTab->getFrameArea().Width() );
1544
1545 // The first one defines the chain, if a chain is defined, only members of the chain
1546 // will be added.
1547 if (!pChain || pChain->IsAnFollow( pTab ) || pTab->IsAnFollow(pChain))
1548 {
1549 pChain = pTab; // defines my chain (even it is already)
1550 if( pTab->IsVertical() )
1551 nRet += pLast->getFrameArea().Width();
1552 else
1553 nRet += pLast->getFrameArea().Height();
1554 // Optimization, if there are no master/follows in my chain, nothing more to add
1555 if( !pTab->HasFollow() && !pTab->IsFollow() )
1556 break;
1557 // This is not an optimization, this is necessary to avoid double additions of
1558 // repeating rows
1559 if( pTab->IsInHeadline(*pLast) )
1560 break;
1561 }
1562 }
1563 return nRet;
1564}
1565
1567{
1568 for (size_t i = 0; i < m_aBoxes.size(); ++i)
1569 {
1570 if ( !m_aBoxes[i]->IsEmpty() )
1571 return false;
1572 }
1573 return true;
1574}
1575
1577{
1578 for (size_t i = 0; i < m_aLines.size(); ++i)
1579 {
1580 if ( !m_aLines[i]->IsEmpty() )
1581 return false;
1582 }
1583 return true;
1584}
1585
1587{
1589 if ( aRedlineTable.empty() )
1590 return false;
1591
1592 SwRedlineTable::size_type nRedlinePos = 0;
1593 for (size_t i = 0; i < m_aLines.size(); ++i)
1594 {
1595 if ( m_aLines[i]->IsDeleted(nRedlinePos) )
1596 return true;
1597 }
1598 return false;
1599}
1600
1602{
1604 if ( aRedlineTable.empty() )
1605 return false;
1606
1607 SwRedlineTable::size_type nRedlinePos = 0;
1608 for (size_t i = 0; i < m_aLines.size(); ++i)
1609 {
1610 if ( !m_aLines[i]->IsDeleted(nRedlinePos) )
1611 return false;
1612 }
1613 return true;
1614}
1615
1617{
1618 auto pDoc = GetFrameFormat()->GetDoc();
1619 auto pFieldType = pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Table, OUString(), false);
1620 if(!pFieldType)
1621 return;
1622 std::vector<SwFormatField*> vFields;
1623 pFieldType->GatherFields(vFields);
1624 for(auto pFormatField : vFields)
1625 {
1626 SwTableField* pField = static_cast<SwTableField*>(pFormatField->GetField());
1627 // table where this field is located
1628 const SwTableNode* pTableNd;
1629 const SwTextNode& rTextNd = pFormatField->GetTextField()->GetTextNode();
1630 pTableNd = rTextNd.FindTableNode();
1631 if(pTableNd == nullptr || &pTableNd->GetTable() != this)
1632 continue;
1633
1634 switch(eFlags)
1635 {
1636 case TBL_BOXNAME:
1637 // to the external representation
1638 pField->PtrToBoxNm(this);
1639 break;
1640 case TBL_RELBOXNAME:
1641 // to the relative representation
1642 pField->ToRelBoxNm(this);
1643 break;
1644 case TBL_BOXPTR:
1645 // to the internal representation
1646 // JP 17.06.96: internal representation on all formulas
1647 // (reference to other table!!!)
1648 pField->BoxNmToPtr( &pTableNd->GetTable() );
1649 break;
1650 default:
1651 assert(false); // Only TBL_BOXNAME, TBL_RELBOXNAME and TBL_BOXPTR are supported
1652 break;
1653 }
1654 }
1655 // process all table box formulas
1656 SwTableFormulaUpdate aHint(this);
1657 aHint.m_eFlags = eFlags;
1658 for(const SfxPoolItem* pItem : pDoc->GetAttrPool().GetItemSurrogates(RES_BOXATR_FORMULA))
1659 {
1660 auto pBoxFormula = const_cast<SwTableBoxFormula*>(pItem->DynamicWhichCast(RES_BOXATR_FORMULA));
1661 if(pBoxFormula && pBoxFormula->GetDefinedIn())
1662 {
1663 if(eFlags == TBL_BOXPTR)
1664 pBoxFormula->TryBoxNmToPtr();
1665 else
1666 pBoxFormula->ChangeState(&aHint);
1667 }
1668 }
1669}
1670
1672{
1673 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTable"));
1674 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1675 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("table-format"), "%p", GetFrameFormat());
1676 for (const auto& pLine : GetTabLines())
1677 {
1678 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTableLine"));
1679 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", pLine);
1680 pLine->GetFrameFormat()->dumpAsXml(pWriter);
1681 (void)xmlTextWriterEndElement(pWriter);
1682 }
1683 (void)xmlTextWriterEndElement(pWriter);
1684}
1685
1686// TODO Set HasTextChangesOnly=true, if needed based on the redlines in the cells.
1687// At tracked row deletion, return with the newest deletion of the row or
1688// at tracked row insertion, return with the oldest insertion in the row, which
1689// contain the change data of the row change.
1690// If the return value is SwRedlineTable::npos, there is no tracked row change.
1692 SwRedlineTable::size_type& rRedlinePos, bool bUpdateProperty ) const
1693{
1696
1697 // check table row property "HasTextChangesOnly", if it's defined and its
1698 // value is false, and all text content is in delete redlines, the row is deleted
1699 const SvxPrintItem *pHasTextChangesOnlyProp =
1701 if ( pHasTextChangesOnlyProp && !pHasTextChangesOnlyProp->GetValue() )
1702 {
1703 const SwTableBoxes & rBoxes = GetTabBoxes();
1704 size_t nBoxes = rBoxes.size();
1705 bool bInsertion = false;
1706 bool bPlainTextInLine = false;
1709 for (size_t nBoxIndex = 0; nBoxIndex < nBoxes && rRedlinePos < aRedlineTable.size(); ++nBoxIndex)
1710 {
1711 auto pBox = rBoxes[nBoxIndex];
1712 if ( pBox->IsEmpty( /*bWithRemainingNestedTable =*/ false ) )
1713 {
1714 // no text content, check the next cells
1715 continue;
1716 }
1717
1718 bool bHasRedlineInBox = false;
1719 SwPosition aCellStart( *pBox->GetSttNd(), SwNodeOffset(0) );
1720 SwPosition aCellEnd( *pBox->GetSttNd()->EndOfSectionNode(), SwNodeOffset(-1) );
1721 SwNodeIndex pEndNodeIndex(aCellEnd.GetNode());
1722 SwRangeRedline* pPreviousDeleteRedline = nullptr;
1723 for( ; rRedlinePos < aRedlineTable.size(); ++rRedlinePos )
1724 {
1725 const SwRangeRedline* pRedline = aRedlineTable[ rRedlinePos ];
1726
1727 if ( pRedline->Start()->GetNodeIndex() > pEndNodeIndex.GetIndex() )
1728 {
1729 // no more redlines in the actual cell,
1730 // check the next ones
1731 break;
1732 }
1733
1734 // redline in the cell
1735 if ( aCellStart <= *pRedline->Start() )
1736 {
1737 if ( !bHasRedlineInBox )
1738 {
1739 bHasRedlineInBox = true;
1740 // plain text before the first redline in the text
1741 if ( pRedline->Start()->GetContentIndex() > 0 )
1742 bPlainTextInLine = true;
1743 }
1744
1745 RedlineType nType = pRedline->GetType();
1746
1747 // first insert redline
1748 if ( !bInsertion )
1749 {
1750 if ( RedlineType::Insert == nType )
1751 {
1752 bInsertion = true;
1753 }
1754 else
1755 {
1756 // plain text between the delete redlines
1757 if ( pPreviousDeleteRedline &&
1758 *pPreviousDeleteRedline->End() < *pRedline->Start() &&
1759 // in the same section, i.e. not in a nested table
1760 pPreviousDeleteRedline->End()->nNode.GetNode().StartOfSectionNode() ==
1761 pRedline->Start()->nNode.GetNode().StartOfSectionNode() )
1762 {
1763 bPlainTextInLine = true;
1764 }
1765 pPreviousDeleteRedline = const_cast<SwRangeRedline*>(pRedline);
1766 }
1767 }
1768
1769 // search newest and oldest redlines
1770 if ( nNewestRedline == SwRedlineTable::npos ||
1771 aRedlineTable[nNewestRedline]->GetRedlineData().GetTimeStamp() <
1772 pRedline->GetRedlineData().GetTimeStamp() )
1773 {
1774 nNewestRedline = rRedlinePos;
1775 }
1776 if ( nOldestRedline == SwRedlineTable::npos ||
1777 aRedlineTable[nOldestRedline]->GetRedlineData().GetTimeStamp() >
1778 pRedline->GetRedlineData().GetTimeStamp() )
1779 {
1780 nOldestRedline = rRedlinePos;
1781 }
1782 }
1783 }
1784
1785 // there is text content outside of redlines: not a deletion
1786 if ( !bInsertion && ( !bHasRedlineInBox || ( pPreviousDeleteRedline &&
1787 // in the same cell, i.e. not in a nested table
1788 pPreviousDeleteRedline->End()->nNode.GetNode().StartOfSectionNode() ==
1789 aCellEnd.GetNode().StartOfSectionNode() &&
1790 ( pPreviousDeleteRedline->End()->GetNode() < aCellEnd.GetNode() ||
1791 pPreviousDeleteRedline->End()->GetContentIndex() <
1792 aCellEnd.GetNode().GetContentNode()->Len() ) ) ) )
1793 {
1794 bPlainTextInLine = true;
1795 // not deleted cell content: the row is not empty
1796 // maybe insertion of a row, try to search it
1797 bInsertion = true;
1798 }
1799 }
1800
1801 // choose return redline, if it exists or remove changed row attribute
1802 if ( bInsertion && SwRedlineTable::npos != nOldestRedline &&
1803 RedlineType::Insert == aRedlineTable[ nOldestRedline ]->GetType() )
1804 {
1805 // there is an insert redline, which is the oldest redline in the row
1806 nRet = nOldestRedline;
1807 }
1808 else if ( !bInsertion && !bPlainTextInLine && SwRedlineTable::npos != nNewestRedline &&
1809 RedlineType::Delete == aRedlineTable[ nNewestRedline ]->GetType() )
1810 {
1811 // there is a delete redline, which is the newest redline in the row,
1812 // and no text outside of redlines, and no insert redline in the row,
1813 // i.e. whole text content is deleted
1814 nRet = nNewestRedline;
1815 }
1816 else
1817 {
1818 // no longer tracked row insertion or deletion
1819 nRet = SwRedlineTable::npos;
1820 // set TextChangesOnly = true to remove the tracked deletion
1821 // FIXME Undo is not supported here (this is only a fallback,
1822 // because using SetRowNotTracked() is not recommended here)
1823 if ( bUpdateProperty )
1824 {
1825 SvxPrintItem aUnsetTracking(RES_PRINT, true);
1826 SwFrameFormat *pFormat = const_cast<SwTableLine*>(this)->ClaimFrameFormat();
1827 pFormat->LockModify();
1828 pFormat->SetFormatAttr( aUnsetTracking );
1829 pFormat->UnlockModify();
1830 }
1831 }
1832 }
1833
1834 // cache the result
1835 const_cast<SwTableLine*>(this)->SetRedlineType( SwRedlineTable::npos == nRet
1836 ? RedlineType::None
1837 : aRedlineTable[ nRet ]->GetType());
1838
1839 return nRet;
1840}
1841
1843{
1845 if ( nPos != SwRedlineTable::npos )
1846 {
1847 const SwRedlineTable& aRedlineTable =
1849 if ( RedlineType::Delete == aRedlineTable[nPos]->GetType() )
1850 return true;
1851 }
1852 return false;
1853}
1854
1856{
1858 if ( aRedlineTable.empty() )
1859 return RedlineType::None;
1860
1861 // check table row property "HasTextChangesOnly", if it's defined and its value is
1862 // false, return with the cached redline type, if it exists, otherwise calculate it
1863 const SvxPrintItem *pHasTextChangesOnlyProp =
1865 if ( pHasTextChangesOnlyProp && !pHasTextChangesOnlyProp->GetValue() )
1866 {
1867 if ( RedlineType::None != m_eRedlineType )
1868 return m_eRedlineType;
1869
1872 if ( nPos != SwRedlineTable::npos )
1873 return aRedlineTable[nPos]->GetType();
1874 }
1875 else if ( RedlineType::None != m_eRedlineType )
1876 // empty the cache
1877 const_cast<SwTableLine*>(this)->SetRedlineType( RedlineType::None );
1878
1879 return RedlineType::None;
1880}
1881
1882SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, sal_uInt16 nLines, SwTableLine *pUp )
1883 : SwClient(nullptr)
1884 , m_aLines()
1885 , m_pStartNode(nullptr)
1886 , m_pUpper(pUp)
1887 , mnRowSpan(1)
1888 , mbDummyFlag(false)
1889 , mbDirectFormatting(false)
1890{
1891 m_aLines.reserve( nLines );
1892 CheckBoxFormat( pFormat )->Add( this );
1893}
1894
1896 SwTableLine *pUp )
1897 : SwClient(nullptr)
1898 , m_aLines()
1899 , m_pUpper(pUp)
1900 , mnRowSpan(1)
1901 , mbDummyFlag(false)
1902 , mbDirectFormatting(false)
1903{
1904 CheckBoxFormat( pFormat )->Add( this );
1905
1907
1908 // insert into the table
1909 const SwTableNode* pTableNd = m_pStartNode->FindTableNode();
1910 assert(pTableNd && "In which table is that box?");
1911 SwTableSortBoxes& rSrtArr = const_cast<SwTableSortBoxes&>(pTableNd->GetTable().
1912 GetTabSortBoxes());
1913 SwTableBox* p = this; // error: &this
1914 rSrtArr.insert( p ); // insert
1915}
1916
1918 : SwClient(nullptr)
1919 , m_aLines()
1920 , m_pStartNode(&rSttNd)
1921 , m_pUpper(pUp)
1922 , mnRowSpan(1)
1923 , mbDummyFlag(false)
1924 , mbDirectFormatting(false)
1925{
1926 CheckBoxFormat( pFormat )->Add( this );
1927
1928 // insert into the table
1929 const SwTableNode* pTableNd = m_pStartNode->FindTableNode();
1930 OSL_ENSURE( pTableNd, "In which table is the box?" );
1931 SwTableSortBoxes& rSrtArr = const_cast<SwTableSortBoxes&>(pTableNd->GetTable().
1932 GetTabSortBoxes());
1933 SwTableBox* p = this; // error: &this
1934 rSrtArr.insert( p ); // insert
1935}
1936
1938{
1939 if (m_pStartNode) // box containing contents?
1940 {
1941 // remove from table
1942 const SwTableNode* pTableNd = m_pStartNode->FindTableNode();
1943 assert(pTableNd && "In which table is that box?");
1944 SwTableSortBoxes& rSrtArr = const_cast<SwTableSortBoxes&>(pTableNd->GetTable().
1945 GetTabSortBoxes());
1946 SwTableBox *p = this; // error: &this
1947 rSrtArr.erase( p ); // remove
1948 m_pStartNode = nullptr; // clear it so this is only run once
1949 }
1950}
1951
1953{
1954 if (!GetFrameFormat()->GetDoc()->IsInDtor())
1955 {
1957 }
1958
1959 // the TabelleBox can be deleted if it's the last client of the FrameFormat
1960 sw::BroadcastingModify* pMod = GetFrameFormat();
1961 pMod->Remove( this ); // remove,
1962 if( !pMod->HasWriterListeners() )
1963 delete pMod; // and delete
1964}
1965
1967{
1968 // We might need to create a new format here, because the box must be
1969 // added to the format solely if pFormat has a value or form.
1970 if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE, false ) ||
1971 SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMULA, false ) )
1972 {
1973 SwTableBox* pOther = SwIterator<SwTableBox,SwFormat>( *pFormat ).First();
1974 if( pOther )
1975 {
1976 SwTableBoxFormat* pNewFormat = pFormat->GetDoc()->MakeTableBoxFormat();
1977 pNewFormat->LockModify();
1978 *pNewFormat = *pFormat;
1979
1980 // Remove values and formulas
1982 pNewFormat->UnlockModify();
1983
1984 pFormat = pNewFormat;
1985 }
1986 }
1987 return pFormat;
1988}
1989
1991{
1992 // This method makes sure that this object is an exclusive SwTableBox client
1993 // of an SwTableBoxFormat object
1994 // If other SwTableBox objects currently listen to the same SwTableBoxFormat as
1995 // this one, something needs to be done
1996 SwTableBoxFormat *pRet = static_cast<SwTableBoxFormat*>(GetFrameFormat());
1997 SwIterator<SwTableBox,SwFormat> aIter( *pRet );
1998 for( SwTableBox* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1999 {
2000 if ( pLast != this )
2001 {
2002 // Found another SwTableBox object
2003 // create a new Format as a copy and assign me to it
2004 // don't copy values and formulas
2005 SwTableBoxFormat* pNewFormat = pRet->GetDoc()->MakeTableBoxFormat();
2006 pNewFormat->LockModify();
2007 *pNewFormat = *pRet;
2009 pNewFormat->UnlockModify();
2010
2011 // re-register SwCellFrame objects that know me
2012 SwIterator<SwCellFrame,SwFormat> aFrameIter( *pRet );
2013 for( SwCellFrame* pCell = aFrameIter.First(); pCell; pCell = aFrameIter.Next() )
2014 if( pCell->GetTabBox() == this )
2015 pCell->RegisterToFormat( *pNewFormat );
2016
2017 // re-register myself
2018 pNewFormat->Add( this );
2019 pRet = pNewFormat;
2020 break;
2021 }
2022 }
2023 return pRet;
2024}
2025
2026void SwTableBox::ChgFrameFormat(SwTableBoxFormat* pNewFormat, bool bNeedToReregister)
2027{
2028 SwFrameFormat* pOld = GetFrameFormat();
2029 // tdf#84635 We set bNeedToReregister=false to avoid a quadratic slowdown on loading large tables,
2030 // and since we are creating the table for the first time, no re-registration is necessary.
2031 // First, re-register the Frames.
2032 if(bNeedToReregister)
2033 pOld->CallSwClientNotify(sw::TableBoxFormatChanged(*pNewFormat, *this));
2034 // Now, re-register self.
2035 pNewFormat->Add(this);
2036 if(!pOld->HasWriterListeners())
2037 delete pOld;
2038}
2039
2040// Return the name of this box. This is determined dynamically
2041// resulting from the position in the lines/boxes/tables.
2042void sw_GetTableBoxColStr( sal_uInt16 nCol, OUString& rNm )
2043{
2044 const sal_uInt16 coDiff = 52; // 'A'-'Z' 'a' - 'z'
2045
2046 do {
2047 const sal_uInt16 nCalc = nCol % coDiff;
2048 if( nCalc >= 26 )
2049 rNm = OUStringChar( sal_Unicode('a' - 26 + nCalc) ) + rNm;
2050 else
2051 rNm = OUStringChar( sal_Unicode('A' + nCalc) ) + rNm;
2052
2053 nCol = nCol - nCalc;
2054 if( 0 == nCol )
2055 break;
2056 nCol /= coDiff;
2057 --nCol;
2058 } while( true );
2059}
2060
2062{
2063 if( !m_pStartNode ) // box without content?
2064 {
2065 // search for the next first box?
2066 return Point( 0, 0 );
2067 }
2068
2069 const SwTable& rTable = m_pStartNode->FindTableNode()->GetTable();
2070 sal_uInt16 nX, nY;
2071 const SwTableBox* pBox = this;
2072 do {
2073 const SwTableLine* pLine = pBox->GetUpper();
2074 // at the first level?
2075 const SwTableLines* pLines = pLine->GetUpper()
2076 ? &pLine->GetUpper()->GetTabLines() : &rTable.GetTabLines();
2077
2078 nY = pLines->GetPos( pLine ) + 1 ;
2079 nX = pBox->GetUpper()->GetBoxPos( pBox ) + 1;
2080 pBox = pLine->GetUpper();
2081 } while( pBox );
2082 return Point( nX, nY );
2083}
2084
2085OUString SwTableBox::GetName() const
2086{
2087 if( !m_pStartNode ) // box without content?
2088 {
2089 // search for the next first box?
2090 return OUString();
2091 }
2092
2093 const SwTable& rTable = m_pStartNode->FindTableNode()->GetTable();
2094 sal_uInt16 nPos;
2095 OUString sNm, sTmp;
2096 const SwTableBox* pBox = this;
2097 do {
2098 const SwTableLine* pLine = pBox->GetUpper();
2099 // at the first level?
2100 const SwTableLines* pLines = pLine->GetUpper()
2101 ? &pLine->GetUpper()->GetTabLines() : &rTable.GetTabLines();
2102
2103 nPos = pLines->GetPos( pLine ) + 1;
2104 sTmp = OUString::number( nPos );
2105 if( !sNm.isEmpty() )
2106 sNm = sTmp + "." + sNm;
2107 else
2108 sNm = sTmp;
2109
2110 nPos = pBox->GetUpper()->GetBoxPos( pBox );
2111 sTmp = OUString::number(nPos + 1);
2112 pBox = pLine->GetUpper();
2113 if( nullptr != pBox )
2114 sNm = sTmp + "." + sNm;
2115 else
2116 sw_GetTableBoxColStr( nPos, sNm );
2117
2118 } while( pBox );
2119 return sNm;
2120}
2121
2122bool SwTableBox::IsInHeadline( const SwTable* pTable ) const
2123{
2124 if( !GetUpper() ) // should only happen upon merge.
2125 return false;
2126
2127 if( !pTable )
2128 pTable = &m_pStartNode->FindTableNode()->GetTable();
2129
2130 const SwTableLine* pLine = GetUpper();
2131 while( pLine->GetUpper() )
2132 pLine = pLine->GetUpper()->GetUpper();
2133
2134 // Headerline?
2135 return pTable->GetTabLines()[ 0 ] == pLine;
2136}
2137
2139{
2141}
2142
2143bool SwTableBox::IsEmpty( bool bWithRemainingNestedTable ) const
2144{
2145 const SwStartNode *pSttNd = GetSttNd();
2146
2147 if ( !pSttNd )
2148 return false;
2149
2150 const SwNode * pFirstNode = pSttNd->GetNodes()[pSttNd->GetIndex() + 1];
2151
2152 if ( pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex() )
2153 {
2154 // single empty node in the box
2155 const SwContentNode *pCNd = pFirstNode->GetContentNode();
2156 if ( pCNd && !pCNd->Len() )
2157 return true;
2158 }
2159 else if ( bWithRemainingNestedTable )
2160 {
2161 if ( const SwTableNode * pTableNode = pFirstNode->GetTableNode() )
2162 {
2163 // empty nested table in the box and
2164 // no text content after it
2165 if ( pTableNode->EndOfSectionIndex() + 2 == pSttNd->EndOfSectionIndex() )
2166 return pTableNode->GetTable().IsEmpty();
2167 }
2168 }
2169
2170 return false;
2171}
2172
2173 // retrieve information from the client
2174bool SwTable::GetInfo( SfxPoolItem& rInfo ) const
2175{
2176 switch( rInfo.Which() )
2177 {
2179 {
2180 const SwTableNode* pNode = GetTableNode();
2181 if (pNode && &pNode->GetNodes() == static_cast<SwAutoFormatGetDocNode&>(rInfo).pNodes)
2182 {
2184 {
2185 SwNodeIndex aIdx( *m_TabSortContentBoxes[0]->GetSttNd() );
2186 GetFrameFormat()->GetDoc()->GetNodes().GoNext( &aIdx );
2187 }
2188 return false;
2189 }
2190 break;
2191 }
2193 if( GetFrameFormat() &&
2194 GetFrameFormat()->GetFormatAttr( RES_PAGEDESC ).GetPageDesc() &&
2196 m_TabSortContentBoxes[0]->GetSttNd()->GetNodes().IsDocNodes() )
2197 static_cast<SwFindNearestNode&>(rInfo).CheckNode( *
2198 m_TabSortContentBoxes[0]->GetSttNd()->FindTableNode() );
2199 break;
2200
2203 return false;
2204 }
2205 return true;
2206}
2207
2209{
2210 return pFormat
2212 : nullptr;
2213}
2214
2216{
2217 return !GetTabSortBoxes().empty() ?
2218 const_cast<SwTableNode*>(GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode()) :
2220}
2221
2223{
2224 if( m_xRefObj.is() )
2225 m_xRefObj->Closed();
2226
2227 m_xRefObj = pObj;
2228}
2229
2230void SwTable::SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout> const& r)
2231{
2232 m_xHTMLLayout = r;
2233}
2234
2235static void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
2236 bool bChgAlign )
2237{
2238 SwNodeOffset nNdPos = rBox.IsValidNumTextNd();
2239 ChgTextToNum( rBox,rText,pCol,bChgAlign,nNdPos);
2240}
2241void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
2242 bool bChgAlign, SwNodeOffset nNdPos )
2243{
2244
2245 if( NODE_OFFSET_MAX == nNdPos )
2246 return;
2247
2248 SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
2249 SwTextNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTextNode();
2250
2251 // assign adjustment
2252 if( bChgAlign )
2253 {
2254 const SfxPoolItem* pItem;
2255 pItem = &pTNd->SwContentNode::GetAttr( RES_PARATR_ADJUST );
2256 SvxAdjust eAdjust = static_cast<const SvxAdjustItem*>(pItem)->GetAdjust();
2257 if( SvxAdjust::Left == eAdjust || SvxAdjust::Block == eAdjust )
2258 {
2259 SvxAdjustItem aAdjust( *static_cast<const SvxAdjustItem*>(pItem) );
2260 aAdjust.SetAdjust( SvxAdjust::Right );
2261 pTNd->SetAttr( aAdjust );
2262 }
2263 }
2264
2265 // assign color or save "user color"
2266 const SvxColorItem* pColorItem = nullptr;
2267 if( pTNd->GetpSwAttrSet() )
2268 pColorItem = pTNd->GetpSwAttrSet()->GetItemIfSet( RES_CHRATR_COLOR, false );
2269
2270 const std::optional<Color>& pOldNumFormatColor = rBox.GetSaveNumFormatColor();
2271 std::optional<Color> pNewUserColor;
2272 if (pColorItem)
2273 pNewUserColor = pColorItem->GetValue();
2274
2275 if( ( pNewUserColor && pOldNumFormatColor &&
2276 *pNewUserColor == *pOldNumFormatColor ) ||
2277 ( !pNewUserColor && !pOldNumFormatColor ))
2278 {
2279 // Keep the user color, set updated values, delete old NumFormatColor if needed
2280 if( pCol )
2281 // if needed, set the color
2282 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2283 else if( pColorItem )
2284 {
2285 pNewUserColor = rBox.GetSaveUserColor();
2286 if( pNewUserColor )
2287 pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
2288 else
2289 pTNd->ResetAttr( RES_CHRATR_COLOR );
2290 }
2291 }
2292 else
2293 {
2294 // Save user color, set NumFormat color if needed, but never reset the color
2295 rBox.SetSaveUserColor( pNewUserColor ? *pNewUserColor : std::optional<Color>() );
2296
2297 if( pCol )
2298 // if needed, set the color
2299 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2300
2301 }
2302 rBox.SetSaveNumFormatColor( pCol ? *pCol : std::optional<Color>() );
2303
2304 if( pTNd->GetText() != rText )
2305 {
2306 // Exchange text. Bugfix to keep Tabs (front and back!) and annotations (inword comment anchors)
2307 const OUString& rOrig = pTNd->GetText();
2308 sal_Int32 n;
2309
2310 for( n = 0; n < rOrig.getLength() && ('\x9' == rOrig[n] || CH_TXTATR_INWORD == rOrig[n]); ++n )
2311 ;
2312 for( ; n < rOrig.getLength() && '\x01' == rOrig[n]; ++n )
2313 ;
2314 SwContentIndex aIdx( pTNd, n );
2315 for( n = rOrig.getLength(); n && ('\x9' == rOrig[--n] || CH_TXTATR_INWORD == rOrig[n]); )
2316 ;
2317 sal_Int32 nEndPos = n;
2318 n -= aIdx.GetIndex() - 1;
2319
2320 // Reset DontExpand-Flags before exchange, to retrigger expansion
2321 {
2322 SwContentIndex aResetIdx( aIdx, n );
2323 pTNd->DontExpandFormat( aResetIdx.GetIndex(), false, false );
2324 }
2325
2327 {
2328 SwPaM aTemp(*pTNd, 0, *pTNd, rOrig.getLength());
2329 pDoc->getIDocumentRedlineAccess().DeleteRedline(aTemp, true, RedlineType::Any);
2330 }
2331
2332 // preserve comments inside of the number by deleting number portions starting from the back
2333 sal_Int32 nCommentPos = pTNd->GetText().lastIndexOf( CH_TXTATR_INWORD, nEndPos );
2334 while( nCommentPos > aIdx.GetIndex() )
2335 {
2336 pTNd->EraseText( SwContentIndex(pTNd, nCommentPos+1), nEndPos - nCommentPos, SwInsertFlags::EMPTYEXPAND );
2337 // find the next non-sequential comment anchor
2338 do
2339 {
2340 nEndPos = nCommentPos;
2341 n = nEndPos - aIdx.GetIndex();
2342 nCommentPos = pTNd->GetText().lastIndexOf( CH_TXTATR_INWORD, nEndPos );
2343 --nEndPos;
2344 }
2345 while( nCommentPos > aIdx.GetIndex() && nCommentPos == nEndPos );
2346 }
2347
2348 pTNd->EraseText( aIdx, n, SwInsertFlags::EMPTYEXPAND );
2349 pTNd->InsertText( rText, aIdx, SwInsertFlags::EMPTYEXPAND );
2350
2352 {
2353 SwPaM aTemp(*pTNd, 0, *pTNd, rText.getLength());
2354 pDoc->getIDocumentRedlineAccess().AppendRedline(new SwRangeRedline(RedlineType::Insert, aTemp), true);
2355 }
2356 }
2357
2358 // assign vertical orientation
2359 const SwFormatVertOrient* pVertOrientItem;
2360 if( bChgAlign &&
2361 ( !(pVertOrientItem = rBox.GetFrameFormat()->GetItemIfSet( RES_VERT_ORIENT )) ||
2362 text::VertOrientation::TOP == pVertOrientItem->GetVertOrient() ))
2363 {
2364 rBox.GetFrameFormat()->SetFormatAttr( SwFormatVertOrient( 0, text::VertOrientation::BOTTOM ));
2365 }
2366
2367}
2368
2369static void ChgNumToText( SwTableBox& rBox, sal_uLong nFormat )
2370{
2371 SwNodeOffset nNdPos = rBox.IsValidNumTextNd( false );
2372 if( NODE_OFFSET_MAX == nNdPos )
2373 return;
2374
2375 SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
2376 SwTextNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTextNode();
2377 bool bChgAlign = pDoc->IsInsTableAlignNum();
2378
2379 const Color * pCol = nullptr;
2380 if( getSwDefaultTextFormat() != nFormat )
2381 {
2382 // special text format:
2383 OUString sTmp;
2384 const OUString sText( pTNd->GetText() );
2385 pDoc->GetNumberFormatter()->GetOutputString( sText, nFormat, sTmp, &pCol );
2386 if( sText != sTmp )
2387 {
2388 // exchange text
2389 // Reset DontExpand-Flags before exchange, to retrigger expansion
2390 pTNd->DontExpandFormat( sText.getLength(), false, false );
2391 SwContentIndex aIdx( pTNd, 0 );
2393 pTNd->InsertText( sTmp, aIdx, SwInsertFlags::EMPTYEXPAND );
2394 }
2395 }
2396
2397 const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
2398
2399 // assign adjustment
2400 const SvxAdjustItem* pAdjustItem;
2401 if( bChgAlign && pAttrSet &&
2402 (pAdjustItem = pAttrSet->GetItemIfSet( RES_PARATR_ADJUST, false )) &&
2403 SvxAdjust::Right == pAdjustItem->GetAdjust() )
2404 {
2405 pTNd->SetAttr( SvxAdjustItem( SvxAdjust::Left, RES_PARATR_ADJUST ) );
2406 }
2407
2408 // assign color or save "user color"
2409 const SvxColorItem* pColorItem = nullptr;
2410 if( pAttrSet )
2411 pColorItem = pAttrSet->GetItemIfSet( RES_CHRATR_COLOR, false );
2412
2413 const std::optional<Color>& pOldNumFormatColor = rBox.GetSaveNumFormatColor();
2414 std::optional<Color> pNewUserColor;
2415 if (pColorItem)
2416 pNewUserColor = pColorItem->GetValue();
2417
2418 if( ( pNewUserColor && pOldNumFormatColor &&
2419 *pNewUserColor == *pOldNumFormatColor ) ||
2420 ( !pNewUserColor && !pOldNumFormatColor ))
2421 {
2422 // Keep the user color, set updated values, delete old NumFormatColor if needed
2423 if( pCol )
2424 // if needed, set the color
2425 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2426 else if( pColorItem )
2427 {
2428 pNewUserColor = rBox.GetSaveUserColor();
2429 if( pNewUserColor )
2430 pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
2431 else
2432 pTNd->ResetAttr( RES_CHRATR_COLOR );
2433 }
2434 }
2435 else
2436 {
2437 // Save user color, set NumFormat color if needed, but never reset the color
2438 rBox.SetSaveUserColor( pNewUserColor );
2439
2440 if( pCol )
2441 // if needed, set the color
2442 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
2443
2444 }
2445 rBox.SetSaveNumFormatColor( pCol ? *pCol : std::optional<Color>() );
2446
2447 // assign vertical orientation
2448 const SwFormatVertOrient* pVertOrientItem;
2449 if( bChgAlign &&
2450 (pVertOrientItem = rBox.GetFrameFormat()->GetItemIfSet( RES_VERT_ORIENT, false )) &&
2451 text::VertOrientation::BOTTOM == pVertOrientItem->GetVertOrient() )
2452 {
2453 rBox.GetFrameFormat()->SetFormatAttr( SwFormatVertOrient( 0, text::VertOrientation::TOP ));
2454 }
2455
2456}
2457void SwTableBoxFormat::BoxAttributeChanged(SwTableBox& rBox, const SwTableBoxNumFormat* pNewFormat, const SwTableBoxFormula* pNewFormula, const SwTableBoxValue* pNewValue, sal_uLong nOldFormat)
2458{
2459 sal_uLong nNewFormat;
2460 if(pNewFormat)
2461 {
2462 nNewFormat = pNewFormat->GetValue();
2463 // new formatting
2464 // is it newer or has the current been removed?
2465 if( SfxItemState::SET != GetItemState(RES_BOXATR_VALUE, false))
2466 pNewFormat = nullptr;
2467 }
2468 else
2469 {
2470 // fetch the current Item
2471 pNewFormat = GetItemIfSet(RES_BOXATR_FORMAT, false);
2472 nOldFormat = GetTableBoxNumFormat().GetValue();
2473 nNewFormat = pNewFormat ? pNewFormat->GetValue() : nOldFormat;
2474 }
2475
2476 // is it newer or has the current been removed?
2477 if(pNewValue)
2478 {
2479 if(GetDoc()->GetNumberFormatter()->IsTextFormat(nNewFormat))
2480 nOldFormat = 0;
2481 else
2482 {
2483 if(SfxItemState::SET == GetItemState(RES_BOXATR_VALUE, false))
2484 nOldFormat = getSwDefaultTextFormat();
2485 else
2486 nNewFormat = getSwDefaultTextFormat();
2487 }
2488 }
2489
2490 // Logic:
2491 // Value change: -> "simulate" a format change!
2492 // Format change:
2493 // Text -> !Text or format change:
2494 // - align right for horizontal alignment, if LEFT or JUSTIFIED
2495 // - align bottom for vertical alignment, if TOP is set, or default
2496 // - replace text (color? negative numbers RED?)
2497 // !Text -> Text:
2498 // - align left for horizontal alignment, if RIGHT
2499 // - align top for vertical alignment, if BOTTOM is set
2500 SvNumberFormatter* pNumFormatr = GetDoc()->GetNumberFormatter();
2501 bool bNewIsTextFormat = pNumFormatr->IsTextFormat(nNewFormat);
2502
2503 if((!bNewIsTextFormat && nOldFormat != nNewFormat) || pNewFormula)
2504 {
2505 bool bIsNumFormat = false;
2506 OUString aOrigText;
2507 bool bChgText = true;
2508 double fVal = 0;
2509 if(!pNewValue)
2510 pNewValue = GetItemIfSet(RES_BOXATR_VALUE, false);
2511 if(!pNewValue)
2512 {
2513 // so far, no value has been set, so try to evaluate the content
2514 SwNodeOffset nNdPos = rBox.IsValidNumTextNd();
2515 if(NODE_OFFSET_MAX != nNdPos)
2516 {
2517 sal_uInt32 nTmpFormatIdx = nNewFormat;
2518 OUString aText(GetDoc()->GetNodes()[nNdPos] ->GetTextNode()->GetRedlineText());
2519 aOrigText = aText;
2520 if(aText.isEmpty())
2521 bChgText = false;
2522 else
2523 {
2524 // Keep Tabs
2526
2527 // JP 22.04.98: Bug 49659 -
2528 // Special casing for percent
2529 if(SvNumFormatType::PERCENT == pNumFormatr->GetType(nNewFormat))
2530 {
2531 sal_uInt32 nTmpFormat = 0;
2532 if(GetDoc()->IsNumberFormat(aText, nTmpFormat, fVal))
2533 {
2534 if(SvNumFormatType::NUMBER == pNumFormatr->GetType( nTmpFormat))
2535 aText += "%";
2536
2537 bIsNumFormat = GetDoc()->IsNumberFormat(aText, nTmpFormatIdx, fVal);
2538 }
2539 }
2540 else
2541 bIsNumFormat = GetDoc()->IsNumberFormat(aText, nTmpFormatIdx, fVal);
2542
2543 if(bIsNumFormat)
2544 {
2545 // directly assign value - without Modify
2546 bool bIsLockMod = IsModifyLocked();
2547 LockModify();
2549 if(!bIsLockMod)
2550 UnlockModify();
2551 }
2552 }
2553 }
2554 }
2555 else
2556 {
2557 fVal = pNewValue->GetValue();
2558 bIsNumFormat = true;
2559 }
2560
2561 // format contents with the new value assigned and write to paragraph
2562 const Color* pCol = nullptr;
2563 OUString sNewText;
2564 bool bChangeFormat = true;
2565 if(DBL_MAX == fVal)
2566 {
2568 }
2569 else
2570 {
2571 if(bIsNumFormat)
2572 pNumFormatr->GetOutputString(fVal, nNewFormat, sNewText, &pCol);
2573 else
2574 {
2575 // Original text could not be parsed as
2576 // number/date/time/..., so keep the text.
2577#if 0
2578 // Actually the text should be formatted
2579 // according to the format, which may include
2580 // additional text from the format, for example
2581 // in {0;-0;"BAD: "@}. But other places when
2582 // entering a new value or changing text or
2583 // changing to a different format of type Text
2584 // don't do this (yet?).
2585 pNumFormatr->GetOutputString(aOrigText, nNewFormat, sNewText, &pCol);
2586#else
2587 sNewText = aOrigText;
2588#endif
2589 // Remove the newly assigned numbering format as well if text actually exists.
2590 // Exception: assume user-defined formats are always intentional.
2591 if (bChgText && pNumFormatr->IsTextFormat(nOldFormat)
2592 && !pNumFormatr->IsUserDefined(nNewFormat))
2593 {
2595 bChangeFormat = false;
2596 }
2597 }
2598
2599 if(!bChgText)
2600 sNewText.clear();
2601 }
2602
2603 // across all boxes
2604 if (bChangeFormat)
2605 ChgTextToNum(rBox, sNewText, pCol, GetDoc()->IsInsTableAlignNum());
2606
2607 }
2608 else if(bNewIsTextFormat && nOldFormat != nNewFormat)
2609 ChgNumToText(rBox, nNewFormat);
2610}
2611
2612SwTableBox* SwTableBoxFormat::SwTableBoxFormat::GetTableBox()
2613{
2615 auto pBox = aIter.First();
2616 SAL_INFO_IF(!pBox, "sw.core", "no box found at format");
2617 SAL_WARN_IF(pBox && aIter.Next(), "sw.core", "more than one box found at format");
2618 return pBox;
2619}
2620
2621// for detection of modifications (mainly TableBoxAttribute)
2623{
2624 if(rHint.GetId() != SfxHintId::SwLegacyModify)
2625 return;
2626 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
2627 if(IsModifyLocked() || !GetDoc() || GetDoc()->IsInDtor())
2628 {
2629 SwFrameFormat::SwClientNotify(rMod, rHint);
2630 return;
2631 }
2632 const SwTableBoxNumFormat* pNewFormat = nullptr;
2633 const SwTableBoxFormula* pNewFormula = nullptr;
2634 const SwTableBoxValue* pNewVal = nullptr;
2635 sal_uLong nOldFormat = getSwDefaultTextFormat();
2636
2637 switch(pLegacy->m_pNew ? pLegacy->m_pNew->Which() : 0)
2638 {
2639 case RES_ATTRSET_CHG:
2640 {
2641 const SfxItemSet& rSet = *static_cast<const SwAttrSetChg*>(pLegacy->m_pNew)->GetChgSet();
2642 pNewFormat = rSet.GetItemIfSet( RES_BOXATR_FORMAT, false);
2643 if(pNewFormat)
2644 nOldFormat = static_cast<const SwAttrSetChg*>(pLegacy->m_pOld)->GetChgSet()->Get(RES_BOXATR_FORMAT).GetValue();
2645 pNewFormula = rSet.GetItemIfSet(RES_BOXATR_FORMULA, false);
2646 pNewVal = rSet.GetItemIfSet(RES_BOXATR_VALUE, false);
2647 break;
2648 }
2649 case RES_BOXATR_FORMAT:
2650 pNewFormat = static_cast<const SwTableBoxNumFormat*>(pLegacy->m_pNew);
2651 nOldFormat = static_cast<const SwTableBoxNumFormat*>(pLegacy->m_pOld)->GetValue();
2652 break;
2653 case RES_BOXATR_FORMULA:
2654 pNewFormula = static_cast<const SwTableBoxFormula*>(pLegacy->m_pNew);
2655 break;
2656 case RES_BOXATR_VALUE:
2657 pNewVal = static_cast<const SwTableBoxValue*>(pLegacy->m_pNew);
2658 break;
2659 }
2660
2661 // something changed and some BoxAttribut remained in the set!
2662 if( pNewFormat || pNewFormula || pNewVal )
2663 {
2665
2666 if(SfxItemState::SET == GetItemState(RES_BOXATR_FORMAT, false) ||
2667 SfxItemState::SET == GetItemState(RES_BOXATR_VALUE, false) ||
2668 SfxItemState::SET == GetItemState(RES_BOXATR_FORMULA, false) )
2669 {
2670 if(auto pBox = GetTableBox())
2671 BoxAttributeChanged(*pBox, pNewFormat, pNewFormula, pNewVal, nOldFormat);
2672 }
2673 }
2674 // call base class
2675 SwFrameFormat::SwClientNotify(rMod, rHint);
2676}
2677
2679{
2680 return false;
2681}
2682
2684{
2685 return false;
2686}
2687
2689{
2690 return false;
2691}
2692
2693bool SwTableBox::HasNumContent( double& rNum, sal_uInt32& rFormatIndex,
2694 bool& rIsEmptyTextNd ) const
2695{
2696 bool bRet = false;
2697 SwNodeOffset nNdPos = IsValidNumTextNd();
2698 if( NODE_OFFSET_MAX != nNdPos )
2699 {
2700 OUString aText( m_pStartNode->GetNodes()[ nNdPos ]->GetTextNode()->GetRedlineText() );
2701 // Keep Tabs
2702 lcl_TabToBlankAtSttEnd( aText );
2703 rIsEmptyTextNd = aText.isEmpty();
2705
2706 if( const SwTableBoxNumFormat* pItem = GetFrameFormat()->GetItemIfSet( RES_BOXATR_FORMAT, false) )
2707 {
2708 rFormatIndex = pItem->GetValue();
2709 // Special casing for percent
2710 if( !rIsEmptyTextNd && SvNumFormatType::PERCENT == pNumFormatr->GetType( rFormatIndex ))
2711 {
2712 sal_uInt32 nTmpFormat = 0;
2713 if( GetFrameFormat()->GetDoc()->IsNumberFormat( aText, nTmpFormat, rNum ) &&
2714 SvNumFormatType::NUMBER == pNumFormatr->GetType( nTmpFormat ))
2715 aText += "%";
2716 }
2717 }
2718 else
2719 rFormatIndex = 0;
2720
2721 bRet = GetFrameFormat()->GetDoc()->IsNumberFormat( aText, rFormatIndex, rNum );
2722 }
2723 else
2724 rIsEmptyTextNd = false;
2725 return bRet;
2726}
2727
2729{
2730 bool bRet = true;
2731
2732 if( SfxItemState::SET == GetFrameFormat()->GetItemState( RES_BOXATR_FORMULA, false ))
2733 {
2734 const SwTableBoxNumFormat *pNumFormat = GetFrameFormat()->GetItemIfSet( RES_BOXATR_FORMAT, false );
2735 const SwTableBoxValue *pValue = GetFrameFormat()->GetItemIfSet( RES_BOXATR_VALUE, false );
2736
2737 SwNodeOffset nNdPos;
2738 if( pNumFormat && pValue && NODE_OFFSET_MAX != ( nNdPos = IsValidNumTextNd() ) )
2739 {
2740 OUString sNewText, sOldText( m_pStartNode->GetNodes()[ nNdPos ]->
2741 GetTextNode()->GetRedlineText() );
2742 lcl_DelTabsAtSttEnd( sOldText );
2743
2744 const Color* pCol = nullptr;
2746 pValue->GetValue(), pNumFormat->GetValue(), sNewText, &pCol );
2747
2748 bRet = sNewText != sOldText ||
2749 !( ( !pCol && !GetSaveNumFormatColor() ) ||
2750 ( pCol && GetSaveNumFormatColor() &&
2751 *pCol == *GetSaveNumFormatColor() ));
2752 }
2753 }
2754 return bRet;
2755}
2756
2758{
2760 if( m_pStartNode )
2761 {
2762 SwNodeIndex aIdx( *m_pStartNode );
2763 SwNodeOffset nIndex = aIdx.GetIndex();
2764 const SwNodeOffset nIndexEnd = m_pStartNode->GetNodes()[ nIndex ]->EndOfSectionIndex();
2765 const SwTextNode *pTextNode = nullptr;
2766 while( ++nIndex < nIndexEnd )
2767 {
2768 const SwNode* pNode = m_pStartNode->GetNodes()[nIndex];
2769 if( pNode->IsTableNode() )
2770 {
2771 pTextNode = nullptr;
2772 break;
2773 }
2774 if( pNode->IsTextNode() )
2775 {
2776 if( pTextNode )
2777 {
2778 pTextNode = nullptr;
2779 break;
2780 }
2781 else
2782 {
2783 pTextNode = pNode->GetTextNode();
2784 nPos = nIndex;
2785 }
2786 }
2787 }
2788 if( pTextNode )
2789 {
2790 if( bCheckAttr )
2791 {
2792 const SwpHints* pHts = pTextNode->GetpSwpHints();
2793 // do some tests if there's only text in the node!
2794 // Flys/fields/...
2795 if( pHts )
2796 {
2797 sal_Int32 nNextSetField = 0;
2798 for( size_t n = 0; n < pHts->Count(); ++n )
2799 {
2800 const SwTextAttr* pAttr = pHts->Get(n);
2801 if( RES_TXTATR_NOEND_BEGIN <= pAttr->Which() )
2802 {
2803 if ( (pAttr->GetStart() == nNextSetField)
2804 && (pAttr->Which() == RES_TXTATR_FIELD))
2805 {
2806 // #i104949# hideous hack for report builder:
2807 // it inserts hidden variable-set fields at
2808 // the beginning of para in cell, but they
2809 // should not turn cell into text cell
2810 const SwField* pField = pAttr->GetFormatField().GetField();
2811 if (pField &&
2812 (pField->GetTypeId() == SwFieldTypesEnum::Set) &&
2813 (0 != (static_cast<SwSetExpField const*>
2814 (pField)->GetSubType() &
2816 {
2817 nNextSetField = pAttr->GetStart() + 1;
2818 continue;
2819 }
2820 }
2821 else if( RES_TXTATR_ANNOTATION == pAttr->Which() ||
2822 RES_TXTATR_FTN == pAttr->Which() )
2823 {
2824 continue;
2825 }
2827 break;
2828 }
2829 }
2830 }
2831 }
2832 }
2833 else
2835 }
2836 return nPos;
2837}
2838
2839// is this a Formula box or one with numeric content (AutoSum)
2841{
2842 sal_uInt16 nWhich = 0;
2843 const SwTextNode* pTNd;
2844 SwFrameFormat* pFormat = GetFrameFormat();
2845 if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMULA, false ))
2846 nWhich = RES_BOXATR_FORMULA;
2847 else if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE, false ) &&
2848 !pFormat->GetDoc()->GetNumberFormatter()->IsTextFormat(
2849 pFormat->GetTableBoxNumFormat().GetValue() ))
2850 nWhich = RES_BOXATR_VALUE;
2852 && nullptr != ( pTNd = m_pStartNode->GetNodes()[ m_pStartNode->GetIndex() + 1 ]
2853 ->GetTextNode() ) && pTNd->GetText().isEmpty())
2854 nWhich = USHRT_MAX;
2855
2856 return nWhich;
2857}
2858
2860{
2861 SwFrameFormat* pFormat = GetFrameFormat();
2862 const SwTableBoxNumFormat *pFormatItem = pFormat->GetItemIfSet( RES_BOXATR_FORMAT, true );
2863 if (!pFormatItem)
2864 return;
2865 const SwTableBoxValue *pValItem = pFormat->GetItemIfSet( RES_BOXATR_VALUE );
2866 if (!pValItem)
2867 return;
2868
2869 const sal_uLong nFormatId = pFormatItem->GetValue();
2871 SvNumberFormatter* pNumFormatr = pFormat->GetDoc()->GetNumberFormatter();
2872
2873 if( !pNumFormatr->IsTextFormat( nFormatId ) &&
2874 NODE_OFFSET_MAX != (nNdPos = IsValidNumTextNd()) )
2875 {
2876 double fVal = pValItem->GetValue();
2877 const Color* pCol = nullptr;
2878 OUString sNewText;
2879 pNumFormatr->GetOutputString( fVal, nFormatId, sNewText, &pCol );
2880
2881 const OUString& rText = m_pStartNode->GetNodes()[ nNdPos ]->GetTextNode()->GetText();
2882 if( rText != sNewText )
2883 ChgTextToNum( *this, sNewText, pCol, false ,nNdPos);
2884 }
2885}
2886
2888{
2894
2895public:
2897 : m_pTable(nullptr), m_pCellFrame(nullptr), m_pTabFrame(nullptr)
2898 {
2899 }
2900
2901 void setTable(const SwTable * pTable)
2902 {
2903 m_pTable = pTable;
2904 SwFrameFormat * pFrameFormat = m_pTable->GetFrameFormat();
2906 if (m_pTabFrame && m_pTabFrame->IsFollow())
2908 }
2909
2910 const SwCellFrame * getCellFrame() const { return m_pCellFrame; }
2911
2912 const SwFrame * getNextFrameInTable(const SwFrame * pFrame);
2913 const SwCellFrame * getNextCellFrame(const SwFrame * pFrame);
2914 const SwCellFrame * getNextTableBoxsCellFrame(const SwFrame * pFrame);
2915 bool getNext();
2916};
2917
2919{
2920 const SwFrame * pResult = nullptr;
2921
2922 if (((! pFrame->IsTabFrame()) || pFrame == m_pTabFrame) && pFrame->GetLower())
2923 pResult = pFrame->GetLower();
2924 else if (pFrame->GetNext())
2925 pResult = pFrame->GetNext();
2926 else
2927 {
2928 while (pFrame->GetUpper() != nullptr)
2929 {
2930 pFrame = pFrame->GetUpper();
2931
2932 if (pFrame->IsTabFrame())
2933 {
2934 m_pTabFrame = static_cast<const SwTabFrame *>(pFrame)->GetFollow();
2935 pResult = m_pTabFrame;
2936 break;
2937 }
2938 else if (pFrame->GetNext())
2939 {
2940 pResult = pFrame->GetNext();
2941 break;
2942 }
2943 }
2944 }
2945
2946 return pResult;
2947}
2948
2950{
2951 const SwCellFrame * pResult = nullptr;
2952
2953 while ((pFrame = getNextFrameInTable(pFrame)) != nullptr)
2954 {
2955 if (pFrame->IsCellFrame())
2956 {
2957 pResult = static_cast<const SwCellFrame *>(pFrame);
2958 break;
2959 }
2960 }
2961
2962 return pResult;
2963}
2964
2966{
2967 const SwCellFrame * pResult = nullptr;
2968
2969 while ((pFrame = getNextCellFrame(pFrame)) != nullptr)
2970 {
2971 const SwCellFrame * pCellFrame = static_cast<const SwCellFrame *>(pFrame);
2972 const SwTableBox * pTabBox = pCellFrame->GetTabBox();
2973 auto aIt = m_HandledTableBoxes.insert(pTabBox);
2974 if (aIt.second)
2975 {
2976 pResult = pCellFrame;
2977 break;
2978 }
2979 }
2980
2981 return pResult;
2982}
2983
2985{
2986 return m_pImpl->getCellFrame();
2987}
2988
2990{
2991 if (m_pCellFrame == nullptr)
2992 {
2993 if (m_pTabFrame != nullptr)
2994 m_pCellFrame = Impl::getNextTableBoxsCellFrame(m_pTabFrame);
2995 }
2996 else
2997 m_pCellFrame = Impl::getNextTableBoxsCellFrame(m_pCellFrame);
2998
2999 return m_pCellFrame != nullptr;
3000}
3001
3003 : m_pImpl(std::make_unique<Impl>())
3004{
3005 m_pImpl->setTable(pTable);
3006}
3007
3009{
3010}
3011
3013{
3014 return m_pImpl->getNext();
3015}
3016
3018{
3019 SwRect aRet;
3020
3021 if (getCellFrame() != nullptr)
3022 aRet = getCellFrame()->getFrameArea();
3023
3024 return aRet;
3025}
3026
3028{
3029 const SwTableBox * pRet = nullptr;
3030
3031 if (getCellFrame() != nullptr)
3032 pRet = getCellFrame()->GetTabBox();
3033
3034 return pRet;
3035}
3036
3038{
3039 rFormat.Add( this );
3040}
3041
3043{
3044 const SwFrameFormat* pFrameFormat = GetFrameFormat();
3045 //a table in a clipboard document doesn't have any layout information
3046 return pFrameFormat && SwIterator<SwTabFrame,SwFormat>(*pFrameFormat).First();
3047}
3048
3050{
3051 rFormat.Add( this );
3052}
3053
3054// free's any remaining child objects
3056{
3057 for ( const_iterator it = begin(); it != end(); ++it )
3058 delete *it;
3059}
3060
3061/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr sal_uInt32 getSwDefaultTextFormat()
The number formatter's default locale's @ Text format.
Definition: cellatr.hxx:34
sal_uInt32 GetValue() const
virtual bool SetFieldsDirty(bool b, const SwNode *pChk, SwNodeOffset nLen)=0
virtual SwFieldType * GetFieldType(SwFieldIds nResId, const OUString &rName, bool bDbFieldMatching) const =0
virtual sfx2::LinkManager & GetLinkManager()=0
virtual bool IsIgnoreRedline() const =0
virtual bool DeleteRedline(const SwPaM &rPam, bool bSaveInUndo, RedlineType nDelType)=0
static bool IsRedlineOn(const RedlineFlags eM)
virtual const SwRedlineTable & GetRedlineTable() const =0
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
SfxHintId GetId() const
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
bool HasItem(sal_uInt16 nWhich, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
sal_uInt16 Which() const
void GetOutputString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &sOutString, const Color **ppColor, bool bUseStarFormat=false)
bool IsTextFormat(sal_uInt32 nFIndex) const
SvNumFormatType GetType(sal_uInt32 nFIndex) const
bool IsUserDefined(sal_uInt32 F_Index) const
SvxAdjust GetAdjust() const
void SetAdjust(const SvxAdjust eType)
const Color & GetValue() const
void SetRight(const tools::Long nR, const sal_uInt16 nProp=100)
void SetLeft(const tools::Long nL, const sal_uInt16 nProp=100)
sal_uInt16 CalcShadowSpace(SvxShadowItemSide nShadow) const
tools::Long GetWidth() const
void SetWidth(tools::Long n)
const SwAttrSet * GetChgSet() const
What has changed.
Definition: hints.hxx:343
const SwNodes * pNodes
Definition: hints.hxx:323
SwCellFrame is one table cell in the document layout.
Definition: cellfrm.hxx:31
const SwTableBox * GetTabBox() const
Definition: cellfrm.hxx:52
std::optional< sw::ModifyChangedHint > CheckRegistration(const SfxPoolItem *pOldValue)
Definition: calbck.cxx:77
Marks a character position inside a document model content node (SwContentNode)
sal_Int32 GetIndex() const
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:765
virtual sal_Int32 Len() const
Definition: node.cxx:1258
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:493
Definition: doc.hxx:195
bool IsNumberFormat(std::u16string_view aString, sal_uInt32 &F_Index, double &fOutNumber)
Definition: ndtbl.cxx:3990
SwTableBoxFormat * MakeTableBoxFormat()
Definition: docfmt.cxx:1718
bool IsInDtor() const
Definition: doc.hxx:415
SwTableLineFormat * MakeTableLineFormat()
Definition: docfmt.cxx:1726
IDocumentLinksAdministration const & getIDocumentLinksAdministration() const
Definition: doc.cxx:268
SwNodes & GetNodes()
Definition: doc.hxx:420
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:365
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:343
const SwTextFormatColl * GetDfltTextFormatColl() const
Definition: doc.hxx:787
void DelTableFrameFormat(SwTableFormat *pFormat)
Definition: docfmt.cxx:737
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1423
bool IsInsTableAlignNum() const
Definition: doc.cxx:1713
void GatherFields(std::vector< SwFormatField * > &rvFormatFields, bool bCollectOnlyInDocNodes=true) const
Definition: fldbas.cxx:203
Base class of all fields.
Definition: fldbas.hxx:295
SwFieldTypesEnum GetTypeId() const
Definition: fldbas.cxx:261
const std::shared_ptr< SfxItemSet > & GetStyleHandle() const
Definition: fmtautofmt.hxx:49
const SwField * GetField() const
Definition: fmtfld.hxx:131
void SetWidthPercent(sal_uInt8 n)
Definition: fmtfsize.hxx:95
Defines the horizontal position of a fly frame.
Definition: fmtornt.hxx:73
void SetHoriOrient(sal_Int16 eNew)
Definition: fmtornt.hxx:96
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:94
Defines the vertical position of a fly frame.
Definition: fmtornt.hxx:37
sal_Int16 GetVertOrient() const
Definition: fmtornt.hxx:57
Base class for various Writer styles.
Definition: format.hxx:47
const SwTableBoxNumFormat & GetTableBoxNumFormat(bool=true) const
TableBox attributes - implemented in cellatr.hxx.
Definition: cellatr.hxx:106
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:98
virtual bool ResetFormatAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: format.cxx:618
const SvxShadowItem & GetShadow(bool=true) const
Definition: frmatr.hxx:112
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
Definition: format.cxx:385
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:115
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:447
const T * GetItemIfSet(TypedWhichId< T > nWhich, bool bSrchInParent=true) const
Templatized version of GetItemState() to directly return the correct type.
Definition: format.hxx:111
const SwRect & getFrameArea() const
Definition: frame.hxx:179
Style of a layout element.
Definition: frmfmt.hxx:62
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: atrfrm.cxx:2620
Base class of the Writer layout elements.
Definition: frame.hxx:315
bool IsCellFrame() const
Definition: frame.hxx:1232
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1105
SwFrame * GetNext()
Definition: frame.hxx:682
bool IsTabFrame() const
Definition: frame.hxx:1224
SwFrame * GetLower()
Definition: findfrm.cxx:196
SwLayoutFrame * GetUpper()
Definition: frame.hxx:684
bool IsVertical() const
Definition: frame.hxx:979
TElementType * Next()
Definition: calbck.hxx:380
TElementType * First()
Definition: calbck.hxx:372
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
Base class of the Writer document model elements.
Definition: node.hxx:98
SwStartNode * GetStartNode()
Definition: node.hxx:642
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:903
SwNodeOffset GetIndex() const
Definition: node.hxx:312
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:744
bool IsTableNode() const
Definition: node.hxx:691
bool IsTextNode() const
Definition: node.hxx:687
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:380
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:728
SwContentNode * GetContentNode()
Definition: node.hxx:666
SwTableNode * GetTableNode()
Definition: node.hxx:650
bool InsBoxen(SwTableNode *, SwTableLine *, SwTableBoxFormat *, SwTextFormatColl *, const SfxItemSet *pAutoAttr, sal_uInt16 nInsPos, sal_uInt16 nCnt=1)
Insert a new box in the line before InsPos.
Definition: ndtbl.cxx:234
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1299
SwNodeOffset Count() const
Definition: ndarr.hxx:142
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
const SwPosition * End() const
Definition: pam.hxx:271
const SwPosition * Start() const
Definition: pam.hxx:266
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1940
const SwRedlineData & GetRedlineData(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1963
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void Height(tools::Long nNew)
Definition: swrect.hxx:193
void Width(tools::Long nNew)
Definition: swrect.hxx:189
const DateTime & GetTimeStamp() const
Definition: redline.hxx:130
bool empty() const
Definition: docary.hxx:266
static constexpr size_type npos
Definition: docary.hxx:223
size_type size() const
Definition: docary.hxx:267
vector_type::size_type size_type
Definition: docary.hxx:222
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:29
virtual sal_uInt16 GetSubType() const override
Definition: expfld.cxx:890
void SetSize(SwTableBox &rBox, const SwFormatFrameSize &rSz)
Definition: tblrwcl.cxx:3288
Starts a section of nodes in the document model.
Definition: node.hxx:348
const SwTabColsEntry & GetEntry(size_t nPos) const
Definition: tabcol.hxx:74
size_t Count() const
Definition: tabcol.hxx:65
void Remove(size_t nPos, size_t nCount=1)
Definition: tabcol.cxx:79
tools::Long GetLeft() const
Definition: tabcol.hxx:78
tools::Long GetRight() const
Definition: tabcol.hxx:79
tools::Long GetRightMax() const
Definition: tabcol.hxx:80
void SetHidden(size_t nPos, bool bValue)
Definition: tabcol.hxx:68
void Insert(tools::Long nValue, bool bValue, size_t nPos)
Definition: tabcol.cxx:69
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:49
SwTabFrame * FindMaster(bool bFirstMaster=false) const
Definition: flowfrm.cxx:773
bool IsInHeadline(const SwFrame &rFrame) const
Definition: tabfrm.cxx:5824
SwTableBox * GetTableBox()
void BoxAttributeChanged(SwTableBox &rBox, const SwTableBoxNumFormat *pNewFormat, const SwTableBoxFormula *pNewFormula, const SwTableBoxValue *pNewValue, const sal_uLong nOldFormat)
Definition: swtable.cxx:2457
virtual bool supportsFullDrawingLayerFillAttributeSet() const override
Definition: swtable.cxx:2678
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: swtable.cxx:2622
void TryBoxNmToPtr()
Definition: cellatr.cxx:97
double GetValue() const
Definition: cellatr.hxx:96
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:436
SwTableLine * GetUpper()
Definition: swtable.hxx:470
void RemoveFromTable()
Definition: swtable.cxx:1937
SwNodeOffset IsValidNumTextNd(bool bCheckAttr=true) const
Definition: swtable.cxx:2757
void SetSaveUserColor(std::optional< Color > p)
Definition: swtable.hxx:530
bool IsEmpty(bool bWithRemainingNestedTable=true) const
Definition: swtable.cxx:2143
sal_uInt16 IsFormulaOrValueBox() const
Definition: swtable.cxx:2840
bool IsNumberChanged() const
Definition: swtable.cxx:2728
sal_Int32 getRowSpan() const
Definition: swtable.hxx:533
void ActualiseValueBox()
Definition: swtable.cxx:2859
SwNodeOffset GetSttIdx() const
Definition: swtable.cxx:2138
const std::optional< Color > & GetSaveUserColor() const
Definition: swtable.hxx:528
void setRowSpan(sal_Int32 nNewRowSpan)
Definition: swtable.cxx:80
OUString GetName() const
Definition: swtable.cxx:2085
const SwStartNode * m_pStartNode
Definition: swtable.hxx:445
static SwTableBoxFormat * CheckBoxFormat(SwTableBoxFormat *)
Definition: swtable.cxx:1966
void SetSaveNumFormatColor(std::optional< Color > p)
Definition: swtable.hxx:531
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:474
SwTableLines & GetTabLines()
Definition: swtable.hxx:467
bool getDummyFlag() const
Definition: swtable.cxx:85
void setDummyFlag(bool bDummy)
Definition: swtable.cxx:90
bool HasNumContent(double &rNum, sal_uInt32 &rFormatIndex, bool &rIsEmptyTextNd) const
Definition: swtable.cxx:2693
Point GetCoordinates() const
Definition: swtable.cxx:2061
bool IsInHeadline(const SwTable *pTable) const
Definition: swtable.cxx:2122
virtual ~SwTableBox() override
Definition: swtable.cxx:1952
bool mbDummyFlag
Definition: swtable.hxx:451
const std::optional< Color > & GetSaveNumFormatColor() const
Definition: swtable.hxx:529
sal_Int32 mnRowSpan
Definition: swtable.hxx:450
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:488
void RegisterToFormat(SwFormat &rFormat)
Definition: swtable.cxx:3049
SwTableLines m_aLines
Definition: swtable.hxx:444
void ChgFrameFormat(SwTableBoxFormat *pNewFormat, bool bNeedToReregister=true)
Definition: swtable.cxx:2026
SwTableBox(const SwTableBox &)=delete
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1990
const SwCellFrame * getCellFrame() const
Definition: swtable.cxx:2984
std::unique_ptr< Impl > m_pImpl
Definition: swtable.hxx:553
SwTableCellInfo(SwTableCellInfo const &)=delete
SwRect getRect() const
Definition: swtable.cxx:3017
const SwTableBox * getTableBox() const
Definition: swtable.cxx:3027
virtual bool supportsFullDrawingLayerFillAttributeSet() const override
Definition: swtable.cxx:2683
TableFormulaUpdateFlags m_eFlags
Definition: hints.hxx:312
void ToRelBoxNm(const SwTable *pTable)
create from the external/internal formula the relative formula
Definition: cellfml.cxx:630
void BoxNmToPtr(const SwTable *pTable)
create from the external formula the internal
Definition: cellfml.cxx:605
void PtrToBoxNm(const SwTable *pTable)
create from the internal formula (for CORE) the external formula (for UI)
Definition: cellfml.cxx:580
virtual bool supportsFullDrawingLayerFillAttributeSet() const override
Definition: swtable.cxx:2688
SwTableLine is one table row in the document model.
Definition: swtable.hxx:374
SwTableBoxes m_aBoxes
Definition: swtable.hxx:375
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:396
SwTableLine(SwTableLineFormat *, sal_uInt16 nBoxes, SwTableBox *pUp)
Definition: swtable.cxx:1459
SwRedlineTable::size_type UpdateTextChangesOnly(SwRedlineTable::size_type &rRedlinePos, bool bUpdateProperty=true) const
Definition: swtable.cxx:1691
void ChgFrameFormat(SwTableLineFormat *pNewFormat)
Definition: swtable.cxx:1514
SwTwips GetTableLineHeight(bool &bLayoutAvailable) const
Definition: swtable.cxx:1524
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1481
void SetRedlineType(RedlineType eType)
Definition: swtable.hxx:431
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:384
RedlineType GetRedlineType() const
Definition: swtable.cxx:1855
bool IsDeleted(SwRedlineTable::size_type &rRedlinePos) const
Definition: swtable.cxx:1842
RedlineType m_eRedlineType
Definition: swtable.hxx:377
bool IsEmpty() const
Definition: swtable.cxx:1566
sal_uInt16 GetBoxPos(const SwTableBox *pBox) const
Definition: swtable.hxx:386
virtual ~SwTableLine() override
Definition: swtable.cxx:1468
SwTableBox * GetUpper()
Definition: swtable.hxx:392
std::vector< SwTableLine * >::const_iterator const_iterator
Definition: swtable.hxx:70
size_type size() const
Definition: swtable.hxx:76
SwTableLine * back() const
Definition: swtable.hxx:82
iterator end()
Definition: swtable.hxx:79
SwTableLine * front() const
Definition: swtable.hxx:81
void reserve(size_type nSize)
Definition: swtable.hxx:93
iterator begin()
Definition: swtable.hxx:77
sal_uInt16 GetPos(const SwTableLine *pBox) const
Definition: swtable.hxx:98
bool empty() const
Definition: swtable.hxx:75
const SwTable & GetTable() const
Definition: node.hxx:542
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
void SetTabCols(const SwTabCols &rNew, const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly)
Definition: swtable.cxx:822
bool IsEmpty() const
Definition: swtable.cxx:1576
virtual ~SwTable() override
Definition: swtable.cxx:218
SwTableNode * GetTableNode() const
Definition: swtable.cxx:2215
void SetHTMLTableLayout(std::shared_ptr< SwHTMLTableLayout > const &r)
Definition: swtable.cxx:2230
std::shared_ptr< SwHTMLTableLayout > m_xHTMLLayout
Definition: swtable.hxx:120
void LockModify()
Definition: swtable.hxx:189
SwTableSortBoxes m_TabSortContentBoxes
Definition: swtable.hxx:117
bool IsDeleted() const
Definition: swtable.cxx:1601
void AdjustWidths(const tools::Long nOld, const tools::Long nNew)
Definition: swtable.cxx:358
SwTableNode * m_pTableNode
Definition: swtable.hxx:126
SwTableLines & GetTabLines()
Definition: swtable.hxx:206
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:209
SwTableLines m_aLines
Definition: swtable.hxx:116
bool IsTableComplex() const
Definition: swtable.cxx:1444
void RegisterToFormat(SwFormat &rFormat)
Definition: swtable.cxx:3037
TableChgMode m_eTableChgMode
Definition: swtable.hxx:129
SwTable()
Definition: swtable.cxx:186
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1343
bool HasDeletedRow() const
Definition: swtable.cxx:1586
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: swtable.cxx:1671
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: swtable.cxx:324
virtual bool GetInfo(SfxPoolItem &) const override
Definition: swtable.cxx:2174
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:2208
static sal_uInt16 GetBoxNum(OUString &rStr, bool bFirst=false, const bool bPerformValidCheck=false)
Definition: swtable.cxx:1283
void UnlockModify()
Definition: swtable.hxx:190
SwTableSortBoxes & GetTabSortBoxes()
Definition: swtable.hxx:267
bool m_bModifyLocked
Definition: swtable.hxx:138
void GetTabCols(SwTabCols &rToFill, const SwTableBox *pStart, bool bHidden=false, bool bCurRowOnly=false) const
Definition: swtable.cxx:517
tools::SvRef< SwServerObject > m_xRefObj
Definition: swtable.hxx:118
bool IsNewModel() const
Definition: swtable.hxx:193
void NewSetTabCols(Parm &rP, const SwTabCols &rNew, const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly)
Definition: swtable.cxx:1164
void SetRefObject(SwServerObject *)
Definition: swtable.cxx:2222
bool HasLayout() const
Definition: swtable.cxx:3042
void UpdateFields(TableFormulaUpdateFlags eFlags)
Definition: swtable.cxx:1616
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
sal_uInt16 Which() const
Definition: txatbase.hxx:116
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:199
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:5091
void EraseText(const SwContentIndex &rIdx, const sal_Int32 nCount=SAL_MAX_INT32, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
delete text content ATTENTION: must not be called with a range that overlaps the start of an attribut...
Definition: ndtxt.cxx:2775
OUString InsertText(const OUString &rStr, const SwContentIndex &rIdx, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
insert text content
Definition: ndtxt.cxx:2370
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:252
const OUString & GetText() const
Definition: ndtxt.hxx:244
bool DontExpandFormat(sal_Int32 nContentIdx, bool bFlag=true, bool bFormatToTextAttributes=true)
When appropriate set DontExpand-flag at INet or character styles respectively.
Definition: ndtxt.cxx:1679
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0) override
Definition: ndtxt.cxx:5318
static ShellResource * GetShellRes()
Definition: viewsh.cxx:2656
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:68
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
size_t Count() const
Definition: ndhints.hxx:142
size_type erase(const Value &x)
bool empty() const
size_type size() const
std::pair< const_iterator, bool > insert(Value &&x)
void RemoveServer(SvLinkSource *rObj)
T * get() const
bool is() const
RedlineType
int nCount
struct _xmlTextWriter * xmlTextWriterPtr
float u
TableChgMode GetTableChgDefaultMode()
Definition: edtwin3.cxx:103
EmbeddedObjectRef * pObject
@ Variable
Frame is variable in Var-direction.
constexpr TypedWhichId< SwFormatFootnote > RES_TXTATR_FTN(59)
constexpr TypedWhichId< SwFindNearestNode > RES_FINDNEARESTNODE(184)
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(158)
constexpr TypedWhichId< SwFormatFrameSize > RES_FRM_SIZE(89)
constexpr TypedWhichId< SwFormatVertOrient > RES_VERT_ORIENT(108)
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(99)
constexpr TypedWhichId< SvxAdjustItem > RES_PARATR_ADJUST(64)
constexpr TypedWhichId< SwTableBoxFormula > RES_BOXATR_FORMULA(157)
constexpr TypedWhichId< SwAttrSetChg > RES_ATTRSET_CHG(169)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(60)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
constexpr TypedWhichId< SwFormatAutoFormat > RES_PARATR_LIST_AUTOFMT(87)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:176
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_CONTENT_VISIBLE(185)
constexpr TypedWhichId< SwAutoFormatGetDocNode > RES_AUTOFMT_DOCNODE(176)
constexpr TypedWhichId< SvxColorItem > RES_CHRATR_COLOR(3)
constexpr TypedWhichId< SvxPrintItem > RES_PRINT(104)
TableFormulaUpdateFlags
SwTableFormulaUpdate is sent when the table has to be newly calculated or when a table itself is merg...
Definition: hints.hxx:295
@ TBL_BOXPTR
Definition: hints.hxx:297
@ TBL_BOXNAME
Definition: hints.hxx:296
@ TBL_RELBOXNAME
Definition: hints.hxx:298
sal_Int32 nIndex
void * p
sal_Int64 n
sal_uInt16 nPos
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
tools::Long const nBorder
size
int i
const SwExtendedSubType SUB_INVISIBLE
Invisible.
Definition: fldbas.hxx:214
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
None
long Long
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
constexpr SwNodeOffset NODE_OFFSET_MAX(SAL_MAX_INT32)
SwNodeOffset abs(const SwNodeOffset &a)
Definition: nodeoffset.hxx:34
const char GetValue[]
QPRO_FUNC_TYPE nType
static SfxItemSet & rSet
sal_uIntPtr sal_uLong
SwShareBoxFormats aShareFormats
Definition: swtable.cxx:608
const SwTabCols & rNew
Definition: swtable.cxx:603
tools::Long nOldWish
Definition: swtable.cxx:606
std::deque< SwTableBox * > aBoxArr
Definition: swtable.cxx:607
const SwTabCols & rOld
Definition: swtable.cxx:604
Parm(const SwTabCols &rN, const SwTabCols &rO)
Definition: swtable.cxx:610
tools::Long nNewWish
Definition: swtable.cxx:605
OUString aCalc_Error
Definition: shellres.hxx:41
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
SwNodeIndex nNode
Definition: pam.hxx:38
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:77
sal_Int32 GetContentIndex() const
Definition: pam.hxx:84
tools::Long nPos
Definition: tabcol.hxx:30
tools::Long nMax
Definition: tabcol.hxx:32
tools::Long nMin
Definition: tabcol.hxx:31
const SwTable * m_pTable
Definition: swtable.cxx:2889
TableBoxes_t m_HandledTableBoxes
Definition: swtable.cxx:2893
const SwTabFrame * m_pTabFrame
Definition: swtable.cxx:2891
const SwCellFrame * m_pCellFrame
Definition: swtable.cxx:2890
const SwCellFrame * getNextCellFrame(const SwFrame *pFrame)
Definition: swtable.cxx:2949
void setTable(const SwTable *pTable)
Definition: swtable.cxx:2901
const SwCellFrame * getNextTableBoxsCellFrame(const SwFrame *pFrame)
Definition: swtable.cxx:2965
const SwCellFrame * getCellFrame() const
Definition: swtable.cxx:2910
o3tl::sorted_vector< const SwTableBox * > TableBoxes_t
Definition: swtable.cxx:2892
const SwFrame * getNextFrameInTable(const SwFrame *pFrame)
Definition: swtable.cxx:2918
sal_uInt16 GetWhich() const
Definition: calbck.hxx:75
SvxAdjust
std::list< ColChange > ChangeList
Definition: swtable.cxx:990
#define COLFUZZY
Definition: swtable.cxx:75
static void lcl_AdjustWidthsInLine(SwTableLine *pLine, ChangeList &rOldNew, Parm &rParm, sal_uInt16 nColFuzzy)
Definition: swtable.cxx:992
static void lcl_ProcessBoxPtr(SwTableBox *pBox, std::deque< SwTableBox * > &rBoxArr, bool bBefore)
Definition: swtable.cxx:779
std::pair< sal_uInt16, sal_uInt16 > ColChange
Definition: swtable.cxx:989
static void lcl_ProcessLine(SwTableLine *pLine, Parm &rParm)
Definition: swtable.cxx:617
static OUString & lcl_TabToBlankAtSttEnd(OUString &rText)
Definition: swtable.cxx:96
static void lcl_ProcessLineGet(const SwTableLine *pLine, SwTabCols &rToFill, const SwFrameFormat *pTabFormat)
Definition: swtable.cxx:503
static void ChgNumToText(SwTableBox &rBox, sal_uLong nFormat)
Definition: swtable.cxx:2369
static void lcl_ProcessBoxSet(SwTableBox *pBox, Parm &rParm)
Definition: swtable.cxx:627
static void lcl_ModifyLines(SwTableLines &rLines, const tools::Long nOld, const tools::Long nNew, std::vector< SwFormat * > &rFormatArr, const bool bCheckSum)
Definition: swtable.cxx:266
static void lcl_ModifyBoxes(SwTableBoxes &rBoxes, const tools::Long nOld, const tools::Long nNew, std::vector< SwFormat * > &rFormatArr)
Definition: swtable.cxx:284
static void lcl_ProcessBoxGet(const SwTableBox *pBox, SwTabCols &rToFill, const SwFrameFormat *pTabFormat, bool bRefreshHidden)
Definition: swtable.cxx:486
static void lcl_AdjustBox(SwTableBox *pBox, const tools::Long nDiff, Parm &rParm)
Definition: swtable.cxx:810
static void lcl_AdjustLines(SwTableLines &rLines, const tools::Long nDiff, Parm &rParm)
Definition: swtable.cxx:800
static void FormatInArr(std::vector< SwFormat * > &rFormatArr, SwFormat *pBoxFormat)
Definition: swtable.cxx:256
#define CHECK_TABLE(t)
Definition: swtable.cxx:67
static void lcl_CalcNewWidths(std::vector< sal_uInt16 > &rSpanPos, ChangeList &rChanges, SwTableLine *pLine, tools::Long nWish, tools::Long nWidth, bool bTop)
Definition: swtable.cxx:1041
static bool lcl_IsValidRowName(std::u16string_view rStr)
Definition: swtable.cxx:1268
static void ChgTextToNum(SwTableBox &rBox, const OUString &rText, const Color *pCol, bool bChgAlign, SwNodeOffset nNdPos)
Definition: swtable.cxx:2241
static void lcl_RefreshHidden(SwTabCols &rToFill, size_t nPos)
Definition: swtable.cxx:365
void DelBoxNode(SwTableSortBoxes const &rSortCntBoxes)
Definition: swtable.cxx:210
static void lcl_SortedTabColInsert(SwTabCols &rToFill, const SwTableBox *pBox, const SwFrameFormat *pTabFormat, const bool bHidden, const bool bRefreshHidden)
Definition: swtable.cxx:377
static OUString & lcl_DelTabsAtSttEnd(OUString &rText)
Definition: swtable.cxx:110
void sw_GetTableBoxColStr(sal_uInt16 nCol, OUString &rNm)
Definition: swtable.cxx:2042
void InsTableBox(SwDoc &rDoc, SwTableNode *pTableNd, SwTableLine *pLine, SwTableBoxFormat *pBoxFrameFormat, SwTableBox *pBox, sal_uInt16 nInsPos, sal_uInt16 nCnt)
Definition: swtable.cxx:130
std::vector< SwTableBox * > SwTableBoxes
Definition: swtable.hxx:105
tools::Long SwTwips
Definition: swtypes.hxx:51
sal_Int32 mnRowSpan
void CheckBoxWidth(const SwTableLine &rLine, SwTwips nSize)
Definition: tblrwcl.cxx:2576
#define SAL_MAX_UINT16
#define SAL_MAX_INT32
sal_uInt16 sal_Unicode