LCOV - code coverage report
Current view: top level - sw/source/core/table - swtable.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 910 1435 63.4 %
Date: 2015-06-13 12:38:46 Functions: 111 144 77.1 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <ctype.h>
      21             : #include <float.h>
      22             : #include <hintids.hxx>
      23             : #include <hints.hxx>
      24             : #include <editeng/lrspitem.hxx>
      25             : #include <editeng/shaditem.hxx>
      26             : #include <editeng/adjustitem.hxx>
      27             : #include <editeng/colritem.hxx>
      28             : #include <sfx2/linkmgr.hxx>
      29             : #include <editeng/boxitem.hxx>
      30             : #include <o3tl/make_unique.hxx>
      31             : #include <fmtfsize.hxx>
      32             : #include <fmtornt.hxx>
      33             : #include <fmtpdsc.hxx>
      34             : #include <fldbas.hxx>
      35             : #include <fmtfld.hxx>
      36             : #include <frmatr.hxx>
      37             : #include <doc.hxx>
      38             : #include <IDocumentLinksAdministration.hxx>
      39             : #include <IDocumentRedlineAccess.hxx>
      40             : #include <IDocumentFieldsAccess.hxx>
      41             : #include <docary.hxx>
      42             : #include <frame.hxx>
      43             : #include <swtable.hxx>
      44             : #include <ndtxt.hxx>
      45             : #include <tabcol.hxx>
      46             : #include <tabfrm.hxx>
      47             : #include <cellfrm.hxx>
      48             : #include <rowfrm.hxx>
      49             : #include <swserv.hxx>
      50             : #include <expfld.hxx>
      51             : #include <mdiexp.hxx>
      52             : #include <cellatr.hxx>
      53             : #include <txatbase.hxx>
      54             : #include <htmltbl.hxx>
      55             : #include <swtblfmt.hxx>
      56             : #include <ndindex.hxx>
      57             : #include <tblrwcl.hxx>
      58             : #include <shellres.hxx>
      59             : #include <viewsh.hxx>
      60             : #include <redline.hxx>
      61             : #include <list>
      62             : #include <calbck.hxx>
      63             : 
      64             : #ifdef DBG_UTIL
      65             : #define CHECK_TABLE(t) (t).CheckConsistency();
      66             : #else
      67             : #define CHECK_TABLE(t)
      68             : #endif
      69             : 
      70             : using namespace com::sun::star;
      71             : 
      72      619091 : TYPEINIT1( SwTable, SwClient );
      73     1975428 : TYPEINIT1( SwTableBox, SwClient );
      74      395835 : TYPEINIT1( SwTableLine, SwClient );
      75       25122 : TYPEINIT1( SwTableFormat, SwFrameFormat );
      76        5708 : TYPEINIT1( SwTableBoxFormat, SwFrameFormat );
      77        5678 : TYPEINIT1( SwTableLineFormat, SwFrameFormat );
      78             : 
      79             : #define COLFUZZY 20
      80             : 
      81             : void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
      82             :                     bool bChgAlign, sal_uLong nNdPos );
      83             : 
      84             : class SwTableBox_Impl
      85             : {
      86             :     Color *mpUserColor, *mpNumFormatColor;
      87             :     long mnRowSpan;
      88             :     bool mbDummyFlag;
      89             : 
      90             :     static void SetNewCol( Color** ppCol, const Color* pNewCol );
      91             : public:
      92         231 :     SwTableBox_Impl() : mpUserColor(0), mpNumFormatColor(0), mnRowSpan(1),
      93         231 :         mbDummyFlag( false ) {}
      94         231 :     ~SwTableBox_Impl() { delete mpUserColor; delete mpNumFormatColor; }
      95             : 
      96           0 :     const Color* GetSaveUserColor() const       { return mpUserColor; }
      97          23 :     const Color* GetSaveNumFormatColor() const     { return mpNumFormatColor; }
      98          46 :     void SetSaveUserColor(const Color* p )      { SetNewCol( &mpUserColor, p ); }
      99          46 :     void SetSaveNumFormatColor( const Color* p )   { SetNewCol( &mpNumFormatColor, p ); }
     100        6474 :     long getRowSpan() const { return mnRowSpan; }
     101         209 :     void setRowSpan( long nNewRowSpan ) { mnRowSpan = nNewRowSpan; }
     102           0 :     bool getDummyFlag() const { return mbDummyFlag; }
     103           0 :     void setDummyFlag( bool bDummy ) { mbDummyFlag = bDummy; }
     104             : };
     105             : 
     106           0 : inline const Color* SwTableBox::GetSaveUserColor() const
     107             : {
     108           0 :     return pImpl ? pImpl->GetSaveUserColor() : 0;
     109             : }
     110             : 
     111         110 : inline const Color* SwTableBox::GetSaveNumFormatColor() const
     112             : {
     113         110 :     return pImpl ? pImpl->GetSaveNumFormatColor() : 0;
     114             : }
     115             : 
     116          46 : inline void SwTableBox::SetSaveUserColor(const Color* p )
     117             : {
     118          46 :     if( pImpl )
     119          20 :         pImpl->SetSaveUserColor( p );
     120          26 :     else if( p )
     121          26 :         ( pImpl = new SwTableBox_Impl ) ->SetSaveUserColor( p );
     122          46 : }
     123             : 
     124         101 : inline void SwTableBox::SetSaveNumFormatColor( const Color* p )
     125             : {
     126         101 :     if( pImpl )
     127          46 :         pImpl->SetSaveNumFormatColor( p );
     128          55 :     else if( p )
     129           0 :         ( pImpl = new SwTableBox_Impl )->SetSaveNumFormatColor( p );
     130         101 : }
     131             : 
     132      594325 : long SwTableBox::getRowSpan() const
     133             : {
     134      594325 :     return pImpl ? pImpl->getRowSpan() : 1;
     135             : }
     136             : 
     137        1155 : void SwTableBox::setRowSpan( long nNewRowSpan )
     138             : {
     139        1155 :     if( !pImpl )
     140             :     {
     141        1151 :         if( nNewRowSpan == 1 )
     142        2101 :             return;
     143         205 :         pImpl = new SwTableBox_Impl();
     144             :     }
     145         209 :     pImpl->setRowSpan( nNewRowSpan );
     146             : }
     147             : 
     148           0 : bool SwTableBox::getDummyFlag() const
     149             : {
     150           0 :     return pImpl && pImpl->getDummyFlag();
     151             : }
     152             : 
     153           0 : void SwTableBox::setDummyFlag( bool bDummy )
     154             : {
     155           0 :     if( !pImpl )
     156             :     {
     157           0 :         if( !bDummy )
     158           0 :             return;
     159           0 :         pImpl = new SwTableBox_Impl();
     160             :     }
     161           0 :     pImpl->setDummyFlag( bDummy );
     162             : }
     163             : 
     164             : //JP 15.09.98: Bug 55741 - Keep tabs (front and rear)
     165           0 : static OUString& lcl_TabToBlankAtSttEnd( OUString& rText )
     166             : {
     167             :     sal_Unicode c;
     168             :     sal_Int32 n;
     169             : 
     170           0 :     for( n = 0; n < rText.getLength() && ' ' >= ( c = rText[n] ); ++n )
     171           0 :         if( '\x9' == c )
     172           0 :             rText = rText.replaceAt( n, 1, " " );
     173           0 :     for( n = rText.getLength(); n && ' ' >= ( c = rText[--n] ); )
     174           0 :         if( '\x9' == c )
     175           0 :             rText = rText.replaceAt( n, 1, " " );
     176           0 :     return rText;
     177             : }
     178             : 
     179           0 : static OUString& lcl_DelTabsAtSttEnd( OUString& rText )
     180             : {
     181             :     sal_Unicode c;
     182             :     sal_Int32 n;
     183           0 :     OUStringBuffer sBuff(rText);
     184             : 
     185           0 :     for( n = 0; n < sBuff.getLength() && ' ' >= ( c = sBuff[ n ]); ++n )
     186             :     {
     187           0 :         if( '\x9' == c )
     188           0 :             sBuff.remove( n--, 1 );
     189             :     }
     190           0 :     for( n = sBuff.getLength(); n && ' ' >= ( c = sBuff[ --n ]); )
     191             :     {
     192           0 :         if( '\x9' == c )
     193           0 :             sBuff.remove( n, 1 );
     194             :     }
     195           0 :     rText = sBuff.makeStringAndClear();
     196           0 :     return rText;
     197             : }
     198             : 
     199           9 : void _InsTableBox( SwDoc* pDoc, SwTableNode* pTableNd,
     200             :                         SwTableLine* pLine, SwTableBoxFormat* pBoxFrameFormat,
     201             :                         SwTableBox* pBox,
     202             :                         sal_uInt16 nInsPos, sal_uInt16 nCnt )
     203             : {
     204             :     OSL_ENSURE( pBox->GetSttNd(), "Box with no start node" );
     205           9 :     SwNodeIndex aIdx( *pBox->GetSttNd(), +1 );
     206           9 :     SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
     207           9 :     if( !pCNd )
     208           0 :         pCNd = pDoc->GetNodes().GoNext( &aIdx );
     209             :     OSL_ENSURE( pCNd, "Box with no content node" );
     210             : 
     211           9 :     if( pCNd->IsTextNode() )
     212             :     {
     213           9 :         if( pBox->GetSaveNumFormatColor() && pCNd->GetpSwAttrSet() )
     214             :         {
     215           0 :             SwAttrSet aAttrSet( *pCNd->GetpSwAttrSet() );
     216           0 :             if( pBox->GetSaveUserColor() )
     217           0 :                 aAttrSet.Put( SvxColorItem( *pBox->GetSaveUserColor(), RES_CHRATR_COLOR ));
     218             :             else
     219           0 :                 aAttrSet.ClearItem( RES_CHRATR_COLOR );
     220           0 :             pDoc->GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
     221             :                                     static_cast<SwTextNode*>(pCNd)->GetTextColl(),
     222           0 :                                     &aAttrSet, nInsPos, nCnt );
     223             :         }
     224             :         else
     225           9 :             pDoc->GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
     226             :                                     static_cast<SwTextNode*>(pCNd)->GetTextColl(),
     227           9 :                                     pCNd->GetpSwAttrSet(),
     228          27 :                                     nInsPos, nCnt );
     229             :     }
     230             :     else
     231           0 :         pDoc->GetNodes().InsBoxen( pTableNd, pLine, pBoxFrameFormat,
     232             :                 pDoc->GetDfltTextFormatColl(), 0,
     233           0 :                 nInsPos, nCnt );
     234             : 
     235           9 :     long nRowSpan = pBox->getRowSpan();
     236           9 :     if( nRowSpan != 1 )
     237             :     {
     238           0 :         SwTableBoxes& rTableBoxes = pLine->GetTabBoxes();
     239           0 :         for( sal_uInt16 i = 0; i < nCnt; ++i )
     240             :         {
     241           0 :             pBox = rTableBoxes[ i + nInsPos ];
     242           0 :             pBox->setRowSpan( nRowSpan );
     243             :         }
     244           9 :     }
     245           9 : }
     246             : 
     247        1098 : SwTable::SwTable( SwTableFormat* pFormat )
     248             :     : SwClient( pFormat ),
     249             :     pHTMLLayout( 0 ),
     250             :     pTableNode( 0 ),
     251             :     nGrfsThatResize( 0 ),
     252             :     nRowsToRepeat( 1 ),
     253             :     bModifyLocked( false ),
     254        1098 :     bNewModel( true )
     255             : {
     256             :     // default value set in the options
     257        1098 :     eTableChgMode = (TableChgMode)GetTableChgDefaultMode();
     258        1098 : }
     259             : 
     260           0 : SwTable::SwTable( const SwTable& rTable )
     261           0 :     : SwClient( rTable.GetFrameFormat() ),
     262             :     pHTMLLayout( 0 ),
     263             :     pTableNode( 0 ),
     264             :     eTableChgMode( rTable.eTableChgMode ),
     265             :     nGrfsThatResize( 0 ),
     266           0 :     nRowsToRepeat( rTable.GetRowsToRepeat() ),
     267             :     bModifyLocked( false ),
     268           0 :     bNewModel( rTable.bNewModel )
     269             : {
     270           0 : }
     271             : 
     272        1097 : void DelBoxNode( SwTableSortBoxes& rSortCntBoxes )
     273             : {
     274       12930 :     for (size_t n = 0; n < rSortCntBoxes.size(); ++n)
     275             :     {
     276       11833 :         rSortCntBoxes[ n ]->pSttNd = 0;
     277             :     }
     278        1097 : }
     279             : 
     280        3291 : SwTable::~SwTable()
     281             : {
     282        1097 :     if( refObj.Is() )
     283             :     {
     284           0 :         SwDoc* pDoc = GetFrameFormat()->GetDoc();
     285           0 :         if( !pDoc->IsInDtor() )         // then remove from the list
     286           0 :             pDoc->getIDocumentLinksAdministration().GetLinkManager().RemoveServer( &refObj );
     287             : 
     288           0 :         refObj->Closed();
     289             :     }
     290             : 
     291             :     // the table can be deleted if it's the last client of the FrameFormat
     292        1097 :     SwTableFormat* pFormat = static_cast<SwTableFormat*>(GetFrameFormat());
     293        1097 :     pFormat->Remove( this );               // remove
     294             : 
     295        1097 :     if( !pFormat->HasWriterListeners() )
     296        1097 :         pFormat->GetDoc()->DelTableFrameFormat( pFormat );   // and delete
     297             : 
     298             :     // Delete the pointers from the SortArray of the boxes. The objects
     299             :     // are preserved and are deleted by the lines/boxes arrays dtor.
     300             :     // Note: unfortunately not enough, pointers to the StartNode of the
     301             :     // section need deletion.
     302        1097 :     DelBoxNode(m_TabSortContentBoxes);
     303        1097 :     m_TabSortContentBoxes.clear();
     304        1097 :     delete pHTMLLayout;
     305        2194 : }
     306             : 
     307             : namespace
     308             : {
     309             : 
     310             : template<class T>
     311       77054 : inline T lcl_MulDiv64(sal_uInt64 nA, sal_uInt64 nM, sal_uInt64 nD)
     312             : {
     313       77054 :     return static_cast<T>((nA*nM)/nD);
     314             : }
     315             : 
     316             : }
     317             : 
     318        5600 : static void FormatInArr( std::vector<SwFormat*>& rFormatArr, SwFormat* pBoxFormat )
     319             : {
     320        5600 :     std::vector<SwFormat*>::const_iterator it = std::find( rFormatArr.begin(), rFormatArr.end(), pBoxFormat );
     321        5600 :     if ( it == rFormatArr.end() )
     322        4884 :         rFormatArr.push_back( pBoxFormat );
     323        5600 : }
     324             : 
     325             : static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
     326             :                          const long nNew, std::vector<SwFormat*>& rFormatArr );
     327             : 
     328         763 : static void lcl_ModifyLines( SwTableLines &rLines, const long nOld,
     329             :                          const long nNew, std::vector<SwFormat*>& rFormatArr, const bool bCheckSum )
     330             : {
     331        4091 :     for ( size_t i = 0; i < rLines.size(); ++i )
     332        3328 :         ::lcl_ModifyBoxes( rLines[i]->GetTabBoxes(), nOld, nNew, rFormatArr );
     333         763 :     if( bCheckSum )
     334             :     {
     335        5647 :         for( size_t i = 0; i < rFormatArr.size(); ++i )
     336             :         {
     337        4884 :             SwFormat* pFormat = rFormatArr[i];
     338        4884 :             const SwTwips nBox = lcl_MulDiv64<SwTwips>(pFormat->GetFrmSize().GetWidth(), nNew, nOld);
     339        4884 :             SwFormatFrmSize aNewBox( ATT_VAR_SIZE, nBox, 0 );
     340        4884 :             pFormat->LockModify();
     341        4884 :             pFormat->SetFormatAttr( aNewBox );
     342        4884 :             pFormat->UnlockModify();
     343        4884 :         }
     344             :     }
     345         763 : }
     346             : 
     347        3328 : static void lcl_ModifyBoxes( SwTableBoxes &rBoxes, const long nOld,
     348             :                          const long nNew, std::vector<SwFormat*>& rFormatArr )
     349             : {
     350        3328 :     sal_uInt64 nSum = 0; // To avoid rounding errors we summarize all box widths
     351        3328 :     sal_uInt64 nOriginalSum = 0; // Sum of original widths
     352       12395 :     for ( size_t i = 0; i < rBoxes.size(); ++i )
     353             :     {
     354        9067 :         SwTableBox &rBox = *rBoxes[i];
     355        9067 :         if ( !rBox.GetTabLines().empty() )
     356             :         {
     357             :             // For SubTables the rounding problem will not be solved :-(
     358           0 :             ::lcl_ModifyLines( rBox.GetTabLines(), nOld, nNew, rFormatArr, false );
     359             :         }
     360             :         // Adjust the box
     361        9067 :         SwFrameFormat *pFormat = rBox.GetFrameFormat();
     362        9067 :         sal_uInt64 nBox = pFormat->GetFrmSize().GetWidth();
     363        9067 :         nOriginalSum += nBox;
     364        9067 :         nBox *= nNew;
     365        9067 :         nBox /= nOld;
     366        9067 :         const sal_uInt64 nWishedSum = lcl_MulDiv64<sal_uInt64>(nOriginalSum, nNew, nOld) - nSum;
     367        9067 :         if( nWishedSum > 0 )
     368             :         {
     369        9067 :             if( nBox == nWishedSum )
     370        5600 :                 FormatInArr( rFormatArr, pFormat );
     371             :             else
     372             :             {
     373        3467 :                 nBox = nWishedSum;
     374        3467 :                 pFormat = rBox.ClaimFrameFormat();
     375        3467 :                 SwFormatFrmSize aNewBox( ATT_VAR_SIZE, static_cast< SwTwips >(nBox), 0 );
     376        3467 :                 pFormat->LockModify();
     377        3467 :                 pFormat->SetFormatAttr( aNewBox );
     378        3467 :                 pFormat->UnlockModify();
     379             :             }
     380             :         }
     381             :         else {
     382             :             OSL_FAIL( "Rounding error" );
     383             :         }
     384        9067 :         nSum += nBox;
     385             :     }
     386        3328 : }
     387             : 
     388        6309 : void SwTable::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
     389             : {
     390             :     // catch SSize changes, to adjust the lines/boxes
     391        6309 :     const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
     392        6309 :     const SwFormatFrmSize* pNewSize = 0, *pOldSize = 0;
     393             : 
     394        6309 :     if( RES_ATTRSET_CHG == nWhich )
     395             :     {
     396        8058 :         if (pOld && pNew && SfxItemState::SET == static_cast<const SwAttrSetChg*>(pNew)->GetChgSet()->GetItemState(
     397        4029 :             RES_FRM_SIZE, false, reinterpret_cast<const SfxPoolItem**>(&pNewSize)))
     398             :         {
     399         766 :             pOldSize = &static_cast<const SwAttrSetChg*>(pOld)->GetChgSet()->GetFrmSize();
     400             :         }
     401             :     }
     402        2280 :     else if( RES_FRM_SIZE == nWhich )
     403             :     {
     404           0 :         pOldSize = static_cast<const SwFormatFrmSize*>(pOld);
     405           0 :         pNewSize = static_cast<const SwFormatFrmSize*>(pNew);
     406             :     }
     407             :     else
     408        2280 :         CheckRegistration( pOld, pNew );
     409             : 
     410        6309 :     if (pOldSize && pNewSize && !IsModifyLocked())
     411         763 :         AdjustWidths( pOldSize->GetWidth(), pNewSize->GetWidth() );
     412        6309 : }
     413             : 
     414         763 : void SwTable::AdjustWidths( const long nOld, const long nNew )
     415             : {
     416         763 :     std::vector<SwFormat*> aFormatArr;
     417         763 :     aFormatArr.reserve( aLines[0]->GetTabBoxes().size() );
     418         763 :     ::lcl_ModifyLines( aLines, nOld, nNew, aFormatArr, true );
     419         763 : }
     420             : 
     421           0 : static void lcl_RefreshHidden( SwTabCols &rToFill, size_t nPos )
     422             : {
     423           0 :     for ( size_t i = 0; i < rToFill.Count(); ++i )
     424             :     {
     425           0 :         if ( std::abs(static_cast<long>(nPos) - rToFill[i]) <= COLFUZZY )
     426             :         {
     427           0 :             rToFill.SetHidden( i, false );
     428           0 :             break;
     429             :         }
     430             :     }
     431           0 : }
     432             : 
     433        8275 : static void lcl_SortedTabColInsert( SwTabCols &rToFill, const SwTableBox *pBox,
     434             :                    const SwFrameFormat *pTabFormat, const bool bHidden,
     435             :                    const bool bRefreshHidden )
     436             : {
     437        8275 :     const long nWish = pTabFormat->GetFrmSize().GetWidth();
     438             :     OSL_ENSURE(nWish, "weird <= 0 width frmfrm");
     439             : 
     440             :     // The value for the left edge of the box is calculated from the
     441             :     // widths of the previous boxes.
     442        8275 :     long nPos = 0;
     443        8275 :     long nLeftMin = 0;
     444        8275 :     long nRightMax = 0;
     445        8275 :     if (nWish != 0) //fdo#33012 0 width frmfmt
     446             :     {
     447        8275 :         SwTwips nSum = 0;
     448        8275 :         const SwTableBox  *pCur  = pBox;
     449        8275 :         const SwTableLine *pLine = pBox->GetUpper();
     450        8275 :         const long nAct  = rToFill.GetRight() - rToFill.GetLeft();  // +1 why?
     451             : 
     452       24825 :         while ( pLine )
     453             :         {
     454        8275 :             const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
     455       22039 :             for ( size_t i = 0; i < rBoxes.size(); ++i )
     456             :             {
     457       22039 :                 const SwTwips nWidth = rBoxes[i]->GetFrameFormat()->GetFrmSize().GetWidth();
     458       22039 :                 nSum += nWidth;
     459       22039 :                 const long nTmp = lcl_MulDiv64<long>(nSum, nAct, nWish);
     460             : 
     461       22039 :                 if (rBoxes[i] != pCur)
     462             :                 {
     463       13764 :                     if ( pLine == pBox->GetUpper() || 0 == nLeftMin )
     464       13764 :                         nLeftMin = nTmp - nPos;
     465       13764 :                     nPos = nTmp;
     466             :                 }
     467             :                 else
     468             :                 {
     469        8275 :                     nSum -= nWidth;
     470        8275 :                     if ( 0 == nRightMax )
     471        8275 :                         nRightMax = nTmp - nPos;
     472        8275 :                     break;
     473             :                 }
     474             :             }
     475        8275 :             pCur  = pLine->GetUpper();
     476        8275 :             pLine = pCur ? pCur->GetUpper() : 0;
     477             :         }
     478             :     }
     479             : 
     480        8275 :     bool bInsert = !bRefreshHidden;
     481       22061 :     for ( size_t j = 0; bInsert && (j < rToFill.Count()); ++j )
     482             :     {
     483       13786 :         long nCmp = rToFill[j];
     484       27572 :         if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
     485       13786 :              (nPos <= (nCmp + COLFUZZY)) )
     486             :         {
     487          44 :             bInsert = false;        // Already has it.
     488             :         }
     489       13742 :         else if ( nPos < nCmp )
     490             :         {
     491           0 :             bInsert = false;
     492           0 :             rToFill.Insert( nPos, bHidden, j );
     493             :         }
     494             :     }
     495        8275 :     if ( bInsert )
     496        8231 :         rToFill.Insert( nPos, bHidden, rToFill.Count() );
     497          44 :     else if ( bRefreshHidden )
     498           0 :         ::lcl_RefreshHidden( rToFill, nPos );
     499             : 
     500        8275 :     if ( bHidden && !bRefreshHidden )
     501             :     {
     502             :         // calculate minimum/maximum values for the existing entries:
     503          40 :         nLeftMin = nPos - nLeftMin;
     504          40 :         nRightMax = nPos + nRightMax;
     505             : 
     506             :         // check if nPos is entry:
     507          40 :         bool bFoundPos = false;
     508          40 :         bool bFoundMax = false;
     509         120 :         for ( size_t j = 0; !(bFoundPos && bFoundMax ) && j < rToFill.Count(); ++j )
     510             :         {
     511          80 :             SwTabColsEntry& rEntry = rToFill.GetEntry( j );
     512          80 :             long nCmp = rToFill[j];
     513             : 
     514         140 :             if ( (nPos >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
     515          60 :                  (nPos <= (nCmp + COLFUZZY)) )
     516             :             {
     517             :                 // check if nLeftMin is > old minimum for entry nPos:
     518          40 :                 const long nOldMin = rEntry.nMin;
     519          40 :                 if ( nLeftMin > nOldMin )
     520           0 :                     rEntry.nMin = nLeftMin;
     521             :                 // check if nRightMin is < old maximum for entry nPos:
     522          40 :                 const long nOldMax = rEntry.nMax;
     523          40 :                 if ( nRightMax < nOldMax )
     524           8 :                     rEntry.nMax = nRightMax;
     525             : 
     526          40 :                 bFoundPos = true;
     527             :             }
     528          80 :             else if ( (nRightMax >= ((nCmp >= COLFUZZY) ? nCmp - COLFUZZY : nCmp)) &&
     529          40 :                       (nRightMax <= (nCmp + COLFUZZY)) )
     530             :             {
     531             :                 // check if nPos is > old minimum for entry nRightMax:
     532          20 :                 const long nOldMin = rEntry.nMin;
     533          20 :                 if ( nPos > nOldMin )
     534           0 :                     rEntry.nMin = nPos;
     535             : 
     536          20 :                 bFoundMax = true;
     537             :             }
     538             :         }
     539             :     }
     540        8275 : }
     541             : 
     542        8235 : static void lcl_ProcessBoxGet( const SwTableBox *pBox, SwTabCols &rToFill,
     543             :                         const SwFrameFormat *pTabFormat, bool bRefreshHidden )
     544             : {
     545        8235 :     if ( !pBox->GetTabLines().empty() )
     546             :     {
     547           0 :         const SwTableLines &rLines = pBox->GetTabLines();
     548           0 :         for ( size_t i = 0; i < rLines.size(); ++i )
     549             :         {
     550           0 :             const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
     551           0 :             for ( size_t j = 0; j < rBoxes.size(); ++j )
     552           0 :                 ::lcl_ProcessBoxGet( rBoxes[j], rToFill, pTabFormat, bRefreshHidden);
     553             :         }
     554             :     }
     555             :     else
     556        8235 :         ::lcl_SortedTabColInsert( rToFill, pBox, pTabFormat, false, bRefreshHidden );
     557        8235 : }
     558             : 
     559          20 : static void lcl_ProcessLineGet( const SwTableLine *pLine, SwTabCols &rToFill,
     560             :                          const SwFrameFormat *pTabFormat )
     561             : {
     562          60 :     for ( size_t i = 0; i < pLine->GetTabBoxes().size(); ++i )
     563             :     {
     564          40 :         const SwTableBox *pBox = pLine->GetTabBoxes()[i];
     565          40 :         if ( pBox->GetSttNd() )
     566          40 :             ::lcl_SortedTabColInsert( rToFill, pBox, pTabFormat, true, false );
     567             :         else
     568           0 :             for ( size_t j = 0; j < pBox->GetTabLines().size(); ++j )
     569           0 :                 ::lcl_ProcessLineGet( pBox->GetTabLines()[j], rToFill, pTabFormat );
     570             :     }
     571          20 : }
     572             : 
     573        2919 : void SwTable::GetTabCols( SwTabCols &rToFill, const SwTableBox *pStart,
     574             :               bool bRefreshHidden, bool bCurRowOnly ) const
     575             : {
     576             :     // Optimization: if bHidden is set, we only update the Hidden Array.
     577        2919 :     if ( bRefreshHidden )
     578             :     {
     579             :         // remove corrections
     580           0 :         for ( size_t i = 0; i < rToFill.Count(); ++i )
     581             :         {
     582           0 :             SwTabColsEntry& rEntry = rToFill.GetEntry( i );
     583           0 :             rEntry.nPos -= rToFill.GetLeft();
     584           0 :             rEntry.nMin -= rToFill.GetLeft();
     585           0 :             rEntry.nMax -= rToFill.GetLeft();
     586             :         }
     587             : 
     588             :         // All are hidden, so add the visible ones.
     589           0 :         for ( size_t i = 0; i < rToFill.Count(); ++i )
     590           0 :             rToFill.SetHidden( i, true );
     591             :     }
     592             :     else
     593             :     {
     594        2919 :         rToFill.Remove( 0, rToFill.Count() );
     595             :     }
     596             : 
     597             :     // Insertion cases:
     598             :     // 1. All boxes which are inferior to Line which is superior to the Start,
     599             :     //    as well as their inferior boxes if present.
     600             :     // 2. Starting from the Line, the superior box plus its neighbours; but no inferiors.
     601             :     // 3. Apply 2. to the Line superior to the chain of boxes,
     602             :     //    until the Line's superior is not a box but the table.
     603             :     // Only those boxes are inserted that don't contain further rows. The insertion
     604             :     // function takes care to avoid duplicates. In order to achieve this, we work
     605             :     // with some degree of fuzzyness (to avoid rounding errors).
     606             :     // Only the left edge of the boxes are inserted.
     607             :     // Finally, the first entry is removed again, because it's already
     608             :     // covered by the border.
     609             :     // 4. Scan the table again and insert _all_ boxes, this time as hidden.
     610             : 
     611        2919 :     const SwFrameFormat *pTabFormat = GetFrameFormat();
     612             : 
     613             :     // 1.
     614        2919 :     const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
     615             : 
     616       11154 :     for ( size_t i = 0; i < rBoxes.size(); ++i )
     617        8235 :         ::lcl_ProcessBoxGet( rBoxes[i], rToFill, pTabFormat, bRefreshHidden );
     618             : 
     619             :     // 2. and 3.
     620        2919 :     const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
     621        2919 :                                 pStart->GetUpper()->GetUpper()->GetUpper() : 0;
     622        5838 :     while ( pLine )
     623             :     {
     624           0 :         const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
     625           0 :         for ( size_t k = 0; k < rBoxes2.size(); ++k )
     626           0 :             ::lcl_SortedTabColInsert( rToFill, rBoxes2[k],
     627           0 :                                       pTabFormat, false, bRefreshHidden );
     628           0 :         pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
     629             :     }
     630             : 
     631        2919 :     if ( !bRefreshHidden )
     632             :     {
     633             :         // 4.
     634        2919 :         if ( !bCurRowOnly )
     635             :         {
     636          24 :             for ( size_t i = 0; i < aLines.size(); ++i )
     637          20 :                 ::lcl_ProcessLineGet( aLines[i], rToFill, pTabFormat );
     638             :         }
     639             : 
     640        2919 :         rToFill.Remove( 0, 1 );
     641             :     }
     642             : 
     643             :     // Now the coordinates are relative to the left table border - i.e.
     644             :     // relative to SwTabCols.nLeft. However, they are expected
     645             :     // relative to the left document border, i.e. SwTabCols.nLeftMin.
     646             :     // So all values need to be extended by nLeft.
     647        8231 :     for ( size_t i = 0; i < rToFill.Count(); ++i )
     648             :     {
     649        5312 :         SwTabColsEntry& rEntry = rToFill.GetEntry( i );
     650        5312 :         rEntry.nPos += rToFill.GetLeft();
     651        5312 :         rEntry.nMin += rToFill.GetLeft();
     652        5312 :         rEntry.nMax += rToFill.GetLeft();
     653             :     }
     654        2919 : }
     655             : 
     656             : // Structure for parameter passing
     657        2516 : struct Parm
     658             : {
     659             :     const SwTabCols &rNew;
     660             :     const SwTabCols &rOld;
     661             :     long nNewWish,
     662             :          nOldWish;
     663             :     std::deque<SwTableBox*> aBoxArr;
     664             :     SwShareBoxFormats aShareFormats;
     665             : 
     666        2516 :     Parm( const SwTabCols &rN, const SwTabCols &rO )
     667        2516 :         : rNew( rN ), rOld( rO ), nNewWish(0), nOldWish(0)
     668        2516 :     {}
     669             : };
     670             : 
     671             : static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm );
     672             : 
     673           0 : static void lcl_ProcessLine( SwTableLine *pLine, Parm &rParm )
     674             : {
     675           0 :     SwTableBoxes &rBoxes = pLine->GetTabBoxes();
     676           0 :     for ( size_t i = rBoxes.size(); i > 0; )
     677             :     {
     678           0 :         --i;
     679           0 :         ::lcl_ProcessBoxSet( rBoxes[i], rParm );
     680             :     }
     681           0 : }
     682             : 
     683           0 : static void lcl_ProcessBoxSet( SwTableBox *pBox, Parm &rParm )
     684             : {
     685           0 :     if ( !pBox->GetTabLines().empty() )
     686             :     {
     687           0 :         SwTableLines &rLines = pBox->GetTabLines();
     688           0 :         for ( size_t i = rLines.size(); i > 0; )
     689             :         {
     690           0 :             --i;
     691           0 :             lcl_ProcessLine( rLines[i], rParm );
     692             :         }
     693             :     }
     694             :     else
     695             :     {
     696             :         // Search the old TabCols for the current position (calculate from
     697             :         // left and right edge). Adjust the box if the values differ from
     698             :         // the new TabCols. If the adjusted edge has no neighbour we also
     699             :         // adjust all superior boxes.
     700             : 
     701           0 :         const long nOldAct = rParm.rOld.GetRight() -
     702           0 :                              rParm.rOld.GetLeft(); // +1 why?
     703             : 
     704             :         // The value for the left edge of the box is calculated from the
     705             :         // widths of the previous boxes plus the left edge.
     706           0 :         long nLeft = rParm.rOld.GetLeft();
     707           0 :         const  SwTableBox  *pCur  = pBox;
     708           0 :         const  SwTableLine *pLine = pBox->GetUpper();
     709             : 
     710           0 :         while ( pLine )
     711             :         {
     712           0 :             const SwTableBoxes &rBoxes = pLine->GetTabBoxes();
     713           0 :             for ( size_t i = 0; (i < rBoxes.size()) && (rBoxes[i] != pCur); ++i)
     714             :             {
     715             :                 nLeft += lcl_MulDiv64<long>(
     716           0 :                     rBoxes[i]->GetFrameFormat()->GetFrmSize().GetWidth(),
     717           0 :                     nOldAct, rParm.nOldWish);
     718             :             }
     719           0 :             pCur  = pLine->GetUpper();
     720           0 :             pLine = pCur ? pCur->GetUpper() : 0;
     721             :         }
     722           0 :         long nLeftDiff = 0;
     723           0 :         long nRightDiff = 0;
     724           0 :         if ( nLeft != rParm.rOld.GetLeft() ) // There are still boxes before this.
     725             :         {
     726             :             // Right edge is left edge plus width.
     727             :             const long nWidth = lcl_MulDiv64<long>(
     728           0 :                 pBox->GetFrameFormat()->GetFrmSize().GetWidth(),
     729           0 :                 nOldAct, rParm.nOldWish);
     730           0 :             const long nRight = nLeft + nWidth;
     731           0 :             size_t nLeftPos  = 0;
     732           0 :             size_t nRightPos = 0;
     733           0 :             bool bFoundLeftPos = false;
     734           0 :             bool bFoundRightPos = false;
     735           0 :             for ( size_t i = 0; i < rParm.rOld.Count(); ++i )
     736             :             {
     737           0 :                 if ( nLeft >= (rParm.rOld[i] - COLFUZZY) &&
     738           0 :                      nLeft <= (rParm.rOld[i] + COLFUZZY) )
     739             :                 {
     740           0 :                     nLeftPos = i;
     741           0 :                     bFoundLeftPos = true;
     742             :                 }
     743           0 :                 else if ( nRight >= (rParm.rOld[i] - COLFUZZY) &&
     744           0 :                           nRight <= (rParm.rOld[i] + COLFUZZY) )
     745             :                 {
     746           0 :                     nRightPos = i;
     747           0 :                     bFoundRightPos = true;
     748             :                 }
     749             :             }
     750             :             nLeftDiff = bFoundLeftPos ?
     751           0 :                 rParm.rOld[nLeftPos] - rParm.rNew[nLeftPos] : 0;
     752             :             nRightDiff= bFoundRightPos ?
     753           0 :                 rParm.rNew[nRightPos] - rParm.rOld[nRightPos] : 0;
     754             :         }
     755             :         else    // The first box.
     756             :         {
     757           0 :             nLeftDiff = rParm.rOld.GetLeft() - rParm.rNew.GetLeft();
     758           0 :             if ( rParm.rOld.Count() )
     759             :             {
     760             :                 // Calculate the difference to the edge touching the first box.
     761             :                 const long nWidth = lcl_MulDiv64<long>(
     762           0 :                     pBox->GetFrameFormat()->GetFrmSize().GetWidth(),
     763           0 :                     nOldAct, rParm.nOldWish);
     764           0 :                 const long nTmp = nWidth + rParm.rOld.GetLeft();
     765           0 :                 for ( size_t i = 0; i < rParm.rOld.Count(); ++i )
     766             :                 {
     767           0 :                     if ( nTmp >= (rParm.rOld[i] - COLFUZZY) &&
     768           0 :                          nTmp <= (rParm.rOld[i] + COLFUZZY) )
     769             :                     {
     770           0 :                         nRightDiff = rParm.rNew[i] - rParm.rOld[i];
     771           0 :                         break;
     772             :                     }
     773             :                 }
     774             :             }
     775             :         }
     776             : 
     777           0 :         if( pBox->getRowSpan() == 1 )
     778             :         {
     779           0 :             SwTableBoxes& rTableBoxes = pBox->GetUpper()->GetTabBoxes();
     780           0 :             const sal_uInt16 nPos = rTableBoxes.GetPos( pBox );
     781           0 :             if( nPos && rTableBoxes[ nPos - 1 ]->getRowSpan() != 1 )
     782           0 :                 nLeftDiff = 0;
     783           0 :             if( nPos + 1 < (sal_uInt16)rTableBoxes.size() &&
     784           0 :                 rTableBoxes[ nPos + 1 ]->getRowSpan() != 1 )
     785           0 :                 nRightDiff = 0;
     786             :         }
     787             :         else
     788           0 :             nLeftDiff = nRightDiff = 0;
     789             : 
     790           0 :         if ( nLeftDiff || nRightDiff )
     791             :         {
     792             :             // The difference is the actual difference amount. For stretched
     793             :             // tables, it does not make sense to adjust the attributes of the
     794             :             // boxes by this amount. The difference amount needs to be converted
     795             :             // accordingly.
     796           0 :             long nTmp = rParm.rNew.GetRight() - rParm.rNew.GetLeft(); // +1 why?
     797           0 :             nLeftDiff *= rParm.nNewWish;
     798           0 :             nLeftDiff /= nTmp;
     799           0 :             nRightDiff *= rParm.nNewWish;
     800           0 :             nRightDiff /= nTmp;
     801           0 :             long nDiff = nLeftDiff + nRightDiff;
     802             : 
     803             :             // Adjust the box and all superiors by the difference amount.
     804           0 :             while ( pBox )
     805             :             {
     806           0 :                 SwFormatFrmSize aFormatFrmSize( pBox->GetFrameFormat()->GetFrmSize() );
     807           0 :                 aFormatFrmSize.SetWidth( aFormatFrmSize.GetWidth() + nDiff );
     808           0 :                 if ( aFormatFrmSize.GetWidth() < 0 )
     809           0 :                     aFormatFrmSize.SetWidth( -aFormatFrmSize.GetWidth() );
     810           0 :                 rParm.aShareFormats.SetSize( *pBox, aFormatFrmSize );
     811             : 
     812             :                 // The outer cells of the last row are responsible to adjust a surrounding cell.
     813             :                 // Last line check:
     814           0 :                 if ( pBox->GetUpper()->GetUpper() &&
     815           0 :                      pBox->GetUpper() != pBox->GetUpper()->GetUpper()->GetTabLines().back())
     816             :                 {
     817           0 :                     pBox = 0;
     818             :                 }
     819             :                 else
     820             :                 {
     821             :                     // Middle cell check:
     822           0 :                     if ( pBox != pBox->GetUpper()->GetTabBoxes().front() )
     823           0 :                         nDiff = nRightDiff;
     824             : 
     825           0 :                     if ( pBox != pBox->GetUpper()->GetTabBoxes().back() )
     826           0 :                         nDiff -= nRightDiff;
     827             : 
     828           0 :                     pBox = nDiff ? pBox->GetUpper()->GetUpper() : 0;
     829             :                 }
     830           0 :             }
     831             :         }
     832             :     }
     833           0 : }
     834             : 
     835           0 : static void lcl_ProcessBoxPtr( SwTableBox *pBox, std::deque<SwTableBox*> &rBoxArr,
     836             :                            bool bBefore )
     837             : {
     838           0 :     if ( !pBox->GetTabLines().empty() )
     839             :     {
     840           0 :         const SwTableLines &rLines = pBox->GetTabLines();
     841           0 :         for ( size_t i = 0; i < rLines.size(); ++i )
     842             :         {
     843           0 :             const SwTableBoxes &rBoxes = rLines[i]->GetTabBoxes();
     844           0 :             for ( size_t j = 0; j < rBoxes.size(); ++j )
     845           0 :                 ::lcl_ProcessBoxPtr( rBoxes[j], rBoxArr, bBefore );
     846             :         }
     847             :     }
     848           0 :     else if ( bBefore )
     849           0 :         rBoxArr.push_front( pBox );
     850             :     else
     851           0 :         rBoxArr.push_back( pBox );
     852           0 : }
     853             : 
     854             : static void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm );
     855             : 
     856           0 : static void lcl_AdjustLines( SwTableLines &rLines, const long nDiff, Parm &rParm )
     857             : {
     858           0 :     for ( size_t i = 0; i < rLines.size(); ++i )
     859             :     {
     860           0 :         SwTableBox *pBox = rLines[i]->GetTabBoxes()
     861           0 :                                 [rLines[i]->GetTabBoxes().size()-1];
     862           0 :         lcl_AdjustBox( pBox, nDiff, rParm );
     863             :     }
     864           0 : }
     865             : 
     866           0 : static void lcl_AdjustBox( SwTableBox *pBox, const long nDiff, Parm &rParm )
     867             : {
     868           0 :     if ( !pBox->GetTabLines().empty() )
     869           0 :         ::lcl_AdjustLines( pBox->GetTabLines(), nDiff, rParm );
     870             : 
     871             :     // Adjust the size of the box.
     872           0 :     SwFormatFrmSize aFormatFrmSize( pBox->GetFrameFormat()->GetFrmSize() );
     873           0 :     aFormatFrmSize.SetWidth( aFormatFrmSize.GetWidth() + nDiff );
     874             : 
     875           0 :     rParm.aShareFormats.SetSize( *pBox, aFormatFrmSize );
     876           0 : }
     877             : 
     878        2516 : void SwTable::SetTabCols( const SwTabCols &rNew, const SwTabCols &rOld,
     879             :                           const SwTableBox *pStart, bool bCurRowOnly )
     880             : {
     881             :     CHECK_TABLE( *this )
     882             : 
     883        2516 :     SetHTMLTableLayout( 0 );    // delete HTML-Layout
     884             : 
     885             :     // FME: Made rOld const. The caller is responsible for passing correct
     886             :     // values of rOld. Therefore we do not have to call GetTabCols anymore:
     887             :     //GetTabCols( rOld, pStart );
     888             : 
     889        2516 :     Parm aParm( rNew, rOld );
     890             : 
     891             :     OSL_ENSURE( rOld.Count() == rNew.Count(), "Columnanzahl veraendert.");
     892             : 
     893             :     // Convert the edges. We need to adjust the size of the table and some boxes.
     894             :     // For the size adjustment, we must not make use of the Modify, since that'd
     895             :     // adjust all boxes, which we really don't want.
     896        2516 :     SwFrameFormat *pFormat = GetFrameFormat();
     897        2516 :     aParm.nOldWish = aParm.nNewWish = pFormat->GetFrmSize().GetWidth();
     898        5032 :     if ( (rOld.GetLeft() != rNew.GetLeft()) ||
     899        2516 :          (rOld.GetRight()!= rNew.GetRight()) )
     900             :     {
     901           0 :         LockModify();
     902             :         {
     903           0 :             SvxLRSpaceItem aLR( pFormat->GetLRSpace() );
     904           0 :             SvxShadowItem aSh( pFormat->GetShadow() );
     905             : 
     906           0 :             SwTwips nShRight = aSh.CalcShadowSpace( SvxShadowItemSide::RIGHT );
     907           0 :             SwTwips nShLeft = aSh.CalcShadowSpace( SvxShadowItemSide::LEFT );
     908             : 
     909           0 :             aLR.SetLeft ( rNew.GetLeft() - nShLeft );
     910           0 :             aLR.SetRight( rNew.GetRightMax() - rNew.GetRight() - nShRight );
     911           0 :             pFormat->SetFormatAttr( aLR );
     912             : 
     913             :             // The alignment of the table needs to be adjusted accordingly.
     914             :             // This is done by preserving the exact positions that have been
     915             :             // set by the user.
     916           0 :             SwFormatHoriOrient aOri( pFormat->GetHoriOrient() );
     917           0 :             if(text::HoriOrientation::NONE != aOri.GetHoriOrient())
     918             :             {
     919           0 :                 const bool bLeftDist = rNew.GetLeft() != nShLeft;
     920           0 :                 const bool bRightDist = rNew.GetRight() + nShRight != rNew.GetRightMax();
     921           0 :                 if(!bLeftDist && !bRightDist)
     922           0 :                     aOri.SetHoriOrient( text::HoriOrientation::FULL );
     923           0 :                 else if(!bRightDist && rNew.GetLeft() > nShLeft )
     924           0 :                     aOri.SetHoriOrient( text::HoriOrientation::RIGHT );
     925           0 :                 else if(!bLeftDist && rNew.GetRight() + nShRight < rNew.GetRightMax())
     926           0 :                     aOri.SetHoriOrient( text::HoriOrientation::LEFT );
     927             :                 else
     928           0 :                     aOri.SetHoriOrient( text::HoriOrientation::LEFT_AND_WIDTH );
     929             :             }
     930           0 :             pFormat->SetFormatAttr( aOri );
     931             :         }
     932           0 :         const long nAct = rOld.GetRight() - rOld.GetLeft(); // +1 why?
     933           0 :         long nTabDiff = 0;
     934             : 
     935           0 :         if ( rOld.GetLeft() != rNew.GetLeft() )
     936             :         {
     937           0 :             nTabDiff = rOld.GetLeft() - rNew.GetLeft();
     938           0 :             nTabDiff *= aParm.nOldWish;
     939           0 :             nTabDiff /= nAct;
     940             :         }
     941           0 :         if ( rOld.GetRight() != rNew.GetRight() )
     942             :         {
     943           0 :             long nDiff = rNew.GetRight() - rOld.GetRight();
     944           0 :             nDiff *= aParm.nOldWish;
     945           0 :             nDiff /= nAct;
     946           0 :             nTabDiff += nDiff;
     947           0 :             if( !IsNewModel() )
     948           0 :                 ::lcl_AdjustLines( GetTabLines(), nDiff, aParm );
     949             :         }
     950             : 
     951             :         // Adjust the size of the table, watch out for stretched tables.
     952           0 :         if ( nTabDiff )
     953             :         {
     954           0 :             aParm.nNewWish += nTabDiff;
     955           0 :             if ( aParm.nNewWish < 0 )
     956           0 :                 aParm.nNewWish = USHRT_MAX; // Oops! Have to roll back.
     957           0 :             SwFormatFrmSize aSz( pFormat->GetFrmSize() );
     958           0 :             if ( aSz.GetWidth() != aParm.nNewWish )
     959             :             {
     960           0 :                 aSz.SetWidth( aParm.nNewWish );
     961           0 :                 aSz.SetWidthPercent( 0 );
     962           0 :                 pFormat->SetFormatAttr( aSz );
     963           0 :             }
     964             :         }
     965           0 :         UnlockModify();
     966             :     }
     967             : 
     968        2516 :     if( IsNewModel() )
     969        2516 :         NewSetTabCols( aParm, rNew, rOld, pStart, bCurRowOnly );
     970             :     else
     971             :     {
     972           0 :         if ( bCurRowOnly )
     973             :         {
     974             :             // To adjust the current row, we need to process all its boxes,
     975             :             // similar to the filling of the TabCols (see GetTabCols()).
     976             :             // Unfortunately we again have to take care to adjust the boxes
     977             :             // from back to front, respectively from outer to inner.
     978             :             // The best way to achieve this is probably to track the boxes
     979             :             // in a PtrArray.
     980           0 :             const SwTableBoxes &rBoxes = pStart->GetUpper()->GetTabBoxes();
     981           0 :             for ( size_t i = 0; i < rBoxes.size(); ++i )
     982           0 :                 ::lcl_ProcessBoxPtr( rBoxes[i], aParm.aBoxArr, false );
     983             : 
     984           0 :             const SwTableLine *pLine = pStart->GetUpper()->GetUpper() ?
     985           0 :                                     pStart->GetUpper()->GetUpper()->GetUpper() : 0;
     986           0 :             const SwTableBox  *pExcl = pStart->GetUpper()->GetUpper();
     987           0 :             while ( pLine )
     988             :             {
     989           0 :                 const SwTableBoxes &rBoxes2 = pLine->GetTabBoxes();
     990           0 :                 bool bBefore = true;
     991           0 :                 for ( size_t i = 0; i < rBoxes2.size(); ++i )
     992             :                 {
     993           0 :                     if ( rBoxes2[i] != pExcl )
     994           0 :                         ::lcl_ProcessBoxPtr( rBoxes2[i], aParm.aBoxArr, bBefore );
     995             :                     else
     996           0 :                         bBefore = false;
     997             :                 }
     998           0 :                 pExcl = pLine->GetUpper();
     999           0 :                 pLine = pLine->GetUpper() ? pLine->GetUpper()->GetUpper() : 0;
    1000             :             }
    1001             :             // After we've inserted a bunch of boxes (hopefully all and in
    1002             :             // correct order), we just need to process them in reverse order.
    1003           0 :             for ( int j = aParm.aBoxArr.size()-1; j >= 0; --j )
    1004             :             {
    1005           0 :                 SwTableBox *pBox = aParm.aBoxArr[j];
    1006           0 :                 ::lcl_ProcessBoxSet( pBox, aParm );
    1007             :             }
    1008             :         }
    1009             :         else
    1010             :         {
    1011             :             // Adjusting the entire table is 'easy'. All boxes without lines are
    1012             :             // adjusted, as are their superiors. Of course we need to process
    1013             :             // in reverse order to prevent fooling ourselves!
    1014           0 :             SwTableLines &rLines = GetTabLines();
    1015           0 :             for ( size_t i = rLines.size(); i > 0; )
    1016             :             {
    1017           0 :                 --i;
    1018           0 :                 ::lcl_ProcessLine( rLines[i], aParm );
    1019             :             }
    1020             :         }
    1021        2516 :     }
    1022             : 
    1023             : #ifdef DBG_UTIL
    1024             :     {
    1025             :         // do some checking for correct table widths
    1026             :         SwTwips nSize = GetFrameFormat()->GetFrmSize().GetWidth();
    1027             :         for (size_t n = 0; n < aLines.size(); ++n)
    1028             :         {
    1029             :             _CheckBoxWidth( *aLines[ n ], nSize );
    1030             :         }
    1031             :     }
    1032             : #endif
    1033        2516 : }
    1034             : 
    1035             : typedef std::pair<sal_uInt16, sal_uInt16> ColChange;
    1036             : typedef std::list< ColChange > ChangeList;
    1037             : 
    1038        2484 : static void lcl_AdjustWidthsInLine( SwTableLine* pLine, ChangeList& rOldNew,
    1039             :     Parm& rParm, sal_uInt16 nColFuzzy )
    1040             : {
    1041        2484 :     ChangeList::iterator pCurr = rOldNew.begin();
    1042        2484 :     if( pCurr == rOldNew.end() )
    1043        2484 :         return;
    1044        2484 :     const size_t nCount = pLine->GetTabBoxes().size();
    1045        2484 :     SwTwips nBorder = 0;
    1046        2484 :     SwTwips nRest = 0;
    1047       10150 :     for( size_t i = 0; i < nCount; ++i )
    1048             :     {
    1049        7666 :         SwTableBox* pBox = pLine->GetTabBoxes()[i];
    1050        7666 :         SwTwips nWidth = pBox->GetFrameFormat()->GetFrmSize().GetWidth();
    1051        7666 :         SwTwips nNewWidth = nWidth - nRest;
    1052        7666 :         nRest = 0;
    1053        7666 :         nBorder += nWidth;
    1054        7666 :         if( pCurr != rOldNew.end() && nBorder + nColFuzzy >= pCurr->first )
    1055             :         {
    1056        5128 :             nBorder -= nColFuzzy;
    1057       12740 :             while( pCurr != rOldNew.end() && nBorder > pCurr->first )
    1058        2484 :                 ++pCurr;
    1059        5128 :             if( pCurr != rOldNew.end() )
    1060             :             {
    1061        5128 :                 nBorder += nColFuzzy;
    1062        5128 :                 if( nBorder + nColFuzzy >= pCurr->first )
    1063             :                 {
    1064        5080 :                     if( pCurr->second == pCurr->first )
    1065           0 :                         nRest = 0;
    1066             :                     else
    1067        5080 :                         nRest = pCurr->second - nBorder;
    1068        5080 :                     nNewWidth += nRest;
    1069        5080 :                     ++pCurr;
    1070             :                 }
    1071             :             }
    1072             :         }
    1073        7666 :         if( nNewWidth != nWidth )
    1074             :         {
    1075        6874 :             if( nNewWidth < 0 )
    1076             :             {
    1077           0 :                 nRest += 1 - nNewWidth;
    1078           0 :                 nNewWidth = 1;
    1079             :             }
    1080        6874 :             SwFormatFrmSize aFormatFrmSize( pBox->GetFrameFormat()->GetFrmSize() );
    1081        6874 :             aFormatFrmSize.SetWidth( nNewWidth );
    1082        6874 :             rParm.aShareFormats.SetSize( *pBox, aFormatFrmSize );
    1083             :         }
    1084             :     }
    1085             : }
    1086             : 
    1087        4153 : static void lcl_CalcNewWidths( std::list<sal_uInt16> &rSpanPos, ChangeList& rChanges,
    1088             :     SwTableLine* pLine, long nWish, long nWidth, bool bTop )
    1089             : {
    1090        4153 :     if( rChanges.empty() )
    1091             :     {
    1092           0 :         rSpanPos.clear();
    1093           0 :         return;
    1094             :     }
    1095        4153 :     if( rSpanPos.empty() )
    1096             :     {
    1097           0 :         rChanges.clear();
    1098           0 :         return;
    1099             :     }
    1100        4153 :     std::list<sal_uInt16> aNewSpanPos;
    1101        8306 :     ChangeList aNewChanges;
    1102        4153 :     ChangeList::iterator pCurr = rChanges.begin();
    1103        4153 :     aNewChanges.push_back( *pCurr ); // Nullposition
    1104        4153 :     std::list<sal_uInt16>::iterator pSpan = rSpanPos.begin();
    1105        4153 :     sal_uInt16 nCurr = 0;
    1106        4153 :     SwTwips nOrgSum = 0;
    1107        4153 :     bool bRowSpan = false;
    1108        4153 :     sal_uInt16 nRowSpanCount = 0;
    1109        4153 :     const size_t nCount = pLine->GetTabBoxes().size();
    1110       16927 :     for( size_t nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
    1111             :     {
    1112       12774 :         SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
    1113       12774 :         SwTwips nCurrWidth = pBox->GetFrameFormat()->GetFrmSize().GetWidth();
    1114       12774 :         const long nRowSpan = pBox->getRowSpan();
    1115             :         const bool bCurrRowSpan = bTop ? nRowSpan < 0 :
    1116       12774 :             ( nRowSpan > 1 || nRowSpan < -1 );
    1117       12774 :         if( bRowSpan || bCurrRowSpan )
    1118           0 :             aNewSpanPos.push_back( nRowSpanCount );
    1119       12774 :         bRowSpan = bCurrRowSpan;
    1120       12774 :         nOrgSum += nCurrWidth;
    1121             :         const sal_uInt16 nPos = lcl_MulDiv64<sal_uInt16>(
    1122             :             lcl_MulDiv64<sal_uInt64>(nOrgSum, nWidth, nWish),
    1123       12774 :             nWish, nWidth);
    1124       38200 :         while( pCurr != rChanges.end() && pCurr->first < nPos )
    1125             :         {
    1126       12652 :             ++nCurr;
    1127       12652 :             ++pCurr;
    1128             :         }
    1129       12774 :         bool bNew = true;
    1130       21273 :         if( pCurr != rChanges.end() && pCurr->first <= nPos &&
    1131        8499 :             pCurr->first != pCurr->second )
    1132             :         {
    1133       25497 :             while( pSpan != rSpanPos.end() && *pSpan < nCurr )
    1134        8499 :                 ++pSpan;
    1135        8499 :             if( pSpan != rSpanPos.end() && *pSpan == nCurr )
    1136             :             {
    1137        8499 :                 aNewChanges.push_back( *pCurr );
    1138        8499 :                 ++nRowSpanCount;
    1139        8499 :                 bNew = false;
    1140             :             }
    1141             :         }
    1142       12774 :         if( bNew )
    1143             :         {
    1144        4275 :             ColChange aTmp( nPos, nPos );
    1145        4275 :             aNewChanges.push_back( aTmp );
    1146        4275 :             ++nRowSpanCount;
    1147             :         }
    1148             :     }
    1149             : 
    1150        4153 :     pCurr = aNewChanges.begin();
    1151        4153 :     ChangeList::iterator pLast = pCurr;
    1152        4153 :     ChangeList::iterator pLeftMove = pCurr;
    1153       25233 :     while( pCurr != aNewChanges.end() )
    1154             :     {
    1155       16927 :         if( pLeftMove == pCurr )
    1156             :         {
    1157        7687 :             while( ++pLeftMove != aNewChanges.end() && pLeftMove->first <= pLeftMove->second )
    1158             :                 ;
    1159             :         }
    1160       16927 :         if( pCurr->second == pCurr->first )
    1161             :         {
    1162        8428 :             if( pLeftMove != aNewChanges.end() && pCurr->second > pLeftMove->second )
    1163             :             {
    1164           0 :                 if( pLeftMove->first == pLast->first )
    1165           0 :                     pCurr->second = pLeftMove->second;
    1166             :                 else
    1167             :                 {
    1168           0 :                     pCurr->second = lcl_MulDiv64<sal_uInt16>(
    1169           0 :                         pCurr->first - pLast->first,
    1170           0 :                         pLeftMove->second - pLast->second,
    1171           0 :                         pLeftMove->first - pLast->first) + pLast->second;
    1172             :                 }
    1173             :             }
    1174        8428 :             pLast = pCurr;
    1175        8428 :             ++pCurr;
    1176             :         }
    1177        8499 :         else if( pCurr->second > pCurr->first )
    1178             :         {
    1179        4965 :             pLast = pCurr;
    1180        4965 :             ++pCurr;
    1181        4965 :             ChangeList::iterator pNext = pCurr;
    1182       11745 :             while( pNext != pLeftMove && pNext->second == pNext->first &&
    1183        1815 :                 pNext->second < pLast->second )
    1184           0 :                 ++pNext;
    1185        9930 :             while( pCurr != pNext )
    1186             :             {
    1187           0 :                 if( pNext == aNewChanges.end() || pNext->first == pLast->first )
    1188           0 :                     pCurr->second = pLast->second;
    1189             :                 else
    1190             :                 {
    1191           0 :                     pCurr->second = lcl_MulDiv64<sal_uInt16>(
    1192           0 :                         pCurr->first - pLast->first,
    1193           0 :                         pNext->second - pLast->second,
    1194           0 :                         pNext->first - pLast->first) + pLast->second;
    1195             :                 }
    1196           0 :                 ++pCurr;
    1197             :             }
    1198        4965 :             pLast = pCurr;
    1199             :         }
    1200             :         else
    1201             :         {
    1202        3534 :             pLast = pCurr;
    1203        3534 :             ++pCurr;
    1204             :         }
    1205             :     }
    1206             : 
    1207        4153 :     rChanges.clear();
    1208        4153 :     ChangeList::iterator pCopy = aNewChanges.begin();
    1209       25233 :     while( pCopy != aNewChanges.end() )
    1210       16927 :         rChanges.push_back( *pCopy++ );
    1211        4153 :     rSpanPos.clear();
    1212        4153 :     std::list<sal_uInt16>::iterator pSpCopy = aNewSpanPos.begin();
    1213        8306 :     while( pSpCopy != aNewSpanPos.end() )
    1214        4153 :         rSpanPos.push_back( *pSpCopy++ );
    1215             : }
    1216             : 
    1217        2516 : void SwTable::NewSetTabCols( Parm &rParm, const SwTabCols &rNew,
    1218             :     const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly )
    1219             : {
    1220             : #if OSL_DEBUG_LEVEL > 1
    1221             :     static int nCallCount = 0;
    1222             :     ++nCallCount;
    1223             : #endif
    1224             :     // First step: evaluate which lines have been moved/which widths changed
    1225        2516 :     ChangeList aOldNew;
    1226        2516 :     const long nNewWidth = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
    1227        2516 :     const long nOldWidth = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
    1228        2516 :     if( nNewWidth < 1 || nOldWidth < 1 )
    1229           0 :         return;
    1230       10274 :     for( size_t i = 0; i <= rOld.Count(); ++i )
    1231             :     {
    1232             :         long nNewPos;
    1233             :         long nOldPos;
    1234        7758 :         if( i == rOld.Count() )
    1235             :         {
    1236        2516 :             nOldPos = rParm.rOld.GetRight() - rParm.rOld.GetLeft();
    1237        2516 :             nNewPos = rParm.rNew.GetRight() - rParm.rNew.GetLeft();
    1238             :         }
    1239             :         else
    1240             :         {
    1241        5242 :             nOldPos = rOld[i] - rParm.rOld.GetLeft();
    1242        5242 :             nNewPos = rNew[i] - rParm.rNew.GetLeft();
    1243             :         }
    1244        7758 :         nNewPos = lcl_MulDiv64<long>(nNewPos, rParm.nNewWish, nNewWidth);
    1245        7758 :         nOldPos = lcl_MulDiv64<long>(nOldPos, rParm.nOldWish, nOldWidth);
    1246        7758 :         if( nOldPos != nNewPos && nNewPos > 0 && nOldPos > 0 )
    1247             :         {
    1248        5080 :             ColChange aChg( (sal_uInt16)nOldPos, (sal_uInt16)nNewPos );
    1249        5080 :             aOldNew.push_back( aChg );
    1250             :         }
    1251             :     }
    1252             :     // Finished first step
    1253        2516 :     int nCount = aOldNew.size();
    1254        2516 :     if( !nCount )
    1255          32 :         return; // no change, nothing to do
    1256        2484 :     SwTableLines &rLines = GetTabLines();
    1257        2484 :     if( bCurRowOnly )
    1258             :     {
    1259        2484 :         const SwTableLine* pCurrLine = pStart->GetUpper();
    1260        2484 :         sal_uInt16 nCurr = rLines.GetPos( pCurrLine );
    1261        2484 :         if( nCurr >= USHRT_MAX )
    1262           0 :             return;
    1263             : 
    1264        2484 :         ColChange aChg( 0, 0 );
    1265        2484 :         aOldNew.push_front( aChg );
    1266        2484 :         std::list<sal_uInt16> aRowSpanPos;
    1267        2484 :         if( nCurr )
    1268             :         {
    1269        2084 :             ChangeList aCopy;
    1270        2084 :             ChangeList::iterator pCop = aOldNew.begin();
    1271        2084 :             sal_uInt16 nPos = 0;
    1272       10560 :             while( pCop != aOldNew.end() )
    1273             :             {
    1274        6392 :                 aCopy.push_back( *pCop );
    1275        6392 :                 ++pCop;
    1276        6392 :                 aRowSpanPos.push_back( nPos++ );
    1277             :             }
    1278        2084 :             lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
    1279        4168 :                 rParm.nOldWish, nOldWidth, true );
    1280        2084 :             bool bGoOn = !aRowSpanPos.empty();
    1281        2084 :             sal_uInt16 j = nCurr;
    1282        4168 :             while( bGoOn )
    1283             :             {
    1284           0 :                 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[--j],
    1285           0 :                     rParm.nOldWish, nOldWidth, true );
    1286           0 :                 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
    1287           0 :                 bGoOn = !aRowSpanPos.empty() && j > 0;
    1288             :             }
    1289        2084 :             aRowSpanPos.clear();
    1290             :         }
    1291        2484 :         if( nCurr+1 < (sal_uInt16)rLines.size() )
    1292             :         {
    1293        2069 :             ChangeList aCopy;
    1294        2069 :             ChangeList::iterator pCop = aOldNew.begin();
    1295        2069 :             sal_uInt16 nPos = 0;
    1296       10398 :             while( pCop != aOldNew.end() )
    1297             :             {
    1298        6260 :                 aCopy.push_back( *pCop );
    1299        6260 :                 ++pCop;
    1300        6260 :                 aRowSpanPos.push_back( nPos++ );
    1301             :             }
    1302        2069 :             lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[nCurr],
    1303        4138 :                 rParm.nOldWish, nOldWidth, false );
    1304        2069 :             bool bGoOn = !aRowSpanPos.empty();
    1305        2069 :             sal_uInt16 j = nCurr;
    1306        4138 :             while( bGoOn )
    1307             :             {
    1308           0 :                 lcl_CalcNewWidths( aRowSpanPos, aCopy, rLines[++j],
    1309           0 :                     rParm.nOldWish, nOldWidth, false );
    1310           0 :                 lcl_AdjustWidthsInLine( rLines[j], aCopy, rParm, 0 );
    1311           0 :                 bGoOn = !aRowSpanPos.empty() && j+1 < (sal_uInt16)rLines.size();
    1312        2069 :             }
    1313             :         }
    1314        2484 :         ::lcl_AdjustWidthsInLine( rLines[nCurr], aOldNew, rParm, COLFUZZY );
    1315             :     }
    1316             :     else
    1317             :     {
    1318           0 :         for( size_t i = 0; i < rLines.size(); ++i )
    1319           0 :             ::lcl_AdjustWidthsInLine( rLines[i], aOldNew, rParm, COLFUZZY );
    1320        2484 :     }
    1321             :     CHECK_TABLE( *this )
    1322             : }
    1323             : 
    1324             : // return the pointer of the box specified.
    1325           0 : static bool lcl_IsValidRowName( const OUString& rStr )
    1326             : {
    1327           0 :     bool bIsValid = true;
    1328           0 :     sal_Int32 nLen = rStr.getLength();
    1329           0 :     for( sal_Int32 i = 0;  i < nLen && bIsValid; ++i )
    1330             :     {
    1331           0 :         const sal_Unicode cChar = rStr[i];
    1332           0 :         if (cChar < '0' || cChar > '9')
    1333           0 :             bIsValid = false;
    1334             :     }
    1335           0 :     return bIsValid;
    1336             : }
    1337             : 
    1338             : // #i80314#
    1339             : // add 3rd parameter and its handling
    1340       24328 : sal_uInt16 SwTable::_GetBoxNum( OUString& rStr, bool bFirstPart,
    1341             :                             const bool bPerformValidCheck )
    1342             : {
    1343       24328 :     sal_uInt16 nRet = 0;
    1344       24328 :     if( bFirstPart )   // true == column; false == row
    1345             :     {
    1346       12164 :         sal_Int32 nPos = 0;
    1347             :         // the first one uses letters for addressing!
    1348       12164 :         bool bFirst = true;
    1349       36492 :         while (nPos<rStr.getLength())
    1350             :         {
    1351       24328 :             sal_Unicode cChar = rStr[nPos];
    1352       24328 :             if ((cChar<'A' || cChar>'Z') && (cChar<'a' || cChar>'z'))
    1353             :                 break;
    1354       12164 :             if( (cChar -= 'A') >= 26 )
    1355           0 :                 cChar -= 'a' - '[';
    1356       12164 :             if( bFirst )
    1357       12164 :                 bFirst = false;
    1358             :             else
    1359           0 :                 ++nRet;
    1360       12164 :             nRet = nRet * 52 + cChar;
    1361       12164 :             ++nPos;
    1362             :         }
    1363       12164 :         rStr = rStr.copy( nPos );      // Remove char from String
    1364             :     }
    1365             :     else
    1366             :     {
    1367       12164 :         const sal_Int32 nPos = rStr.indexOf( "." );
    1368       12164 :         if ( nPos<0 )
    1369             :         {
    1370       12164 :             nRet = 0;
    1371       12164 :             if ( !bPerformValidCheck || lcl_IsValidRowName( rStr ) )
    1372             :             {
    1373       12164 :                 nRet = static_cast<sal_uInt16>(rStr.toInt32());
    1374             :             }
    1375       12164 :             rStr.clear();
    1376             :         }
    1377             :         else
    1378             :         {
    1379           0 :             nRet = 0;
    1380           0 :             const OUString aText( rStr.copy( 0, nPos ) );
    1381           0 :             if ( !bPerformValidCheck || lcl_IsValidRowName( aText ) )
    1382             :             {
    1383           0 :                 nRet = static_cast<sal_uInt16>(aText.toInt32());
    1384             :             }
    1385           0 :             rStr = rStr.copy( nPos+1 );
    1386             :         }
    1387             :     }
    1388       24328 :     return nRet;
    1389             : }
    1390             : 
    1391             : // #i80314#
    1392             : // add 2nd parameter and its handling
    1393       12164 : const SwTableBox* SwTable::GetTableBox( const OUString& rName,
    1394             :                                       const bool bPerformValidCheck ) const
    1395             : {
    1396       12164 :     const SwTableBox* pBox = 0;
    1397             :     const SwTableLine* pLine;
    1398             :     const SwTableLines* pLines;
    1399             : 
    1400             :     sal_uInt16 nLine, nBox;
    1401       12164 :     OUString aNm( rName );
    1402       36491 :     while( !aNm.isEmpty() )
    1403             :     {
    1404       12164 :         nBox = SwTable::_GetBoxNum( aNm, 0 == pBox, bPerformValidCheck );
    1405             :         // first box ?
    1406       12164 :         if( !pBox )
    1407       12164 :             pLines = &GetTabLines();
    1408             :         else
    1409             :         {
    1410           0 :             pLines = &pBox->GetTabLines();
    1411           0 :             if( nBox )
    1412           0 :                 --nBox;
    1413             :         }
    1414             : 
    1415       12164 :         nLine = SwTable::_GetBoxNum( aNm, false, bPerformValidCheck );
    1416             : 
    1417             :         // determine line
    1418       12164 :         if( !nLine || nLine > pLines->size() )
    1419           0 :             return 0;
    1420       12164 :         pLine = (*pLines)[ nLine-1 ];
    1421             : 
    1422             :         // determine box
    1423       12164 :         const SwTableBoxes* pBoxes = &pLine->GetTabBoxes();
    1424       12164 :         if( nBox >= pBoxes->size() )
    1425           1 :             return 0;
    1426       12163 :         pBox = (*pBoxes)[ nBox ];
    1427             :     }
    1428             : 
    1429             :     // check if the box found has any contents
    1430       12163 :     if( pBox && !pBox->GetSttNd() )
    1431             :     {
    1432             :         OSL_FAIL( "Box without content, looking for the next one!" );
    1433             :         // "drop this" until the first box
    1434           0 :         while( !pBox->GetTabLines().empty() )
    1435           0 :             pBox = pBox->GetTabLines().front()->GetTabBoxes().front();
    1436             :     }
    1437       12163 :     return pBox;
    1438             : }
    1439             : 
    1440        9124 : SwTableBox* SwTable::GetTableBox( sal_uLong nSttIdx )
    1441             : {
    1442             :     // For optimizations, don't always process the entire SortArray.
    1443             :     // Converting text to table, tries certain conditions
    1444             :     // to ask for a table box of a table that is not yet having a format
    1445        9124 :     if(!GetFrameFormat())
    1446           0 :         return 0;
    1447        9124 :     SwTableBox* pRet = 0;
    1448        9124 :     SwNodes& rNds = GetFrameFormat()->GetDoc()->GetNodes();
    1449        9124 :     sal_uLong nIndex = nSttIdx + 1;
    1450        9124 :     SwContentNode* pCNd = 0;
    1451        9124 :     SwTableNode* pTableNd = 0;
    1452             : 
    1453       18248 :     while ( nIndex < rNds.Count() )
    1454             :     {
    1455        9124 :         pTableNd = rNds[ nIndex ]->GetTableNode();
    1456        9124 :         if ( pTableNd )
    1457          28 :             break;
    1458             : 
    1459        9096 :         pCNd = rNds[ nIndex ]->GetContentNode();
    1460        9096 :         if ( pCNd )
    1461        9096 :             break;
    1462             : 
    1463           0 :         ++nIndex;
    1464             :     }
    1465             : 
    1466        9124 :     if ( pCNd || pTableNd )
    1467             :     {
    1468        9124 :         SwModify* pModify = pCNd;
    1469             :         // #144862# Better handling of table in table
    1470        9124 :         if ( pTableNd && pTableNd->GetTable().GetFrameFormat() )
    1471          28 :             pModify = pTableNd->GetTable().GetFrameFormat();
    1472             : 
    1473        9124 :         SwFrm* pFrm = pModify ? SwIterator<SwFrm,SwModify>(*pModify).First() : nullptr;
    1474       18796 :         while ( pFrm && !pFrm->IsCellFrm() )
    1475         548 :             pFrm = pFrm->GetUpper();
    1476        9124 :         if ( pFrm )
    1477         548 :             pRet = const_cast<SwTableBox*>(static_cast<SwCellFrm*>(pFrm)->GetTabBox());
    1478             :     }
    1479             : 
    1480             :     // In case the layout doesn't exist yet or anything else goes wrong.
    1481        9124 :     if ( !pRet )
    1482             :     {
    1483      482994 :         for (size_t n = m_TabSortContentBoxes.size(); n; )
    1484             :         {
    1485      474418 :             if (m_TabSortContentBoxes[ --n ]->GetSttIdx() == nSttIdx)
    1486             :             {
    1487        8576 :                 return m_TabSortContentBoxes[ n ];
    1488             :             }
    1489             :         }
    1490             :     }
    1491         548 :     return pRet;
    1492             : }
    1493             : 
    1494         367 : bool SwTable::IsTableComplex() const
    1495             : {
    1496             :     // Returns true for complex tables, i.e. tables that contain nestings,
    1497             :     // like containing boxes not part of the first line, e.g. results of
    1498             :     // splits/merges which lead to more complex structures.
    1499        4381 :     for (size_t n = 0; n < m_TabSortContentBoxes.size(); ++n)
    1500             :     {
    1501        4028 :         if (m_TabSortContentBoxes[ n ]->GetUpper()->GetUpper())
    1502             :         {
    1503          14 :             return true;
    1504             :         }
    1505             :     }
    1506         353 :     return false;
    1507             : }
    1508             : 
    1509        4128 : SwTableLine::SwTableLine( SwTableLineFormat *pFormat, sal_uInt16 nBoxes,
    1510             :                             SwTableBox *pUp )
    1511             :     : SwClient( pFormat ),
    1512             :     aBoxes(),
    1513        4128 :     pUpper( pUp )
    1514             : {
    1515        4128 :     aBoxes.reserve( nBoxes );
    1516        4128 : }
    1517             : 
    1518       12378 : SwTableLine::~SwTableLine()
    1519             : {
    1520       15971 :     for (size_t i = 0; i < aBoxes.size(); ++i)
    1521             :     {
    1522       11845 :         delete aBoxes[i];
    1523             :     }
    1524             :     // the TabelleLine can be deleted if it's the last client of the FrameFormat
    1525        4126 :     SwModify* pMod = GetFrameFormat();
    1526        4126 :     pMod->Remove( this );               // remove,
    1527        4126 :     if( !pMod->HasWriterListeners() )
    1528        3898 :         delete pMod;    // and delete
    1529        8252 : }
    1530             : 
    1531        6536 : SwFrameFormat* SwTableLine::ClaimFrameFormat()
    1532             : {
    1533             :     // This method makes sure that this object is an exclusive SwTableLine client
    1534             :     // of an SwTableLineFormat object
    1535             :     // If other SwTableLine objects currently listen to the same SwTableLineFormat as
    1536             :     // this one, something needs to be done
    1537        6536 :     SwTableLineFormat *pRet = static_cast<SwTableLineFormat*>(GetFrameFormat());
    1538        6536 :     SwIterator<SwTableLine,SwFormat> aIter( *pRet );
    1539       10707 :     for( SwTableLine* pLast = aIter.First(); pLast; pLast = aIter.Next() )
    1540             :     {
    1541        6869 :         if ( pLast != this )
    1542             :         {
    1543             :             // found another SwTableLine that is a client of the current Format
    1544             :             // create a new Format as a copy and use it for this object
    1545        2698 :             SwTableLineFormat *pNewFormat = pRet->GetDoc()->MakeTableLineFormat();
    1546        2698 :             *pNewFormat = *pRet;
    1547             : 
    1548             :             // register SwRowFrms that know me as clients at the new Format
    1549        2698 :             SwIterator<SwRowFrm,SwFormat> aFrmIter( *pRet );
    1550        2722 :             for( SwRowFrm* pFrm = aFrmIter.First(); pFrm; pFrm = aFrmIter.Next() )
    1551          24 :                 if( pFrm->GetTabLine() == this )
    1552           1 :                     pFrm->RegisterToFormat( *pNewFormat );
    1553             : 
    1554             :             // register myself
    1555        2698 :             pNewFormat->Add( this );
    1556        2698 :             pRet = pNewFormat;
    1557        2698 :             break;
    1558             :         }
    1559             :     }
    1560             : 
    1561        6536 :     return pRet;
    1562             : }
    1563             : 
    1564           0 : void SwTableLine::ChgFrameFormat( SwTableLineFormat *pNewFormat )
    1565             : {
    1566           0 :     SwFrameFormat *pOld = GetFrameFormat();
    1567           0 :     SwIterator<SwRowFrm,SwFormat> aIter( *pOld );
    1568             : 
    1569             :     // First, re-register the Frms.
    1570           0 :     for( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
    1571             :     {
    1572           0 :         if( pRow->GetTabLine() == this )
    1573             :         {
    1574           0 :             pRow->RegisterToFormat( *pNewFormat );
    1575             : 
    1576           0 :             pRow->InvalidateSize();
    1577           0 :             pRow->_InvalidatePrt();
    1578           0 :             pRow->SetCompletePaint();
    1579           0 :             pRow->ReinitializeFrmSizeAttrFlags();
    1580             : 
    1581             :             // #i35063#
    1582             :             // consider 'split row allowed' attribute
    1583           0 :             SwTabFrm* pTab = pRow->FindTabFrm();
    1584           0 :             bool bInFollowFlowRow = false;
    1585           0 :             const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
    1586           0 :                                                 pRow == pTab->GetFirstNonHeadlineRow();
    1587           0 :             if ( bInFirstNonHeadlineRow ||
    1588           0 :                  !pRow->GetNext() ||
    1589           0 :                  ( bInFollowFlowRow = pRow->IsInFollowFlowRow() ) ||
    1590           0 :                  0 != pRow->IsInSplitTableRow() )
    1591             :             {
    1592           0 :                 if ( bInFirstNonHeadlineRow || bInFollowFlowRow )
    1593           0 :                     pTab = pTab->FindMaster();
    1594             : 
    1595           0 :                 pTab->SetRemoveFollowFlowLinePending( true );
    1596           0 :                 pTab->InvalidatePos();
    1597             :             }
    1598             :         }
    1599             :     }
    1600             : 
    1601             :     // Now, re-register self.
    1602           0 :     pNewFormat->Add( this );
    1603             : 
    1604           0 :     if ( !pOld->HasWriterListeners() )
    1605           0 :         delete pOld;
    1606           0 : }
    1607             : 
    1608       30100 : SwTwips SwTableLine::GetTableLineHeight( bool& bLayoutAvailable ) const
    1609             : {
    1610       30100 :     SwTwips nRet = 0;
    1611       30100 :     bLayoutAvailable = false;
    1612       30100 :     SwIterator<SwRowFrm,SwFormat> aIter( *GetFrameFormat() );
    1613             :     // A row could appear several times in headers/footers so only one chain of master/follow tables
    1614             :     // will be accepted...
    1615       30100 :     const SwTabFrm* pChain = NULL; // My chain
    1616       56250 :     for( SwRowFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
    1617             :     {
    1618       30612 :         if( pLast->GetTabLine() == this )
    1619             :         {
    1620       30612 :             const SwTabFrm* pTab = pLast->FindTabFrm();
    1621       30612 :             bLayoutAvailable = ( pTab && pTab->IsVertical() ) ?
    1622           0 :                                ( 0 < pTab->Frm().Height() ) :
    1623       30612 :                                ( 0 < pTab->Frm().Width() );
    1624             : 
    1625             :             // The first one defines the chain, if a chain is defined, only members of the chain
    1626             :             // will be added.
    1627       30612 :             if (pTab && (!pChain || pChain->IsAnFollow( pTab ) || pTab->IsAnFollow(pChain)))
    1628             :             {
    1629       30612 :                 pChain = pTab; // defines my chain (even it is already)
    1630       30612 :                 if( pTab->IsVertical() )
    1631           0 :                     nRet += pLast->Frm().Width();
    1632             :                 else
    1633       30612 :                     nRet += pLast->Frm().Height();
    1634             :                 // Optimization, if there are no master/follows in my chain, nothing more to add
    1635       30612 :                 if( !pTab->HasFollow() && !pTab->IsFollow() )
    1636        4458 :                     break;
    1637             :                 // This is not an optimization, this is necessary to avoid double additions of
    1638             :                 // repeating rows
    1639       26154 :                 if( pTab->IsInHeadline(*pLast) )
    1640           4 :                     break;
    1641             :             }
    1642             :         }
    1643             :     }
    1644       30100 :     return nRet;
    1645             : }
    1646             : 
    1647          12 : SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, sal_uInt16 nLines, SwTableLine *pUp )
    1648             :     : SwClient( 0 ),
    1649             :     aLines(),
    1650             :     pSttNd( 0 ),
    1651             :     pUpper( pUp ),
    1652          12 :     pImpl( 0 )
    1653             : {
    1654          12 :     aLines.reserve( nLines );
    1655          12 :     CheckBoxFormat( pFormat )->Add( this );
    1656          12 : }
    1657             : 
    1658        2208 : SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, const SwNodeIndex &rIdx,
    1659             :                         SwTableLine *pUp )
    1660             :     : SwClient( 0 ),
    1661             :     aLines(),
    1662             :     pUpper( pUp ),
    1663        2208 :     pImpl( 0 )
    1664             : {
    1665        2208 :     CheckBoxFormat( pFormat )->Add( this );
    1666             : 
    1667        2208 :     pSttNd = rIdx.GetNode().GetStartNode();
    1668             : 
    1669             :     // insert into the table
    1670        2208 :     const SwTableNode* pTableNd = pSttNd->FindTableNode();
    1671             :     OSL_ENSURE( pTableNd, "In which table is that box?" );
    1672        2208 :     SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTableNd->GetTable().
    1673        2208 :                                 GetTabSortBoxes();
    1674        2208 :     SwTableBox* p = this;   // error: &this
    1675        2208 :     rSrtArr.insert( p );        // insert
    1676        2208 : }
    1677             : 
    1678        9636 : SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, const SwStartNode& rSttNd, SwTableLine *pUp ) :
    1679             :     SwClient( 0 ),
    1680             :     aLines(),
    1681             :     pSttNd( &rSttNd ),
    1682             :     pUpper( pUp ),
    1683        9636 :     pImpl( 0 )
    1684             : {
    1685        9636 :     CheckBoxFormat( pFormat )->Add( this );
    1686             : 
    1687             :     // insert into the table
    1688        9636 :     const SwTableNode* pTableNd = pSttNd->FindTableNode();
    1689             :     OSL_ENSURE( pTableNd, "In which table is the box?" );
    1690        9636 :     SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTableNd->GetTable().
    1691        9636 :                                 GetTabSortBoxes();
    1692        9636 :     SwTableBox* p = this;   // error: &this
    1693        9636 :     rSrtArr.insert( p );        // insert
    1694        9636 : }
    1695             : 
    1696         990 : void SwTableBox::RemoveFromTable()
    1697             : {
    1698         990 :     if (pSttNd) // box containing contents?
    1699             :     {
    1700             :         // remove from table
    1701           7 :         const SwTableNode* pTableNd = pSttNd->FindTableNode();
    1702             :         assert(pTableNd && "In which table is that box?");
    1703           7 :         SwTableSortBoxes& rSrtArr = (SwTableSortBoxes&)pTableNd->GetTable().
    1704           7 :                                     GetTabSortBoxes();
    1705           7 :         SwTableBox *p = this;   // error: &this
    1706           7 :         rSrtArr.erase( p );        // remove
    1707           7 :         pSttNd = 0; // clear it so this is only run once
    1708             :     }
    1709         990 : }
    1710             : 
    1711       35556 : SwTableBox::~SwTableBox()
    1712             : {
    1713       11852 :     if (!GetFrameFormat()->GetDoc()->IsInDtor())
    1714             :     {
    1715         990 :         RemoveFromTable();
    1716             :     }
    1717             : 
    1718             :     // the TabelleBox can be deleted if it's the last client of the FrameFormat
    1719       11852 :     SwModify* pMod = GetFrameFormat();
    1720       11852 :     pMod->Remove( this );               // remove,
    1721       11852 :     if( !pMod->HasWriterListeners() )
    1722       11177 :         delete pMod;    // and delete
    1723             : 
    1724       11852 :     delete pImpl;
    1725       23704 : }
    1726             : 
    1727       11856 : SwTableBoxFormat* SwTableBox::CheckBoxFormat( SwTableBoxFormat* pFormat )
    1728             : {
    1729             :     // We might need to create a new format here, because the box must be
    1730             :     // added to the format solely if pFormat has a value or formular.
    1731       23711 :     if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE, false ) ||
    1732       11855 :         SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMULA, false ) )
    1733             :     {
    1734           1 :         SwTableBox* pOther = SwIterator<SwTableBox,SwFormat>( *pFormat ).First();
    1735           1 :         if( pOther )
    1736             :         {
    1737           1 :             SwTableBoxFormat* pNewFormat = pFormat->GetDoc()->MakeTableBoxFormat();
    1738           1 :             pNewFormat->LockModify();
    1739           1 :             *pNewFormat = *pFormat;
    1740             : 
    1741             :             // Remove values and formulars
    1742           1 :             pNewFormat->ResetFormatAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
    1743           1 :             pNewFormat->UnlockModify();
    1744             : 
    1745           1 :             pFormat = pNewFormat;
    1746             :         }
    1747             :     }
    1748       11856 :     return pFormat;
    1749             : }
    1750             : 
    1751       94051 : SwFrameFormat* SwTableBox::ClaimFrameFormat()
    1752             : {
    1753             :     // This method makes sure that this object is an exclusive SwTableBox client
    1754             :     // of an SwTableBoxFormat object
    1755             :     // If other SwTableBox objects currently listen to the same SwTableBoxFormat as
    1756             :     // this one, something needs to be done
    1757       94051 :     SwTableBoxFormat *pRet = static_cast<SwTableBoxFormat*>(GetFrameFormat());
    1758       94051 :     SwIterator<SwTableBox,SwFormat> aIter( *pRet );
    1759      179552 :     for( SwTableBox* pLast = aIter.First(); pLast; pLast = aIter.Next() )
    1760             :     {
    1761       94605 :         if ( pLast != this )
    1762             :         {
    1763             :             // Found another SwTableBox object
    1764             :             // create a new Format as a copy and assign me to it
    1765             :             // don't copy values and formulas
    1766        9104 :             SwTableBoxFormat* pNewFormat = pRet->GetDoc()->MakeTableBoxFormat();
    1767        9104 :             pNewFormat->LockModify();
    1768        9104 :             *pNewFormat = *pRet;
    1769        9104 :             pNewFormat->ResetFormatAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
    1770        9104 :             pNewFormat->UnlockModify();
    1771             : 
    1772             :             // re-register SwCellFrm objects that know me
    1773        9104 :             SwIterator<SwCellFrm,SwFormat> aFrmIter( *pRet );
    1774        9449 :             for( SwCellFrm* pCell = aFrmIter.First(); pCell; pCell = aFrmIter.Next() )
    1775         345 :                 if( pCell->GetTabBox() == this )
    1776          64 :                     pCell->RegisterToFormat( *pNewFormat );
    1777             : 
    1778             :             // re-register myself
    1779        9104 :             pNewFormat->Add( this );
    1780        9104 :             pRet = pNewFormat;
    1781        9104 :             break;
    1782             :         }
    1783             :     }
    1784       94051 :     return pRet;
    1785             : }
    1786             : 
    1787         486 : void SwTableBox::ChgFrameFormat( SwTableBoxFormat* pNewFormat )
    1788             : {
    1789         486 :     SwFrameFormat *pOld = GetFrameFormat();
    1790         486 :     SwIterator<SwCellFrm,SwFormat> aIter( *pOld );
    1791             : 
    1792             :     // First, re-register the Frms.
    1793         596 :     for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() )
    1794             :     {
    1795         110 :         if( pCell->GetTabBox() == this )
    1796             :         {
    1797           6 :             pCell->RegisterToFormat( *pNewFormat );
    1798           6 :             pCell->InvalidateSize();
    1799           6 :             pCell->_InvalidatePrt();
    1800           6 :             pCell->SetCompletePaint();
    1801           6 :             pCell->SetDerivedVert( false );
    1802           6 :             pCell->CheckDirChange();
    1803             : 
    1804             :             // #i47489#
    1805             :             // make sure that the row will be formatted, in order
    1806             :             // to have the correct Get(Top|Bottom)MarginForLowers values
    1807             :             // set at the row.
    1808           6 :             const SwTabFrm* pTab = pCell->FindTabFrm();
    1809           6 :             if ( pTab && pTab->IsCollapsingBorders() )
    1810             :             {
    1811           6 :                 SwFrm* pRow = pCell->GetUpper();
    1812           6 :                 pRow->_InvalidateSize();
    1813           6 :                 pRow->_InvalidatePrt();
    1814             :             }
    1815             :         }
    1816             :     }
    1817             : 
    1818             :     // Now, re-register self.
    1819         486 :     pNewFormat->Add( this );
    1820             : 
    1821         486 :     if( !pOld->HasWriterListeners() )
    1822           2 :         delete pOld;
    1823         486 : }
    1824             : 
    1825             : // Return the name of this box. This is determined dynamically
    1826             : // resulting from the position in the lines/boxes/tables.
    1827       12687 : void sw_GetTableBoxColStr( sal_uInt16 nCol, OUString& rNm )
    1828             : {
    1829       12687 :     const sal_uInt16 coDiff = 52;   // 'A'-'Z' 'a' - 'z'
    1830             : 
    1831             :     do {
    1832       12687 :         const sal_uInt16 nCalc = nCol % coDiff;
    1833       12687 :         if( nCalc >= 26 )
    1834           0 :             rNm = OUString( sal_Unicode('a' - 26 + nCalc ) ) + rNm;
    1835             :         else
    1836       12687 :             rNm = OUString( sal_Unicode('A' + nCalc ) ) + rNm;
    1837             : 
    1838       12687 :         if( 0 == (nCol = nCol - nCalc) )
    1839       12687 :             break;
    1840           0 :         nCol /= coDiff;
    1841           0 :         --nCol;
    1842           0 :     } while( true );
    1843       12687 : }
    1844             : 
    1845           2 : Point SwTableBox::GetCoordinates() const
    1846             : {
    1847           2 :     if( !pSttNd )       // box without content?
    1848             :     {
    1849             :         // search for the next first box?
    1850           0 :         return Point( 0, 0 );
    1851             :     }
    1852             : 
    1853           2 :     const SwTable& rTable = pSttNd->FindTableNode()->GetTable();
    1854             :     sal_uInt16 nX, nY;
    1855           2 :     const SwTableBox* pBox = this;
    1856           2 :     do {
    1857           2 :         const SwTableBoxes* pBoxes = &pBox->GetUpper()->GetTabBoxes();
    1858           2 :         const SwTableLine* pLine = pBox->GetUpper();
    1859             :         // at the first level?
    1860           2 :         const SwTableLines* pLines = pLine->GetUpper()
    1861           2 :                 ? &pLine->GetUpper()->GetTabLines() : &rTable.GetTabLines();
    1862             : 
    1863           2 :         nY = pLines->GetPos( pLine ) + 1 ;
    1864           2 :         nX = pBoxes->GetPos( pBox ) + 1 ;
    1865           2 :         pBox = pLine->GetUpper();
    1866             :     } while( pBox );
    1867           2 :     return Point( nX, nY );
    1868             : }
    1869             : 
    1870         794 : OUString SwTableBox::GetName() const
    1871             : {
    1872         794 :     if( !pSttNd )       // box without content?
    1873             :     {
    1874             :         // search for the next first box?
    1875           0 :         return OUString();
    1876             :     }
    1877             : 
    1878         794 :     const SwTable& rTable = pSttNd->FindTableNode()->GetTable();
    1879             :     sal_uInt16 nPos;
    1880        1588 :     OUString sNm, sTmp;
    1881         794 :     const SwTableBox* pBox = this;
    1882         794 :     do {
    1883         794 :         const SwTableBoxes* pBoxes = &pBox->GetUpper()->GetTabBoxes();
    1884         794 :         const SwTableLine* pLine = pBox->GetUpper();
    1885             :         // at the first level?
    1886         794 :         const SwTableLines* pLines = pLine->GetUpper()
    1887         794 :                 ? &pLine->GetUpper()->GetTabLines() : &rTable.GetTabLines();
    1888             : 
    1889         794 :         sTmp = OUString::number( nPos = pLines->GetPos( pLine ) + 1 );
    1890         794 :         if( !sNm.isEmpty() )
    1891           0 :             sNm = sTmp + "." + sNm;
    1892             :         else
    1893         794 :             sNm = sTmp;
    1894             : 
    1895         794 :         sTmp = OUString::number(( nPos = pBoxes->GetPos( pBox )) + 1 );
    1896         794 :         if( 0 != ( pBox = pLine->GetUpper()) )
    1897           0 :             sNm = sTmp + "." + sNm;
    1898             :         else
    1899         794 :             sw_GetTableBoxColStr( nPos, sNm );
    1900             : 
    1901             :     } while( pBox );
    1902        1588 :     return sNm;
    1903             : }
    1904             : 
    1905         985 : bool SwTableBox::IsInHeadline( const SwTable* pTable ) const
    1906             : {
    1907         985 :     if( !GetUpper() )           // should only happen upon merge.
    1908           0 :         return false;
    1909             : 
    1910         985 :     if( !pTable )
    1911           0 :         pTable = &pSttNd->FindTableNode()->GetTable();
    1912             : 
    1913         985 :     const SwTableLine* pLine = GetUpper();
    1914        1970 :     while( pLine->GetUpper() )
    1915           0 :         pLine = pLine->GetUpper()->GetUpper();
    1916             : 
    1917             :     // Headerline?
    1918         985 :     return pTable->GetTabLines()[ 0 ] == pLine;
    1919             : }
    1920             : 
    1921      524598 : sal_uLong SwTableBox::GetSttIdx() const
    1922             : {
    1923      524598 :     return pSttNd ? pSttNd->GetIndex() : 0;
    1924             : }
    1925             : 
    1926             :     // retrieve information from the client
    1927        7366 : bool SwTable::GetInfo( SfxPoolItem& rInfo ) const
    1928             : {
    1929        7366 :     switch( rInfo.Which() )
    1930             :     {
    1931             :         case RES_AUTOFMT_DOCNODE:
    1932             :         {
    1933        3979 :             const SwTableNode* pNode = GetTableNode();
    1934        3979 :             if (pNode && &pNode->GetNodes() == static_cast<SwAutoFormatGetDocNode&>(rInfo).pNodes)
    1935             :             {
    1936        3977 :                 if (!m_TabSortContentBoxes.empty())
    1937             :                 {
    1938        3974 :                     SwNodeIndex aIdx( *m_TabSortContentBoxes[0]->GetSttNd() );
    1939             :                     static_cast<SwAutoFormatGetDocNode&>(rInfo).pContentNode =
    1940        3974 :                                     GetFrameFormat()->GetDoc()->GetNodes().GoNext( &aIdx );
    1941             :                 }
    1942        3977 :                 return false;
    1943             :             }
    1944           2 :             break;
    1945             :         }
    1946             :         case RES_FINDNEARESTNODE:
    1947       12936 :             if( GetFrameFormat() && static_cast<const SwFormatPageDesc&>(GetFrameFormat()->GetFormatAttr(
    1948        6468 :                 RES_PAGEDESC )).GetPageDesc() &&
    1949        9702 :                 !m_TabSortContentBoxes.empty() &&
    1950        3234 :                 m_TabSortContentBoxes[0]->GetSttNd()->GetNodes().IsDocNodes() )
    1951             :                 static_cast<SwFindNearestNode&>(rInfo).CheckNode( *
    1952        3234 :                     m_TabSortContentBoxes[0]->GetSttNd()->FindTableNode() );
    1953        3234 :             break;
    1954             : 
    1955             :         case RES_CONTENT_VISIBLE:
    1956           0 :             static_cast<SwPtrMsgPoolItem&>(rInfo).pObject = SwIterator<SwFrm,SwFormat>( *GetFrameFormat() ).First();
    1957           0 :             return false;
    1958             :     }
    1959        3389 :     return true;
    1960             : }
    1961             : 
    1962      148043 : SwTable * SwTable::FindTable( SwFrameFormat const*const pFormat )
    1963             : {
    1964             :     return (pFormat)
    1965      444129 :         ? SwIterator<SwTable,SwFormat>(*pFormat).First()
    1966      444129 :         : nullptr;
    1967             : }
    1968             : 
    1969        5910 : SwTableNode* SwTable::GetTableNode() const
    1970             : {
    1971        5910 :     return !GetTabSortBoxes().empty() ?
    1972        5907 :            const_cast<SwTableNode*>(GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode()) :
    1973       11817 :            pTableNode;
    1974             : }
    1975             : 
    1976           0 : void SwTable::SetRefObject( SwServerObject* pObj )
    1977             : {
    1978           0 :     if( refObj.Is() )
    1979           0 :         refObj->Closed();
    1980             : 
    1981           0 :     refObj = pObj;
    1982           0 : }
    1983             : 
    1984        2535 : void SwTable::SetHTMLTableLayout( SwHTMLTableLayout *p )
    1985             : {
    1986        2535 :     delete pHTMLLayout;
    1987        2535 :     pHTMLLayout = p;
    1988        2535 : }
    1989             : 
    1990          90 : void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
    1991             :                     bool bChgAlign )
    1992             : {
    1993          90 :     sal_uLong nNdPos = rBox.IsValidNumTextNd( true );
    1994          90 :     ChgTextToNum( rBox,rText,pCol,bChgAlign,nNdPos);
    1995          90 : }
    1996          96 : void ChgTextToNum( SwTableBox& rBox, const OUString& rText, const Color* pCol,
    1997             :                     bool bChgAlign,sal_uLong nNdPos )
    1998             : {
    1999             : 
    2000          96 :     if( ULONG_MAX != nNdPos )
    2001             :     {
    2002          96 :         SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
    2003          96 :         SwTextNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTextNode();
    2004             :         const SfxPoolItem* pItem;
    2005             : 
    2006             :         // assign adjustment
    2007          96 :         if( bChgAlign )
    2008             :         {
    2009           0 :             pItem = &pTNd->SwContentNode::GetAttr( RES_PARATR_ADJUST );
    2010           0 :             SvxAdjust eAdjust = static_cast<const SvxAdjustItem*>(pItem)->GetAdjust();
    2011           0 :             if( SVX_ADJUST_LEFT == eAdjust || SVX_ADJUST_BLOCK == eAdjust )
    2012             :             {
    2013           0 :                 SvxAdjustItem aAdjust( *static_cast<const SvxAdjustItem*>(pItem) );
    2014           0 :                 aAdjust.SetAdjust( SVX_ADJUST_RIGHT );
    2015           0 :                 pTNd->SetAttr( aAdjust );
    2016             :             }
    2017             :         }
    2018             : 
    2019             :         // assign color or save "user color"
    2020         142 :         if( !pTNd->GetpSwAttrSet() || SfxItemState::SET != pTNd->GetpSwAttrSet()->
    2021          46 :             GetItemState( RES_CHRATR_COLOR, false, &pItem ))
    2022          50 :             pItem = 0;
    2023             : 
    2024          96 :         const Color* pOldNumFormatColor = rBox.GetSaveNumFormatColor();
    2025          96 :         const Color* pNewUserColor = pItem ? &static_cast<const SvxColorItem*>(pItem)->GetValue() : 0;
    2026             : 
    2027         142 :         if( ( pNewUserColor && pOldNumFormatColor &&
    2028         242 :                 *pNewUserColor == *pOldNumFormatColor ) ||
    2029          50 :             ( !pNewUserColor && !pOldNumFormatColor ))
    2030             :         {
    2031             :             // Keep the user color, set updated values, delete old NumFormatColor if needed
    2032          50 :             if( pCol )
    2033             :                 // if needed, set the color
    2034           0 :                 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
    2035          50 :             else if( pItem )
    2036             :             {
    2037           0 :                 pNewUserColor = rBox.GetSaveUserColor();
    2038           0 :                 if( pNewUserColor )
    2039           0 :                     pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
    2040             :                 else
    2041           0 :                     pTNd->ResetAttr( RES_CHRATR_COLOR );
    2042             :             }
    2043             :         }
    2044             :         else
    2045             :         {
    2046             :             // Save user color, set NumFormat color if needed, but never reset the color
    2047          46 :             rBox.SetSaveUserColor( pNewUserColor );
    2048             : 
    2049          46 :             if( pCol )
    2050             :                 // if needed, set the color
    2051           0 :                 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
    2052             : 
    2053             :         }
    2054          96 :         rBox.SetSaveNumFormatColor( pCol );
    2055             : 
    2056          96 :         if( pTNd->GetText() != rText )
    2057             :         {
    2058             :             // Exchange text. Bugfix to keep Tabs (front and back!)
    2059          96 :             const OUString& rOrig = pTNd->GetText();
    2060             :             sal_Int32 n;
    2061             : 
    2062          96 :             for( n = 0; n < rOrig.getLength() && '\x9' == rOrig[n]; ++n )
    2063             :                 ;
    2064          96 :             for( ; n < rOrig.getLength() && '\x01' == rOrig[n]; ++n )
    2065             :                 ;
    2066          96 :             SwIndex aIdx( pTNd, n );
    2067          96 :             for( n = rOrig.getLength(); n && '\x9' == rOrig[--n]; )
    2068             :                 ;
    2069          96 :             n -= aIdx.GetIndex() - 1;
    2070             : 
    2071             :             // Reset DontExpand-Flags before exchange, to retrigger expansion
    2072             :             {
    2073          96 :                 SwIndex aResetIdx( aIdx, n );
    2074          96 :                 pTNd->DontExpandFormat( aResetIdx, false, false );
    2075             :             }
    2076             : 
    2077          96 :             if( !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() )
    2078             :             {
    2079           0 :                 SwPaM aTemp(*pTNd, 0, *pTNd, rOrig.getLength());
    2080           0 :                 pDoc->getIDocumentRedlineAccess().DeleteRedline(aTemp, true, USHRT_MAX);
    2081             :             }
    2082             : 
    2083          96 :             pTNd->EraseText( aIdx, n, SwInsertFlags::EMPTYEXPAND );
    2084          96 :             pTNd->InsertText( rText, aIdx, SwInsertFlags::EMPTYEXPAND );
    2085             : 
    2086          96 :             if( pDoc->getIDocumentRedlineAccess().IsRedlineOn() )
    2087             :             {
    2088           0 :                 SwPaM aTemp(*pTNd, 0, *pTNd, rText.getLength());
    2089           0 :                 pDoc->getIDocumentRedlineAccess().AppendRedline(new SwRangeRedline(nsRedlineType_t::REDLINE_INSERT, aTemp), true);
    2090          96 :             }
    2091             :         }
    2092             : 
    2093             :         // assign vertical orientation
    2094          96 :         if( bChgAlign &&
    2095           0 :             ( SfxItemState::SET != rBox.GetFrameFormat()->GetItemState(
    2096           0 :                 RES_VERT_ORIENT, true, &pItem ) ||
    2097           0 :                 text::VertOrientation::TOP == static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient() ))
    2098             :         {
    2099           0 :             rBox.GetFrameFormat()->SetFormatAttr( SwFormatVertOrient( 0, text::VertOrientation::BOTTOM ));
    2100             :         }
    2101             :     }
    2102          96 : }
    2103             : 
    2104           5 : void ChgNumToText( SwTableBox& rBox, sal_uLong nFormat )
    2105             : {
    2106           5 :     sal_uLong nNdPos = rBox.IsValidNumTextNd( false );
    2107           5 :     if( ULONG_MAX != nNdPos )
    2108             :     {
    2109           5 :         SwDoc* pDoc = rBox.GetFrameFormat()->GetDoc();
    2110           5 :         SwTextNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTextNode();
    2111           5 :         bool bChgAlign = pDoc->IsInsTableAlignNum();
    2112             :         const SfxPoolItem* pItem;
    2113             : 
    2114           5 :         Color* pCol = 0;
    2115           5 :         if( css::util::NumberFormat::TEXT != static_cast<sal_Int16>(nFormat) )
    2116             :         {
    2117             :             // special text format:
    2118           0 :             OUString sTmp;
    2119           0 :             const OUString sText( pTNd->GetText() );
    2120           0 :             pDoc->GetNumberFormatter()->GetOutputString( sText, nFormat, sTmp, &pCol );
    2121           0 :             if( sText != sTmp )
    2122             :             {
    2123             :                 // exchange text
    2124           0 :                 SwIndex aIdx( pTNd, sText.getLength() );
    2125             :                 // Reset DontExpand-Flags before exchange, to retrigger expansion
    2126           0 :                 pTNd->DontExpandFormat( aIdx, false, false );
    2127           0 :                 aIdx = 0;
    2128           0 :                 pTNd->EraseText( aIdx, SAL_MAX_INT32, SwInsertFlags::EMPTYEXPAND );
    2129           0 :                 pTNd->InsertText( sTmp, aIdx, SwInsertFlags::EMPTYEXPAND );
    2130           0 :             }
    2131             :         }
    2132             : 
    2133           5 :         const SfxItemSet* pAttrSet = pTNd->GetpSwAttrSet();
    2134             : 
    2135             :         // assign adjustment
    2136           5 :         if( bChgAlign && pAttrSet && SfxItemState::SET == pAttrSet->GetItemState(
    2137           5 :             RES_PARATR_ADJUST, false, &pItem ) &&
    2138           0 :                 SVX_ADJUST_RIGHT == static_cast<const SvxAdjustItem*>(pItem)->GetAdjust() )
    2139             :         {
    2140           0 :             pTNd->SetAttr( SvxAdjustItem( SVX_ADJUST_LEFT, RES_PARATR_ADJUST ) );
    2141             :         }
    2142             : 
    2143             :         // assign color or save "user color"
    2144           5 :         if( !pAttrSet || SfxItemState::SET != pAttrSet->
    2145           0 :             GetItemState( RES_CHRATR_COLOR, false, &pItem ))
    2146           5 :             pItem = 0;
    2147             : 
    2148           5 :         const Color* pOldNumFormatColor = rBox.GetSaveNumFormatColor();
    2149           5 :         const Color* pNewUserColor = pItem ? &static_cast<const SvxColorItem*>(pItem)->GetValue() : 0;
    2150             : 
    2151           5 :         if( ( pNewUserColor && pOldNumFormatColor &&
    2152          15 :                 *pNewUserColor == *pOldNumFormatColor ) ||
    2153           5 :             ( !pNewUserColor && !pOldNumFormatColor ))
    2154             :         {
    2155             :             // Keep the user color, set updated values, delete old NumFormatColor if needed
    2156           5 :             if( pCol )
    2157             :                 // if needed, set the color
    2158           0 :                 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
    2159           5 :             else if( pItem )
    2160             :             {
    2161           0 :                 pNewUserColor = rBox.GetSaveUserColor();
    2162           0 :                 if( pNewUserColor )
    2163           0 :                     pTNd->SetAttr( SvxColorItem( *pNewUserColor, RES_CHRATR_COLOR ));
    2164             :                 else
    2165           0 :                     pTNd->ResetAttr( RES_CHRATR_COLOR );
    2166             :             }
    2167             :         }
    2168             :         else
    2169             :         {
    2170             :             // Save user color, set NumFormat color if needed, but never reset the color
    2171           0 :             rBox.SetSaveUserColor( pNewUserColor );
    2172             : 
    2173           0 :             if( pCol )
    2174             :                 // if needed, set the color
    2175           0 :                 pTNd->SetAttr( SvxColorItem( *pCol, RES_CHRATR_COLOR ));
    2176             : 
    2177             :         }
    2178           5 :         rBox.SetSaveNumFormatColor( pCol );
    2179             : 
    2180             :         // assign vertical orientation
    2181           5 :         if( bChgAlign &&
    2182           0 :             SfxItemState::SET == rBox.GetFrameFormat()->GetItemState(
    2183           5 :             RES_VERT_ORIENT, false, &pItem ) &&
    2184           0 :             text::VertOrientation::BOTTOM == static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient() )
    2185             :         {
    2186           0 :             rBox.GetFrameFormat()->SetFormatAttr( SwFormatVertOrient( 0, text::VertOrientation::TOP ));
    2187             :         }
    2188             :     }
    2189           5 : }
    2190             : 
    2191             : // for detection of modifications (mainly TableBoxAttribute)
    2192       89948 : void SwTableBoxFormat::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
    2193             : {
    2194       89948 :     if( !IsModifyLocked() && !IsInDocDTOR() )
    2195             :     {
    2196       80843 :         const SwTableBoxNumFormat *pNewFormat = 0;
    2197       80843 :         const SwTableBoxFormula *pNewFormula = 0;
    2198       80843 :         const SwTableBoxValue *pNewVal = 0;
    2199       80843 :         sal_uLong nOldFormat = css::util::NumberFormat::TEXT;
    2200             : 
    2201       80843 :         switch( pNew ? pNew->Which() : 0 )
    2202             :         {
    2203             :             case RES_ATTRSET_CHG:
    2204             :             {
    2205       70263 :                 const SfxItemSet& rSet = *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet();
    2206       70263 :                 if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMAT,
    2207       70263 :                                     false, reinterpret_cast<const SfxPoolItem**>(&pNewFormat) ) )
    2208             :                     nOldFormat = static_cast<const SwTableBoxNumFormat&>(static_cast<const SwAttrSetChg*>(pOld)->
    2209          80 :                             GetChgSet()->Get( RES_BOXATR_FORMAT )).GetValue();
    2210             :                 rSet.GetItemState( RES_BOXATR_FORMULA, false,
    2211       70263 :                                     reinterpret_cast<const SfxPoolItem**>(&pNewFormula) );
    2212             :                 rSet.GetItemState( RES_BOXATR_VALUE, false,
    2213       70263 :                                     reinterpret_cast<const SfxPoolItem**>(&pNewVal) );
    2214       70263 :                 break;
    2215             :             }
    2216             :             case RES_BOXATR_FORMAT:
    2217           0 :                 pNewFormat = static_cast<const SwTableBoxNumFormat*>(pNew);
    2218           0 :                 nOldFormat = static_cast<const SwTableBoxNumFormat*>(pOld)->GetValue();
    2219           0 :                 break;
    2220             :             case RES_BOXATR_FORMULA:
    2221           0 :                 pNewFormula = static_cast<const SwTableBoxFormula*>(pNew);
    2222           0 :                 break;
    2223             :             case RES_BOXATR_VALUE:
    2224           0 :                 pNewVal = static_cast<const SwTableBoxValue*>(pNew);
    2225           0 :                 break;
    2226             :         }
    2227             : 
    2228             :         // something changed and some BoxAttribut remained in the set!
    2229       80843 :         if( pNewFormat || pNewFormula || pNewVal )
    2230             :         {
    2231          96 :             GetDoc()->getIDocumentFieldsAccess().SetFieldsDirty(true, NULL, 0);
    2232             : 
    2233         198 :             if( SfxItemState::SET == GetItemState( RES_BOXATR_FORMAT, false ) ||
    2234          97 :                 SfxItemState::SET == GetItemState( RES_BOXATR_VALUE, false ) ||
    2235           1 :                 SfxItemState::SET == GetItemState( RES_BOXATR_FORMULA, false ) )
    2236             :             {
    2237             :                 // fetch the box
    2238          95 :                 SwIterator<SwTableBox,SwFormat> aIter( *this );
    2239          95 :                 SwTableBox* pBox = aIter.First();
    2240          95 :                 if( pBox )
    2241             :                 {
    2242             :                     OSL_ENSURE( !aIter.Next(), "zeor or more than one box at format" );
    2243             : 
    2244             :                     sal_uLong nNewFormat;
    2245          95 :                     if( pNewFormat )
    2246             :                     {
    2247          79 :                         nNewFormat = pNewFormat->GetValue();
    2248             :                         // new formatting
    2249             :                         // is it newer or has the current been removed?
    2250          79 :                         if( SfxItemState::SET != GetItemState( RES_BOXATR_VALUE, false ))
    2251           0 :                             pNewFormat = 0;
    2252             :                     }
    2253             :                     else
    2254             :                     {
    2255             :                         // fetch the current Item
    2256             :                         GetItemState( RES_BOXATR_FORMAT, false,
    2257          16 :                                             reinterpret_cast<const SfxPoolItem**>(&pNewFormat) );
    2258          16 :                         nOldFormat = GetTableBoxNumFormat().GetValue();
    2259          16 :                         nNewFormat = pNewFormat ? pNewFormat->GetValue() : nOldFormat;
    2260             :                     }
    2261             : 
    2262             :                     // is it newer or has the current been removed?
    2263          95 :                     if( pNewVal )
    2264             :                     {
    2265          95 :                         if( css::util::NumberFormat::TEXT != static_cast<sal_Int16>(nNewFormat) )
    2266             :                         {
    2267          90 :                             if( SfxItemState::SET == GetItemState( RES_BOXATR_VALUE, false ))
    2268          90 :                                 nOldFormat = css::util::NumberFormat::TEXT;
    2269             :                             else
    2270           0 :                                 nNewFormat = css::util::NumberFormat::TEXT;
    2271             :                         }
    2272           5 :                         else if( css::util::NumberFormat::TEXT == static_cast<sal_Int16>(nNewFormat) )
    2273           5 :                             nOldFormat = 0;
    2274             :                     }
    2275             : 
    2276             :                     // Logic:
    2277             :                     // Value change: -> "simulate" a format change!
    2278             :                     // Format change:
    2279             :                     // Text -> !Text or format change:
    2280             :                     //          - align right for horizontal alignment, if LEFT or JUSTIFIED
    2281             :                     //          - align bottom for vertical alignment, if TOP is set, or default
    2282             :                     //          - replace text (color? negative numbers RED?)
    2283             :                     // !Text -> Text:
    2284             :                     //          - align left for horizontal alignment, if RIGHT
    2285             :                     //          - align top for vertical alignment, if BOTTOM is set
    2286          95 :                     SvNumberFormatter* pNumFormatr = GetDoc()->GetNumberFormatter();
    2287         190 :                     bool bNewIsTextFormat = pNumFormatr->IsTextFormat( nNewFormat ) ||
    2288         190 :                                         css::util::NumberFormat::TEXT == static_cast<sal_Int16>(nNewFormat);
    2289             : 
    2290          95 :                     if( (!bNewIsTextFormat && nOldFormat != nNewFormat) || pNewFormula )
    2291             :                     {
    2292          90 :                         bool bChgText = true;
    2293          90 :                         double fVal = 0;
    2294          90 :                         if( !pNewVal && SfxItemState::SET != GetItemState(
    2295           0 :                             RES_BOXATR_VALUE, false, reinterpret_cast<const SfxPoolItem**>(&pNewVal) ))
    2296             :                         {
    2297             :                             // so far, no value has been set, so try to evaluate the content
    2298           0 :                             sal_uLong nNdPos = pBox->IsValidNumTextNd( true );
    2299           0 :                             if( ULONG_MAX != nNdPos )
    2300             :                             {
    2301           0 :                                 sal_uInt32 nTmpFormatIdx = nNewFormat;
    2302           0 :                                 OUString aText( GetDoc()->GetNodes()[ nNdPos ]
    2303           0 :                                                 ->GetTextNode()->GetRedlineText());
    2304           0 :                                 if( aText.isEmpty() )
    2305           0 :                                     bChgText = false;
    2306             :                                 else
    2307             :                                 {
    2308             :                                     // Keep Tabs
    2309           0 :                                     lcl_TabToBlankAtSttEnd( aText );
    2310             : 
    2311             :                                     // JP 22.04.98: Bug 49659 -
    2312             :                                     //  Special casing for percent
    2313           0 :                                     bool bIsNumFormat = false;
    2314           0 :                                     if( css::util::NumberFormat::PERCENT ==
    2315           0 :                                         pNumFormatr->GetType( nNewFormat ))
    2316             :                                     {
    2317           0 :                                         sal_uInt32 nTmpFormat = 0;
    2318           0 :                                         if( pNumFormatr->IsNumberFormat(
    2319             :                                                     aText, nTmpFormat, fVal ))
    2320             :                                         {
    2321           0 :                                             if( css::util::NumberFormat::NUMBER ==
    2322           0 :                                                 pNumFormatr->GetType( nTmpFormat ))
    2323           0 :                                                 aText += "%";
    2324             : 
    2325             :                                             bIsNumFormat = pNumFormatr->IsNumberFormat(
    2326           0 :                                                         aText, nTmpFormatIdx, fVal );
    2327             :                                         }
    2328             :                                     }
    2329             :                                     else
    2330             :                                         bIsNumFormat = pNumFormatr->IsNumberFormat(
    2331           0 :                                                         aText, nTmpFormatIdx, fVal );
    2332             : 
    2333           0 :                                     if( bIsNumFormat )
    2334             :                                     {
    2335             :                                         // directly assign value - without Modify
    2336           0 :                                         bool bIsLockMod = IsModifyLocked();
    2337           0 :                                         LockModify();
    2338           0 :                                         SetFormatAttr( SwTableBoxValue( fVal ));
    2339           0 :                                         if( !bIsLockMod )
    2340           0 :                                             UnlockModify();
    2341             :                                     }
    2342           0 :                                 }
    2343             :                             }
    2344             :                         }
    2345             :                         else
    2346          90 :                             fVal = pNewVal->GetValue();
    2347             : 
    2348             :                         // format contents with the new value assigned and write to paragraph
    2349          90 :                         Color* pCol = 0;
    2350          90 :                         OUString sNewText;
    2351          90 :                         if( DBL_MAX == fVal )
    2352             :                         {
    2353           0 :                             sNewText = SwViewShell::GetShellRes()->aCalc_Error;
    2354             :                         }
    2355             :                         else
    2356             :                         {
    2357          90 :                             pNumFormatr->GetOutputString( fVal, nNewFormat, sNewText, &pCol );
    2358             : 
    2359          90 :                             if( !bChgText )
    2360             :                             {
    2361           0 :                                 sNewText.clear();
    2362             :                             }
    2363             :                         }
    2364             : 
    2365             :                         // across all boxes
    2366             :                         ChgTextToNum( *pBox, sNewText, pCol,
    2367          90 :                                         GetDoc()->IsInsTableAlignNum() );
    2368             : 
    2369             :                     }
    2370           5 :                     else if( bNewIsTextFormat && nOldFormat != nNewFormat )
    2371             :                     {
    2372           5 :                         ChgNumToText( *pBox, nNewFormat );
    2373             :                     }
    2374          95 :                 }
    2375             :             }
    2376             :         }
    2377             :     }
    2378             :     // call base class
    2379       89948 :     SwFrameFormat::Modify( pOld, pNew );
    2380       89948 : }
    2381             : 
    2382      109496 : bool SwTableBoxFormat::supportsFullDrawingLayerFillAttributeSet() const
    2383             : {
    2384      109496 :     return false;
    2385             : }
    2386             : 
    2387       18620 : bool SwTableFormat::supportsFullDrawingLayerFillAttributeSet() const
    2388             : {
    2389       18620 :     return false;
    2390             : }
    2391             : 
    2392       22481 : bool SwTableLineFormat::supportsFullDrawingLayerFillAttributeSet() const
    2393             : {
    2394       22481 :     return false;
    2395             : }
    2396             : 
    2397           0 : bool SwTableBox::HasNumContent( double& rNum, sal_uInt32& rFormatIndex,
    2398             :                             bool& rIsEmptyTextNd ) const
    2399             : {
    2400           0 :     bool bRet = false;
    2401           0 :     sal_uLong nNdPos = IsValidNumTextNd( true );
    2402           0 :     if( ULONG_MAX != nNdPos )
    2403             :     {
    2404           0 :         OUString aText( pSttNd->GetNodes()[ nNdPos ]->GetTextNode()->GetRedlineText() );
    2405             :         // Keep Tabs
    2406           0 :         lcl_TabToBlankAtSttEnd( aText );
    2407           0 :         rIsEmptyTextNd = aText.isEmpty();
    2408           0 :         SvNumberFormatter* pNumFormatr = GetFrameFormat()->GetDoc()->GetNumberFormatter();
    2409             : 
    2410             :         const SfxPoolItem* pItem;
    2411           0 :         if( SfxItemState::SET == GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT, false, &pItem ))
    2412             :         {
    2413           0 :             rFormatIndex = static_cast<const SwTableBoxNumFormat*>(pItem)->GetValue();
    2414             :             // Special casing for percent
    2415           0 :             if( !rIsEmptyTextNd && css::util::NumberFormat::PERCENT == pNumFormatr->GetType( rFormatIndex ))
    2416             :             {
    2417           0 :                 sal_uInt32 nTmpFormat = 0;
    2418           0 :                 if( pNumFormatr->IsNumberFormat( aText, nTmpFormat, rNum ) &&
    2419           0 :                     css::util::NumberFormat::NUMBER == pNumFormatr->GetType( nTmpFormat ))
    2420           0 :                     aText += "%";
    2421             :             }
    2422             :         }
    2423             :         else
    2424           0 :             rFormatIndex = 0;
    2425             : 
    2426           0 :         bRet = pNumFormatr->IsNumberFormat( aText, rFormatIndex, rNum );
    2427             :     }
    2428             :     else
    2429           0 :         rIsEmptyTextNd = false;
    2430           0 :     return bRet;
    2431             : }
    2432             : 
    2433           0 : bool SwTableBox::IsNumberChanged() const
    2434             : {
    2435           0 :     bool bRet = true;
    2436             : 
    2437           0 :     if( SfxItemState::SET == GetFrameFormat()->GetItemState( RES_BOXATR_FORMULA, false ))
    2438             :     {
    2439             :         const SwTableBoxNumFormat *pNumFormat;
    2440             :         const SwTableBoxValue *pValue;
    2441             : 
    2442           0 :         if( SfxItemState::SET != GetFrameFormat()->GetItemState( RES_BOXATR_VALUE, false,
    2443           0 :             reinterpret_cast<const SfxPoolItem**>(&pValue) ))
    2444           0 :             pValue = 0;
    2445           0 :         if( SfxItemState::SET != GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT, false,
    2446           0 :             reinterpret_cast<const SfxPoolItem**>(&pNumFormat) ))
    2447           0 :             pNumFormat = 0;
    2448             : 
    2449             :         sal_uLong nNdPos;
    2450           0 :         if( pNumFormat && pValue && ULONG_MAX != ( nNdPos = IsValidNumTextNd( true ) ) )
    2451             :         {
    2452           0 :             OUString sNewText, sOldText( pSttNd->GetNodes()[ nNdPos ]->
    2453           0 :                                     GetTextNode()->GetRedlineText() );
    2454           0 :             lcl_DelTabsAtSttEnd( sOldText );
    2455             : 
    2456           0 :             Color* pCol = 0;
    2457           0 :             GetFrameFormat()->GetDoc()->GetNumberFormatter()->GetOutputString(
    2458           0 :                 pValue->GetValue(), pNumFormat->GetValue(), sNewText, &pCol );
    2459             : 
    2460           0 :             bRet = sNewText != sOldText ||
    2461           0 :                     !( ( !pCol && !GetSaveNumFormatColor() ) ||
    2462           0 :                        ( pCol && GetSaveNumFormatColor() &&
    2463           0 :                         *pCol == *GetSaveNumFormatColor() ));
    2464             :         }
    2465             :     }
    2466           0 :     return bRet;
    2467             : }
    2468             : 
    2469         282 : sal_uLong SwTableBox::IsValidNumTextNd( bool bCheckAttr ) const
    2470             : {
    2471         282 :     sal_uLong nPos = ULONG_MAX;
    2472         282 :     if( pSttNd )
    2473             :     {
    2474         282 :         SwNodeIndex aIdx( *pSttNd );
    2475         282 :         sal_uLong nIndex = aIdx.GetIndex();
    2476         282 :         const sal_uLong nIndexEnd = pSttNd->GetNodes()[ nIndex ]->EndOfSectionIndex();
    2477         282 :         const SwTextNode *pTextNode = 0;
    2478         846 :         while( ++nIndex < nIndexEnd )
    2479             :         {
    2480         282 :             const SwNode* pNode = pSttNd->GetNodes()[nIndex];
    2481         282 :             if( pNode->IsTableNode() )
    2482             :             {
    2483           0 :                 pTextNode = 0;
    2484           0 :                 break;
    2485             :             }
    2486         282 :             if( pNode->IsTextNode() )
    2487             :             {
    2488         282 :                 if( pTextNode )
    2489             :                 {
    2490           0 :                     pTextNode = 0;
    2491           0 :                     break;
    2492             :                 }
    2493             :                 else
    2494             :                 {
    2495         282 :                     pTextNode = pNode->GetTextNode();
    2496         282 :                     nPos = nIndex;
    2497             :                 }
    2498             :             }
    2499             :         }
    2500         282 :         if( pTextNode )
    2501             :         {
    2502         282 :             if( bCheckAttr )
    2503             :             {
    2504         187 :                 const SwpHints* pHts = pTextNode->GetpSwpHints();
    2505             :                 // do some tests if there's only text in the node!
    2506             :                 // Flys/fields/...
    2507         187 :                 if( pHts )
    2508             :                 {
    2509          40 :                     sal_Int32 nNextSetField = 0;
    2510         120 :                     for( size_t n = 0; n < pHts->Count(); ++n )
    2511             :                     {
    2512          80 :                         const SwTextAttr* pAttr = (*pHts)[ n ];
    2513          80 :                         if( RES_TXTATR_NOEND_BEGIN <= pAttr->Which() )
    2514             :                         {
    2515           0 :                             if ( (pAttr->GetStart() == nNextSetField)
    2516           0 :                                  && (pAttr->Which() == RES_TXTATR_FIELD))
    2517             :                             {
    2518             :                                 // #i104949# hideous hack for report builder:
    2519             :                                 // it inserts hidden variable-set fields at
    2520             :                                 // the beginning of para in cell, but they
    2521             :                                 // should not turn cell into text cell
    2522           0 :                                 const SwField* pField = pAttr->GetFormatField().GetField();
    2523           0 :                                 if (pField &&
    2524           0 :                                     (pField->GetTypeId() == TYP_SETFLD) &&
    2525             :                                     (0 != (static_cast<SwSetExpField const*>
    2526           0 :                                            (pField)->GetSubType() &
    2527             :                                         nsSwExtendedSubType::SUB_INVISIBLE)))
    2528             :                                 {
    2529           0 :                                     nNextSetField = pAttr->GetStart() + 1;
    2530           0 :                                     continue;
    2531             :                                 }
    2532             :                             }
    2533           0 :                             nPos = ULONG_MAX;
    2534           0 :                             break;
    2535             :                         }
    2536             :                     }
    2537             :                 }
    2538             :             }
    2539             :         }
    2540             :         else
    2541           0 :             nPos = ULONG_MAX;
    2542             :     }
    2543         282 :     return nPos;
    2544             : }
    2545             : 
    2546             : // is this a Formula box or one with numeric content (AutoSum)
    2547           0 : sal_uInt16 SwTableBox::IsFormulaOrValueBox() const
    2548             : {
    2549           0 :     sal_uInt16 nWhich = 0;
    2550             :     const SwTextNode* pTNd;
    2551           0 :     SwFrameFormat* pFormat = GetFrameFormat();
    2552           0 :     if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMULA, false ))
    2553           0 :         nWhich = RES_BOXATR_FORMULA;
    2554           0 :     else if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE, false ) &&
    2555             :             !pFormat->GetDoc()->GetNumberFormatter()->IsTextFormat(
    2556           0 :                 pFormat->GetTableBoxNumFormat().GetValue() ))
    2557           0 :         nWhich = RES_BOXATR_VALUE;
    2558           0 :     else if( pSttNd && pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex()
    2559           0 :             && 0 != ( pTNd = pSttNd->GetNodes()[ pSttNd->GetIndex() + 1 ]
    2560           0 :             ->GetTextNode() ) && pTNd->GetText().isEmpty())
    2561           0 :         nWhich = USHRT_MAX;
    2562             : 
    2563           0 :     return nWhich;
    2564             : }
    2565             : 
    2566         957 : void SwTableBox::ActualiseValueBox()
    2567             : {
    2568             :     const SfxPoolItem *pFormatItem, *pValItem;
    2569         957 :     SwFrameFormat* pFormat = GetFrameFormat();
    2570        1914 :     if( SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_FORMAT, true, &pFormatItem )
    2571         957 :         && SfxItemState::SET == pFormat->GetItemState( RES_BOXATR_VALUE, true, &pValItem ))
    2572             :     {
    2573           6 :         const sal_uLong nFormatId = static_cast<const SwTableBoxNumFormat*>(pFormatItem)->GetValue();
    2574           6 :         sal_uLong nNdPos = ULONG_MAX;
    2575           6 :         SvNumberFormatter* pNumFormatr = pFormat->GetDoc()->GetNumberFormatter();
    2576             : 
    2577           6 :         if( !pNumFormatr->IsTextFormat( nFormatId ) &&
    2578             :             ULONG_MAX != (nNdPos = IsValidNumTextNd( true )) )
    2579             :         {
    2580           6 :             double fVal = static_cast<const SwTableBoxValue*>(pValItem)->GetValue();
    2581           6 :             Color* pCol = 0;
    2582           6 :             OUString sNewText;
    2583           6 :             pNumFormatr->GetOutputString( fVal, nFormatId, sNewText, &pCol );
    2584             : 
    2585           6 :             const OUString& rText = pSttNd->GetNodes()[ nNdPos ]->GetTextNode()->GetText();
    2586           6 :             if( rText != sNewText )
    2587           6 :                 ChgTextToNum( *this, sNewText, pCol, false ,nNdPos);
    2588             :         }
    2589             :     }
    2590         957 : }
    2591             : 
    2592          92 : void SwTableBox_Impl::SetNewCol( Color** ppCol, const Color* pNewCol )
    2593             : {
    2594          92 :     if( *ppCol != pNewCol )
    2595             :     {
    2596          46 :         delete *ppCol;
    2597          46 :         if( pNewCol )
    2598          46 :             *ppCol = new Color( *pNewCol );
    2599             :         else
    2600           0 :             *ppCol = 0;
    2601             :     }
    2602          92 : }
    2603             : 
    2604             : struct SwTableCellInfo::Impl
    2605             : {
    2606             :     const SwTable * m_pTable;
    2607             :     const SwCellFrm * m_pCellFrm;
    2608             :     const SwTabFrm * m_pTabFrm;
    2609             :     typedef ::std::set<const SwTableBox *> TableBoxes_t;
    2610             :     TableBoxes_t m_HandledTableBoxes;
    2611             : 
    2612             : public:
    2613           8 :     Impl()
    2614           8 :         : m_pTable(NULL), m_pCellFrm(NULL), m_pTabFrm(NULL)
    2615             :     {
    2616           8 :     }
    2617             : 
    2618           8 :     ~Impl() {}
    2619             : 
    2620           8 :     void setTable(const SwTable * pTable)
    2621             :     {
    2622           8 :         m_pTable = pTable;
    2623           8 :         SwFrameFormat * pFrameFormat = m_pTable->GetFrameFormat();
    2624           8 :         m_pTabFrm = SwIterator<SwTabFrm,SwFormat>(*pFrameFormat).First();
    2625           8 :         if (m_pTabFrm && m_pTabFrm->IsFollow())
    2626           0 :             m_pTabFrm = m_pTabFrm->FindMaster(true);
    2627           8 :     }
    2628             : 
    2629         228 :     const SwCellFrm * getCellFrm() const { return m_pCellFrm; }
    2630             : 
    2631             :     const SwFrm * getNextFrmInTable(const SwFrm * pFrm);
    2632             :     const SwCellFrm * getNextCellFrm(const SwFrm * pFrm);
    2633             :     const SwCellFrm * getNextTableBoxsCellFrm(const SwFrm * pFrm);
    2634             :     bool getNext();
    2635             : };
    2636             : 
    2637         151 : const SwFrm * SwTableCellInfo::Impl::getNextFrmInTable(const SwFrm * pFrm)
    2638             : {
    2639         151 :     const SwFrm * pResult = NULL;
    2640             : 
    2641         151 :     if (((! pFrm->IsTabFrm()) || pFrm == m_pTabFrm) && pFrm->GetLower())
    2642         101 :         pResult = pFrm->GetLower();
    2643          50 :     else if (pFrm->GetNext())
    2644           1 :         pResult = pFrm->GetNext();
    2645             :     else
    2646             :     {
    2647         150 :         while (pFrm->GetUpper() != NULL)
    2648             :         {
    2649         101 :             pFrm = pFrm->GetUpper();
    2650             : 
    2651         101 :             if (pFrm->IsTabFrm())
    2652             :             {
    2653           8 :                 m_pTabFrm = static_cast<const SwTabFrm *>(pFrm)->GetFollow();
    2654           8 :                 pResult = m_pTabFrm;
    2655           8 :                 break;
    2656             :             }
    2657          93 :             else if (pFrm->GetNext())
    2658             :             {
    2659          41 :                 pResult = pFrm->GetNext();
    2660          41 :                 break;
    2661             :             }
    2662             :         }
    2663             :     }
    2664             : 
    2665         151 :     return pResult;
    2666             : }
    2667             : 
    2668          65 : const SwCellFrm * SwTableCellInfo::Impl::getNextCellFrm(const SwFrm * pFrm)
    2669             : {
    2670          65 :     const SwCellFrm * pResult = NULL;
    2671             : 
    2672         216 :     while ((pFrm = getNextFrmInTable(pFrm)) != NULL)
    2673             :     {
    2674         143 :         if (pFrm->IsCellFrm())
    2675             :         {
    2676          57 :             pResult = static_cast<const SwCellFrm *>(pFrm);
    2677          57 :             break;
    2678             :         }
    2679             :     }
    2680             : 
    2681          65 :     return pResult;
    2682             : }
    2683             : 
    2684          65 : const SwCellFrm * SwTableCellInfo::Impl::getNextTableBoxsCellFrm(const SwFrm * pFrm)
    2685             : {
    2686          65 :     const SwCellFrm * pResult = NULL;
    2687             : 
    2688         130 :     while ((pFrm = getNextCellFrm(pFrm)) != NULL)
    2689             :     {
    2690          57 :         const SwCellFrm * pCellFrm = static_cast<const SwCellFrm *>(pFrm);
    2691          57 :         const SwTableBox * pTabBox = pCellFrm->GetTabBox();
    2692          57 :         TableBoxes_t::const_iterator aIt = m_HandledTableBoxes.find(pTabBox);
    2693             : 
    2694          57 :         if (aIt == m_HandledTableBoxes.end())
    2695             :         {
    2696          57 :             pResult = pCellFrm;
    2697          57 :             m_HandledTableBoxes.insert(pTabBox);
    2698          57 :             break;
    2699             :         }
    2700             :     }
    2701             : 
    2702          65 :     return pResult;
    2703             : }
    2704             : 
    2705         228 : const SwCellFrm * SwTableCellInfo::getCellFrm() const
    2706             : {
    2707         228 :     return m_pImpl->getCellFrm();
    2708             : }
    2709             : 
    2710          65 : bool SwTableCellInfo::Impl::getNext()
    2711             : {
    2712          65 :     if (m_pCellFrm == NULL)
    2713             :     {
    2714           8 :         if (m_pTabFrm != NULL)
    2715           8 :             m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pTabFrm);
    2716             :     }
    2717             :     else
    2718          57 :         m_pCellFrm = Impl::getNextTableBoxsCellFrm(m_pCellFrm);
    2719             : 
    2720          65 :     return m_pCellFrm != NULL;
    2721             : }
    2722             : 
    2723           8 : SwTableCellInfo::SwTableCellInfo(const SwTable * pTable)
    2724           8 :     : m_pImpl(o3tl::make_unique<Impl>())
    2725             : {
    2726           8 :     m_pImpl->setTable(pTable);
    2727           8 : }
    2728             : 
    2729           8 : SwTableCellInfo::~SwTableCellInfo()
    2730             : {
    2731           8 : }
    2732             : 
    2733          65 : bool SwTableCellInfo::getNext()
    2734             : {
    2735          65 :     return m_pImpl->getNext();
    2736             : }
    2737             : 
    2738          57 : SwRect SwTableCellInfo::getRect() const
    2739             : {
    2740          57 :     SwRect aRet;
    2741             : 
    2742          57 :     if (getCellFrm() != NULL)
    2743          57 :         aRet = getCellFrm()->Frm();
    2744             : 
    2745          57 :     return aRet;
    2746             : }
    2747             : 
    2748          57 : const SwTableBox * SwTableCellInfo::getTableBox() const
    2749             : {
    2750          57 :     const SwTableBox * pRet = NULL;
    2751             : 
    2752          57 :     if (getCellFrm() != NULL)
    2753          57 :         pRet = getCellFrm()->GetTabBox();
    2754             : 
    2755          57 :     return pRet;
    2756             : }
    2757             : 
    2758        1098 : void SwTable::RegisterToFormat( SwFormat& rFormat )
    2759             : {
    2760        1098 :     rFormat.Add( this );
    2761        1098 : }
    2762             : 
    2763          14 : bool SwTable::HasLayout() const
    2764             : {
    2765          14 :     const SwFrameFormat* pFrameFormat = GetFrameFormat();
    2766             :     //a table in a clipboard document doesn't have any layout information
    2767          14 :     return pFrameFormat && SwIterator<SwTabFrm,SwFormat>(*pFrameFormat).First();
    2768             : }
    2769             : 
    2770           0 : void SwTableLine::RegisterToFormat( SwFormat& rFormat )
    2771             : {
    2772           0 :     rFormat.Add( this );
    2773           0 : }
    2774             : 
    2775           0 : void SwTableBox::RegisterToFormat( SwFormat& rFormat )
    2776             : {
    2777           0 :     rFormat.Add( this );
    2778           0 : }
    2779             : 
    2780             : // free's any remaining child objects
    2781       25898 : SwTableLines::~SwTableLines()
    2782             : {
    2783       17073 :     for ( const_iterator it = begin(); it != end(); ++it )
    2784        4124 :         delete *it;
    2785       13126 : }
    2786             : 
    2787             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11