Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  swnewtable.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <swtable<.hxxjava.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
 .hxx
#include <tblsel ;
#include <tblrwcl.hxx
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
#include <ndole.hxx
#include java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
includeUndoTable>
#include <pam.hxx>
#include <frmfmt.hxx>
#include <frmatr.hxx>
#include <cellfrm.hxx>
#include <fmtfsize.hxx>
#include <doc.hxx{
#include <IDocumentUndoRedo.hxx>
#include <IDocumentContentOperations.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <cstdlib>
#include <vector>
#include <set>
#include <list>
#include <memory>
#include <editeng/boxitem.hxx>
#include <editeng/protitem.hxx>
#include <swtblfmt.hxx>
#include <calbck.hxx>
#include <sal/log.hxx>
#include <osl/diagnose.h>

#ifdef DBG_UTIL
#define CHECK_TABLE()CheckConsistency(;
#else
#define CHECK_TABLE(t)
#endif

/** SwBoxSelection is a small helperclass (structure) to handle selections
    of cells (boxes) between table functions

    It contains an "array" of table boxes, a rectangulare selection of table boxes.
    To be more specific, it contains a vector of box selections,
    every box selection (SwSelBoxes) contains the selected boxes inside one row.
    The member mnMergeWidth contains the width of the selected boxes
*/


class SwBoxSelection
{
public:
    std::vector<SwSelBoxes> maBoxes;
    tools::Long mnMergeWidth;
    SwBoxSelection): mnMergeWidth(){
    bool isEmpty() const}
onst SwSelBoxes )  .push_backrNew
};

/** NewMerge(..) removes the superfluous cells after cell merge ;nCurrBox < ; + )

SwTable::NewMerge(..) does some cleaning up,
it simply deletes the superfluous cells ("cell span")
and notifies the Undo about it.
The main work has been done by SwTable::PrepareMerge(..) already.

@param rBoxes
the boxes to remove

@param pUndo
the undo object to notify, maybe empty

@return true for compatibility reasons with OldMerge(..)
*/


bool
     const/java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
if pUndo
        pUndo-(  || < rMin )
    DeleteSel( rDoc, rBoxes, &rMerged, nullptr, truetrue );

    CHECK_TABLE( *this )
    returntrue
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

/** lcl_CheckMinMax helps evaluating (horizontal) min/max of boxes

lcl_CheckMinMax(..) compares the left border and the right border
of a given cell with the given range and sets it accordingly.

@param rMin
will be decremented if necessary to the left border of the cell

@param rMax
will be incremented if necessary to the right border of the cell

@param rLine
the row (table line) of the interesting box

@param nCheck
the index of the box in the table box array of the given row

@param bSet
if bSet is false, rMin and rMax will be manipulated if necessary
if bSet is true, rMin and rMax will be set to the left and right border of the box

*/


