LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/table - swnewtable.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 99 1063 9.3 %
Date: 2012-12-27 Functions: 4 38 10.5 %
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             : 
      21             : #include <swtable.hxx>
      22             : #include <tblsel.hxx>
      23             : #include <tblrwcl.hxx>
      24             : #include <node.hxx>
      25             : #include <UndoTable.hxx>
      26             : #include <pam.hxx>
      27             : #include <frmfmt.hxx>
      28             : #include <frmatr.hxx>
      29             : #include <cellfrm.hxx>
      30             : #include <fmtfsize.hxx>
      31             : #include <doc.hxx>
      32             : #include <IDocumentUndoRedo.hxx>
      33             : #include <vector>
      34             : #include <set>
      35             : #include <list>
      36             : #include <memory>
      37             : #include <boost/scoped_array.hpp>
      38             : #include <editeng/boxitem.hxx>
      39             : #include <editeng/protitem.hxx>
      40             : #include <swtblfmt.hxx>
      41             : #include <switerator.hxx>
      42             : 
      43             : #ifdef DBG_UTIL
      44             : #define CHECK_TABLE(t) (t).CheckConsistency();
      45             : #else
      46             : #define CHECK_TABLE(t)
      47             : #endif
      48             : 
      49             : // ---------------------------------------------------------------
      50             : 
      51             : /** SwBoxSelection is a small helperclass (structure) to handle selections
      52             :     of cells (boxes) between table functions
      53             : 
      54             :     It contains an "array" of table boxes, a rectangulare selection of table boxes.
      55             :     To be more specific, it contains a vector of box selections,
      56             :     every box selection (SwSelBoxes) contains the selected boxes inside one row.
      57             :     The member mnMergeWidth contains the width of the selected boxes
      58             : */
      59             : 
      60           0 : class SwBoxSelection
      61             : {
      62             : public:
      63             :     std::vector<const SwSelBoxes*> aBoxes;
      64             :     long mnMergeWidth;
      65           0 :     SwBoxSelection() : mnMergeWidth(0) {}
      66           0 :     bool isEmpty() const { return aBoxes.empty(); }
      67           0 :     void insertBoxes( const SwSelBoxes* pNew ){ aBoxes.insert( aBoxes.end(), pNew ); }
      68             : };
      69             : 
      70             : /** NewMerge(..) removes the superfluous cells after cell merge
      71             : 
      72             : SwTable::NewMerge(..) does some cleaning up,
      73             : it simply deletes the superfluous cells ("cell span")
      74             : and notifies the Undo about it.
      75             : The main work has been done by SwTable::PrepareMerge(..) already.
      76             : 
      77             : @param rBoxes
      78             : the boxes to remove
      79             : 
      80             : @param pUndo
      81             : the undo object to notify, maybe empty
      82             : 
      83             : @return sal_True for compatibility reasons with OldMerge(..)
      84             : */
      85             : 
      86           0 : sal_Bool SwTable::NewMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
      87             :      const SwSelBoxes& rMerged, SwTableBox*, SwUndoTblMerge* pUndo )
      88             : {
      89           0 :     if( pUndo )
      90           0 :         pUndo->SetSelBoxes( rBoxes );
      91           0 :     DeleteSel( pDoc, rBoxes, &rMerged, 0, true, true );
      92             : 
      93             :     CHECK_TABLE( *this )
      94           0 :     return sal_True;
      95             : }
      96             : 
      97             : /** lcl_CheckMinMax helps evaluating (horizontal) min/max of boxes
      98             : 
      99             : lcl_CheckMinMax(..) compares the left border and the right border
     100             : of a given cell with the given range and sets it accordingly.
     101             : 
     102             : @param rMin
     103             : will be decremented if necessary to the left border of the cell
     104             : 
     105             : @param rMax
     106             : will be incremented if necessary to the right border of the cell
     107             : 
     108             : @param rLine
     109             : the row (table line) of the interesting box
     110             : 
     111             : @param nCheck
     112             : the index of the box in the table box array of the given row
     113             : 
     114             : @param bSet
     115             : if bSet is false, rMin and rMax will be manipulated if necessary
     116             : if bSet is true, rMin and rMax will be set to the left and right border of the box
     117             : 
     118             : */
     119             : 
     120          11 : static void lcl_CheckMinMax( long& rMin, long& rMax, const SwTableLine& rLine, sal_uInt16 nCheck, bool bSet )
     121             : {
     122          11 :     ++nCheck;
     123          11 :     if( rLine.GetTabBoxes().size() < nCheck )
     124             :     {   // robust
     125             :         OSL_FAIL( "Box out of table line" );
     126           0 :         nCheck = rLine.GetTabBoxes().size();
     127             :     }
     128             : 
     129          11 :     long nNew = 0; // will be the right border of the current box
     130          11 :     long nWidth = 0; // the width of the current box
     131          23 :     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCheck; ++nCurrBox )
     132             :     {
     133          12 :         SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
     134             :         OSL_ENSURE( pBox, "Missing table box" );
     135          12 :         nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
     136          12 :         nNew += nWidth;
     137             :     }
     138             :     // nNew is the right border of the wished box
     139          11 :     if( bSet || nNew > rMax )
     140          11 :         rMax = nNew;
     141          11 :     nNew -= nWidth; // nNew becomes the left border of the wished box
     142          11 :     if( bSet || nNew < rMin )
     143          11 :         rMin = nNew;
     144          11 : }
     145             : 
     146             : /** lcl_Box2LeftBorder(..) delivers the left (logical) border of a table box
     147             : 
     148             : The left logical border of a table box is the sum of the cell width before this
     149             : box.
     150             : 
     151             : @param rBox
     152             : is the requested table box
     153             : 
     154             : @return is the left logical border (long, even it cannot be negative)
     155             : 
     156             : */
     157             : 
     158           0 : static long lcl_Box2LeftBorder( const SwTableBox& rBox )
     159             : {
     160           0 :     if( !rBox.GetUpper() )
     161           0 :         return 0;
     162           0 :     long nLeft = 0;
     163           0 :     const SwTableLine &rLine = *rBox.GetUpper();
     164           0 :     sal_uInt16 nCount = rLine.GetTabBoxes().size();
     165           0 :     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
     166             :     {
     167           0 :         SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
     168             :         OSL_ENSURE( pBox, "Missing table box" );
     169           0 :         if( pBox == &rBox )
     170           0 :             return nLeft;
     171           0 :         nLeft += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
     172             :     }
     173             :     OSL_FAIL( "Box not found in own upper?" );
     174           0 :     return nLeft;
     175             : }
     176             : 
     177             : /** lcl_LeftBorder2Box delivers the box to a given left border
     178             : 
     179             : It's used to find the master/follow table boxes in previous/next rows.
     180             : Don't call this function to check if there is such a box,
     181             : call it if you know there has to be such box.
     182             : 
     183             : @param nLeft
     184             : the left border (logical x-value) of the demanded box
     185             : 
     186             : @param rLine
     187             : the row (table line) to be scanned
     188             : 
     189             : @return a pointer to the table box inside the given row with the wished left border
     190             : 
     191             : */
     192             : 
     193           0 : static SwTableBox* lcl_LeftBorder2Box( long nLeft, const SwTableLine* pLine )
     194             : {
     195           0 :     if( !pLine )
     196           0 :         return 0;
     197           0 :     long nCurrLeft = 0;
     198           0 :     sal_uInt16 nCount = pLine->GetTabBoxes().size();
     199           0 :     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
     200             :     {
     201           0 :         SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
     202             :         OSL_ENSURE( pBox, "Missing table box" );
     203           0 :         if( nCurrLeft >= nLeft && pBox->GetFrmFmt()->GetFrmSize().GetWidth() )
     204             :         {
     205             :             OSL_ENSURE( nCurrLeft == nLeft, "Wrong box found" );
     206           0 :             return pBox;
     207             :         }
     208           0 :         nCurrLeft += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
     209             :     }
     210             :     OSL_FAIL( "Didn't found wished box" );
     211           0 :     return 0;
     212             : }
     213             : 
     214             : /** lcl_ChangeRowSpan corrects row span after insertion/deletion of rows
     215             : 
     216             : lcl_ChangeRowSpan(..) has to be called after an insertion or deletion of rows
     217             : to adjust the row spans of previous rows accordingly.
     218             : If rows are deleted, the previous rows with row spans into the deleted area
     219             : have to be decremented by the number of _overlapped_ inserted rows.
     220             : If rows are inserted, the previous rows with row span into the inserted area
     221             : have to be incremented by the number of inserted rows.
     222             : For those row spans which ends exactly above the inserted area it has to be
     223             : decided by the parameter bSingle if they have to be expanded or not.
     224             : 
     225             : @param rTable
     226             : the table to manipulate (has to be a new model table)
     227             : 
     228             : @param nDiff
     229             : the number of rows which has been inserted (nDiff > 0) or deleted (nDiff < 0)
     230             : 
     231             : @param nRowIdx
     232             : the index of the first row which has to be checked
     233             : 
     234             : @param bSingle
     235             : true if the new inserted row should not extend row spans which ends in the row above
     236             : this is for rows inserted by UI "insert row"
     237             : false if all cells of an inserted row has to be overlapped by the previous row
     238             : this is for rows inserted by "split row"
     239             : false is also needed for deleted rows
     240             : 
     241             : */
     242             : 
     243           0 : static void lcl_ChangeRowSpan( const SwTable& rTable, const long nDiff,
     244             :                         sal_uInt16 nRowIdx, const bool bSingle )
     245             : {
     246           0 :     if( !nDiff || nRowIdx >= rTable.GetTabLines().size() )
     247           0 :         return;
     248             :     OSL_ENSURE( !bSingle || nDiff > 0, "Don't set bSingle when deleting lines!" );
     249             :     bool bGoOn;
     250             :     // nDistance is the distance between the current row and the critical row,
     251             :     // e.g. the deleted rows or the inserted rows.
     252             :     // If the row span is lower than the distance there is nothing to do
     253             :     // because the row span ends before the critical area.
     254             :     // When the inserted rows should not be overlapped by row spans which ends
     255             :     // exactly in the row above, the trick is to start with a distance of 1.
     256           0 :     long nDistance = bSingle ? 1 : 0;
     257           0 :     do
     258             :     {
     259           0 :         bGoOn = false; // will be set to true if we found a non-master cell
     260             :         // which has to be manipulated => we have to chekc the previous row, too.
     261           0 :         const SwTableLine* pLine = rTable.GetTabLines()[ nRowIdx ];
     262           0 :         sal_uInt16 nBoxCount = pLine->GetTabBoxes().size();
     263           0 :         for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
     264             :         {
     265           0 :             long nRowSpan = pLine->GetTabBoxes()[nCurrBox]->getRowSpan();
     266           0 :             long nAbsSpan = nRowSpan > 0 ? nRowSpan : -nRowSpan;
     267             :             // Check if the last overlapped cell is above or below
     268             :             // the critical area
     269           0 :             if( nAbsSpan > nDistance )
     270             :             {
     271           0 :                 if( nDiff > 0 )
     272             :                 {
     273           0 :                     if( nRowSpan > 0 )
     274           0 :                         nRowSpan += nDiff; // increment row span of master cell
     275             :                     else
     276             :                     {
     277           0 :                         nRowSpan -= nDiff; // increment row span of non-master cell
     278           0 :                         bGoOn = true;
     279             :                     }
     280             :                 }
     281             :                 else
     282             :                 {
     283           0 :                     if( nRowSpan > 0 )
     284             :                     {   // A master cell
     285             :                          // end of row span behind the deleted area ..
     286           0 :                         if( nRowSpan - nDistance > -nDiff )
     287           0 :                             nRowSpan += nDiff;
     288             :                         else // .. or inside the deleted area
     289           0 :                             nRowSpan = nDistance + 1;
     290             :                     }
     291             :                     else
     292             :                     {   // Same for a non-master cell
     293           0 :                         if( nRowSpan + nDistance < nDiff )
     294           0 :                             nRowSpan -= nDiff;
     295             :                         else
     296           0 :                             nRowSpan = -nDistance - 1;
     297           0 :                         bGoOn = true; // We have to continue
     298             :                     }
     299             :                 }
     300           0 :                 pLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan );
     301             :             }
     302             :         }
     303           0 :         ++nDistance;
     304           0 :         if( nRowIdx )
     305           0 :             --nRowIdx;
     306             :         else
     307           0 :             bGoOn = false; //robust
     308             :     } while( bGoOn );
     309             : }
     310             : 
     311             : /** CollectBoxSelection(..) create a rectangulare selection based on the given SwPaM
     312             :     and prepares the selected cells for merging
     313             : */
     314             : 
     315           0 : SwBoxSelection* SwTable::CollectBoxSelection( const SwPaM& rPam ) const
     316             : {
     317             :     OSL_ENSURE( bNewModel, "Don't call me for old tables" );
     318           0 :     if( aLines.empty() )
     319           0 :         return 0;
     320           0 :     const SwNode* pStartNd = rPam.Start()->nNode.GetNode().FindTableBoxStartNode();
     321           0 :     const SwNode* pEndNd = rPam.End()->nNode.GetNode().FindTableBoxStartNode();
     322           0 :     if( !pStartNd || !pEndNd || pStartNd == pEndNd )
     323           0 :         return 0;
     324             : 
     325           0 :     sal_uInt16 nLines = aLines.size();
     326           0 :     sal_uInt16 nTop = 0, nBottom = 0;
     327           0 :     long nMin = 0, nMax = 0;
     328           0 :     int nFound = 0;
     329           0 :     for( sal_uInt16 nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
     330             :     {
     331           0 :         SwTableLine* pLine = aLines[nRow];
     332             :         OSL_ENSURE( pLine, "Missing table line" );
     333           0 :         sal_uInt16 nCols = pLine->GetTabBoxes().size();
     334           0 :         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
     335             :         {
     336           0 :             SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
     337             :             OSL_ENSURE( pBox, "Missing table box" );
     338           0 :             if( nFound )
     339             :             {
     340           0 :                 if( pBox->GetSttNd() == pEndNd )
     341             :                 {
     342           0 :                     nBottom = nRow;
     343           0 :                     lcl_CheckMinMax( nMin, nMax, *pLine, nCol, false );
     344           0 :                     ++nFound;
     345           0 :                     break;
     346             :                 }
     347             :             }
     348           0 :             else if( pBox->GetSttNd() == pStartNd )
     349             :             {
     350           0 :                 nTop = nRow;
     351           0 :                 lcl_CheckMinMax( nMin, nMax, *pLine, nCol, true );
     352           0 :                 ++nFound;
     353             :             }
     354             :         }
     355             :     }
     356           0 :     if( nFound < 2 )
     357           0 :         return 0;
     358             : 
     359           0 :     bool bOkay = true;
     360           0 :     long nMid = ( nMin + nMax ) / 2;
     361             : 
     362           0 :     SwBoxSelection* pRet = new SwBoxSelection();
     363           0 :     std::list< std::pair< SwTableBox*, long > > aNewWidthList;
     364           0 :     sal_uInt16 nCheckBottom = nBottom;
     365           0 :     long nLeftSpan = 0;
     366           0 :     long nRightSpan = 0;
     367           0 :     long nLeftSpanCnt = 0;
     368           0 :     long nRightSpanCnt = 0;
     369           0 :     for( sal_uInt16 nRow = nTop; nRow <= nBottom && bOkay; ++nRow )
     370             :     {
     371           0 :         SwTableLine* pLine = aLines[nRow];
     372             :         OSL_ENSURE( pLine, "Missing table line" );
     373           0 :         SwSelBoxes *pBoxes = new SwSelBoxes();
     374           0 :         long nLeft = 0;
     375           0 :         long nRight = 0;
     376           0 :         long nRowSpan = 1;
     377           0 :         sal_uInt16 nCount = pLine->GetTabBoxes().size();
     378           0 :         for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
     379             :         {
     380           0 :             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
     381             :             OSL_ENSURE( pBox, "Missing table box" );
     382           0 :             nLeft = nRight;
     383           0 :             nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
     384           0 :             nRowSpan = pBox->getRowSpan();
     385           0 :             if( nRight <= nMin )
     386             :             {
     387           0 :                 if( nRight == nMin && nLeftSpanCnt )
     388           0 :                     bOkay = false;
     389           0 :                 continue;
     390             :             }
     391           0 :             SwTableBox* pInnerBox = 0;
     392           0 :             SwTableBox* pLeftBox = 0;
     393           0 :             SwTableBox* pRightBox = 0;
     394           0 :             long nDiff = 0;
     395           0 :             long nDiff2 = 0;
     396           0 :             if( nLeft < nMin )
     397             :             {
     398           0 :                 if( nRight >= nMid || nRight + nLeft >= nMin + nMin )
     399             :                 {
     400           0 :                     if( nCurrBox )
     401             :                     {
     402           0 :                         pBoxes->insert( pBox );
     403           0 :                         pInnerBox = pBox;
     404           0 :                         pLeftBox = pLine->GetTabBoxes()[nCurrBox-1];
     405           0 :                         nDiff = nMin - nLeft;
     406           0 :                         if( nRight > nMax )
     407             :                         {
     408           0 :                             if( nCurrBox+1 < nCount )
     409             :                             {
     410           0 :                                 pRightBox = pLine->GetTabBoxes()[nCurrBox+1];
     411           0 :                                 nDiff2 = nRight - nMax;
     412             :                             }
     413             :                             else
     414           0 :                                 bOkay = false;
     415             :                         }
     416           0 :                         else if( nRightSpanCnt && nRight == nMax )
     417           0 :                             bOkay = false;
     418             :                     }
     419             :                     else
     420           0 :                         bOkay = false;
     421             :                 }
     422           0 :                 else if( nCurrBox+1 < nCount )
     423             :                 {
     424           0 :                     pLeftBox = pBox;
     425           0 :                     pInnerBox = pLine->GetTabBoxes()[nCurrBox+1];
     426           0 :                     nDiff = nMin - nRight;
     427             :                 }
     428             :                 else
     429           0 :                     bOkay = false;
     430             :             }
     431           0 :             else if( nRight <= nMax )
     432             :             {
     433           0 :                 pBoxes->insert( pBox );
     434           0 :                 if( nRow == nTop && nRowSpan < 0 )
     435             :                 {
     436           0 :                     bOkay = false;
     437             :                     break;
     438             :                 }
     439           0 :                 if( nRowSpan > 1 && nRow + nRowSpan - 1 > nBottom )
     440           0 :                     nBottom = nRow + (sal_uInt16)nRowSpan - 1;
     441           0 :                 if( nRowSpan < -1 && nRow - nRowSpan - 1 > nBottom )
     442           0 :                     nBottom = (sal_uInt16)(nRow - nRowSpan - 1);
     443           0 :                 if( nRightSpanCnt && nRight == nMax )
     444           0 :                     bOkay = false;
     445             :             }
     446           0 :             else if( nLeft < nMax )
     447             :             {
     448           0 :                 if( nLeft <= nMid || nRight + nLeft <= nMax )
     449             :                 {
     450           0 :                     if( nCurrBox+1 < nCount )
     451             :                     {
     452           0 :                         pBoxes->insert( pBox );
     453           0 :                         pInnerBox = pBox;
     454           0 :                         pRightBox = pLine->GetTabBoxes()[nCurrBox+1];
     455           0 :                         nDiff = nRight - nMax;
     456             :                     }
     457             :                     else
     458           0 :                         bOkay = false;
     459             :                 }
     460           0 :                 else if( nCurrBox )
     461             :                 {
     462           0 :                     pRightBox = pBox;
     463           0 :                     pInnerBox = pLine->GetTabBoxes()[nCurrBox-1];
     464           0 :                     nDiff = nLeft - nMax;
     465             :                 }
     466             :                 else
     467           0 :                     bOkay = false;
     468             :             }
     469             :             else
     470             :                 break;
     471           0 :             if( pInnerBox )
     472             :             {
     473           0 :                 if( nRow == nBottom )
     474             :                 {
     475           0 :                     long nTmpSpan = pInnerBox->getRowSpan();
     476           0 :                     if( nTmpSpan > 1 )
     477           0 :                         nBottom += (sal_uInt16)nTmpSpan - 1;
     478           0 :                     else if( nTmpSpan < -1 )
     479           0 :                         nBottom = (sal_uInt16)( nBottom - nTmpSpan - 1 );
     480             :                 }
     481           0 :                 SwTableBox* pOuterBox = pLeftBox;
     482           0 :                 do
     483             :                 {
     484           0 :                     if( pOuterBox )
     485             :                     {
     486           0 :                         long nOutSpan = pOuterBox->getRowSpan();
     487           0 :                         if( nOutSpan != 1 )
     488             :                         {
     489           0 :                             sal_uInt16 nCheck = nRow;
     490           0 :                             if( nOutSpan < 0 )
     491             :                             {
     492             :                                 const SwTableBox& rBox =
     493           0 :                                     pOuterBox->FindStartOfRowSpan( *this, USHRT_MAX );
     494           0 :                                 nOutSpan = rBox.getRowSpan();
     495           0 :                                 const SwTableLine* pTmpL = rBox.GetUpper();
     496           0 :                                 nCheck = GetTabLines().GetPos( pTmpL );
     497           0 :                                 if( nCheck < nTop )
     498           0 :                                     bOkay = false;
     499           0 :                                 if( pOuterBox == pLeftBox )
     500             :                                 {
     501           0 :                                     if( !nLeftSpanCnt || nMin - nDiff != nLeftSpan )
     502           0 :                                         bOkay = false;
     503             :                                 }
     504             :                                 else
     505             :                                 {
     506           0 :                                     if( !nRightSpanCnt || nMax + nDiff != nRightSpan )
     507           0 :                                         bOkay = false;
     508             :                                 }
     509             :                             }
     510             :                             else
     511             :                             {
     512           0 :                                 if( pOuterBox == pLeftBox )
     513             :                                 {
     514           0 :                                     if( nLeftSpanCnt )
     515           0 :                                         bOkay = false;
     516           0 :                                     nLeftSpan = nMin - nDiff;
     517           0 :                                     nLeftSpanCnt = nOutSpan;
     518             :                                 }
     519             :                                 else
     520             :                                 {
     521           0 :                                     if( nRightSpanCnt )
     522           0 :                                         bOkay = false;
     523           0 :                                     nRightSpan = nMax + nDiff;
     524           0 :                                     nRightSpanCnt = nOutSpan;
     525             :                                 }
     526             :                             }
     527           0 :                             nCheck += (sal_uInt16)nOutSpan - 1;
     528           0 :                             if( nCheck > nCheckBottom )
     529           0 :                                 nCheckBottom = nCheck;
     530             :                         }
     531           0 :                         else if( ( nLeftSpanCnt && pLeftBox == pOuterBox ) ||
     532             :                             ( nRightSpanCnt && pRightBox == pOuterBox ) )
     533           0 :                             bOkay = false;
     534           0 :                         std::pair< SwTableBox*, long > aTmp;
     535           0 :                         aTmp.first = pInnerBox;
     536           0 :                         aTmp.second = -nDiff;
     537           0 :                         aNewWidthList.push_back( aTmp );
     538           0 :                         aTmp.first = pOuterBox;
     539           0 :                         aTmp.second = nDiff;
     540           0 :                         aNewWidthList.push_back( aTmp );
     541             :                     }
     542           0 :                     pOuterBox = pOuterBox == pRightBox ? 0 : pRightBox;
     543           0 :                     if( nDiff2 )
     544           0 :                         nDiff = nDiff2;
     545             :                 } while( pOuterBox );
     546             :             }
     547             :         }
     548           0 :         if( nLeftSpanCnt )
     549           0 :             --nLeftSpanCnt;
     550           0 :         if( nRightSpanCnt )
     551           0 :             --nRightSpanCnt;
     552           0 :         pRet->insertBoxes( pBoxes );
     553             :     }
     554           0 :     pRet->mnMergeWidth = nMax - nMin;
     555           0 :     if( nCheckBottom > nBottom )
     556           0 :         bOkay = false;
     557           0 :     if( bOkay )
     558             :     {
     559             :         std::list< std::pair< SwTableBox*, long > >::iterator
     560           0 :             pCurr = aNewWidthList.begin();
     561           0 :         while( pCurr != aNewWidthList.end() )
     562             :         {
     563           0 :             SwFrmFmt* pFmt = pCurr->first->ClaimFrmFmt();
     564           0 :             long nNewWidth = pFmt->GetFrmSize().GetWidth() + pCurr->second;
     565           0 :             pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nNewWidth, 0 ) );
     566           0 :             ++pCurr;
     567             :         }
     568             :     }
     569             :     else
     570             :     {
     571           0 :         delete pRet;
     572           0 :         pRet = 0;
     573             :     }
     574           0 :     return pRet;
     575             : }
     576             : 
     577             : /** lcl_InvalidateCellFrm(..) invalidates all layout representations of a given cell
     578             :     to initiate a reformatting
     579             : */
     580             : 
     581           0 : static void lcl_InvalidateCellFrm( const SwTableBox& rBox )
     582             : {
     583           0 :     SwIterator<SwCellFrm,SwFmt> aIter( *rBox.GetFrmFmt() );
     584           0 :     for( SwCellFrm* pCell = aIter.First(); pCell; pCell = aIter.Next() )
     585             :     {
     586           0 :         if( pCell->GetTabBox() == &rBox )
     587             :         {
     588           0 :             pCell->InvalidateSize();
     589           0 :             SwFrm* pLower = pCell->GetLower();
     590           0 :             if( pLower )
     591           0 :                 pLower->_InvalidateSize();
     592             :         }
     593           0 :     }
     594           0 : }
     595             : 
     596             : /** lcl_InsertPosition(..) evaluates the insert positions in every table line,
     597             :     when a selection of cells is given and returns the average cell widths
     598             : */
     599             : 
     600           0 : static long lcl_InsertPosition( SwTable &rTable, std::vector<sal_uInt16>& rInsPos,
     601             :     const SwSelBoxes& rBoxes, bool bBehind )
     602             : {
     603           0 :     sal_Int32 nAddWidth = 0;
     604           0 :     long nCount = 0;
     605           0 :     for (size_t j = 0; j < rBoxes.size(); ++j)
     606             :     {
     607           0 :         SwTableBox *pBox = rBoxes[j];
     608           0 :         SwTableLine* pLine = pBox->GetUpper();
     609           0 :         long nWidth = rBoxes[j]->GetFrmFmt()->GetFrmSize().GetWidth();
     610           0 :         nAddWidth += nWidth;
     611           0 :         sal_uInt16 nCurrBox = pLine->GetTabBoxes().GetPos( pBox );
     612           0 :         sal_uInt16 nCurrLine = rTable.GetTabLines().GetPos( pLine );
     613             :         OSL_ENSURE( nCurrLine != USHRT_MAX, "Time to say Good-Bye.." );
     614           0 :         if( rInsPos[ nCurrLine ] == USHRT_MAX )
     615             :         {
     616           0 :             rInsPos[ nCurrLine ] = nCurrBox;
     617           0 :             ++nCount;
     618             :         }
     619           0 :         else if( ( rInsPos[ nCurrLine ] > nCurrBox ) == !bBehind )
     620           0 :             rInsPos[ nCurrLine ] = nCurrBox;
     621             :     }
     622           0 :     if( nCount )
     623           0 :         nAddWidth /= nCount;
     624           0 :     return nAddWidth;
     625             : }
     626             : 
     627             : /** SwTable::NewInsertCol(..) insert new column(s) into a table
     628             : 
     629             : 
     630             : @param pDoc
     631             : the document
     632             : 
     633             : @param rBoxes
     634             : the selected boxes
     635             : 
     636             : @param nCnt
     637             : the number of columns to insert
     638             : 
     639             : @param bBehind
     640             : insertion behind (true) or before (false) the selected boxes
     641             : 
     642             : @return true, if any insertion has been done successfully
     643             : 
     644             : */
     645             : 
     646           0 : bool SwTable::NewInsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes,
     647             :     sal_uInt16 nCnt, bool bBehind )
     648             : {
     649           0 :     if( aLines.empty() || !nCnt )
     650           0 :         return false;
     651             : 
     652             :     CHECK_TABLE( *this )
     653           0 :     long nNewBoxWidth = 0;
     654           0 :     std::vector< sal_uInt16 > aInsPos( aLines.size(), USHRT_MAX );
     655             :     { // Calculation of the insert positions and the width of the new boxes
     656           0 :         sal_uInt64 nTableWidth = 0;
     657           0 :         for( sal_uInt16 i = 0; i < aLines[0]->GetTabBoxes().size(); ++i )
     658           0 :             nTableWidth += aLines[0]->GetTabBoxes()[i]->GetFrmFmt()->GetFrmSize().GetWidth();
     659             : 
     660             :         // Fill the vector of insert positions and the (average) width to insert
     661           0 :         sal_uInt64 nAddWidth = lcl_InsertPosition( *this, aInsPos, rBoxes, bBehind );
     662             : 
     663             :         // Given is the (average) width of the selected boxes, if we would
     664             :         // insert nCnt of columns the table would grow
     665             :         // So we will shrink the table first, then insert the new boxes and
     666             :         // get a table with the same width than before.
     667             :         // But we will not shrink the table by the full already calculated value,
     668             :         // we will reduce this value proportional to the old table width
     669           0 :         nAddWidth *= nCnt; // we have to insert nCnt boxes per line
     670           0 :         sal_uInt64 nResultingWidth = nAddWidth + nTableWidth;
     671           0 :         if( !nResultingWidth )
     672           0 :             return false;
     673           0 :         nAddWidth = (nAddWidth * nTableWidth) / nResultingWidth;
     674           0 :         nNewBoxWidth = long( nAddWidth / nCnt ); // Rounding
     675           0 :         nAddWidth = nNewBoxWidth * nCnt; // Rounding
     676           0 :         if( !nAddWidth || nAddWidth >= nTableWidth )
     677           0 :             return false;
     678           0 :         AdjustWidths( static_cast< long >(nTableWidth), static_cast< long >(nTableWidth - nAddWidth) );
     679             :     }
     680             : 
     681           0 :     _FndBox aFndBox( 0, 0 );
     682           0 :     aFndBox.SetTableLines( rBoxes, *this );
     683           0 :     aFndBox.DelFrms( *this );
     684             : 
     685           0 :     SwTableNode* pTblNd = GetTableNode();
     686           0 :     std::vector<SwTableBoxFmt*> aInsFormat( nCnt, 0 );
     687           0 :     sal_uInt16 nLastLine = USHRT_MAX;
     688           0 :     long nLastRowSpan = 1;
     689             : 
     690           0 :     for( sal_uInt16 i = 0; i < aLines.size(); ++i )
     691             :     {
     692           0 :         SwTableLine* pLine = aLines[ i ];
     693           0 :         sal_uInt16 nInsPos = aInsPos[i];
     694             :         assert(nInsPos != USHRT_MAX); // didn't find insert position
     695           0 :         SwTableBox* pBox = pLine->GetTabBoxes()[ nInsPos ];
     696           0 :         if( bBehind )
     697           0 :             ++nInsPos;
     698           0 :         SwTableBoxFmt* pBoxFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
     699           0 :         ::_InsTblBox( pDoc, pTblNd, pLine, pBoxFrmFmt, pBox, nInsPos, nCnt );
     700           0 :         long nRowSpan = pBox->getRowSpan();
     701           0 :         long nDiff = i - nLastLine;
     702           0 :         bool bNewSpan = false;
     703           0 :         if( nLastLine != USHRT_MAX && nDiff <= nLastRowSpan &&
     704             :             nRowSpan != nDiff - nLastRowSpan )
     705             :         {
     706           0 :             bNewSpan = true;
     707           0 :             while( nLastLine < i )
     708             :             {
     709           0 :                 SwTableLine* pTmpLine = aLines[ nLastLine ];
     710           0 :                 sal_uInt16 nTmpPos = aInsPos[nLastLine];
     711           0 :                 if( bBehind )
     712           0 :                     ++nTmpPos;
     713           0 :                 for( sal_uInt16 j = 0; j < nCnt; ++j )
     714           0 :                     pTmpLine->GetTabBoxes()[nTmpPos+j]->setRowSpan( nDiff );
     715           0 :                 if( nDiff > 0 )
     716           0 :                     nDiff = -nDiff;
     717           0 :                 ++nDiff;
     718           0 :                 ++nLastLine;
     719             :             }
     720             :         }
     721           0 :         if( nRowSpan > 0 )
     722           0 :             bNewSpan = true;
     723           0 :         if( bNewSpan )
     724             :         {
     725           0 :             nLastLine = i;
     726           0 :             if( nRowSpan < 0 )
     727           0 :                 nLastRowSpan = -nRowSpan;
     728             :             else
     729           0 :                 nLastRowSpan = nRowSpan;
     730             :         }
     731           0 :         const SvxBoxItem& aSelBoxItem = pBoxFrmFmt->GetBox();
     732           0 :         SvxBoxItem* pNoRightBorder = 0;
     733           0 :         if( aSelBoxItem.GetRight() )
     734             :         {
     735           0 :             pNoRightBorder = new SvxBoxItem( aSelBoxItem );
     736           0 :             pNoRightBorder->SetLine( 0, BOX_LINE_RIGHT );
     737             :         }
     738           0 :         for( sal_uInt16 j = 0; j < nCnt; ++j )
     739             :         {
     740           0 :             SwTableBox *pCurrBox = pLine->GetTabBoxes()[nInsPos+j];
     741           0 :             if( bNewSpan )
     742             :             {
     743           0 :                 pCurrBox->setRowSpan( nLastRowSpan );
     744           0 :                 SwFrmFmt* pFrmFmt = pCurrBox->ClaimFrmFmt();
     745           0 :                 SwFmtFrmSize aFrmSz( pFrmFmt->GetFrmSize() );
     746           0 :                 aFrmSz.SetWidth( nNewBoxWidth );
     747           0 :                 pFrmFmt->SetFmtAttr( aFrmSz );
     748           0 :                 if( pNoRightBorder && ( !bBehind || j+1 < nCnt ) )
     749           0 :                     pFrmFmt->SetFmtAttr( *pNoRightBorder );
     750           0 :                 aInsFormat[j] = (SwTableBoxFmt*)pFrmFmt;
     751             :             }
     752             :             else
     753           0 :                 pCurrBox->ChgFrmFmt( aInsFormat[j] );
     754             :         }
     755           0 :         if( bBehind && pNoRightBorder )
     756             :         {
     757           0 :             SwFrmFmt* pFrmFmt = pBox->ClaimFrmFmt();
     758           0 :             pFrmFmt->SetFmtAttr( *pNoRightBorder );
     759             :         }
     760           0 :         delete pNoRightBorder;
     761             :     }
     762             : 
     763           0 :     aFndBox.MakeFrms( *this );
     764             : #if OSL_DEBUG_LEVEL > 0
     765             :     {
     766             :         const SwTableBoxes &rTabBoxes = aLines[0]->GetTabBoxes();
     767             :         long nNewWidth = 0;
     768             :         for( sal_uInt16 i = 0; i < rTabBoxes.size(); ++i )
     769             :             nNewWidth += rTabBoxes[i]->GetFrmFmt()->GetFrmSize().GetWidth();
     770             :         OSL_ENSURE( nNewWidth > 0, "Very small" );
     771             :     }
     772             : #endif
     773             :     CHECK_TABLE( *this )
     774             : 
     775           0 :     return true;
     776             : }
     777             : 
     778             : /** SwTable::PrepareMerge(..) some preparation for the coming Merge(..)
     779             : 
     780             : For the old table model, ::GetMergeSel(..) is called only,
     781             : for the new table model, PrepareMerge does the main work.
     782             : It modifices all cells to merge (width, border, rowspan etc.) and collects
     783             : the cells which have to be deleted by Merge(..) afterwards.
     784             : If there are superfluous rows, these cells are put into the deletion list as well.
     785             : 
     786             : @param rPam
     787             : the selection to merge
     788             : 
     789             : @param rBoxes
     790             : should be empty at the beginning, at the end it is filled with boxes to delete.
     791             : 
     792             : @param ppMergeBox
     793             : will be set to the master cell box
     794             : 
     795             : @param pUndo
     796             : the undo object to record all changes
     797             : can be Null, e.g. when called by Redo(..)
     798             : 
     799             : @return
     800             : 
     801             : */
     802             : 
     803           0 : bool SwTable::PrepareMerge( const SwPaM& rPam, SwSelBoxes& rBoxes,
     804             :    SwSelBoxes& rMerged, SwTableBox** ppMergeBox, SwUndoTblMerge* pUndo )
     805             : {
     806           0 :     if( !bNewModel )
     807             :     {
     808           0 :         ::GetMergeSel( rPam, rBoxes, ppMergeBox, pUndo );
     809           0 :         return rBoxes.size() > 1;
     810             :     }
     811             :     CHECK_TABLE( *this )
     812             :     // We have to assert a "rectangular" box selection before we start to merge
     813           0 :     std::auto_ptr< SwBoxSelection > pSel( CollectBoxSelection( rPam ) );
     814           0 :     if( !pSel.get() || pSel->isEmpty() )
     815           0 :         return false;
     816             :     // Now we should have a rectangle of boxes,
     817             :     // i.e. contiguous cells in contiguous rows
     818           0 :     bool bMerge = false; // will be set if any content is transferred from
     819             :     // a "not already overlapped" cell into the new master cell.
     820           0 :     SwTableBox *pMergeBox = (*pSel->aBoxes[0])[0]; // the master cell box
     821           0 :     if( !pMergeBox )
     822           0 :         return false;
     823           0 :     (*ppMergeBox) = pMergeBox;
     824             :     // The new master box will get the left and the top border of the top-left
     825             :     // box of the selection and because the new master cell _is_ the top-left
     826             :     // box, the left and right border does not need to be changed.
     827             :     // The right and bottom border instead has to be derived from the right-
     828             :     // bottom box of the selection. If this is a overlapped cell,
     829             :     // the appropriate master box.
     830           0 :     SwTableBox* pLastBox = 0; // the right-bottom (master) cell
     831           0 :     SwDoc* pDoc = GetFrmFmt()->GetDoc();
     832           0 :     SwPosition aInsPos( *pMergeBox->GetSttNd()->EndOfSectionNode() );
     833           0 :     SwPaM aChkPam( aInsPos );
     834             :     // The number of lines in the selection rectangle: nLineCount
     835           0 :     const sal_uInt16 nLineCount = sal_uInt16(pSel->aBoxes.size());
     836             :     // BTW: nLineCount is the rowspan of the new master cell
     837           0 :     long nRowSpan = nLineCount;
     838             :     // We will need the first and last line of the selection
     839             :     // to check if there any superfluous row after merging
     840           0 :     SwTableLine* pFirstLn = 0;
     841           0 :     SwTableLine* pLastLn = 0;
     842             :     // Iteration over the lines of the selection...
     843           0 :     for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
     844             :     {
     845             :         // The selected boxes in the current line
     846           0 :         const SwSelBoxes* pBoxes = pSel->aBoxes[ nCurrLine ];
     847           0 :         size_t nColCount = pBoxes->size();
     848             :         // Iteration over the selected cell in the current row
     849           0 :         for (size_t nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol)
     850             :         {
     851           0 :             SwTableBox* pBox = (*pBoxes)[nCurrCol];
     852           0 :             rMerged.insert( pBox );
     853             :             // Only the first selected cell in every row will be alive,
     854             :             // the other will be deleted => put into rBoxes
     855           0 :             if( nCurrCol )
     856           0 :                 rBoxes.insert( pBox );
     857             :             else
     858             :             {
     859           0 :                 if( nCurrLine == 1 )
     860           0 :                     pFirstLn = pBox->GetUpper(); // we need this line later on
     861           0 :                 if( nCurrLine + 1 == nLineCount )
     862           0 :                     pLastLn = pBox->GetUpper(); // and this one, too.
     863             :             }
     864             :             // A box has to be merged if it's not the master box itself,
     865             :             // but an already overlapped cell must not be merged as well.
     866           0 :             bool bDoMerge = pBox != pMergeBox && pBox->getRowSpan() > 0;
     867             :             // The last box has to be in the last "column" of the selection
     868             :             // and it has to be a master cell
     869           0 :             if( nCurrCol+1 == nColCount && pBox->getRowSpan() > 0 )
     870           0 :                 pLastBox = pBox;
     871           0 :             if( bDoMerge )
     872             :             {
     873           0 :                 bMerge = true;
     874             :                 // If the cell to merge contains only one empty paragraph,
     875             :                 // we do not transfer this paragraph.
     876           0 :                 if( !IsEmptyBox( *pBox, aChkPam ) )
     877             :                 {
     878           0 :                     SwNodeIndex& rInsPosNd = aInsPos.nNode;
     879           0 :                     SwPaM aPam( aInsPos );
     880           0 :                     aPam.GetPoint()->nNode.Assign( *pBox->GetSttNd()->EndOfSectionNode(), -1 );
     881           0 :                     SwCntntNode* pCNd = aPam.GetCntntNode();
     882           0 :                     sal_uInt16 nL = pCNd ? pCNd->Len() : 0;
     883           0 :                     aPam.GetPoint()->nContent.Assign( pCNd, nL );
     884           0 :                     SwNodeIndex aSttNdIdx( *pBox->GetSttNd(), 1 );
     885           0 :                     bool const bUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
     886           0 :                     if( pUndo )
     887             :                     {
     888           0 :                         pDoc->GetIDocumentUndoRedo().DoUndo(false);
     889             :                     }
     890           0 :                     pDoc->AppendTxtNode( *aPam.GetPoint() );
     891           0 :                     if( pUndo )
     892             :                     {
     893           0 :                         pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
     894             :                     }
     895           0 :                     SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
     896           0 :                     if( pUndo )
     897           0 :                         pUndo->MoveBoxCntnt( pDoc, aRg, rInsPosNd );
     898             :                     else
     899             :                     {
     900             :                         pDoc->MoveNodeRange( aRg, rInsPosNd,
     901           0 :                             IDocumentContentOperations::DOC_NO_DELFRMS );
     902           0 :                     }
     903             :                 }
     904             :             }
     905             :             // Only the cell of the first selected column will stay alive
     906             :             // and got a new row span
     907           0 :             if( !nCurrCol )
     908           0 :                 pBox->setRowSpan( nRowSpan );
     909             :         }
     910           0 :         if( nRowSpan > 0 ) // the master cell is done, from now on we set
     911           0 :             nRowSpan = -nRowSpan; // negative row spans
     912           0 :         ++nRowSpan; // ... -3, -2, -1
     913             :     }
     914           0 :     if( bMerge )
     915             :     {
     916             :         // A row containing overlapped cells is superfluous,
     917             :         // these cells can be put into rBoxes for deletion
     918           0 :         _FindSuperfluousRows( rBoxes, pFirstLn, pLastLn );
     919             :         // pNewFmt will be set to the new master box and the overlapped cells
     920           0 :         SwFrmFmt* pNewFmt = pMergeBox->ClaimFrmFmt();
     921           0 :         pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, pSel->mnMergeWidth, 0 ) );
     922           0 :         for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
     923             :         {
     924           0 :             const SwSelBoxes* pBoxes = pSel->aBoxes[ nCurrLine ];
     925           0 :             size_t nColCount = pBoxes->size();
     926           0 :             for (size_t nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol)
     927             :             {
     928           0 :                 SwTableBox* pBox = (*pBoxes)[nCurrCol];
     929           0 :                 if( nCurrCol )
     930             :                 {
     931             :                     // Even this box will be deleted soon,
     932             :                     // we have to correct the width to avoid side effects
     933           0 :                     SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
     934           0 :                     pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, 0, 0 ) );
     935             :                 }
     936             :                 else
     937           0 :                     pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt );
     938             :             }
     939             :         }
     940           0 :         if( pLastBox ) // Robust
     941             :         {
     942             :             // The new borders of the master cell...
     943           0 :             SvxBoxItem aBox( pMergeBox->GetFrmFmt()->GetBox() );
     944           0 :             bool bOld = aBox.GetRight() || aBox.GetBottom();
     945           0 :             const SvxBoxItem& rBox = pLastBox->GetFrmFmt()->GetBox();
     946           0 :             aBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT );
     947           0 :             aBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM );
     948           0 :             if( bOld || aBox.GetLeft() || aBox.GetTop() || aBox.GetRight() || aBox.GetBottom() )
     949           0 :                 (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( aBox );
     950             :         }
     951             : 
     952           0 :         if( pUndo )
     953           0 :             pUndo->AddNewBox( pMergeBox->GetSttIdx() );
     954             :     }
     955           0 :     return bMerge;
     956             : }
     957             : 
     958             : /** SwTable::_FindSuperfluousRows(..) is looking for superfluous rows, i.e. rows
     959             :     containing overlapped cells only.
     960             : */
     961             : 
     962           0 : void SwTable::_FindSuperfluousRows( SwSelBoxes& rBoxes,
     963             :     SwTableLine* pFirstLn, SwTableLine* pLastLn )
     964             : {
     965           0 :     if( !pFirstLn || !pLastLn )
     966             :     {
     967           0 :         if( rBoxes.empty() )
     968           0 :             return;
     969           0 :         pFirstLn = rBoxes[0]->GetUpper();
     970           0 :         pLastLn = rBoxes.back()->GetUpper();
     971             :     }
     972           0 :     sal_uInt16 nFirstLn = GetTabLines().GetPos( pFirstLn );
     973           0 :     sal_uInt16 nLastLn = GetTabLines().GetPos( pLastLn );
     974           0 :     for( sal_uInt16 nRow = nFirstLn; nRow <= nLastLn; ++nRow )
     975             :     {
     976           0 :         SwTableLine* pLine = aLines[nRow];
     977             :         OSL_ENSURE( pLine, "Missing table line" );
     978           0 :         sal_uInt16 nCols = pLine->GetTabBoxes().size();
     979           0 :         bool bSuperfl = true;
     980           0 :         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
     981             :         {
     982           0 :             SwTableBox *pBox = pLine->GetTabBoxes()[nCol];
     983           0 :             if( pBox->getRowSpan() > 0 &&
     984           0 :                 rBoxes.end() == rBoxes.find( pBox ) )
     985             :             {
     986           0 :                 bSuperfl = false;
     987             :                 break;
     988             :             }
     989             :         }
     990           0 :         if( bSuperfl )
     991             :         {
     992           0 :             for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
     993             :             {
     994           0 :                 SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
     995           0 :                 rBoxes.insert( pBox );
     996             :             }
     997             :         }
     998             :     }
     999             : }
    1000             : 
    1001             : /** SwTableBox::FindStartOfRowSpan(..) retruns the "master" cell, the cell which
    1002             :     overlaps the given cell, it maybe the cell itself.
    1003             : */
    1004             : 
    1005           0 : SwTableBox& SwTableBox::FindStartOfRowSpan( const SwTable& rTable, sal_uInt16 nMaxStep )
    1006             : {
    1007           0 :     if( getRowSpan() > 0 || !nMaxStep )
    1008           0 :         return *this;
    1009             : 
    1010           0 :     long nLeftBorder = lcl_Box2LeftBorder( *this );
    1011           0 :     SwTableBox* pBox = this;
    1012           0 :     const SwTableLine* pMyUpper = GetUpper();
    1013           0 :     sal_uInt16 nLine = rTable.GetTabLines().GetPos( pMyUpper );
    1014           0 :     if( nLine && nLine < rTable.GetTabLines().size() )
    1015             :     {
    1016             :         SwTableBox* pNext;
    1017           0 :         do
    1018             :         {
    1019           0 :             pNext = lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[--nLine] );
    1020           0 :             if( pNext )
    1021           0 :                 pBox = pNext;
    1022           0 :         } while( nLine && --nMaxStep && pNext && pBox->getRowSpan() < 1 );
    1023             :     }
    1024             : 
    1025           0 :     return *pBox;
    1026             : }
    1027             : 
    1028             : /** SwTableBox::FindEndOfRowSpan(..) returns the last overlapped cell if there is
    1029             :     any. Otherwise the cell itself will returned.
    1030             : */
    1031             : 
    1032           0 : SwTableBox& SwTableBox::FindEndOfRowSpan( const SwTable& rTable, sal_uInt16 nMaxStep )
    1033             : {
    1034           0 :     long nAbsSpan = getRowSpan();
    1035           0 :     if( nAbsSpan < 0 )
    1036           0 :         nAbsSpan = -nAbsSpan;
    1037           0 :     if( nAbsSpan == 1 || !nMaxStep )
    1038           0 :         return *this;
    1039             : 
    1040           0 :     if( nMaxStep > --nAbsSpan )
    1041           0 :         nMaxStep = (sal_uInt16)nAbsSpan;
    1042           0 :     const SwTableLine* pMyUpper = GetUpper();
    1043           0 :     sal_uInt16 nLine = rTable.GetTabLines().GetPos( pMyUpper );
    1044           0 :     nMaxStep = nLine + nMaxStep;
    1045           0 :     if( nMaxStep >= rTable.GetTabLines().size() )
    1046           0 :         nMaxStep = rTable.GetTabLines().size() - 1;
    1047           0 :     long nLeftBorder = lcl_Box2LeftBorder( *this );
    1048             :     SwTableBox* pBox =
    1049           0 :         lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[ nMaxStep ] );
    1050           0 :     if ( !pBox )
    1051           0 :         pBox = this;
    1052             : 
    1053           0 :     return *pBox;
    1054             : }
    1055             : 
    1056             : /** lcl_getAllMergedBoxes(..) collects all overlapped boxes to a given (master) box
    1057             : */
    1058             : 
    1059           0 : static void lcl_getAllMergedBoxes( const SwTable& rTable, SwSelBoxes& rBoxes, SwTableBox& rBox )
    1060             : {
    1061           0 :     SwTableBox* pBox = &rBox;
    1062             :     OSL_ENSURE( pBox == &rBox.FindStartOfRowSpan( rTable, USHRT_MAX ), "Not a master box" );
    1063           0 :     rBoxes.insert( pBox );
    1064           0 :     if( pBox->getRowSpan() == 1 )
    1065           0 :         return;
    1066           0 :     const SwTableLine* pMyUpper = pBox->GetUpper();
    1067           0 :     sal_uInt16 nLine = rTable.GetTabLines().GetPos( pMyUpper );
    1068           0 :     long nLeftBorder = lcl_Box2LeftBorder( *pBox );
    1069           0 :     sal_uInt16 nCount = rTable.GetTabLines().size();
    1070           0 :     while( ++nLine < nCount && pBox && pBox->getRowSpan() != -1 )
    1071             :     {
    1072           0 :         pBox = lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines()[nLine] );
    1073           0 :         if( pBox )
    1074           0 :             rBoxes.insert( pBox );
    1075             :     };
    1076             : }
    1077             : 
    1078             : /** lcl_UnMerge(..) manipulates the row span attribute of a given master cell
    1079             :     and its overlapped cells to split them into several pieces.
    1080             : */
    1081             : 
    1082           0 : static void lcl_UnMerge( const SwTable& rTable, SwTableBox& rBox, size_t nCnt,
    1083             :     sal_Bool bSameHeight )
    1084             : {
    1085           0 :     SwSelBoxes aBoxes;
    1086           0 :     lcl_getAllMergedBoxes( rTable, aBoxes, rBox );
    1087           0 :     size_t const nCount = aBoxes.size();
    1088           0 :     if( nCount < 2 )
    1089           0 :         return;
    1090           0 :     if( nCnt > nCount )
    1091           0 :         nCnt = nCount;
    1092           0 :     ::boost::scoped_array<size_t> const pSplitIdx(new size_t[nCnt]);
    1093           0 :     if( bSameHeight )
    1094             :     {
    1095           0 :         ::boost::scoped_array<SwTwips> const pHeights(new SwTwips[nCount]);
    1096           0 :         SwTwips nHeight = 0;
    1097           0 :         for (size_t i = 0; i < nCount; ++i)
    1098             :         {
    1099           0 :             SwTableLine* pLine = aBoxes[ i ]->GetUpper();
    1100           0 :             SwFrmFmt *pRowFmt = pLine->GetFrmFmt();
    1101           0 :             pHeights[ i ] = pRowFmt->GetFrmSize().GetHeight();
    1102           0 :             nHeight += pHeights[ i ];
    1103             :         }
    1104           0 :         SwTwips nSumH = 0;
    1105           0 :         size_t nIdx = 0;
    1106           0 :         for (size_t i = 1; i <= nCnt; ++i)
    1107             :         {
    1108           0 :             SwTwips nSplit = ( i * nHeight ) / nCnt;
    1109           0 :             while( nSumH < nSplit && nIdx < nCount )
    1110           0 :                 nSumH += pHeights[ nIdx++ ];
    1111           0 :             pSplitIdx[ i - 1 ] = nIdx;
    1112           0 :         }
    1113             :     }
    1114             :     else
    1115             :     {
    1116           0 :         for (size_t i = 1; i <= nCnt; ++i)
    1117             :         {
    1118           0 :             pSplitIdx[ i - 1 ] = ( i * nCount ) / nCnt;
    1119             :         }
    1120             :     }
    1121           0 :     size_t nIdx = 0;
    1122           0 :     for (size_t i = 0; i < nCnt; ++i)
    1123             :     {
    1124           0 :         size_t nNextIdx = pSplitIdx[ i ];
    1125           0 :         aBoxes[ nIdx ]->setRowSpan( nNextIdx - nIdx );
    1126           0 :         lcl_InvalidateCellFrm( *aBoxes[ nIdx ] );
    1127           0 :         while( ++nIdx < nNextIdx )
    1128           0 :             aBoxes[ nIdx ]->setRowSpan( nIdx - nNextIdx );
    1129           0 :     }
    1130             : }
    1131             : 
    1132             : /** lcl_FillSelBoxes(..) puts all boxes of a given line into the selection structure
    1133             : */
    1134             : 
    1135           0 : static void lcl_FillSelBoxes( SwSelBoxes &rBoxes, SwTableLine &rLine )
    1136             : {
    1137           0 :     sal_uInt16 nBoxCount = rLine.GetTabBoxes().size();
    1138           0 :     for( sal_uInt16 i = 0; i < nBoxCount; ++i )
    1139           0 :         rBoxes.insert( rLine.GetTabBoxes()[i] );
    1140           0 : }
    1141             : 
    1142             : /** SwTable::InsertSpannedRow(..) inserts "superfluous" rows, i.e. rows containig
    1143             :     overlapped cells only. This is a preparation for an upcoming split.
    1144             : */
    1145             : 
    1146           0 : void SwTable::InsertSpannedRow( SwDoc* pDoc, sal_uInt16 nRowIdx, sal_uInt16 nCnt )
    1147             : {
    1148             :     CHECK_TABLE( *this )
    1149             :     OSL_ENSURE( nCnt && nRowIdx < GetTabLines().size(), "Wrong call of InsertSpannedRow" );
    1150           0 :     SwSelBoxes aBoxes;
    1151           0 :     SwTableLine& rLine = *GetTabLines()[ nRowIdx ];
    1152           0 :     lcl_FillSelBoxes( aBoxes, rLine );
    1153           0 :     SwFmtFrmSize aFSz( rLine.GetFrmFmt()->GetFrmSize() );
    1154           0 :     if( ATT_VAR_SIZE != aFSz.GetHeightSizeType() )
    1155             :     {
    1156           0 :         SwFrmFmt* pFrmFmt = rLine.ClaimFrmFmt();
    1157           0 :         long nNewHeight = aFSz.GetHeight() / ( nCnt + 1 );
    1158           0 :         if( !nNewHeight )
    1159           0 :             ++nNewHeight;
    1160           0 :         aFSz.SetHeight( nNewHeight );
    1161           0 :         pFrmFmt->SetFmtAttr( aFSz );
    1162             :     }
    1163           0 :     _InsertRow( pDoc, aBoxes, nCnt, true );
    1164           0 :     sal_uInt16 nBoxCount = rLine.GetTabBoxes().size();
    1165           0 :     for( sal_uInt16 n = 0; n < nCnt; ++n )
    1166             :     {
    1167           0 :         SwTableLine *pNewLine = GetTabLines()[ nRowIdx + nCnt - n ];
    1168           0 :         for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
    1169             :         {
    1170           0 :             long nRowSpan = rLine.GetTabBoxes()[nCurrBox]->getRowSpan();
    1171           0 :             if( nRowSpan > 0 )
    1172           0 :                 nRowSpan = - nRowSpan;
    1173           0 :             pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
    1174             :         }
    1175             :     }
    1176           0 :     lcl_ChangeRowSpan( *this, nCnt, nRowIdx, false );
    1177             :     CHECK_TABLE( *this )
    1178           0 : }
    1179             : 
    1180             : typedef std::pair< sal_uInt16, sal_uInt16 > SwLineOffset;
    1181             : typedef std::list< SwLineOffset > SwLineOffsetArray;
    1182             : 
    1183             : /******************************************************************************
    1184             : When a couple of table boxes has to be split,
    1185             : lcl_SophisticatedFillLineIndices delivers the information where and how many
    1186             : rows have to be inserted.
    1187             : Input
    1188             :     rTable: the table to manipulate
    1189             :     rBoxes: an array of boxes to split
    1190             :     nCnt:   how many parts are wanted
    1191             : Output
    1192             :     rArr:   a list of pairs ( line index, number of lines to insert )
    1193             : 
    1194             : ******************************************************************************/
    1195             : 
    1196           0 : static void lcl_SophisticatedFillLineIndices( SwLineOffsetArray &rArr,
    1197             :     const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
    1198             : {
    1199           0 :     std::list< SwLineOffset > aBoxes;
    1200           0 :     SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
    1201           0 :     for (size_t i = 0; i < rBoxes.size(); ++i)
    1202             :     {   // Collect all end line indices and the row spans
    1203           0 :         const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
    1204             :         OSL_ENSURE( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" );
    1205           0 :         if( nCnt > rBox.getRowSpan() )
    1206             :         {
    1207           0 :             const SwTableLine *pLine = rBox.GetUpper();
    1208           0 :             const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() +
    1209           0 :                 rTable.GetTabLines().GetPos(  pLine ) );
    1210             :             // The next if statement is a small optimization
    1211           0 :             if( aLnOfs.first != nEnd || aLnOfs.second != rBox.getRowSpan() )
    1212             :             {
    1213           0 :                 aLnOfs.first = nEnd; // ok, this is the line behind the box
    1214           0 :                 aLnOfs.second = sal_uInt16( rBox.getRowSpan() ); // the row span
    1215           0 :                 aBoxes.insert( aBoxes.end(), aLnOfs );
    1216             :             }
    1217             :         }
    1218             :     }
    1219             :     // As I said, I noted the line index _behind_ the last line of the boxes
    1220             :     // in the resulting array the index has to be _on_ the line
    1221             :     // nSum is to evaluate the wished value
    1222           0 :     sal_uInt16 nSum = 1;
    1223           0 :     while( !aBoxes.empty() )
    1224             :     {
    1225             :         // I. step:
    1226             :         // Looking for the "smallest" line end with the smallest row span
    1227           0 :         std::list< SwLineOffset >::iterator pCurr = aBoxes.begin();
    1228           0 :         aLnOfs = *pCurr; // the line end and row span of the first box
    1229           0 :         while( ++pCurr != aBoxes.end() )
    1230             :         {
    1231           0 :             if( aLnOfs.first > pCurr->first )
    1232             :             {   // Found a smaller line end
    1233           0 :                 aLnOfs.first = pCurr->first;
    1234           0 :                 aLnOfs.second = pCurr->second; // row span
    1235             :             }
    1236           0 :             else if( aLnOfs.first == pCurr->first &&
    1237           0 :                      aLnOfs.second < pCurr->second )
    1238           0 :                 aLnOfs.second = pCurr->second; // Found a smaller row span
    1239             :         }
    1240             :         OSL_ENSURE( aLnOfs.second < nCnt, "Clean-up failed" );
    1241           0 :         aLnOfs.second = nCnt - aLnOfs.second; // the number of rows to insert
    1242             :         rArr.insert( rArr.end(),
    1243           0 :             SwLineOffset( aLnOfs.first - nSum, aLnOfs.second ) );
    1244             :         // the correction has to be incremented because in the following
    1245             :         // loops the line ends were manipulated
    1246           0 :         nSum = nSum + aLnOfs.second;
    1247             : 
    1248           0 :         pCurr = aBoxes.begin();
    1249           0 :         while( pCurr != aBoxes.end() )
    1250             :         {
    1251           0 :             if( pCurr->first == aLnOfs.first )
    1252             :             {   // These boxes can be removed because the last insertion
    1253             :                 // of rows will expand their row span above the needed value
    1254           0 :                 std::list< SwLineOffset >::iterator pDel = pCurr;
    1255           0 :                 ++pCurr;
    1256           0 :                 aBoxes.erase( pDel );
    1257             :             }
    1258             :             else
    1259             :             {
    1260           0 :                 bool bBefore = ( pCurr->first - pCurr->second < aLnOfs.first );
    1261             :                 // Manipulation of the end line indices as if the rows are
    1262             :                 // already inserted
    1263           0 :                 pCurr->first = pCurr->first + aLnOfs.second;
    1264           0 :                 if( bBefore )
    1265             :                 {   // If the insertion is inside the box,
    1266             :                     // its row span has to be incremented
    1267           0 :                     pCurr->second = pCurr->second + aLnOfs.second;
    1268           0 :                     if( pCurr->second >= nCnt )
    1269             :                     {   // if the row span is bigger than the split factor
    1270             :                         // this box is done
    1271           0 :                         std::list< SwLineOffset >::iterator pDel = pCurr;
    1272           0 :                         ++pCurr;
    1273           0 :                         aBoxes.erase( pDel );
    1274             :                     }
    1275             :                     else
    1276           0 :                         ++pCurr;
    1277             :                 }
    1278             :                 else
    1279           0 :                     ++pCurr;
    1280             :             }
    1281             :         }
    1282           0 :     }
    1283           0 : }
    1284             : 
    1285             : typedef std::set< SwTwips > SwSplitLines;
    1286             : 
    1287             : /** lcl_CalculateSplitLineHeights(..) delivers all y-positions where table rows have
    1288             :     to be splitted to fulfill the requested "split same height"
    1289             : */
    1290             : 
    1291           0 : static sal_uInt16 lcl_CalculateSplitLineHeights( SwSplitLines &rCurr, SwSplitLines &rNew,
    1292             :     const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
    1293             : {
    1294           0 :     if( nCnt < 2 )
    1295           0 :         return 0;
    1296           0 :     std::list< SwLineOffset > aBoxes;
    1297           0 :     SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
    1298           0 :     sal_uInt16 nFirst = USHRT_MAX; // becomes the index of the first line
    1299           0 :     sal_uInt16 nLast = 0; // becomes the index of the last line of the splitting
    1300           0 :     for (size_t i = 0; i < rBoxes.size(); ++i)
    1301             :     {   // Collect all pairs (start+end) of line indices to split
    1302           0 :         const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
    1303             :         OSL_ENSURE( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" );
    1304           0 :         const SwTableLine *pLine = rBox.GetUpper();
    1305           0 :         const sal_uInt16 nStart = rTable.GetTabLines().GetPos( pLine );
    1306           0 :         const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() + nStart - 1 );
    1307             :         // The next if statement is a small optimization
    1308           0 :         if( aLnOfs.first != nStart || aLnOfs.second != nEnd )
    1309             :         {
    1310           0 :             aLnOfs.first = nStart;
    1311           0 :             aLnOfs.second = nEnd;
    1312           0 :             aBoxes.insert( aBoxes.end(), aLnOfs );
    1313           0 :             if( nStart < nFirst )
    1314           0 :                 nFirst = nStart;
    1315           0 :             if( nEnd > nLast )
    1316           0 :                 nLast = nEnd;
    1317             :         }
    1318             :     }
    1319             : 
    1320           0 :     if( aBoxes.empty() )
    1321           0 :         return 0;
    1322           0 :     SwTwips nHeight = 0;
    1323           0 :     SwTwips* pLines = new SwTwips[ nLast + 1 - nFirst ];
    1324           0 :     for( sal_uInt16 i = nFirst; i <= nLast; ++i )
    1325             :     {
    1326           0 :         bool bLayoutAvailable = false;
    1327           0 :         nHeight += rTable.GetTabLines()[ i ]->GetTableLineHeight( bLayoutAvailable );
    1328           0 :         rCurr.insert( rCurr.end(), nHeight );
    1329           0 :         pLines[ i - nFirst ] = nHeight;
    1330             :     }
    1331           0 :     std::list< SwLineOffset >::iterator pSplit = aBoxes.begin();
    1332           0 :     while( pSplit != aBoxes.end() )
    1333             :     {
    1334           0 :         SwTwips nBase = pSplit->first <= nFirst ? 0 :
    1335           0 :                         pLines[ pSplit->first - nFirst - 1 ];
    1336           0 :         SwTwips nDiff = pLines[ pSplit->second - nFirst ] - nBase;
    1337           0 :         for( sal_uInt16 i = 1; i < nCnt; ++i )
    1338             :         {
    1339           0 :             SwTwips nSplit = nBase + ( i * nDiff ) / nCnt;
    1340           0 :             rNew.insert( nSplit );
    1341             :         }
    1342           0 :         ++pSplit;
    1343             :     }
    1344           0 :     delete[] pLines;
    1345           0 :     return nFirst;
    1346             : }
    1347             : 
    1348             : /** lcl_LineIndex(..) delivers the line index of the line behind or above
    1349             :     the box selection.
    1350             : */
    1351             : 
    1352           0 : static sal_uInt16 lcl_LineIndex( const SwTable& rTable, const SwSelBoxes& rBoxes,
    1353             :                       bool bBehind )
    1354             : {
    1355           0 :     sal_uInt16 nDirect = USHRT_MAX;
    1356           0 :     sal_uInt16 nSpan = USHRT_MAX;
    1357           0 :     for (size_t i = 0; i < rBoxes.size(); ++i)
    1358             :     {
    1359           0 :         SwTableBox *pBox = rBoxes[i];
    1360           0 :         const SwTableLine* pLine = rBoxes[i]->GetUpper();
    1361           0 :         sal_uInt16 nPos = rTable.GetTabLines().GetPos( pLine );
    1362           0 :         if( USHRT_MAX != nPos )
    1363             :         {
    1364           0 :             if( bBehind )
    1365             :             {
    1366           0 :                 if( nPos > nDirect || nDirect == USHRT_MAX )
    1367           0 :                     nDirect = nPos;
    1368           0 :                 long nRowSpan = pBox->getRowSpan();
    1369           0 :                 if( nRowSpan < 2 )
    1370           0 :                     nSpan = 0;
    1371           0 :                 else if( nSpan )
    1372             :                 {
    1373           0 :                     sal_uInt16 nEndOfRowSpan = (sal_uInt16)(nPos + nRowSpan - 1);
    1374           0 :                     if( nEndOfRowSpan > nSpan || nSpan == USHRT_MAX )
    1375           0 :                         nSpan = nEndOfRowSpan;
    1376             :                 }
    1377             :             }
    1378           0 :             else if( nPos < nDirect )
    1379           0 :                 nDirect = nPos;
    1380             :         }
    1381             :     }
    1382           0 :     if( nSpan && nSpan < USHRT_MAX )
    1383           0 :         return nSpan;
    1384           0 :     return nDirect;
    1385             : }
    1386             : 
    1387             : /** SwTable::NewSplitRow(..) splits all selected boxes horizontally.
    1388             : */
    1389             : 
    1390           0 : sal_Bool SwTable::NewSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
    1391             :     sal_Bool bSameHeight )
    1392             : {
    1393             :     CHECK_TABLE( *this )
    1394           0 :     ++nCnt;
    1395           0 :     _FndBox aFndBox( 0, 0 );
    1396           0 :     aFndBox.SetTableLines( rBoxes, *this );
    1397             : 
    1398           0 :     if( bSameHeight && pDoc->GetCurrentViewShell() )    //swmod 071108//swmod 071225
    1399             :     {
    1400           0 :         SwSplitLines aRowLines;
    1401           0 :         SwSplitLines aSplitLines;
    1402             :         sal_uInt16 nFirst = lcl_CalculateSplitLineHeights( aRowLines, aSplitLines,
    1403           0 :             *this, rBoxes, nCnt );
    1404           0 :         aFndBox.DelFrms( *this );
    1405           0 :         SwTwips nLast = 0;
    1406           0 :         SwSplitLines::iterator pSplit = aSplitLines.begin();
    1407           0 :         SwSplitLines::iterator pCurr = aRowLines.begin();
    1408           0 :         while( pCurr != aRowLines.end() )
    1409             :         {
    1410           0 :             while( pSplit != aSplitLines.end() && *pSplit < *pCurr )
    1411             :             {
    1412           0 :                 InsertSpannedRow( pDoc, nFirst, 1 );
    1413           0 :                 SwTableLine* pRow = GetTabLines()[ nFirst ];
    1414           0 :                 SwFrmFmt* pRowFmt = pRow->ClaimFrmFmt();
    1415           0 :                 SwFmtFrmSize aFSz( pRowFmt->GetFrmSize() );
    1416           0 :                 aFSz.SetHeightSizeType( ATT_MIN_SIZE );
    1417           0 :                 aFSz.SetHeight( *pSplit - nLast );
    1418           0 :                 pRowFmt->SetFmtAttr( aFSz );
    1419           0 :                 nLast = *pSplit;
    1420           0 :                 ++pSplit;
    1421           0 :                 ++nFirst;
    1422           0 :             }
    1423           0 :             if( pSplit != aSplitLines.end() && *pCurr == *pSplit )
    1424           0 :                 ++pSplit;
    1425           0 :             SwTableLine* pRow = GetTabLines()[ nFirst ];
    1426           0 :             SwFrmFmt* pRowFmt = pRow->ClaimFrmFmt();
    1427           0 :             SwFmtFrmSize aFSz( pRowFmt->GetFrmSize() );
    1428           0 :             aFSz.SetHeightSizeType( ATT_MIN_SIZE );
    1429           0 :             aFSz.SetHeight( *pCurr - nLast );
    1430           0 :             pRowFmt->SetFmtAttr( aFSz );
    1431           0 :             nLast = *pCurr;
    1432           0 :             ++pCurr;
    1433           0 :             ++nFirst;
    1434           0 :         }
    1435             :     }
    1436             :     else
    1437             :     {
    1438           0 :         aFndBox.DelFrms( *this );
    1439           0 :         bSameHeight = sal_False;
    1440             :     }
    1441           0 :     if( !bSameHeight )
    1442             :     {
    1443           0 :         SwLineOffsetArray aLineOffs;
    1444           0 :         lcl_SophisticatedFillLineIndices( aLineOffs, *this, rBoxes, nCnt );
    1445           0 :         SwLineOffsetArray::reverse_iterator pCurr( aLineOffs.rbegin() );
    1446           0 :         while( pCurr != aLineOffs.rend() )
    1447             :         {
    1448           0 :             InsertSpannedRow( pDoc, pCurr->first, pCurr->second );
    1449           0 :             ++pCurr;
    1450           0 :         }
    1451             :     }
    1452             : 
    1453           0 :     std::set<size_t> aIndices;
    1454           0 :     for (size_t i = 0; i < rBoxes.size(); ++i)
    1455             :     {
    1456             :         OSL_ENSURE( rBoxes[i]->getRowSpan() != 1, "Forgot to split?" );
    1457           0 :         if( rBoxes[i]->getRowSpan() > 1 )
    1458           0 :             aIndices.insert( i );
    1459             :     }
    1460             : 
    1461           0 :     std::set<size_t>::iterator pCurrBox = aIndices.begin();
    1462           0 :     while( pCurrBox != aIndices.end() )
    1463           0 :         lcl_UnMerge( *this, *rBoxes[*pCurrBox++], nCnt, bSameHeight );
    1464             : 
    1465             :     CHECK_TABLE( *this )
    1466             :     //Layout updaten
    1467           0 :     aFndBox.MakeFrms( *this );
    1468             : 
    1469           0 :     return sal_True;
    1470             : }
    1471             : 
    1472             : /** SwTable::InsertRow(..) inserts one or more rows before or behind the selected
    1473             :     boxes.
    1474             : */
    1475             : 
    1476           0 : bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
    1477             :                         sal_uInt16 nCnt, bool bBehind )
    1478             : {
    1479           0 :     bool bRet = false;
    1480           0 :     if( IsNewModel() )
    1481             :     {
    1482             :         CHECK_TABLE( *this )
    1483           0 :         sal_uInt16 nRowIdx = lcl_LineIndex( *this, rBoxes, bBehind );
    1484           0 :         if( nRowIdx < USHRT_MAX )
    1485             :         {
    1486           0 :             _FndBox aFndBox( 0, 0 );
    1487           0 :             aFndBox.SetTableLines( rBoxes, *this );
    1488           0 :             aFndBox.DelFrms( *this );
    1489             : 
    1490           0 :             bRet = true;
    1491           0 :             SwTableLine *pLine = GetTabLines()[ nRowIdx ];
    1492           0 :             SwSelBoxes aLineBoxes;
    1493           0 :             lcl_FillSelBoxes( aLineBoxes, *pLine );
    1494           0 :             _InsertRow( pDoc, aLineBoxes, nCnt, bBehind );
    1495           0 :             sal_uInt16 nBoxCount = pLine->GetTabBoxes().size();
    1496           0 :             sal_uInt16 nOfs = bBehind ? 0 : 1;
    1497           0 :             for( sal_uInt16 n = 0; n < nCnt; ++n )
    1498             :             {
    1499           0 :                 SwTableLine *pNewLine = GetTabLines()[ nRowIdx+nCnt-n-nOfs];
    1500           0 :                 for( sal_uInt16 nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
    1501             :                 {
    1502           0 :                     long nRowSpan = pLine->GetTabBoxes()[nCurrBox]->getRowSpan();
    1503           0 :                     if( bBehind )
    1504             :                     {
    1505           0 :                         if( nRowSpan == 1 || nRowSpan == -1 )
    1506           0 :                             nRowSpan = n + 1;
    1507           0 :                         else if( nRowSpan > 1 )
    1508           0 :                             nRowSpan = - nRowSpan;
    1509             :                     }
    1510             :                     else
    1511             :                     {
    1512           0 :                         if( nRowSpan > 0 )
    1513           0 :                             nRowSpan = n + 1;
    1514             :                         else
    1515           0 :                             --nRowSpan;
    1516             :                     }
    1517           0 :                     pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
    1518             :                 }
    1519             :             }
    1520           0 :             if( bBehind )
    1521           0 :                 ++nRowIdx;
    1522           0 :             if( nRowIdx )
    1523           0 :                 lcl_ChangeRowSpan( *this, nCnt, --nRowIdx, true );
    1524             :             //Layout update
    1525           0 :             aFndBox.MakeFrms( *this );
    1526             :         }
    1527             :         CHECK_TABLE( *this )
    1528             :     }
    1529             :     else
    1530           0 :         bRet = _InsertRow( pDoc, rBoxes, nCnt, bBehind );
    1531           0 :     return bRet;
    1532             : }
    1533             : 
    1534             : /** SwTable::PrepareDelBoxes(..) adjusts the row span attributes for an upcoming
    1535             :     deletion of table cells and invalidates the layout of these cells.
    1536             : */
    1537             : 
    1538           0 : void SwTable::PrepareDelBoxes( const SwSelBoxes& rBoxes )
    1539             : {
    1540           0 :     if( IsNewModel() )
    1541             :     {
    1542           0 :         for (size_t i = 0; i < rBoxes.size(); ++i)
    1543             :         {
    1544           0 :             SwTableBox* pBox = rBoxes[i];
    1545           0 :             long nRowSpan = pBox->getRowSpan();
    1546           0 :             if( nRowSpan != 1 && pBox->GetFrmFmt()->GetFrmSize().GetWidth() )
    1547             :             {
    1548           0 :                 long nLeft = lcl_Box2LeftBorder( *pBox );
    1549           0 :                 SwTableLine *pLine = pBox->GetUpper();
    1550           0 :                 sal_uInt16 nLinePos = GetTabLines().GetPos( pLine);
    1551             :                 OSL_ENSURE( nLinePos < USHRT_MAX, "Box/table mismatch" );
    1552           0 :                 if( nRowSpan > 1 )
    1553             :                 {
    1554           0 :                     if( ++nLinePos < GetTabLines().size() )
    1555             :                     {
    1556           0 :                         pLine = GetTabLines()[ nLinePos ];
    1557           0 :                         pBox = lcl_LeftBorder2Box( nLeft, pLine );
    1558             :                         OSL_ENSURE( pBox, "RowSpan irritation I" );
    1559           0 :                         if( pBox )
    1560           0 :                             pBox->setRowSpan( --nRowSpan );
    1561             :                     }
    1562             :                 }
    1563           0 :                 else if( nLinePos > 0 )
    1564             :                 {
    1565           0 :                     do
    1566             :                     {
    1567           0 :                         pLine = GetTabLines()[ --nLinePos ];
    1568           0 :                         pBox = lcl_LeftBorder2Box( nLeft, pLine );
    1569             :                         OSL_ENSURE( pBox, "RowSpan irritation II" );
    1570           0 :                         if( pBox )
    1571             :                         {
    1572           0 :                             nRowSpan = pBox->getRowSpan();
    1573           0 :                             if( nRowSpan > 1 )
    1574             :                             {
    1575           0 :                                 lcl_InvalidateCellFrm( *pBox );
    1576           0 :                                 --nRowSpan;
    1577             :                             }
    1578             :                             else
    1579           0 :                                 ++nRowSpan;
    1580           0 :                             pBox->setRowSpan( nRowSpan );
    1581             :                         }
    1582             :                         else
    1583           0 :                             nRowSpan = 1;
    1584             :                     }
    1585             :                     while( nRowSpan < 0 && nLinePos > 0 );
    1586             :                 }
    1587             :             }
    1588             :         }
    1589             :     }
    1590           0 : }
    1591             : 
    1592             : /** lcl_SearchSelBox(..) adds cells of a given table row to the selection structure
    1593             :     if it overlaps with the given x-position range
    1594             : */
    1595             : 
    1596          12 : static void lcl_SearchSelBox( const SwTable &rTable, SwSelBoxes& rBoxes, long nMin, long nMax,
    1597             :                        SwTableLine& rLine, bool bChkProtected, bool bColumn )
    1598             : {
    1599          12 :     long nLeft = 0;
    1600          12 :     long nRight = 0;
    1601          12 :     long nMid = ( nMax + nMin )/ 2;
    1602          12 :     sal_uInt16 nCount = rLine.GetTabBoxes().size();
    1603          15 :     for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
    1604             :     {
    1605          15 :         SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
    1606             :         OSL_ENSURE( pBox, "Missing table box" );
    1607          15 :         long nWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1608          15 :         nRight += nWidth;
    1609          15 :         if( nRight > nMin )
    1610             :         {
    1611          15 :             bool bAdd = false;
    1612          15 :             if( nRight <= nMax )
    1613             :                 bAdd = nLeft >= nMin || nRight >= nMid ||
    1614          14 :                        nRight - nMin > nMin - nLeft;
    1615             :             else
    1616           1 :                 bAdd = nLeft <= nMid || nRight - nMax < nMax - nLeft;
    1617          15 :             long nRowSpan = pBox->getRowSpan();
    1618          29 :             if( bAdd &&
    1619          14 :                 ( !bChkProtected ||
    1620           0 :                 !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) )
    1621             :             {
    1622          14 :                 size_t const nOldCnt = rBoxes.size();
    1623          14 :                 rBoxes.insert( pBox );
    1624          14 :                 if( bColumn && nRowSpan != 1 && nOldCnt < rBoxes.size() )
    1625             :                 {
    1626           0 :                     SwTableBox *pMasterBox = pBox->getRowSpan() > 0 ? pBox
    1627           0 :                         : &pBox->FindStartOfRowSpan( rTable, USHRT_MAX );
    1628           0 :                     lcl_getAllMergedBoxes( rTable, rBoxes, *pMasterBox );
    1629             :                 }
    1630             :             }
    1631             :         }
    1632          15 :         if( nRight >= nMax )
    1633             :             break;
    1634           3 :         nLeft = nRight;
    1635             :     }
    1636          12 : }
    1637             : 
    1638             : /** void SwTable::CreateSelection(..) fills the selection structure with table cells
    1639             :     for a given SwPaM, ie. start and end position inside a table
    1640             : */
    1641             : 
    1642           8 : void SwTable::CreateSelection(  const SwPaM& rPam, SwSelBoxes& rBoxes,
    1643             :     const SearchType eSearch, bool bChkProtected ) const
    1644             : {
    1645             :     OSL_ENSURE( bNewModel, "Don't call me for old tables" );
    1646           8 :     if( aLines.empty() )
    1647           0 :         return;
    1648           8 :     const SwNode* pStartNd = rPam.GetPoint()->nNode.GetNode().FindTableBoxStartNode();
    1649           8 :     const SwNode* pEndNd = rPam.GetMark()->nNode.GetNode().FindTableBoxStartNode();
    1650           8 :     if( !pStartNd || !pEndNd )
    1651           0 :         return;
    1652           8 :     CreateSelection( pStartNd, pEndNd, rBoxes, eSearch, bChkProtected );
    1653             : }
    1654             : 
    1655             : /** void SwTable::CreateSelection(..) fills the selection structure with table cells
    1656             :     for given start and end nodes inside a table
    1657             : */
    1658          10 : void SwTable::CreateSelection( const SwNode* pStartNd, const SwNode* pEndNd,
    1659             :     SwSelBoxes& rBoxes, const SearchType eSearch, bool bChkProtected ) const
    1660             : {
    1661          10 :     rBoxes.clear();
    1662             :     // Looking for start and end of the selection given by SwNode-pointer
    1663          10 :     sal_uInt16 nLines = aLines.size();
    1664             :     // nTop becomes the line number of the upper box
    1665             :     // nBottom becomes the line number of the lower box
    1666          10 :     sal_uInt16 nTop = 0, nBottom = 0;
    1667             :     // nUpperMin becomes the left border value of the upper box
    1668             :     // nUpperMax becomes the right border of the upper box
    1669             :     // nLowerMin and nLowerMax the borders of the lower box
    1670          10 :     long nUpperMin = 0, nUpperMax = 0;
    1671          10 :     long nLowerMin = 0, nLowerMax = 0;
    1672             :     // nFound will incremented if a box is found
    1673             :     // 0 => no box found; 1 => the upper box has been found; 2 => both found
    1674          10 :     int nFound = 0;
    1675          21 :     for( sal_uInt16 nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
    1676             :     {
    1677          11 :         SwTableLine* pLine = aLines[nRow];
    1678             :         OSL_ENSURE( pLine, "Missing table line" );
    1679          11 :         sal_uInt16 nCols = pLine->GetTabBoxes().size();
    1680          30 :         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
    1681             :         {
    1682          20 :             SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
    1683             :             OSL_ENSURE( pBox, "Missing table box" );
    1684          20 :             if( pBox->GetSttNd() == pEndNd || pBox->GetSttNd() == pStartNd )
    1685             :             {
    1686          11 :                 if( !bChkProtected ||
    1687           0 :                     !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
    1688          11 :                     rBoxes.insert( pBox );
    1689          11 :                 if( nFound )
    1690             :                 {
    1691           1 :                     nBottom = nRow;
    1692           1 :                     lcl_CheckMinMax( nLowerMin, nLowerMax, *pLine, nCol, true );
    1693           1 :                     ++nFound;
    1694             :                     break;
    1695             :                 }
    1696             :                 else
    1697             :                 {
    1698          10 :                     nTop = nRow;
    1699          10 :                     lcl_CheckMinMax( nUpperMin, nUpperMax, *pLine, nCol, true );
    1700          10 :                     ++nFound;
    1701             :                      // If start and end node are identical, we're nearly done..
    1702          10 :                     if( pEndNd == pStartNd )
    1703             :                     {
    1704           9 :                         nBottom = nTop;
    1705           9 :                         nLowerMin = nUpperMin;
    1706           9 :                         nLowerMax = nUpperMax;
    1707           9 :                         ++nFound;
    1708             :                     }
    1709             :                 }
    1710             :             }
    1711             :         }
    1712             :     }
    1713          10 :     if( nFound < 2 )
    1714             :         return; // At least one node was not a part of the given table
    1715          10 :     if( eSearch == SEARCH_ROW )
    1716             :     {
    1717             :         // Selection of a row is quiet easy:
    1718             :         // every (unprotected) box between start and end line
    1719             :         // with a positive row span will be collected
    1720           0 :         for( sal_uInt16 nRow = nTop; nRow <= nBottom; ++nRow )
    1721             :         {
    1722           0 :             SwTableLine* pLine = aLines[nRow];
    1723             :             OSL_ENSURE( pLine, "Missing table line" );
    1724           0 :             sal_uInt16 nCount = pLine->GetTabBoxes().size();
    1725           0 :             for( sal_uInt16 nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
    1726             :             {
    1727           0 :                 SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
    1728             :                 OSL_ENSURE( pBox, "Missing table box" );
    1729           0 :                 if( pBox->getRowSpan() > 0 && ( !bChkProtected ||
    1730           0 :                     !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) )
    1731           0 :                     rBoxes.insert( pBox );
    1732             :             }
    1733             :         }
    1734             :         return;
    1735             :     }
    1736          10 :     bool bCombine = nTop == nBottom;
    1737          10 :     if( !bCombine )
    1738             :     {
    1739           1 :         long nMinWidth = nUpperMax - nUpperMin;
    1740           1 :         long nTmp = nLowerMax - nLowerMin;
    1741           1 :         if( nMinWidth > nTmp )
    1742           0 :             nMinWidth = nTmp;
    1743           1 :         nTmp = nLowerMax < nUpperMax ? nLowerMax : nUpperMax;
    1744           1 :         nTmp -= ( nLowerMin < nUpperMin ) ? nUpperMin : nLowerMin;
    1745             :         // If the overlapping between upper and lower box is less than half
    1746             :         // of the width (of the smaller cell), bCombine is set,
    1747             :         // e.g. if upper and lower cell are in different columns
    1748           1 :         bCombine = ( nTmp + nTmp < nMinWidth );
    1749             :     }
    1750          10 :     if( bCombine )
    1751             :     {
    1752          10 :         if( nUpperMin < nLowerMin )
    1753           1 :             nLowerMin = nUpperMin;
    1754             :         else
    1755           9 :             nUpperMin = nLowerMin;
    1756          10 :         if( nUpperMax > nLowerMax )
    1757           0 :             nLowerMax = nUpperMax;
    1758             :         else
    1759          10 :             nUpperMax = nLowerMax;
    1760             :     }
    1761          10 :     const bool bColumn = eSearch == SEARCH_COL;
    1762          10 :     if( bColumn )
    1763             :     {
    1764           8 :         for( sal_uInt16 i = 0; i < nTop; ++i )
    1765             :             lcl_SearchSelBox( *this, rBoxes, nUpperMin, nUpperMax,
    1766           0 :                               *aLines[i], bChkProtected, bColumn );
    1767             :     }
    1768             : 
    1769             :     {
    1770          10 :         long nMin = nUpperMin < nLowerMin ? nUpperMin : nLowerMin;
    1771          10 :         long nMax = nUpperMax < nLowerMax ? nLowerMax : nUpperMax;
    1772          21 :         for( sal_uInt16 i = nTop; i <= nBottom; ++i )
    1773          11 :             lcl_SearchSelBox( *this, rBoxes, nMin, nMax, *aLines[i],
    1774          22 :                               bChkProtected, bColumn );
    1775             :     }
    1776          10 :     if( bColumn )
    1777             :     {
    1778           9 :         for( sal_uInt16 i = nBottom + 1; i < nLines; ++i )
    1779           1 :             lcl_SearchSelBox( *this, rBoxes, nLowerMin, nLowerMax, *aLines[i],
    1780           2 :                               bChkProtected, true );
    1781             :     }
    1782             : }
    1783             : 
    1784             : /** void SwTable::ExpandColumnSelection(..) adds cell to the give selection to
    1785             :     assure that at least one cell of every row is part of the selection.
    1786             : */
    1787             : 
    1788           0 : void SwTable::ExpandColumnSelection( SwSelBoxes& rBoxes, long &rMin, long &rMax ) const
    1789             : {
    1790             :     OSL_ENSURE( bNewModel, "Don't call me for old tables" );
    1791           0 :     rMin = 0;
    1792           0 :     rMax = 0;
    1793           0 :     if( aLines.empty() || rBoxes.empty() )
    1794           0 :         return;
    1795             : 
    1796           0 :     sal_uInt16 nLineCnt = aLines.size();
    1797           0 :     size_t const nBoxCnt = rBoxes.size();
    1798           0 :     size_t nBox = 0;
    1799           0 :     for( sal_uInt16 nRow = 0; nRow < nLineCnt && nBox < nBoxCnt; ++nRow )
    1800             :     {
    1801           0 :         SwTableLine* pLine = aLines[nRow];
    1802             :         OSL_ENSURE( pLine, "Missing table line" );
    1803           0 :         sal_uInt16 nCols = pLine->GetTabBoxes().size();
    1804           0 :         for( sal_uInt16 nCol = 0; nCol < nCols; ++nCol )
    1805             :         {
    1806           0 :             SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
    1807             :             OSL_ENSURE( pBox, "Missing table box" );
    1808           0 :             if( pBox == rBoxes[nBox] )
    1809             :             {
    1810           0 :                 lcl_CheckMinMax( rMin, rMax, *pLine, nCol, nBox == 0 );
    1811           0 :                 if( ++nBox >= nBoxCnt )
    1812           0 :                     break;
    1813             :             }
    1814             :         }
    1815             :     }
    1816           0 :     for( sal_uInt16 nRow = 0; nRow < nLineCnt; ++nRow )
    1817             :     {
    1818           0 :         SwTableLine* pLine = aLines[nRow];
    1819           0 :         sal_uInt16 nCols = pLine->GetTabBoxes().size();
    1820           0 :         long nLeft = 0;
    1821           0 :         long nRight = 0;
    1822           0 :         for( sal_uInt16 nCurrBox = 0; nCurrBox < nCols; ++nCurrBox )
    1823             :         {
    1824           0 :             nLeft = nRight;
    1825           0 :             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
    1826           0 :             nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1827           0 :             if( nLeft >= rMin && nRight <= rMax )
    1828           0 :                 rBoxes.insert( pBox );
    1829             :         }
    1830             :     }
    1831             : }
    1832             : 
    1833             : /** SwTable::PrepareDeleteCol(..) adjusts the widths of the neighbour cells of
    1834             :     a cell selection for an upcoming (column) deletion
    1835             : */
    1836           0 : void SwTable::PrepareDeleteCol( long nMin, long nMax )
    1837             : {
    1838             :     OSL_ENSURE( bNewModel, "Don't call me for old tables" );
    1839           0 :     if( aLines.empty() || nMax < nMin )
    1840           0 :         return;
    1841           0 :     long nMid = nMin ? ( nMin + nMax ) / 2 : 0;
    1842           0 :     const SwTwips nTabSize = GetFrmFmt()->GetFrmSize().GetWidth();
    1843           0 :     if( nTabSize == nMax )
    1844           0 :         nMid = nMax;
    1845           0 :     sal_uInt16 nLineCnt = aLines.size();
    1846           0 :     for( sal_uInt16 nRow = 0; nRow < nLineCnt; ++nRow )
    1847             :     {
    1848           0 :         SwTableLine* pLine = aLines[nRow];
    1849           0 :         sal_uInt16 nCols = pLine->GetTabBoxes().size();
    1850           0 :         long nLeft = 0;
    1851           0 :         long nRight = 0;
    1852           0 :         for( sal_uInt16 nCurrBox = 0; nCurrBox < nCols; ++nCurrBox )
    1853             :         {
    1854           0 :             nLeft = nRight;
    1855           0 :             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrBox];
    1856           0 :             nRight += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1857           0 :             if( nRight < nMin )
    1858           0 :                 continue;
    1859           0 :             if( nLeft > nMax )
    1860           0 :                 break;
    1861           0 :             long nNewWidth = -1;
    1862           0 :             if( nLeft < nMin )
    1863             :             {
    1864           0 :                 if( nRight <= nMax )
    1865           0 :                     nNewWidth = nMid - nLeft;
    1866             :             }
    1867           0 :             else if( nRight > nMax )
    1868           0 :                 nNewWidth = nRight - nMid;
    1869             :             else
    1870           0 :                 nNewWidth = 0;
    1871           0 :             if( nNewWidth >= 0 )
    1872             :             {
    1873           0 :                 SwFrmFmt* pFrmFmt = pBox->ClaimFrmFmt();
    1874           0 :                 SwFmtFrmSize aFrmSz( pFrmFmt->GetFrmSize() );
    1875           0 :                 aFrmSz.SetWidth( nNewWidth );
    1876           0 :                 pFrmFmt->SetFmtAttr( aFrmSz );
    1877             :             }
    1878             :         }
    1879             :     }
    1880             : }
    1881             : 
    1882             : 
    1883             : 
    1884             : /** SwTable::ExpandSelection(..) adds all boxes to the box selections which are
    1885             :     overlapped by it.
    1886             : */
    1887             : 
    1888           0 : void SwTable::ExpandSelection( SwSelBoxes& rBoxes ) const
    1889             : {
    1890           0 :     for (size_t i = 0; i < rBoxes.size(); ++i)
    1891             :     {
    1892           0 :         SwTableBox *pBox = rBoxes[i];
    1893           0 :         long nRowSpan = pBox->getRowSpan();
    1894           0 :         if( nRowSpan != 1 )
    1895             :         {
    1896             :             SwTableBox *pMasterBox = nRowSpan > 0 ? pBox
    1897           0 :                     : &pBox->FindStartOfRowSpan( *this, USHRT_MAX );
    1898           0 :             lcl_getAllMergedBoxes( *this, rBoxes, *pMasterBox );
    1899             :         }
    1900             :     }
    1901           0 : }
    1902             : 
    1903             : /** SwTable::CheckRowSpan(..) looks for the next line without an overlapping to
    1904             :     the previous line.
    1905             : */
    1906             : 
    1907           0 : void SwTable::CheckRowSpan( SwTableLine* &rpLine, bool bUp ) const
    1908             : {
    1909             :     OSL_ENSURE( IsNewModel(), "Don't call me for old tables" );
    1910           0 :     sal_uInt16 nLineIdx = GetTabLines().GetPos( rpLine );
    1911             :     OSL_ENSURE( nLineIdx < GetTabLines().size(), "Start line out of range" );
    1912           0 :     bool bChange = true;
    1913           0 :     if( bUp )
    1914             :     {
    1915           0 :         while( bChange )
    1916             :         {
    1917           0 :             bChange = false;
    1918           0 :             rpLine = GetTabLines()[ nLineIdx ];
    1919           0 :             sal_uInt16 nCols = rpLine->GetTabBoxes().size();
    1920           0 :             for( sal_uInt16 nCol = 0; !bChange && nCol < nCols; ++nCol )
    1921             :             {
    1922           0 :                 SwTableBox* pBox = rpLine->GetTabBoxes()[nCol];
    1923           0 :                 if( pBox->getRowSpan() > 1 || pBox->getRowSpan() < -1 )
    1924           0 :                     bChange = true;
    1925             :             }
    1926           0 :             if( bChange )
    1927             :             {
    1928           0 :                 if( nLineIdx )
    1929           0 :                     --nLineIdx;
    1930             :                 else
    1931             :                 {
    1932           0 :                     bChange = false;
    1933           0 :                     rpLine = 0;
    1934             :                 }
    1935             :             }
    1936             :         }
    1937             :     }
    1938             :     else
    1939             :     {
    1940           0 :         sal_uInt16 nMaxLine = GetTabLines().size();
    1941           0 :         while( bChange )
    1942             :         {
    1943           0 :             bChange = false;
    1944           0 :             rpLine = GetTabLines()[ nLineIdx ];
    1945           0 :             sal_uInt16 nCols = rpLine->GetTabBoxes().size();
    1946           0 :             for( sal_uInt16 nCol = 0; !bChange && nCol < nCols; ++nCol )
    1947             :             {
    1948           0 :                 SwTableBox* pBox = rpLine->GetTabBoxes()[nCol];
    1949           0 :                 if( pBox->getRowSpan() < 0 )
    1950           0 :                     bChange = true;
    1951             :             }
    1952           0 :             if( bChange )
    1953             :             {
    1954           0 :                 ++nLineIdx;
    1955           0 :                 if( nLineIdx >= nMaxLine )
    1956             :                 {
    1957           0 :                     bChange = false;
    1958           0 :                     rpLine = 0;
    1959             :                 }
    1960             :             }
    1961             :         }
    1962             :     }
    1963           0 : }
    1964             : 
    1965             : // This structure corrects the row span attributes for a top line of a table
    1966             : // In a top line no negative row span is allowed, so these have to be corrected.
    1967             : // If there has been at least one correction, all values are stored
    1968             : // and can be used by undo of table split
    1969           0 : SwSaveRowSpan::SwSaveRowSpan( SwTableBoxes& rBoxes, sal_uInt16 nSplitLn )
    1970           0 :     : mnSplitLine( nSplitLn )
    1971             : {
    1972           0 :     bool bDontSave = true; // nothing changed, nothing to save
    1973           0 :     sal_uInt16 nColCount = rBoxes.size();
    1974             :     OSL_ENSURE( nColCount, "Empty Table Line" );
    1975           0 :     mnRowSpans.resize( nColCount );
    1976           0 :     for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
    1977             :     {
    1978           0 :         SwTableBox* pBox = rBoxes[nCurrCol];
    1979             :         OSL_ENSURE( pBox, "Missing Table Box" );
    1980           0 :         long nRowSp = pBox->getRowSpan();
    1981           0 :         mnRowSpans[ nCurrCol ] = nRowSp;
    1982           0 :         if( nRowSp < 0 )
    1983             :         {
    1984           0 :             bDontSave = false;
    1985           0 :             nRowSp = -nRowSp;
    1986           0 :             pBox->setRowSpan( nRowSp ); // correction needed
    1987             :         }
    1988             :     }
    1989           0 :     if( bDontSave )
    1990           0 :         mnRowSpans.clear();
    1991           0 : }
    1992             : 
    1993             : // This function is called by undo of table split to restore the old row span
    1994             : // values at the split line
    1995           0 : void SwTable::RestoreRowSpan( const SwSaveRowSpan& rSave )
    1996             : {
    1997           0 :     if( !IsNewModel() ) // for new model only
    1998           0 :         return;
    1999           0 :     sal_uInt16 nLineCount = GetTabLines().size();
    2000             :     OSL_ENSURE( rSave.mnSplitLine < nLineCount, "Restore behind last line?" );
    2001           0 :     if( rSave.mnSplitLine < nLineCount )
    2002             :     {
    2003           0 :         SwTableLine* pLine = GetTabLines()[rSave.mnSplitLine];
    2004           0 :         sal_uInt16 nColCount = pLine->GetTabBoxes().size();
    2005             :         OSL_ENSURE( nColCount, "Empty Table Line" );
    2006             :         OSL_ENSURE( nColCount == rSave.mnRowSpans.size(), "Wrong row span store" );
    2007           0 :         if( nColCount == rSave.mnRowSpans.size() )
    2008             :         {
    2009           0 :             for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
    2010             :             {
    2011           0 :                 SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
    2012             :                 OSL_ENSURE( pBox, "Missing Table Box" );
    2013           0 :                 long nRowSp = pBox->getRowSpan();
    2014           0 :                 if( nRowSp != rSave.mnRowSpans[ nCurrCol ] )
    2015             :                 {
    2016             :                     OSL_ENSURE( -nRowSp == rSave.mnRowSpans[ nCurrCol ], "Pardon me?!" );
    2017             :                     OSL_ENSURE( rSave.mnRowSpans[ nCurrCol ] < 0, "Pardon me?!" );
    2018           0 :                     pBox->setRowSpan( -nRowSp );
    2019             : 
    2020           0 :                     sal_uInt16 nLine = rSave.mnSplitLine;
    2021           0 :                     if( nLine )
    2022             :                     {
    2023           0 :                         long nLeftBorder = lcl_Box2LeftBorder( *pBox );
    2024             :                         SwTableBox* pNext;
    2025           0 :                         do
    2026             :                         {
    2027           0 :                             pNext = lcl_LeftBorder2Box( nLeftBorder, GetTabLines()[--nLine] );
    2028           0 :                             if( pNext )
    2029             :                             {
    2030           0 :                                 pBox = pNext;
    2031           0 :                                 long nNewSpan = pBox->getRowSpan();
    2032           0 :                                 if( pBox->getRowSpan() < 1 )
    2033           0 :                                     nNewSpan -= nRowSp;
    2034             :                                 else
    2035             :                                 {
    2036           0 :                                     nNewSpan += nRowSp;
    2037           0 :                                     pNext = 0;
    2038             :                                 }
    2039           0 :                                 pBox->setRowSpan( nNewSpan );
    2040             :                             }
    2041             :                         } while( nLine && pNext );
    2042             :                     }
    2043             :                 }
    2044             :             }
    2045             :         }
    2046             :     }
    2047             : }
    2048             : 
    2049           0 : SwSaveRowSpan* SwTable::CleanUpTopRowSpan( sal_uInt16 nSplitLine )
    2050             : {
    2051           0 :     SwSaveRowSpan* pRet = 0;
    2052           0 :     if( !IsNewModel() )
    2053           0 :         return pRet;
    2054           0 :     pRet = new SwSaveRowSpan( GetTabLines()[0]->GetTabBoxes(), nSplitLine );
    2055           0 :     if( pRet->mnRowSpans.empty() )
    2056             :     {
    2057           0 :         delete pRet;
    2058           0 :         pRet = 0;
    2059             :     }
    2060           0 :     return pRet;
    2061             : }
    2062             : 
    2063           0 : void SwTable::CleanUpBottomRowSpan( sal_uInt16 nDelLines )
    2064             : {
    2065           0 :     if( !IsNewModel() )
    2066           0 :         return;
    2067           0 :     sal_uInt16 nLastLine = GetTabLines().size()-1;
    2068           0 :     SwTableLine* pLine = GetTabLines()[nLastLine];
    2069           0 :     sal_uInt16 nColCount = pLine->GetTabBoxes().size();
    2070             :     OSL_ENSURE( nColCount, "Empty Table Line" );
    2071           0 :     for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
    2072             :     {
    2073           0 :         SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
    2074             :         OSL_ENSURE( pBox, "Missing Table Box" );
    2075           0 :         long nRowSp = pBox->getRowSpan();
    2076           0 :         if( nRowSp < 0 )
    2077           0 :             nRowSp = -nRowSp;
    2078           0 :         if( nRowSp > 1 )
    2079             :         {
    2080           0 :             lcl_ChangeRowSpan( *this, -static_cast<long>(nDelLines), nLastLine, false );
    2081           0 :             break;
    2082             :         }
    2083             :     }
    2084             : }
    2085             : 
    2086             : #ifdef DBG_UTIL
    2087             : 
    2088             : struct RowSpanCheck
    2089             : {
    2090             :     long nRowSpan;
    2091             :     SwTwips nLeft;
    2092             :     SwTwips nRight;
    2093             : };
    2094             : 
    2095             : void SwTable::CheckConsistency() const
    2096             : {
    2097             :     if( !IsNewModel() )
    2098             :         return;
    2099             :     sal_uInt16 nLineCount = GetTabLines().size();
    2100             :     const SwTwips nTabSize = GetFrmFmt()->GetFrmSize().GetWidth();
    2101             :     SwTwips nLineWidth = 0;
    2102             :     std::list< RowSpanCheck > aRowSpanCells;
    2103             :     std::list< RowSpanCheck >::iterator aIter = aRowSpanCells.end();
    2104             :     for( sal_uInt16 nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
    2105             :     {
    2106             :         SwTwips nWidth = 0;
    2107             :         SwTableLine* pLine = GetTabLines()[nCurrLine];
    2108             :         SAL_WARN_IF( !pLine, "sw.core", "Missing Table Line" );
    2109             :         sal_uInt16 nColCount = pLine->GetTabBoxes().size();
    2110             :         SAL_WARN_IF( !nColCount, "sw.core", "Empty Table Line" );
    2111             :         for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
    2112             :         {
    2113             :             SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol];
    2114             :             SAL_WARN_IF( !pBox, "sw.core", "Missing Table Box" );
    2115             :             SwTwips nNewWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth() + nWidth;
    2116             :             long nRowSp = pBox->getRowSpan();
    2117             :             if( nRowSp < 0 )
    2118             :             {
    2119             :                 SAL_WARN_IF( aIter == aRowSpanCells.end(),
    2120             :                         "sw.core", "Missing master box");
    2121             :                 SAL_WARN_IF( aIter->nLeft != nWidth || aIter->nRight != nNewWidth,
    2122             :                     "sw.core", "Wrong position/size of overlapped table box");
    2123             :                 --(aIter->nRowSpan);
    2124             :                 SAL_WARN_IF( aIter->nRowSpan != -nRowSp, "sw.core",
    2125             :                         "Wrong row span value" );
    2126             :                 if( nRowSp == -1 )
    2127             :                 {
    2128             :                     std::list< RowSpanCheck >::iterator aEraseIter = aIter;
    2129             :                     ++aIter;
    2130             :                     aRowSpanCells.erase( aEraseIter );
    2131             :                 }
    2132             :                 else
    2133             :                     ++aIter;
    2134             :             }
    2135             :             else if( nRowSp != 1 )
    2136             :             {
    2137             :                 SAL_WARN_IF( !nRowSp, "sw.core", "Zero row span?!" );
    2138             :                 RowSpanCheck aEntry;
    2139             :                 aEntry.nLeft = nWidth;
    2140             :                 aEntry.nRight = nNewWidth;
    2141             :                 aEntry.nRowSpan = nRowSp;
    2142             :                 aRowSpanCells.insert( aIter, aEntry );
    2143             :             }
    2144             :             nWidth = nNewWidth;
    2145             :         }
    2146             :         if( !nCurrLine )
    2147             :             nLineWidth = nWidth;
    2148             :         SAL_WARN_IF( nWidth != nLineWidth, "sw.core",
    2149             :                 "Different Line Widths: first: " << nLineWidth
    2150             :                 << " current [" << nCurrLine << "]: " <<  nWidth);
    2151             :         SAL_WARN_IF( abs(nWidth - nTabSize) > 1 /* how tolerant? */, "sw.core",
    2152             :                 "Line width differs from table width: " << nTabSize
    2153             :                 << " current [" << nCurrLine << "]: " << nWidth);
    2154             :         SAL_WARN_IF( nWidth < 0 || nWidth > USHRT_MAX, "sw.core",
    2155             :                 "Width out of range [" << nCurrLine << "]: " << nWidth);
    2156             :         SAL_WARN_IF( aIter != aRowSpanCells.end(), "sw.core",
    2157             :                 "Missing overlapped box" );
    2158             :         aIter = aRowSpanCells.begin();
    2159             :     }
    2160             :     bool bEmpty = aRowSpanCells.empty();
    2161             :     SAL_WARN_IF( !bEmpty, "sw.core", "Open row span detected" );
    2162             : }
    2163             : 
    2164             : #endif
    2165             : 
    2166             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10