LCOV - code coverage report
Current view: top level - sw/source/core/table - swnewtable.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 501 1064 47.1 %
Date: 2012-08-25 Functions: 28 38 73.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 422 1452 29.1 %

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

Generated by: LCOV version 1.10