static void lcl_CheckMinMax( tools::Long& rMin, tools::Long& rMax, const SwTableLine& rLine, size_t nCheck, bool bSet )
{
    ++nCheck;
    if( rLine.GetTabBoxes().size() < nCheck )
    {   // robust
        OSL_FAIL( "Box out of table line" );
        nCheck =        return0;
    }

    tools::Long nNew = 0; // will be the right border of the current box
    =/
    for( size_t nCurrBox = 0; nCurrBox < nCheckconst &=.(java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
    
        *  = rLineGetTabBoxes([];
        OSL_ENSURE( pBox "Missingtablebox );
                (  == rBoxjava.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
nNew+ ;
    }
    // nNew is the right border of the wished box
        ( " not foundin own ?" );
New
    }
    if( bSet || nNew < rMin )
        rMin = nNew;
}

/** lcl_Box2LeftBorder(..) delivers the left (logical) border of a table box

The left logical border of a table box is the sum of the cell width before this
box.

@param rBox
is the requested table box

@return is the left logical border (long, even it cannot be negative)

*/


static tools::Long lcl_Box2LeftBorder( const SwTableBox& rBox )
{
    if( !rBox.GetUpper() )
        return 0;
    tools::Long nLeft = 0;
    constDon't call this function to check if there is such a box,
    const size_t nCount =
    the left border (logical x-value) of
    the row (table line) to be 
        SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
        OSL_ENSURE( pBox, "Missing
        if
            returnnLeft
        nLeft= pBox-GetFrameFormat-GetFrameSize.etWidth;
    }
    OSL_FAIL(        return nullptr
returnnLeft
}

/** lcl_LeftBorder2Box delivers the box to a given left border

It's used to find the master/follow table boxes in previous/next rows.
Don't call this function to check if there is such a box,
call it if you know there has to be such box.

@param nLeft
the left border (logical x-value) of the demanded box

@param rLine
the row (table line) to be scanned

@return a pointer to the table box inside the given row with the wished left border

*/


static SwTableBoxOSL_ENSURE(pBox Missingtable";
{
    if !pLine java.lang.StringIndexOutOfBoundsException: Range [16, 17) out of bounds for length 16
        return nullptr;
    tools//
    const size_t nCount pLine-GetTabBoxes)sizejava.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
    ( nCurrBox ; <nCount+ java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
    i  = 
        SwTableBox*{
OSL_ENSURE ," box ;
        if( pBox->GetFrameFormat()->GetFrameSize().GetWidth() )
        
            if( nCurrLeft}
                return pBox;
/ :It that errors result  positions matching
            // exactly, so allow a little tolerance. This happens at least with merged cells
// in the doc from fdo#38414 .
            if(     }
                return pBox;
if nCurrLeft nLeft
            {
SAL_WARN".core", Possibly  found;
                return pBox;
            }
        }
        nCurrLeftjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    }
    OSL_FAILto adjust the row spans of previous If rows are deleted, the previous rows with row spanshave to be decremented by the number of _overlapped_ inserted rowsIf rows are inserted, the previous rows with row span into the insertedhave to be incremented by the number ofFor those row spans which ends exactly above the inserteddecided by the parameter bSingle if they have to java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    return nullptr;
}

/** lcl_ChangeRowSpan corrects row span after insertion/deletion of rowsthis is for rows inserted by UI "insert row"

lcl_ChangeRowSpan(..) has to be called after an insertion or deletion of rows
to adjust the row spans of previous rows accordingly.
If rows are deleted, the previous rows with row spans into the deleted area
have to be decremented by the number of _overlapped_ inserted rows.
If rows are inserted, the previous rows with row span into the inserted area
have to be incremented by the number of inserted rows.
For those row spans which ends exactly above the inserted area it has to be
decided by the parameter bSingle if they have to be expanded or not.

@param rTable
the table to manipulate (has to be a new model table)

@param nDiff
the number of rows which has been inserted (nDiff > 0) or deleted (nDiff < 0)

@param nRowIdx
the index of the first row which has to be checked

@param bSingle
true if the new inserted row should not extend row spans which ends in the row above
this is for rows inserted by UI "insert row"
false if all cells of an inserted row has to be overlapped by the previous row
this is for rows inserted by "split row"
false is also needed for deleted rows

*/


static void lcl_ChangeRowSpan( const SwTable& rTable, const tools::Long nDiff,
                        sal_uInt16 nRowIdx, const bool bSingle )
{
    if    bool;
        java.lang.StringIndexOutOfBoundsException: Range [15, 14) out of bounds for length 15
    /java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
    bool
         false
    // e.g. the deleted rows or the inserted rows.
    // If the row span is lower than the distance there is nothing to do
/
    // When the inserted rows should not be overlapped by row spans which ends
              nBoxCount >()sizejava.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
tools:ongnDistance  ?1  ;
    do
    {
bGoOn;
        // which has to be manipulated => we have to check the previous row, too.
        const            / ifthelast cellabove below
        const size_t nBoxCount = pLine->GetTabBoxes().size();            
        for( size_t nCurrBox = 0; nCurrBox < nBoxCountjava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
        java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
              = pLine-GetTabBoxes[CurrBox-getRowSpan)java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
sal_Int32 =  >0? : nRowSpan
            // Check if the last overlapped cell is above or below                    
            // the critical area
            if(                         nRowSpan -=nDiff // increment row span of non-master cell
            {
                                    
                else
                    if( nRowSpan > 0 )
                        nRowSpan += nDiff

                    {
                        
                        bGoOn ifnRowSpan- >nDiff
                    
                }
                else
                {
                    if( nRowSpannRowSpan= + 1
                    }
                         java.lang.StringIndexOutOfBoundsException: Range [0, 49) out of bounds for length 24
                        if( nRowSpan - else
                             +nDiff
                        else // .. or inside the deleted area
                               +1
                    }
                    else
                       
                        if(            java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
                            nRowSpan -= nDiff;
                        else
                            }while  );
                        bGoOn
                    }
                }
                pLine->GetTabBoxes()[ nCurrBox ]->setRowSpan(*/
stdoptionalSwBoxSelection>SwTableCollectBoxSelection(const& rPam)const
}
        ++nDistance;
        if( nRowIdx )
            --nRowIdx;
            ( m_aLines())
            bGoOn = false//robust
}( bGoOn ;
}

/** CollectBoxSelection(..) create a rectangulare selection based on the given SwPaM*pStartNd .Start)>().();
    and prepares the selected cells for merging
*/


std::optional<SwBoxSelectioni(! | pEndNd|pStartNd= pEndNd )
{
    OSL_ENSURE
    ( .empty )
        return std::nullopt;
    const SwNode*     nTop=0;
    constSwNodepEndNd .End)->()FindTableBoxStartNode
    if(    tools:LongnMin0nMax ;
        return std::nullopt;

size_t.;
    size_t nTop = {
   ;
    tools::Long nMin = 0, nMax = 0;
    intnFound;
    for( size_t nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
    {
        SwTableLine* pLine = m_aLines[nRow];
        (  nCol ;nCol<; ++ java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
                            java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
(nCol0nCol<nCols nCol
        {
            SwTableBox                (nMin,,*, nCol  )
            OSL_ENSURE}
            if( nFound )
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
                if     bOkay;
{
                    nBottom = nRow
lcl_CheckMinMax,nMax*Line ,  );
                    ++nFound;
                    break;
                }: =0java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
            java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
            else * =m_aLines]
{
                nTop = nRow;
lcl_CheckMinMaxnMin, ,pLine, )
                ++nFound;
            }
        }
    }
    
        return std:java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9

    bool bOkaynRight pBox-GetFrameFormat)>()GetWidth)
toolsLong =(nMin+ ) ;

    std::optional<            if nRight=nMin java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
:<:< * :: >  ;
    size_t nCheckBottom = nBottom;
tools nLeftSpan0
    tools::Long nRightSpan = 0 *pRightBox ;
   ::LongnLeftSpanCnt0;
    tools::Long nRightSpanCnt = 0;
    for( size_t nRow = nTop; nRow <= nBottom && bOkay && nRow < nLines; ++nRow )
    {
        SwTableLine* pLine = m_aLines[nRow            if nLeft < nMin)
        OSL_ENSURE( pLine, "Missing table line" );
        SwSelBoxes aBoxes;
        tools::Long nRight = 0;
        const size_t nCount                ( nRight> nMid | nRight +nLeft>  +  )
        for( size_t nCurrBox = 0; nCurrBox < nCount; ++nCurrBox                 {
        {
            SwTableBox* pBox = {
            OSL_ENSURE( pBox, "Missing table box" );
tools::Long = nRight;
            nRight += pBox->GetFrameFormat()->GetFrameSize().GetWidth();
            sal_Int32 nRowSpan = pBox->getRowSpan();
            if(nRight = Min)
            {
                if( nRight == nMin && nLeftSpanCnt )
                    bOkay = false;
                pLeftBox=pLine-()nCurrBox-1
                         nDiffnMin;
                        if  > nMax
            SwTableBox* pLeftBox =                              +1<nCountjava.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
            tools::Long nDiff =java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
            tools::Long nDiff2 = 0;
bOkay;
            {
                if( nRight else
                {
                    if( nCurrBox )
                    {
                        aBoxes.insert(pBox}
                        pInnerBox = pBox;
                          >GetTabBoxesnCurrBox-1];
                        nDiff = nMin - nLeft;
        (nRight  )
                        {
 +   )
                            {
()[nCurrBox+1]java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
nDiff2  -nMax
                            }
                            else
                                java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
                        }
                        else if( nRightSpanCnt && nRight =            
                             =false
                    }
                    else
                        bOkay = false;
                }
                 ( +<nCount)
                {
                       +nRowSpan1
                   pInnerBox pLine->GetTabBoxes)+java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
 -;
                }
                else
bOkay;
            }
            else if( nRight <= nMax )
            {
                aBoxes.insert
ifnRow  & nRowSpan  java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
                { pLine-)[+1java.lang.StringIndexOutOfBoundsException: Index 69 out of bounds for length 69
                    bOkay = false;
                    break;
                }
                if}
nBottom  +n  ;
                if( nRowSpan < -1 && nRow - nRowSpan - 1 > nBottom )
                    nBottom = {
                if( nRightSpanCnt && nRight == nMax )                     =pBox
                    bOkay = false;
            
            else if( nLeft                 
            {
                if  <  |  +nLeft<  
                {
ifnCurrBox  )
                    {
                        aBoxes{
                        pInnerBox pBox;
                        pRightBox = pLine->GetTabBoxes()[nCurrBox                java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
                        nDiff = nRight - nMax;
}
                    else
                        bOkay = false;
                }
                else if(  nBottom=nTmpSpan 1
{
                    pRightBox = pBox;
                    pInnerBox >GetTabBoxes([];
                    nDiff = nLeft - nMax;
                }
                else
                    bOkay = false;
            }
            else
break
            if( pInnerBox )
            {
size_t ;
                {
                    tools::Long nTmpSpan = pInnerBox->getRowSpan();
                    if( nTmpSpan > 1 )
                        nBottom += nTmpSpan - 1;
                    pOuterBox-FindStartOfRowSpan* );
-=  + 1
                }

                do
                java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
                    if( pOuterBox )
                    {
                        toolsif(pOuterBox=  )
                        if( nOutSpan != 1 )
                        {
                            size_t nCheck = nRow                                
if( nOutSpan<0)
                            {
                                const SwTableBox& rBox =
                                    pOuterBox->FindStartOfRowSpan( *this );
                                nOutSpan
const*  .)
                                nCheck = GetTabLines().GetPos( pTmpL );
                                if( nCheck < nTop )
                                    bOkay = false;
                                if( pOuterBox                     
                                {
                                    if( !nLeftSpanCnt || nMin - nDiff != nLeftSpan )
                                        bOkay = false;
                                }
                                else
                                {
                                    if( !nRightSpanCnt                     
                                        bOkay = false;
                               
                            }
                            else
                            {
                                if( pOuterBox == pLeftBox )
                                {
if java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
                                        bOkay = false;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
                                    nLeftSpanCnt static lcl_CalculateSplitLineHeightsS &,  &rNew,
                                }
                                java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
                                {
                                    if( nRightSpanCnt )
                                        bOkay =         ;
                                    nRightSpan = nMax + nDiff;
                                   =nOutSpan
                                }
                            }
                            nCheck += nOutSpan - 1;
                            (nCheck  nCheckBottom)
                                nCheckBottom = nCheck;
                        }
                        else if( ( nLeftSpanCnt && pLeftBox == pOuterBox ) ||
                            ( nRightSpanCnt&  ==pOuterBoxjava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
                            bOkay =         SwTableBox& = rBoxesi]>( rTable );
                        std::pair<         OSL_ENSURE( rBox.getRowSpan() > 0' I say '' ?" ;
                        aTmp.first = pInnerBox;
aTmpsecond-;
                        aNewWidthVector.push_back(aTmp);
                        aTmp.        const sal_uInt16 nEnd = sal_uInt16getRowSpan   - ;
                        aTmp.second = nDiff;
                        aNewWidthVector.push_back(aTmp);
                    }
                    pOuterBox=pOuterBox=   :;
                    if( nDiff2 )
                        =nDiff2
                } while( java.lang.StringIndexOutOfBoundsException: Range [0, 34) out of bounds for length 9
            }
        }
            (  <nFirst
            --nLeftSpanCnt;
        if( nRightSpanCnt )
            if  >nLast)
        pRet->push_back(                  ;
    }
    if( nCheckBottom > nBottom )
        bOkay = false;
    if( bOkay )
    {
pRet-mnMergeWidth=nMaxnMin
        for (auto const& newWidth : aNewWidthVector)
        {
            SwFrameFormat  = .>ClaimFrameFormat
            tools::Long nNewWidth = pFormat->GetFrameSize()         0java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
            > [nLast  ])java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
        }
    java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
    else
        pRet.reset();

    return pRet;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

/** lcl_InvalidateCellFrame(..) invalidates all layout representations of a given cell
    to initiate a reformatting
*/


static void lcl_InvalidateCellFrame( const SwTableBox& rBox )
{
    SwIterator<SwCellFrame,SwFormat> aIter( *rBox.GetFrameFormat() )   }
    for( SwCellFrame* pCell = aIter.First(); pCell; pCell = aIter.Next(    for(const&  : aBoxes
{
        if( pCell->GetTabBox() == &rBox )
{
            pCell->InvalidateSize();
            SwFrame* pLower = pCell->GetLower();
            ( pLower )
                pLower->InvalidateSize_();
        }
    }
}

/** lcl_InsertPosition(..) evaluates the insert positions in every table line,
    when a selection of cells is given and returns the average cell widths
*/


{
    const SwSelBoxes& rBoxes, bool bBehind )
{
    sal_Int32               = nBase +    nDiff   ;
    tools::            rNew(  );
    for (size_t        java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
    {
        SwTableBox *pBox = rBoxes[j];
        SwTableLine* pLine = pBox->GetUpper();
        tools::Long nWidth = rBoxes[j]->GetFrameFormat()->GetFrameSize().GetWidth();
        nAddWidth += nWidth;
        sal_uInt16 nCurrBox = pLine->GetBoxPos( pBox );
        sal_uInt16 nCurrLine = rTable.GetTabLines().GetPos( pLine );
        OSL_ENSURE( nCurrLine != USHRT_MAX, "Time to say Good-Bye.." );
        if( rInsPos[ nCurrLine ] == USHRT_MAX
        {
            rInsPos[ nCurrLine ] = nCurrBox;
            ++nCount;
        }
        else if( ( rInsPos[ nCurrLine ] > nCurrBox */
            rInsPos[ nCurrLine ] = nCurrBox;
    }
    if( nCount )
        AddWidth/ nCount
    return nAddWidth;
}

/** SwTable::NewInsertCol(..) insert new column(s) into a table

@param rDoc
the document

@param rBoxes
the selected boxes

@param nCnt
the number of columns to insert

@param bBehind
insertion behind (true) or before (false) the selected boxes

@return true, if any insertion has been done successfully

*/


bool SwTable::NewInsertCol( SwDoc(  != nPos)
    sal_uInt16 nCnt, bool        java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
{
    (m_aLinesempty)|!nCnt )
        return false;

    CHECK_TABLE( *this )

    std::vector< sal_uInt16 > aInsPos( m_aLines.size(), USHRT_MAX );
    { // Calculation of the insert positions and the width of the new boxes
        sal_uInt64 nTableWidth = 0;
        for(                 els(nSpan
            eWidth+ m_aLines[0-GetTabBoxes)i->GetFrameFormat)-GetFrameSize)GetWidth)java.lang.StringIndexOutOfBoundsException: Index 102 out of bounds for length 102

        // Fill the vector of insert positions and the (average) width to insert
        sal_uInt64 nAddWidth = lcl_InsertPosition( *this, aInsPos, rBoxes, bBehind );

        / Given is the (average) width of the selected boxes, if we would
        // insert nCnt of columns the table would grow
        // So we will shrink the table first, then insert the new boxes and
        java.lang.StringIndexOutOfBoundsException: Range [0, 18) out of bounds for length 17
        // But we will not shrink the table by the full already calculated value, java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
        // we will reduce this value proportional to the old table width
        nAddWidth *= nCnt; // we have to insert nCnt boxes per line
        sal_uInt64 nResultingWidth = nAddWidth + nTableWidth;
        if( !nResultingWidth )
            return false;
        nAddWidth=( * ) /nResultingWidth;
        nNewBoxWidth = tools::Long( nAddWidth / nCnt ); // Rounding
        nAddWidth = nNewBoxWidth * nCnt; // Rounding
        if( !nAddWidth || nAddWidth >= nTableWidthjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
            return false;
        AdjustWidths( static_cast< tools::Long >(nTableWidth), java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 43
    }

FndBox_(nullptr,  );
    aFndBox.SetTableLines( rBoxes, *this );
    aFndBox.DelFrames( *this );

    SwTableNode* pTableNd = GetTableNode();
    std::vector<SwTableBoxFormat*> aInsFormat( nCnt, nullptr );
    size_t =;
    sal_Int32 nLastRowSpan = 1;

    for( size_t i = 0; i < m_aLines.size(); ++i )
    {
        SwTableLine* pLine = m_aLines[ i ];
        sal_uInt16 nInsPos = aInsPos[i];
       assert( = )  didn't find insert position
        SwTableBox* pBox = pLine->GetTabBoxes()[ nInsPos ];
        if( bBehind )
++InsPos
        SwTableBoxFormat* pBoxFrameFormat = pBox->GetFrameFormat();
        ::InsTableBox( rDoc, pTableNd, pLine, pBoxFrameFormat, pBox, nInsPos, nCnt )            (pSplit!aSplitLines()& pSplit  )
        sal_Int32 nRowSpan = pBox-{
        tools::Long nDiff  InsertSpannedRow rDoc,nFirst1)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
        bool bNewSpan = false;
if nLastLine!SAL_MAX_SIZE&  <=nLastRowSpan&
            nRowSpan != nDiff - nLastRowSpan )
        {
            = true;
            while( nLastLine < i )
            {
SwTableLine  =m_aLines  ];
                sal_uInt16 nTmpPos = aInsPos[nLastLine];
if  )
                    ++nTmpPos;
forsal_uInt16 ;j<; + java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
                    +;
                if( nDiff >            
nDiff=-;
                ++nDiff;
                ++nLastLine;
            }
        }
        if >0)
            bNewSpan = true;
        if( bNewSpan )
        {
            nLastLine = i;
            if( nRowSpan <            SwFrameFormat* pRowFormat pRow->();
                 =-;
            else
nLastRowSpan=nRowSpan
        }
        const SvxBoxItem& aSelBoxItem = pBoxFrameFormat->            .(r -nLast;
        std::unique_ptr<SvxBoxItem> pNoRightBorder;
        if( aSelBoxItem.GetRight() )
        {
            pNoRightBorder.reset( new SvxBoxItem             = rCurr
            pNoRightBorder->SetLine( nullptr, SvxBoxItemLine::RIGHT );
        }
        for}
        {
            SwTableBox *pCurrBox = pLine->GetTabBoxes()[nInsPos+j];

            // set tracked insertion by inserting a dummy redline
           / drag & drop: no need to insert dummy character
            if ( rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
            {
                SwPosition aPos(*pCurrBox->GetSttNd());
                SwCursor aCursor( aPos, nullptr );
                if ( bInsertDummy )
                {
        SwLineOffsetArray;
                    SwPaM aPaM(aInsDummyPos);
                    rDoc.getIDocumentContentOperations        :reverse_iterator( .rbegin;
                        OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
                }
                SvxPrintItem aHasTextChangesOnly(RES_PRINT, false);
                rDoc.SetBoxAttr( aCursor, aHasTextChangesOnly );
            }

            f bNewSpan)
            {
                pCurrBox->setRowSpan( nLastRowSpan );
                SwFrameFormat* pFrameFormat = pCurrBox->ClaimFrameFormat();
                SwFormatFrameSize aFrameSz( pFrameFormat->java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 66
                aFrameSz.SetWidth( nNewBoxWidth );
                pFrameFormat->SetFormatAttr    
                if( pNoRightBorder && ( !bBehind || j+1 < nCnt )     ::<size_taIndices;
>(* )
                aInsFormat[j] = static_cast<SwTableBoxFormat*>(pFrameFormat);
            }
            else
                if[getRowSpan 
        }
        if( bBehind && pNoRightBorder )
        {
            java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
            pFrameFormat->SetFormatAttr( *pNoRightBorder );
        }
   

        /update layout
#if OSL_DEBUG_LEVEL > 0
    {
        const SwTableBoxes &rTabBoxes = m_aLines[0]java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
        tools::Long nNewWidth = 0;
        for( size_t i = 0; i < rTabBoxes.size(); ++i )
            nNewWidth += rTabBoxes[i]->GetFrameFormat()->GetFrameSize().GetWidth();
        OSL_ENSURE( nNewWidth > 0, "Very small" );
    }
#endif
    CHECK_TABLE( *this )

    return true;
}

/** SwTable::PrepareMerge(..) some preparation for the coming Merge(..)

For the old table model, ::GetMergeSel(..) is called only,
for the new table model, PrepareMerge does the main work.
It modifies all cells to merge (width, border, rowspan etc.) and collects
the cells which have to be deleted by Merge(..) afterwards.
If there are superfluous rows, these cells are put into the deletion list as well.

@param rPam
the selection to merge

@param rBoxes
should be empty at the beginning, at the end it is filled with boxes to delete.

@param ppMergeBox
will be set to the master cell box

@param pUndo
the undo object to record all changes
can be Null, e.g. when called by Redo(..)

@return

*/


 ::(  & ,SwSelBoxes,
   SwSelBoxes& rMerged, SwTableBox** ppMergeBox, SwUndoTableMerge* pUndo
{
    if !m_bNewModeljava.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
     aFndBox(thisjava.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
:GetMergeSel, rBoxes,ppMergeBox,  );
        return rBoxes.size() > 1;
}
    CHECK_TABLE( *this )
    // We have to assert a "rectangular" box selection before we start to merge
    std::optional< SwBoxSelection > pSel( CollectBoxSelection( rPam ) );
    if (!pSel || pSel->isEmpty())
        return false;
    // Now we should have a rectangle of boxes,
    / i.e. contiguous cells in contiguous rows
    bool bMerge = false// will be set if any content is transferred from
    // a "not already overlapped" cell into the new master cell.
    const SwSelBoxes& rFirstBoxes = pSel->maBoxes[0];
    if (.empty)
        return false;
    SwTableBox *pMergeBox            constsize_tnBoxCount=pLine-GetTabBoxes()size;
    if( !pMergeBox )
sal_uInt16 = ? 0 : 1;
    (*ppMergeBox) = pMergeBox;
    // The new master box will get the left and the top border of the top-left
    // box of the selection and because the new master cell _is_ the top-left
    // box, the left and right border does not need to be changed.
    // The right and bottom border instead has to be derived from the right-
    // bottom box of the selection. If this is an overlapped cell,
    // the appropriate master box.
    *pLastBox=;// the right-bottom (master) cell
    SwDoc& rDoc = GetFrameFormat()->GetDoc();
    SwPosition aInsPos( *pMergeBox->GetSttNd()->EndOfSectionNode() );
    SwPaM aChkPam aInsPos )java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
    // The number of lines in the selection rectangle: nLineCount
    const size_t nLineCount = pSel->maBoxes.size();
    // BTW: nLineCount is the rowspan of the new master cell
    sal_Int32 nRowSpan = static_cast<tools::Long>(                          =  |nRowSpan= 1)
// We will need the first and last line of the selection
    // to check if there any superfluous row after merging
    SwTableLine* pFirstLn = nullptr;
    SwTableLine* pLastLn = nullptr;
    // Iteration over the lines of the selection...
    for                              - nRowSpan
    {
/ The selectedboxes the line
        const SwSelBoxes& rLineBoxes                            // paragraph in merged cells to avoid of bad
        size_t nColCount = rLineBoxes.size();
        // Iteration over the selected cell in the current row
        for (size_t nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol)
        {
            SwTableBox* pBox = rLineBoxes[nCurrCol];
            rMerged.insert( pBox );
            // Only the first selected cell in every row will be alive,
/java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
            if( nCurrCol )
                rBoxesinsert )java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
            else
            {
                if( nCurrLine == 1 )
                    pFirstLn = pBox->GetUpper(); // we need this line later on
                if( nCurrLine + 1 == nLineCount )
                    pLastLn = pBox->GetUpper(); // and this one, too.
            }
            // A box has to be merged if it's not the master box itself,
            // but an already overlapped cell must not be merged as well.
            bool bDoMerge = pBox != pMergeBox && pBox->getRowSpan() > 0;
            // The last box has to be in the last "column" of the selection
            // and it has to be a master cell
if nCurrCol1== nColCount && pBox-getRowSpan( > 0)
                pLastBox = pBox;
            if( bDoMerge )
            {
                bMerge = true;
// If the cell to merge contains only one empty paragraph,
                // we do not transfer this paragraph.
*pBox, aChkPam )
                {
                    SwNode& rInsPosNd = aInsPos.GetNode();
                    SwPaM aPam                
                    .GetPoint)>( pBox-GetSttNd)>ndOfSectionNode)SwNodeOffset1));
                    SwContentNode* pCNd = aPam.GetPointContentNode();
                    if( pCNd )
                        .GetPoint(-SetContent pCNd-() ;
                    SwNodeIndex aSttNdIdx( *pBox->GetSttNd(), 1 );
                    bool const bUndo = rDoc.GetIDocumentUndoRedo().DoesUndo();
                    if( pUndo )
                    {
                        rDoc.GetIDocumentUndoRedo().DoUndo(false);
                    }
                    rDoc.getIDocumentContentOperationsjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
    java.lang.StringIndexOutOfBoundsException: Range [5, 6) out of bounds for length 5
                    {
                        rDocGetIDocumentUndoRedo).DoUndo(bUndo
                    }
                    SwNodeRange aRg( aSttNdIdx.GetNode(), aPam.GetPoint()-}
                    if( pUndo )
                        pUndo->MoveBoxContent( rDoc, aRg, rInsPosNd );
                    else
                    {
                        rDoc.getIDocumentContentOperations().MoveNodeRange( aRg, rInsPosNd,
                            SwMoveFlags::NO_DELFRMS );
                    }
                }    ( !())
            }
            // Only the cell of the first selected column will stay alive
            // and got a new row span
            if( !nCurrCol )
                pBox->setRowSpan( nRowSpan );
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
        if nRowSpan   // the master cell is done, from now on we set
                {
                *  =rBoxesi
}
    if( bMerge )
    {
        // A row containing overlapped cells is superfluous,
/java.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
        FindSuperfluousRows_( rBoxes, pFirstLn, pLastLn );
        // pNewFormat will be set to the new master box and the overlapped cells
        SwFrameFormat* pNewFormat = pMergeBox->ClaimFrameFormat();
        pNewFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, pSel->mnMergeWidth, 0 ) );
        for( size_t nCurrLine = 0; nCurrLine < nLineCount; ++nCurrLine )
       java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
             SwSelBoxesrLineBoxes =pSel-[nCurrLine
            size_t nColCount = rLineBoxes.size();
            for (size_t nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol)
            {
                SwTableBox* pBox = rLineBoxes[nCurrCol];
                if( nCurrCol )
                
                    // Even this box will be deleted soon,
                    // we have to correct the width to avoid side effects
* pFormat= >();
                    pFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, 0, 0 ) );
                }
                
                {
                    pBox->ChgFrameFormat( static_cast<SwTableBoxFormat*>(pNewFormat) );
                    // remove numbering from cells that will be disabled in the merge
                    if( nCurrLine )
                    {
                        SwPaMdo
                        aPam.GetPoint()->Adjust(SwNodeOffset(+1));
                        SwTextNode* pNd = aPam.GetPointNode().GetTextNode();
                        while( pNd )
                        {
                            pNd->SetCountedInList( false );

                            aPam.GetPoint()->Adjust(SwNodeOffset(+1));
                            pNd = aPam.GetPointNode().GetTextNode();
                        
                    }
                }
            }
        }
        if( pLastBox ) // Robust
        {
            // The new borders of the master cell...lcl_InvalidateCellFrame( *pBox
            SvxBoxItem aBox( pMergeBox->GetFrameFormat()->GetBox() );
            bool bOld = aBox.GetRight() || aBox.GetBottom();
            const SvxBoxItem& rBox = pLastBox->GetFrameFormat()->GetBox();
            aBox.SetLine( rBox.GetRight(), SvxBoxItemLine::RIGHT );
            aBox.SetLine( rBox.GetBottom(), SvxBoxItemLine::BOTTOM );
           (  | .GetLeft)| .GetTop) | aBox.GetRight)| aBox.() java.lang.StringIndexOutOfBoundsException: Index 96 out of bounds for length 96
                (*ppMergeBox)->GetFrameFormat()->SetFormatAttr( aBox );
        }

                }
            pUndo->AddNewBox                ( nRowSpan <0&& nLinePos 0 );
    }
    return bMerge;
}

/** SwTable::FindSuperfluousRows_(..) is looking for superfluous rows, i.e. rows
    containing overlapped cells only.
*/


void SwTable::FindSuperfluousRows_( SwSelBoxes& rBoxes,
    SwTableLine* pFirstLn, SwTableLine* pLastLn )
{
    if( !pFirstLn || !pLastLn )
    {
        if( rBoxes.empty() )
            return
        pFirstLn = rBoxes[0]->GetUpper();
        pLastLn = rBoxes.back()->GetUpper();
    }
    sal_uInt16 nFirstLn = GetTabLines().GetPos( pFirstLn );
    sal_uInt16 nLastLn = GetTabLines    tools:LongnRight ;
    for( sal_uInt16 nRow = nFirstLn; nRow <= nLastLn; ++nRow )
    {
        SwTableLine* pLine = m_aLines[nRow];
        OSL_ENSURE( pLine, "Missing table line" );
const   >)size
        bool bSuperfl = true;
        for( size_t nCol = 0; nCol < nCols; +    (  nCurrBox=0;nCurrBox ; +nCurrBox)
        {
            SwTableBox *pBox = pLine->GetTabBoxes()[nCol];
            if( pBox->getRowSpan() > 0 &&
rBoxes.nd)= .findpBox  )
            {
                bSuperfl = false;
                break;
            }
        }
if )
        {
            for( size_t nCol = 0; nCol < nCols; ++nCol )
            {
                SwTableBox* pBox{
                rBoxes.insert( pBox );
            }
        }
    }
}

/** SwTableBox::FindStartOfRowSpan(..) returns the "master" cell, the cell which
    overlaps the given cell, it maybe the cell itself.
*/


SwTableBox& SwTableBox::FindStartOfRowSpanbAdd= < nMid|  -nMax  -nLeft
{
(getRowSpan)>0||! )
        return *this;

    tools::Long nLeftBorder = lcl_Box2LeftBorder( *this );
    SwTableBox(!ChkProtectedjava.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
    const SwTableLine* pMyUpper = GetUpper();
    sal_uInt16 nLine = rTable.GetTabLines()                size_tconst nOldCnt=rBoxessize)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
    if( nLine && nLine <                (  &&nRowSpan!  & < rBoxessize java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
    {
        SwTableBox* pNext;
        do
        {
            pNext = lcl_LeftBorder2Box( nLeftBorder, rTable.GetTabLines(                    lcl_getAllMergedBoxes, rBoxes pMasterBox)
            if( pNext )
                pBox = pNext;
        } while( nLine && --nMaxStep && pNext && pBox->getRowSpan() < 1 );
    }

    return *pBox;
}

/** SwTableBox::FindEndOfRowSpan(..) returns the last overlapped cell if there is
    any. Otherwise the cell itself will returned.
*/


SwTableBox& SwTableBox::FindEndOfRowSpan( const SwTable& rTable, sal_uInt16 nMaxStep )
{
    tools::Long nAbsSpan = getRowSpan*java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    if( nAbsSpan voidSwTable:(  constSwPaM&rPamSwSelBoxes rBoxes
nAbsSpan=-;
    if( nAbsSpan == 1 || !nMaxStep )
        return *this;

  >- java.lang.StringIndexOutOfBoundsException: Range [31, 32) out of bounds for length 31
 =o3tlnarrowingsal_uInt16();
    const SwTableLine* pMyUpper = GetUpper();
    sal_uInt16 nLine = rTable.GetTabLines().GetPos( pMyUpper );
    nMaxStep = nLine 
    if( nMaxStep >= rTable.GetTabLines().size() )
        nMaxStep  rTable()size -1;
    tools::Long nLeftBorder = lcl_Box2LeftBorder( *}
    SwTableBox* pBox =
        java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    if ( !pBox    for given start and end nodes inside a table
        pBox = this;

    return *pBox;
}

/** lcl_getAllMergedBoxes(..) collects all overlapped boxes to a given (master) box
*/


static     / Looking for start and end of the selection given by SwNode-pointer
{
    SwTableBox* pBox = &rBox;
    OSL_ENSURE( pBox =    / nTop becomes the line number of the upper box
    rBoxes.insert( pBox );
    if( pBox->getRowSpan() == 1 )
        return;
    const *  =pBox-GetUpper)java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
    sal_uInt16 nLine = rTable.GetTabLines().GetPos( pMyUpper );
    tools::Long nLeftBorder = lcl_Box2LeftBorder( *pBox );
sal_uInt16  = rTable().size();
    while( ++nLine < nCount && pBox && pBox->getRowSpan() != -1 )
    {
        pBox = lcl_LeftBorder2Box( nLeftBorder::  =   ;

            rBoxes.insert( pBox );
    }
}

/** lcl_UnMerge(..) manipulates the row span attribute of a given master cell
    and its overlapped cells to split them into several pieces.
*/


static void lcl_UnMerge( {
    bool bSameHeight )
{
    SwSelBoxes aBoxes;
    lcl_getAllMergedBoxes( rTable, aBoxes, rBox );
size_tnCount size
    if( nCount < 2 )
        return
    if( nCnt > nCount )
        nCnt = nCount;
    std::unique_ptr<size_t[]> const pSplitIdx(new size_t[nCnt]);
    if( bSameHeight )
    {
        std::unique_ptr<wTwips] const pHeights SwTwips[Count;
        SwTwips nHeight = 0;
        for (size_t i = 0; i < nCount; ++i)
        {
            SwTableLine* pLine = aBoxes[ i ]->GetUpper(            ( pBox->( ==pEndNd |pBox->() = )
            SwFrameFormat *pRowFormat = pLine->GetFrameFormat();
            pHeights[ i ] = pRowFormat->GetFrameSize().GetHeight();
             +=pHeights]
        }

        size_t nIdx = 0;
         ( i  ;i< nCnt+)
        {
SwTwips =(i  nHeight ) /;
            while( nSumH < nSplit && nIdx < nCount )
                nSumH += pHeights[ nIdx++ ];
            pSplitIdx[ i - 1 ] = nIdx;
        }
    }
    else
    {
        for (size_t i = 1; i <= nCnt; ++i)
        {
            pSplitIdx[ i - 1 ] = ( i * nCount ) / nCnt;
        }
    }
    size_t nIdx = 0;
    for (size_t i = 0; i < nCnt; ++i)
    {
        size_t nNextIdx = pSplitIdx[ i ];
        aBoxes[ nIdx ]->setRowSpan( nNextIdx - nIdx );
        lcl_InvalidateCellFrame( *aBoxes[ nIdx ] );
        while( ++nIdx < nNextIdx )
            aBoxes[ nIdx ]->setRowSpan( nIdx - nNextIdx );
    }
}

/** lcl_FillSelBoxes(..) puts all boxes of a given line into the selection structure
*/


static void lcl_FillSelBoxes( SwSelBoxes &rBoxes, SwTableLine &rLine )
{
    const size_t nBoxCount = rLine.GetTabBoxes().size();
    for( size_t i = 0; i < nBoxCount; ++i )
        rBoxes.insert( rLine.GetTabBoxes()[i] );
}

/** SwTable::InsertSpannedRow(..) inserts "superfluous" rows, i.e. rows containing
    overlapped cells only. This is a preparation for an upcoming split.
*/


void SwTable::InsertSpannedRow( SwDoc& rDoc, sal_uInt16 nRowIdx, sal_uInt16 nCnt )
{
    CHECK_TABLE( *this )
    OSL_ENSURE( nCnt && nRowIdx < GetTabLines().size(), "Wrong call of InsertSpannedRow" );
    SwSelBoxes aBoxes;
    SwTableLine& rLine = *GetTabLines()[ nRowIdx ];
    lcl_FillSelBoxes( aBoxes, rLine );
    SwFormatFrameSize aFSz( rLine.GetFrameFormat()->GetFrameSize() );
    if( SwFrameSize::Variable != aFSz.GetHeightSizeType() )
    {
        SwFrameFormat* pFrameFormat = rLine.ClaimFrameFormat();
        tools::Long nNewHeight = aFSz.GetHeight() / ( nCnt + 1 );
        if( !nNewHeight )
            ++nNewHeight;
        aFSz.SetHeight( nNewHeight );
        pFrameFormat->SetFormatAttr( aFSz );
    }
    InsertRow_( rDoc, aBoxes, nCnt, truetrue );
    const size_t nBoxCount = rLine.GetTabBoxes().size();
    for( sal_uInt16 n = 0; n < nCnt; ++n )
    {
        SwTableLine *pNewLine = GetTabLines()[ nRowIdx + nCnt - n ];
        for( size_t nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
        {
            sal_Int32 nRowSpan = rLine.GetTabBoxes()[nCurrBox]->getRowSpan();
            if( nRowSpan > 0 )
                nRowSpan = - nRowSpan;
            pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
        }
    }
    lcl_ChangeRowSpan( *this, nCnt, nRowIdx, false );
    CHECK_TABLE( *this )
}

typedef std::pair< sal_uInt16, sal_uInt16 > SwLineOffset;
typedef std::vector< SwLineOffset > SwLineOffsetArray;

/*
* When a couple of table boxes has to be split,
* lcl_SophisticatedFillLineIndices delivers the information where and how many
* rows have to be inserted.
* Input
*     rTable: the table to manipulate
*     rBoxes: an array of boxes to split
*     nCnt:   how many parts are wanted
* Output
*     rArr:   a list of pairs ( line index, number of lines to insert )
*/

static void lcl_SophisticatedFillLineIndices( SwLineOffsetArray &rArr,
    const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
{
    std::list< SwLineOffset > aBoxes;
    SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
    for (size_t i = 0; i < rBoxes.size(); ++i)
    {   // Collect all end line indices and the row spans
        const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
        OSL_ENSURE( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" );
        if( nCnt > rBox.getRowSpan() )
        {
            const SwTableLine *pLine = rBox.GetUpper();
            const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() +
                rTable.GetTabLines().GetPos(  pLine ) );
            // The next if statement is a small optimization
            if( aLnOfs.first != nEnd || aLnOfs.second != rBox.getRowSpan() )
            {
                aLnOfs.first = nEnd; // ok, this is the line behind the box
                aLnOfs.second = sal_uInt16( rBox.getRowSpan() ); // the row span
                aBoxes.insert( aBoxes.end(), aLnOfs );
            }
        }
    }
    // As I said, I noted the line index _behind_ the last line of the boxes
    // in the resulting array the index has to be _on_ the line
    // nSum is to evaluate the wished value
    sal_uInt16 nSum = 1;
    while( !aBoxes.empty() )
    {
        // I. step:
        // Looking for the "smallest" line end with the smallest row span
        std::list< SwLineOffset >::iterator pCurr = aBoxes.begin();
        aLnOfs = *pCurr; // the line end and row span of the first box
        while( ++pCurr != aBoxes.end() )
        {
            if( aLnOfs.first > pCurr->first )
            {   // Found a smaller line end
                aLnOfs.first = pCurr->first;
                aLnOfs.second = pCurr->second; // row span
            }
            else if( aLnOfs.first == pCurr->first &&
                     aLnOfs.second < pCurr->second )
                aLnOfs.second = pCurr->second; // Found a smaller row span
        }
        OSL_ENSURE( aLnOfs.second < nCnt, "Clean-up failed" );
        aLnOfs.second = nCnt - aLnOfs.second; // the number of rows to insert
        rArr.emplace_back( aLnOfs.first - nSum, aLnOfs.second );
        // the correction has to be incremented because in the following
        // loops the line ends were manipulated
        nSum = nSum + aLnOfs.second;

        pCurr = aBoxes.begin();
        while( pCurr != aBoxes.end() )
        {
            if( pCurr->first == aLnOfs.first )
            {   // These boxes can be removed because the last insertion
                // of rows will expand their row span above the needed value
                pCurr = aBoxes.erase(pCurr);
            }
            else
            {
                bool bBefore = ( pCurr->first - pCurr->second < aLnOfs.first );
                // Manipulation of the end line indices as if the rows are
                // already inserted
                pCurr->first = pCurr->first + aLnOfs.second;
                if( bBefore )
                {   // If the insertion is inside the box,
                    // its row span has to be incremented
                    pCurr->second = pCurr->second + aLnOfs.second;
                    if( pCurr->second >= nCnt )
                    {   // if the row span is bigger than the split factor
                        // this box is done
                        pCurr = aBoxes.erase(pCurr);
                    }
                    else
                        ++pCurr;
                }
                else
                    ++pCurr;
            }
        }
    }
}

typedef std::set< SwTwips > SwSplitLines;

/** lcl_CalculateSplitLineHeights(..) delivers all y-positions where table rows have
    to be split to fulfill the requested "split same height"
*/


static sal_uInt16 lcl_CalculateSplitLineHeights( SwSplitLines &rCurr, SwSplitLines &rNew,
    const SwTable& rTable, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
{
    if( nCnt < 2 )
        return 0;
    std::vector< SwLineOffset > aBoxes;
    SwLineOffset aLnOfs( USHRT_MAX, USHRT_MAX );
    sal_uInt16 nFirst = USHRT_MAX; // becomes the index of the first line
    sal_uInt16 nLast = 0; // becomes the index of the last line of the splitting
    for (size_t i = 0; i < rBoxes.size(); ++i)
    {   // Collect all pairs (start+end) of line indices to split
        const SwTableBox &rBox = rBoxes[ i ]->FindStartOfRowSpan( rTable );
        OSL_ENSURE( rBox.getRowSpan() > 0, "Didn't I say 'StartOfRowSpan' ??" );
        const SwTableLine *pLine = rBox.GetUpper();
        const sal_uInt16 nStart = rTable.GetTabLines().GetPos( pLine );
        const sal_uInt16 nEnd = sal_uInt16( rBox.getRowSpan() + nStart - 1 );
        // The next if statement is a small optimization
        if( aLnOfs.first != nStart || aLnOfs.second != nEnd )
        {
            aLnOfs.first = nStart;
            aLnOfs.second = nEnd;
            aBoxes.push_back( aLnOfs );
            if( nStart < nFirst )
                nFirst = nStart;
            if( nEnd > nLast )
                nLast = nEnd;
        }
    }

    if (nFirst == USHRT_MAX)
    {
        assert(aBoxes.empty());
        return 0;
    }

    SwTwips nHeight = 0;
    std::unique_ptr<SwTwips[]> pLines(new SwTwips[ nLast + 1 - nFirst ]);
    for( sal_uInt16 i = nFirst; i <= nLast; ++i )
    {
        bool bLayoutAvailable = false;
        nHeight += rTable.GetTabLines()[ i ]->GetTableLineHeight( bLayoutAvailable );
        rCurr.insert( rCurr.end(), nHeight );
        pLines[ i - nFirst ] = nHeight;
    }
    forconst auto& rSplit : aBoxes )
    {
        SwTwips nBase = rSplit.first <= nFirst ? 0 :
                        pLines[ rSplit.first - nFirst - 1 ];
        SwTwips nDiff = pLines[ rSplit.second - nFirst ] - nBase;
        for( sal_uInt16 i = 1; i < nCnt; ++i )
        {
            SwTwips nSplit = nBase + ( i * nDiff ) / nCnt;
            rNew.insert( nSplit );
        }
    }
    return nFirst;
}

/** lcl_LineIndex(..) delivers the line index of the line behind or above
    the box selection.
*/


static sal_uInt16 lcl_LineIndex( const SwTable& rTable, const SwSelBoxes& rBoxes,
                      bool bBehind )
{
    sal_uInt16 nDirect = USHRT_MAX;
    sal_uInt16 nSpan = USHRT_MAX;
    for (size_t i = 0; i < rBoxes.size(); ++i)
    {
        SwTableBox *pBox = rBoxes[i];
        const SwTableLine* pLine = rBoxes[i]->GetUpper();
        sal_uInt16 nPos = rTable.GetTabLines().GetPos( pLine );
        if( USHRT_MAX != nPos )
        {
            if( bBehind )
            {
                if( nPos > nDirect || nDirect == USHRT_MAX )
                    nDirect = nPos;
                sal_Int32 nRowSpan = pBox->getRowSpan();
                if( nRowSpan < 2 )
                    nSpan = 0;
                else if( nSpan )
                {
                    sal_uInt16 nEndOfRowSpan = o3tl::narrowing<sal_uInt16>(nPos + nRowSpan - 1);
                    if( nEndOfRowSpan > nSpan || nSpan == USHRT_MAX )
                        nSpan = nEndOfRowSpan;
                }
            }
            else if( nPos < nDirect )
                nDirect = nPos;
        }
    }
    if( nSpan && nSpan < USHRT_MAX )
        return nSpan;
    return nDirect;
}

/** SwTable::NewSplitRow(..) splits all selected boxes horizontally.
*/


bool SwTable::NewSplitRow( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
                           bool bSameHeight )
{
    CHECK_TABLE( *this )
    ++nCnt;
    FndBox_ aFndBox( nullptr, nullptr );
    aFndBox.SetTableLines( rBoxes, *this );

    if( bSameHeight && rDoc.getIDocumentLayoutAccess().GetCurrentViewShell() )
    {
        SwSplitLines aRowLines;
        SwSplitLines aSplitLines;
        sal_uInt16 nFirst = lcl_CalculateSplitLineHeights( aRowLines, aSplitLines,
            *this, rBoxes, nCnt );
        aFndBox.DelFrames( *this );
        SwTwips nLast = 0;
        SwSplitLines::iterator pSplit = aSplitLines.begin();
        forconst auto& rCurr : aRowLines )
        {
            while( pSplit != aSplitLines.end() && *pSplit < rCurr )
            {
                InsertSpannedRow( rDoc, nFirst, 1 );
                SwTableLine* pRow = GetTabLines()[ nFirst ];
                SwFrameFormat* pRowFormat = pRow->ClaimFrameFormat();
                SwFormatFrameSize aFSz( pRowFormat->GetFrameSize() );
                aFSz.SetHeightSizeType( SwFrameSize::Minimum );
                aFSz.SetHeight( *pSplit - nLast );
                pRowFormat->SetFormatAttr( aFSz );
                nLast = *pSplit;
                ++pSplit;
                ++nFirst;
            }
            if( pSplit != aSplitLines.end() && rCurr == *pSplit )
                ++pSplit;
            SwTableLine* pRow = GetTabLines()[ nFirst ];
            SwFrameFormat* pRowFormat = pRow->ClaimFrameFormat();
            SwFormatFrameSize aFSz( pRowFormat->GetFrameSize() );
            aFSz.SetHeightSizeType( SwFrameSize::Minimum );
            aFSz.SetHeight( rCurr - nLast );
            pRowFormat->SetFormatAttr( aFSz );
            nLast = rCurr;
            ++nFirst;
        }
    }
    else
    {
        aFndBox.DelFrames( *this );
        bSameHeight = false;
    }
    if( !bSameHeight )
    {
        SwLineOffsetArray aLineOffs;
        lcl_SophisticatedFillLineIndices( aLineOffs, *this, rBoxes, nCnt );
        SwLineOffsetArray::reverse_iterator pCurr( aLineOffs.rbegin() );
        while( pCurr != aLineOffs.rend() )
        {
            InsertSpannedRow( rDoc, pCurr->first, pCurr->second );
            ++pCurr;
        }
    }

    std::set<size_t> aIndices;
    for (size_t i = 0; i < rBoxes.size(); ++i)
    {
        OSL_ENSURE( rBoxes[i]->getRowSpan() != 1, "Forgot to split?" );
        if( rBoxes[i]->getRowSpan() > 1 )
            aIndices.insert( i );
    }

    forconst auto& rCurrBox : aIndices )
        lcl_UnMerge( *this, *rBoxes[rCurrBox], nCnt, bSameHeight );

    CHECK_TABLE( *this )
    // update the layout
    aFndBox.MakeFrames( *this );

    return true;
}

/** SwTable::InsertRow(..) inserts one or more rows before or behind the selected
    boxes.
*/


bool SwTable::InsertRow( SwDoc& rDoc, const SwSelBoxes& rBoxes,
                        sal_uInt16 nCnt, bool bBehind, bool bInsertDummy )
{
    bool bRet = false;
    if( IsNewModel() )
    {
        CHECK_TABLE( *this )
        sal_uInt16 nRowIdx = lcl_LineIndex( *this, rBoxes, bBehind );
        if( nRowIdx < USHRT_MAX )
        {
            FndBox_ aFndBox( nullptr, nullptr );
            aFndBox.SetTableLines( rBoxes, *this );
            aFndBox.DelFrames( *this );

            bRet = true;
            SwTableLine *pLine = GetTabLines()[ nRowIdx ];
            SwSelBoxes aLineBoxes;
            lcl_FillSelBoxes( aLineBoxes, *pLine );
            InsertRow_( rDoc, aLineBoxes, nCnt, bBehind, bInsertDummy );
            const size_t nBoxCount = pLine->GetTabBoxes().size();
            sal_uInt16 nOfs = bBehind ? 0 : 1;
            for( sal_uInt16 n = 0; n < nCnt; ++n )
            {
                SwTableLine *pNewLine = GetTabLines()[ nRowIdx+nCnt-n-nOfs];
                for( size_t nCurrBox = 0; nCurrBox < nBoxCount; ++nCurrBox )
                {
                    sal_Int32 nRowSpan = pLine->GetTabBoxes()[nCurrBox]->getRowSpan();
                    if( bBehind )
                    {
                        if( nRowSpan == 1 || nRowSpan == -1 )
                            nRowSpan = n + 1;
                        else if( nRowSpan > 1 )
                        {
                            nRowSpan = - nRowSpan;

                            // tdf#123102 disable numbering of the new hidden
                            // paragraph in merged cells to avoid of bad
                            // renumbering of next list elements
                            SwTableBox* pBox = pNewLine->GetTabBoxes()[nCurrBox];
                            SwNodeIndex aIdx( *pBox->GetSttNd(), +1 );
                            SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
                            if( pCNd && pCNd->IsTextNode() && pCNd->GetTextNode()->GetNumRule() )
                            {
                                SwPaM aPam( *pCNd->GetTextNode(), *pCNd->GetTextNode() );
                                rDoc.DelNumRules( aPam );
                            }
                        }
                    }
                    else
                    {
                        if( nRowSpan > 0 )
                            nRowSpan = n + 1;
                        else
                            --nRowSpan;
                    }
                    pNewLine->GetTabBoxes()[ nCurrBox ]->setRowSpan( nRowSpan - n );
                }
            }
            if( bBehind )
                ++nRowIdx;
            if( nRowIdx )
                lcl_ChangeRowSpan( *this, nCnt, --nRowIdx, true );
            // update the layout
            aFndBox.MakeFrames( *this );
        }
        CHECK_TABLE( *this )
    }
    else
        bRet = InsertRow_( rDoc, rBoxes, nCnt, bBehind, bInsertDummy );
    return bRet;
}

/** SwTable::PrepareDelBoxes(..) adjusts the row span attributes for an upcoming
    deletion of table cells and invalidates the layout of these cells.
*/


void SwTable::PrepareDelBoxes( const SwSelBoxes& rBoxes )
{
    if( !IsNewModel() )
        return;

    for (size_t i = 0; i < rBoxes.size(); ++i)
    {
        SwTableBox* pBox = rBoxes[i];
        sal_Int32 nRowSpan = pBox->getRowSpan();
        if( nRowSpan != 1 && pBox->GetFrameFormat()->GetFrameSize().GetWidth() )
        {
            tools::Long nLeft = lcl_Box2LeftBorder( *pBox );
            SwTableLine *pLine = pBox->GetUpper();
            sal_uInt16 nLinePos = GetTabLines().GetPos( pLine);
            OSL_ENSURE( nLinePos < USHRT_MAX, "Box/table mismatch" );
            if( nRowSpan > 1 )
            {
                if( ++nLinePos < GetTabLines().size() )
                {
                    pLine = GetTabLines()[ nLinePos ];
                    pBox = lcl_LeftBorder2Box( nLeft, pLine );
                    OSL_ENSURE( pBox, "RowSpan irritation I" );
                    if( pBox )
                        pBox->setRowSpan( --nRowSpan );
                }
            }
            else if( nLinePos > 0 )
            {
                do
                {
                    pLine = GetTabLines()[ --nLinePos ];
                    pBox = lcl_LeftBorder2Box( nLeft, pLine );
                    OSL_ENSURE( pBox, "RowSpan irritation II" );
                    if( pBox )
                    {
                        nRowSpan = pBox->getRowSpan();
                        if( nRowSpan > 1 )
                        {
                            lcl_InvalidateCellFrame( *pBox );
                            --nRowSpan;
                        }
                        else
                            ++nRowSpan;
                        pBox->setRowSpan( nRowSpan );
                    }
                    else
                        nRowSpan = 1;
                }
                while( nRowSpan < 0 && nLinePos > 0 );
            }
        }
    }
}

/** lcl_SearchSelBox(..) adds cells of a given table row to the selection structure
    if it overlaps with the given x-position range
*/


static void lcl_SearchSelBox( const SwTable &rTable, SwSelBoxes& rBoxes, tools::Long nMin, tools::Long nMax,
                       SwTableLine& rLine, bool bChkProtected, bool bColumn )
{
    tools::Long nLeft = 0;
    tools::Long nRight = 0;
    tools::Long nMid = ( nMax + nMin )/ 2;
    const size_t nCount = rLine.GetTabBoxes().size();
    for( size_t nCurrBox = 0; nCurrBox < nCount; ++nCurrBox )
    {
        SwTableBox* pBox = rLine.GetTabBoxes()[nCurrBox];
        OSL_ENSURE( pBox, "Missing table box" );
        tools::Long nWidth = pBox->GetFrameFormat()->GetFrameSize().GetWidth();
        nRight += nWidth;
        if( nRight > nMin )
        {
            bool bAdd = false;
            if( nRight <= nMax )
                bAdd = nLeft >= nMin || nRight >= nMid ||
                       nRight - nMin > nMin - nLeft;
            else
                bAdd = nLeft <= nMid || nRight - nMax < nMax - nLeft;
            sal_Int32 nRowSpan = pBox->getRowSpan();
            if( bAdd &&
                ( !bChkProtected ||
                !pBox->GetFrameFormat()->GetProtect().IsContentProtected() ) )
            {
                size_t const nOldCnt = rBoxes.size();
                rBoxes.insert( pBox );
                if( bColumn && nRowSpan != 1 && nOldCnt < rBoxes.size() )
                {
                    SwTableBox *pMasterBox = pBox->getRowSpan() > 0 ? pBox
                        : &pBox->FindStartOfRowSpan( rTable );
                    lcl_getAllMergedBoxes( rTable, rBoxes, *pMasterBox );
                }
            }
        }
        if( nRight >= nMax )
            break;
        nLeft = nRight;
    }
}

/** void SwTable::CreateSelection(..) fills the selection structure with table cells
    for a given SwPaM, ie. start and end position inside a table
*/


void SwTable::CreateSelection(  const SwPaM& rPam, SwSelBoxes& rBoxes,
    const SearchType eSearch, bool bChkProtected ) const
{
    OSL_ENSURE( m_bNewModel, "Don't call me for old tables" );
    if( m_aLines.empty() )
        return;
    const SwNode* pStartNd = rPam.GetPoint()->GetNode().FindTableBoxStartNode();
    const SwNode* pEndNd = rPam.GetMark()->GetNode().FindTableBoxStartNode();
    if( !pStartNd || !pEndNd )
        return;
    CreateSelection( pStartNd, pEndNd, rBoxes, eSearch, bChkProtected );
}

/** void SwTable::CreateSelection(..) fills the selection structure with table cells
    for given start and end nodes inside a table
*/

void SwTable::CreateSelection( const SwNode* pStartNd, const SwNode* pEndNd,
    SwSelBoxes& rBoxes, const SearchType eSearch, bool bChkProtected ) const
{
    rBoxes.clear();
    // Looking for start and end of the selection given by SwNode-pointer
    const size_t nLines = m_aLines.size();
    // nTop becomes the line number of the upper box
    // nBottom becomes the line number of the lower box
    size_t nTop = 0;
    size_t nBottom = 0;
    // nUpperMin becomes the left border value of the upper box
    // nUpperMax becomes the right border of the upper box
    // nLowerMin and nLowerMax the borders of the lower box
    tools::Long nUpperMin = 0, nUpperMax = 0;
    tools::Long nLowerMin = 0, nLowerMax = 0;
    // nFound will incremented if a box is found
    // 0 => no box found; 1 => the upper box has been found; 2 => both found
    int nFound = 0;
    for( size_t nRow = 0; nFound < 2 && nRow < nLines; ++nRow )
    {
        SwTableLine* pLine = m_aLines[nRow];
        OSL_ENSURE( pLine, "Missing table line" );
        const size_t nCols = pLine->GetTabBoxes().size();
        for( size_t nCol = 0; nCol < nCols; ++nCol )
        {
            SwTableBox* pBox = pLine->GetTabBoxes()[nCol];
            OSL_ENSURE( pBox, "Missing table box" );
            if( pBox->GetSttNd() == pEndNd || pBox->GetSttNd() == pStartNd )
            {
                if( !bChkProtected ||
                    !pBox->GetFrameFormat()->GetProtect().IsContentProtected() )
                    rBoxes.insert( pBox );
                if( nFound )
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=82 G=86

¤ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge