LCOV - code coverage report
Current view: top level - sw/source/core/frmedt - tblsel.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1273 0.0 %
Date: 2014-04-14 Functions: 0 42 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <editeng/boxitem.hxx>
      21             : #include <editeng/protitem.hxx>
      22             : 
      23             : #include <hintids.hxx>
      24             : #include <fmtanchr.hxx>
      25             : #include <fmtfsize.hxx>
      26             : #include <frmatr.hxx>
      27             : #include <tblsel.hxx>
      28             : #include <crsrsh.hxx>
      29             : #include <doc.hxx>
      30             : #include <IDocumentUndoRedo.hxx>
      31             : #include <docary.hxx>
      32             : #include <pam.hxx>
      33             : #include <ndtxt.hxx>
      34             : #include <ndole.hxx>
      35             : #include <swtable.hxx>
      36             : #include <cntfrm.hxx>
      37             : #include <tabfrm.hxx>
      38             : #include <rowfrm.hxx>
      39             : #include <cellfrm.hxx>
      40             : #include <pagefrm.hxx>
      41             : #include <rootfrm.hxx>
      42             : #include <viscrs.hxx>
      43             : #include <swtblfmt.hxx>
      44             : #include <UndoTable.hxx>
      45             : #include <mvsave.hxx>
      46             : #include <sectfrm.hxx>
      47             : #include <frmtool.hxx>
      48             : #include <switerator.hxx>
      49             : #include <deque>
      50             : #include <boost/foreach.hpp>
      51             : 
      52             : // see also swtable.cxx
      53             : #define COLFUZZY 20L
      54             : 
      55             : // macros, determining how table boxes are merged:
      56             : //  - 1. remove empty lines, all boxes separated with blanks,
      57             : //      all lines separated with ParaBreak
      58             : //  - 2. remove all empty lines and remove all empty boxes at beginning and end,
      59             : //      all boxes separated with Blank,
      60             : //      all lines separated with ParaBreak
      61             : //  - 3. remove all empty boxes, all boxes separated with blanks,
      62             : //      all lines separated with ParaBreak
      63             : 
      64             : #undef      DEL_ONLY_EMPTY_LINES
      65             : #undef      DEL_EMPTY_BOXES_AT_START_AND_END
      66             : 
      67             : struct _CmpLPt
      68             : {
      69             :     Point aPos;
      70             :     const SwTableBox* pSelBox;
      71             :     bool bVert;
      72             : 
      73             :     _CmpLPt( const Point& rPt, const SwTableBox* pBox, bool bVertical );
      74             : 
      75             :     bool operator==( const _CmpLPt& rCmp ) const
      76             :     {   return X() == rCmp.X() && Y() == rCmp.Y(); }
      77             : 
      78           0 :     bool operator<( const _CmpLPt& rCmp ) const
      79             :     {
      80           0 :         if ( bVert )
      81           0 :             return X() > rCmp.X() || ( X() == rCmp.X() && Y() < rCmp.Y() );
      82             :         else
      83           0 :             return Y() < rCmp.Y() || ( Y() == rCmp.Y() && X() < rCmp.X() );
      84             :     }
      85             : 
      86           0 :     long X() const { return aPos.X(); }
      87           0 :     long Y() const { return aPos.Y(); }
      88             : };
      89             : 
      90             : typedef o3tl::sorted_vector<_CmpLPt> _MergePos;
      91             : 
      92             : struct _Sort_CellFrm
      93             : {
      94             :     const SwCellFrm* pFrm;
      95             : 
      96           0 :     _Sort_CellFrm( const SwCellFrm& rCFrm )
      97           0 :         : pFrm( &rCFrm ) {}
      98             : };
      99             : 
     100             : typedef std::deque< _Sort_CellFrm > _Sort_CellFrms;
     101             : 
     102           0 : static const SwLayoutFrm *lcl_FindCellFrm( const SwLayoutFrm *pLay )
     103             : {
     104           0 :     while ( pLay && !pLay->IsCellFrm() )
     105           0 :         pLay = pLay->GetUpper();
     106           0 :     return pLay;
     107             : }
     108             : 
     109           0 : static const SwLayoutFrm *lcl_FindNextCellFrm( const SwLayoutFrm *pLay )
     110             : {
     111             :     // ensure we leave the cell (sections)
     112           0 :     const SwLayoutFrm *pTmp = pLay;
     113           0 :     do {
     114           0 :         pTmp = pTmp->GetNextLayoutLeaf();
     115           0 :     } while( pLay->IsAnLower( pTmp ) );
     116             : 
     117           0 :     while( pTmp && !pTmp->IsCellFrm() )
     118           0 :         pTmp = pTmp->GetUpper();
     119           0 :     return pTmp;
     120             : }
     121             : 
     122           0 : void GetTblSelCrs( const SwCrsrShell &rShell, SwSelBoxes& rBoxes )
     123             : {
     124           0 :     rBoxes.clear();
     125           0 :     if( rShell.IsTableMode() && ((SwCrsrShell&)rShell).UpdateTblSelBoxes())
     126             :     {
     127           0 :         rBoxes.insert(rShell.GetTableCrsr()->GetSelectedBoxes());
     128             :     }
     129           0 : }
     130             : 
     131           0 : void GetTblSelCrs( const SwTableCursor& rTblCrsr, SwSelBoxes& rBoxes )
     132             : {
     133           0 :     rBoxes.clear();
     134             : 
     135           0 :     if (rTblCrsr.IsChgd() || !rTblCrsr.GetSelectedBoxesCount())
     136             :     {
     137           0 :         SwTableCursor* pTCrsr = (SwTableCursor*)&rTblCrsr;
     138           0 :         pTCrsr->GetDoc()->GetCurrentLayout()->MakeTblCrsrs( *pTCrsr );
     139             :     }
     140             : 
     141           0 :     if (rTblCrsr.GetSelectedBoxesCount())
     142             :     {
     143           0 :         rBoxes.insert(rTblCrsr.GetSelectedBoxes());
     144             :     }
     145           0 : }
     146             : 
     147           0 : void GetTblSel( const SwCrsrShell& rShell, SwSelBoxes& rBoxes,
     148             :                 const SwTblSearchType eSearchType )
     149             : {
     150             :     // get start and end cell
     151           0 :     if ( !rShell.IsTableMode() )
     152           0 :         rShell.GetCrsr();
     153             : 
     154           0 :     GetTblSel( *rShell.getShellCrsr(false), rBoxes, eSearchType );
     155           0 : }
     156             : 
     157           0 : void GetTblSel( const SwCursor& rCrsr, SwSelBoxes& rBoxes,
     158             :                 const SwTblSearchType eSearchType )
     159             : {
     160             :     // get start and end cell
     161             :     OSL_ENSURE( rCrsr.GetCntntNode() && rCrsr.GetCntntNode( false ),
     162             :             "Tabselection not on Cnt." );
     163             : 
     164             :     // Row-selection:
     165             :     // Check for complex tables. If Yes, search selected boxes via
     166             :     // the layout. Otherwise via the table structure (for macros !!)
     167           0 :     const SwCntntNode* pContentNd = rCrsr.GetNode()->GetCntntNode();
     168           0 :     const SwTableNode* pTblNd = pContentNd ? pContentNd->FindTableNode() : 0;
     169           0 :     if( pTblNd && pTblNd->GetTable().IsNewModel() )
     170             :     {
     171             :         SwTable::SearchType eSearch;
     172           0 :         switch( nsSwTblSearchType::TBLSEARCH_COL & eSearchType )
     173             :         {
     174           0 :             case nsSwTblSearchType::TBLSEARCH_ROW: eSearch = SwTable::SEARCH_ROW; break;
     175           0 :             case nsSwTblSearchType::TBLSEARCH_COL: eSearch = SwTable::SEARCH_COL; break;
     176           0 :             default: eSearch = SwTable::SEARCH_NONE; break;
     177             :         }
     178           0 :         const bool bChkP = 0 != ( nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType );
     179           0 :         pTblNd->GetTable().CreateSelection( rCrsr, rBoxes, eSearch, bChkP );
     180           0 :         return;
     181             :     }
     182           0 :     if( nsSwTblSearchType::TBLSEARCH_ROW == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) &&
     183           0 :         pTblNd && !pTblNd->GetTable().IsTblComplex() )
     184             :     {
     185           0 :         const SwTable& rTbl = pTblNd->GetTable();
     186           0 :         const SwTableLines& rLines = rTbl.GetTabLines();
     187             : 
     188           0 :         const SwNode* pMarkNode = rCrsr.GetNode( false );
     189           0 :         const sal_uLong nMarkSectionStart = pMarkNode->StartOfSectionIndex();
     190           0 :         const SwTableBox* pMarkBox = rTbl.GetTblBox( nMarkSectionStart );
     191             : 
     192             :         OSL_ENSURE( pMarkBox, "Point in table, mark outside?" );
     193             : 
     194           0 :         const SwTableLine* pLine = pMarkBox ? pMarkBox->GetUpper() : 0;
     195           0 :         sal_uInt16 nSttPos = rLines.GetPos( pLine );
     196             :         OSL_ENSURE( USHRT_MAX != nSttPos, "Where is my row in the table?" );
     197           0 :         pLine = rTbl.GetTblBox( rCrsr.GetNode( true )->StartOfSectionIndex() )->GetUpper();
     198           0 :         sal_uInt16 nEndPos = rLines.GetPos( pLine );
     199             :         OSL_ENSURE( USHRT_MAX != nEndPos, "Where is my row in the table?" );
     200             :         // pb: #i20193# if tableintable then nSttPos == nEndPos == USHRT_MAX
     201           0 :         if ( nSttPos != USHRT_MAX && nEndPos != USHRT_MAX )
     202             :         {
     203           0 :             if( nEndPos < nSttPos )     // exchange
     204             :             {
     205           0 :                 sal_uInt16 nTmp = nSttPos; nSttPos = nEndPos; nEndPos = nTmp;
     206             :             }
     207             : 
     208           0 :             int bChkProtected = nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType;
     209           0 :             for( ; nSttPos <= nEndPos; ++nSttPos )
     210             :             {
     211           0 :                 pLine = rLines[ nSttPos ];
     212           0 :                 for( sal_uInt16 n = pLine->GetTabBoxes().size(); n ; )
     213             :                 {
     214           0 :                     SwTableBox* pBox = pLine->GetTabBoxes()[ --n ];
     215             :                     // check for cell protection??
     216           0 :                     if( !bChkProtected ||
     217           0 :                         !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
     218           0 :                         rBoxes.insert( pBox );
     219             :                 }
     220             :             }
     221             :         }
     222             :     }
     223             :     else
     224             :     {
     225           0 :         Point aPtPos, aMkPos;
     226           0 :         const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr);
     227           0 :         if( pShCrsr )
     228             :         {
     229           0 :             aPtPos = pShCrsr->GetPtPos();
     230           0 :             aMkPos = pShCrsr->GetMkPos();
     231             :         }
     232           0 :         const SwCntntNode *pCntNd = rCrsr.GetCntntNode();
     233             :         const SwLayoutFrm *pStart = pCntNd ?
     234           0 :             pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(), &aPtPos )->GetUpper() : 0;
     235           0 :         pCntNd = rCrsr.GetCntntNode(false);
     236             :         const SwLayoutFrm *pEnd = pCntNd ?
     237           0 :             pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(), &aMkPos )->GetUpper() : 0;
     238           0 :         if( pStart && pEnd )
     239           0 :             GetTblSel( pStart, pEnd, rBoxes, 0, eSearchType );
     240             :     }
     241             : }
     242             : 
     243           0 : void GetTblSel( const SwLayoutFrm* pStart, const SwLayoutFrm* pEnd,
     244             :                 SwSelBoxes& rBoxes, SwCellFrms* pCells,
     245             :                 const SwTblSearchType eSearchType )
     246             : {
     247           0 :     const SwTabFrm* pStartTab = pStart->FindTabFrm();
     248           0 :     if ( !pStartTab )
     249             :     {
     250             :         OSL_FAIL( "GetTblSel without start table" );
     251           0 :         return;
     252             :     }
     253             : 
     254           0 :     int bChkProtected = nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType;
     255             : 
     256             :     bool bTblIsValid;
     257             :     // #i55421# Reduced value 10
     258           0 :     int nLoopMax = 10;
     259             : 
     260             :     do {
     261           0 :         bTblIsValid = true;
     262             : 
     263             :         // First, compute tables and rectangles
     264           0 :         SwSelUnions aUnions;
     265           0 :         ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
     266             : 
     267           0 :         Point aCurrentTopLeft( LONG_MAX, LONG_MAX );
     268           0 :         Point aCurrentTopRight( 0, LONG_MAX );
     269           0 :         Point aCurrentBottomLeft( LONG_MAX, 0 );
     270           0 :         Point aCurrentBottomRight( 0, 0 );
     271           0 :         const SwCellFrm* pCurrentTopLeftFrm     = 0;
     272           0 :         const SwCellFrm* pCurrentTopRightFrm    = 0;
     273           0 :         const SwCellFrm* pCurrentBottomLeftFrm  = 0;
     274           0 :         const SwCellFrm* pCurrentBottomRightFrm  = 0;
     275             : 
     276             :         // Now find boxes for each entry and emit
     277           0 :         for (size_t i = 0; i < aUnions.size() && bTblIsValid; ++i)
     278             :         {
     279           0 :             SwSelUnion *pUnion = &aUnions[i];
     280           0 :             const SwTabFrm *pTable = pUnion->GetTable();
     281           0 :             if( !pTable->IsValid() && nLoopMax )
     282             :             {
     283           0 :                 bTblIsValid = false;
     284           0 :                 break;
     285             :             }
     286             : 
     287             :             // Skip any repeated headlines in the follow:
     288           0 :             const SwLayoutFrm* pRow = pTable->IsFollow() ?
     289             :                                       pTable->GetFirstNonHeadlineRow() :
     290           0 :                                      (const SwLayoutFrm*)pTable->Lower();
     291             : 
     292           0 :             while( pRow && bTblIsValid )
     293             :             {
     294           0 :                 if( !pRow->IsValid() && nLoopMax )
     295             :                 {
     296           0 :                     bTblIsValid = false;
     297           0 :                     break;
     298             :                 }
     299             : 
     300           0 :                 if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
     301             :                 {
     302           0 :                     const SwLayoutFrm *pCell = pRow->FirstCell();
     303             : 
     304           0 :                     while( bTblIsValid && pCell && pRow->IsAnLower( pCell ) )
     305             :                     {
     306           0 :                         if( !pCell->IsValid() && nLoopMax )
     307             :                         {
     308           0 :                             bTblIsValid = false;
     309           0 :                             break;
     310             :                         }
     311             : 
     312             :                         OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
     313           0 :                         if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
     314             :                         {
     315             :                             SwTableBox* pBox = (SwTableBox*)
     316           0 :                                 ((SwCellFrm*)pCell)->GetTabBox();
     317             :                             // check for cell protection??
     318           0 :                             if( !bChkProtected ||
     319           0 :                                 !pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
     320           0 :                                 rBoxes.insert( pBox );
     321             : 
     322           0 :                             if ( pCells )
     323             :                             {
     324           0 :                                 const Point aTopLeft( pCell->Frm().TopLeft() );
     325           0 :                                 const Point aTopRight( pCell->Frm().TopRight() );
     326           0 :                                 const Point aBottomLeft( pCell->Frm().BottomLeft() );
     327           0 :                                 const Point aBottomRight( pCell->Frm().BottomRight() );
     328             : 
     329           0 :                                 if ( aTopLeft.getY() < aCurrentTopLeft.getY() ||
     330           0 :                                      ( aTopLeft.getY() == aCurrentTopLeft.getY() &&
     331           0 :                                        aTopLeft.getX() <  aCurrentTopLeft.getX() ) )
     332             :                                 {
     333           0 :                                     aCurrentTopLeft = aTopLeft;
     334           0 :                                     pCurrentTopLeftFrm = static_cast<const SwCellFrm*>( pCell );
     335             :                                 }
     336             : 
     337           0 :                                 if ( aTopRight.getY() < aCurrentTopRight.getY() ||
     338           0 :                                      ( aTopRight.getY() == aCurrentTopRight.getY() &&
     339           0 :                                        aTopRight.getX() >  aCurrentTopRight.getX() ) )
     340             :                                 {
     341           0 :                                     aCurrentTopRight = aTopRight;
     342           0 :                                     pCurrentTopRightFrm = static_cast<const SwCellFrm*>( pCell );
     343             :                                 }
     344             : 
     345           0 :                                 if ( aBottomLeft.getY() > aCurrentBottomLeft.getY() ||
     346           0 :                                      ( aBottomLeft.getY() == aCurrentBottomLeft.getY() &&
     347           0 :                                        aBottomLeft.getX() <  aCurrentBottomLeft.getX() ) )
     348             :                                 {
     349           0 :                                     aCurrentBottomLeft = aBottomLeft;
     350           0 :                                     pCurrentBottomLeftFrm = static_cast<const SwCellFrm*>( pCell );
     351             :                                 }
     352             : 
     353           0 :                                 if ( aBottomRight.getY() > aCurrentBottomRight.getY() ||
     354           0 :                                      ( aBottomRight.getY() == aCurrentBottomRight.getY() &&
     355           0 :                                        aBottomRight.getX() >  aCurrentBottomRight.getX() ) )
     356             :                                 {
     357           0 :                                     aCurrentBottomRight = aBottomRight;
     358           0 :                                     pCurrentBottomRightFrm = static_cast<const SwCellFrm*>( pCell );
     359             :                                 }
     360             : 
     361             :                             }
     362             :                         }
     363           0 :                         if ( pCell->GetNext() )
     364             :                         {
     365           0 :                             pCell = (const SwLayoutFrm*)pCell->GetNext();
     366           0 :                             if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
     367           0 :                                 pCell = pCell->FirstCell();
     368             :                         }
     369             :                         else
     370           0 :                             pCell = ::lcl_FindNextCellFrm( pCell );
     371             :                     }
     372             :                 }
     373           0 :                 pRow = (const SwLayoutFrm*)pRow->GetNext();
     374             :             }
     375             :         }
     376             : 
     377           0 :         if ( pCells )
     378             :         {
     379           0 :             pCells->clear();
     380           0 :             pCells->push_back( const_cast< SwCellFrm* >(pCurrentTopLeftFrm) );
     381           0 :             pCells->push_back( const_cast< SwCellFrm* >(pCurrentTopRightFrm) );
     382           0 :             pCells->push_back( const_cast< SwCellFrm* >(pCurrentBottomLeftFrm) );
     383           0 :             pCells->push_back( const_cast< SwCellFrm* >(pCurrentBottomRightFrm) );
     384             :         }
     385             : 
     386           0 :         if( bTblIsValid )
     387           0 :             break;
     388             : 
     389           0 :         SwDeletionChecker aDelCheck( pStart );
     390             : 
     391             :         // otherwise quickly "calculate" the table layout and start over
     392           0 :         SwTabFrm *pTable = aUnions.front().GetTable();
     393           0 :         while( pTable )
     394             :         {
     395           0 :             if( pTable->IsValid() )
     396           0 :                 pTable->InvalidatePos();
     397           0 :             pTable->SetONECalcLowers();
     398           0 :             pTable->Calc();
     399           0 :             pTable->SetCompletePaint();
     400           0 :             if( 0 == (pTable = pTable->GetFollow()) )
     401           0 :                 break;
     402             :         }
     403             : 
     404             :         // --> Make code robust, check if pStart has
     405             :         // been deleted due to the formatting of the table:
     406           0 :         if ( aDelCheck.HasBeenDeleted() )
     407             :         {
     408             :             OSL_FAIL( "Current box has been deleted during GetTblSel()" );
     409           0 :             break;
     410             :         }
     411             : 
     412           0 :         rBoxes.clear();
     413           0 :         --nLoopMax;
     414             : 
     415             :     } while( true );
     416           0 :     OSL_ENSURE( nLoopMax, "Table layout is still invalid!" );
     417             : }
     418             : 
     419           0 : sal_Bool ChkChartSel( const SwNode& rSttNd, const SwNode& rEndNd )
     420             : {
     421           0 :     const SwTableNode* pTNd = rSttNd.FindTableNode();
     422           0 :     if( !pTNd )
     423           0 :         return sal_False;
     424             : 
     425           0 :     Point aNullPos;
     426           0 :     SwNodeIndex aIdx( rSttNd );
     427           0 :     const SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
     428           0 :     if( !pCNd )
     429           0 :         pCNd = aIdx.GetNodes().GoNextSection( &aIdx, false, false );
     430             : 
     431             :     // if table is invisible, return
     432             :     // (layout needed for forming table selection further down, so we can't
     433             :     //  continue with invisible tables)
     434             :     // #i22135# - Also the content of the table could be
     435             :     //                          invisible - e.g. in a hidden section
     436             :     // Robust: check, if content was found (e.g. empty table cells)
     437           0 :     if ( !pCNd || pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ) == NULL )
     438           0 :             return sal_False;
     439             : 
     440           0 :     const SwLayoutFrm *pStart = pCNd ? pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aNullPos )->GetUpper() : 0;
     441             :     OSL_ENSURE( pStart, "without frame nothing works" );
     442             : 
     443           0 :     aIdx = rEndNd;
     444           0 :     pCNd = aIdx.GetNode().GetCntntNode();
     445           0 :     if( !pCNd )
     446           0 :         pCNd = aIdx.GetNodes().GoNextSection( &aIdx, false, false );
     447             : 
     448             :     // #i22135# - Robust: check, if content was found and if it's visible
     449           0 :     if ( !pCNd || pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout() ) == NULL )
     450             :     {
     451           0 :         return sal_False;
     452             :     }
     453             : 
     454           0 :     const SwLayoutFrm *pEnd = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &aNullPos )->GetUpper();
     455             :     OSL_ENSURE( pEnd, "without frame nothing works" );
     456             : 
     457             :     bool bTblIsValid, bValidChartSel;
     458             :     // #i55421# Reduced value 10
     459           0 :     int nLoopMax = 10;      //JP 28.06.99: max 100 loops - Bug 67292
     460           0 :     sal_uInt16 i = 0;
     461             : 
     462             :     do {
     463           0 :         bTblIsValid = true;
     464           0 :         bValidChartSel = true;
     465             : 
     466           0 :         sal_uInt16 nRowCells = USHRT_MAX;
     467             : 
     468             :         // First, compute tables and rectangles
     469           0 :         SwSelUnions aUnions;
     470           0 :         ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT );
     471             : 
     472             :         // find boxes for each entry and emit
     473           0 :         for( i = 0; i < aUnions.size() && bTblIsValid &&
     474             :                                     bValidChartSel; ++i )
     475             :         {
     476           0 :             SwSelUnion *pUnion = &aUnions[i];
     477           0 :             const SwTabFrm *pTable = pUnion->GetTable();
     478             : 
     479           0 :             SWRECTFN( pTable )
     480           0 :             sal_Bool bRTL = pTable->IsRightToLeft();
     481             : 
     482           0 :             if( !pTable->IsValid() && nLoopMax  )
     483             :             {
     484           0 :                 bTblIsValid = false;
     485           0 :                 break;
     486             :             }
     487             : 
     488           0 :             _Sort_CellFrms aCellFrms;
     489             : 
     490             :             // Skip any repeated headlines in the follow:
     491           0 :             const SwLayoutFrm* pRow = pTable->IsFollow() ?
     492             :                                       pTable->GetFirstNonHeadlineRow() :
     493           0 :                                       (const SwLayoutFrm*)pTable->Lower();
     494             : 
     495           0 :             while( pRow && bTblIsValid && bValidChartSel )
     496             :             {
     497           0 :                 if( !pRow->IsValid() && nLoopMax )
     498             :                 {
     499           0 :                     bTblIsValid = false;
     500           0 :                     break;
     501             :                 }
     502             : 
     503           0 :                 if( pRow->Frm().IsOver( pUnion->GetUnion() ) )
     504             :                 {
     505           0 :                     const SwLayoutFrm *pCell = pRow->FirstCell();
     506             : 
     507           0 :                     while( bValidChartSel && bTblIsValid && pCell &&
     508           0 :                             pRow->IsAnLower( pCell ) )
     509             :                     {
     510           0 :                         if( !pCell->IsValid() && nLoopMax  )
     511             :                         {
     512           0 :                             bTblIsValid = false;
     513           0 :                             break;
     514             :                         }
     515             : 
     516             :                         OSL_ENSURE( pCell->IsCellFrm(), "Frame ohne Celle" );
     517           0 :                         const SwRect& rUnion = pUnion->GetUnion(),
     518           0 :                                     & rFrmRect = pCell->Frm();
     519             : 
     520           0 :                         const long nUnionRight = rUnion.Right();
     521           0 :                         const long nUnionBottom = rUnion.Bottom();
     522           0 :                         const long nFrmRight = rFrmRect.Right();
     523           0 :                         const long nFrmBottom = rFrmRect.Bottom();
     524             : 
     525             :                         // ignore if FrmRect is outside the union
     526             : 
     527           0 :                         const long nXFuzzy = bVert ? 0 : 20;
     528           0 :                         const long nYFuzzy = bVert ? 20 : 0;
     529             : 
     530           0 :                         if( !(  rUnion.Top()  + nYFuzzy > nFrmBottom ||
     531           0 :                                 nUnionBottom < rFrmRect.Top() + nYFuzzy ||
     532           0 :                                 rUnion.Left() + nXFuzzy > nFrmRight ||
     533           0 :                                 nUnionRight < rFrmRect.Left() + nXFuzzy ))
     534             :                         {
     535             :                             // ok, rUnion is _not_ completely outside of rFrmRect
     536             : 
     537             :                             // if not completely inside the union, then
     538             :                             // for Chart it is an invalid selection
     539           0 :                             if( rUnion.Left()   <= rFrmRect.Left() + nXFuzzy &&
     540           0 :                                 rFrmRect.Left() <= nUnionRight &&
     541           0 :                                 rUnion.Left()   <= nFrmRight &&
     542           0 :                                 nFrmRight       <= nUnionRight + nXFuzzy &&
     543           0 :                                 rUnion.Top()    <= rFrmRect.Top() + nYFuzzy &&
     544           0 :                                 rFrmRect.Top()  <= nUnionBottom &&
     545           0 :                                 rUnion.Top()    <= nFrmBottom &&
     546           0 :                                 nFrmBottom      <= nUnionBottom+ nYFuzzy )
     547             : 
     548             :                                 aCellFrms.push_back(
     549           0 :                                         _Sort_CellFrm( *(SwCellFrm*)pCell) );
     550             :                             else
     551             :                             {
     552           0 :                                 bValidChartSel = false;
     553           0 :                                 break;
     554             :                             }
     555             :                         }
     556           0 :                         if ( pCell->GetNext() )
     557             :                         {
     558           0 :                             pCell = (const SwLayoutFrm*)pCell->GetNext();
     559           0 :                             if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
     560           0 :                                 pCell = pCell->FirstCell();
     561             :                         }
     562             :                         else
     563           0 :                             pCell = ::lcl_FindNextCellFrm( pCell );
     564             :                     }
     565             :                 }
     566           0 :                 pRow = (const SwLayoutFrm*)pRow->GetNext();
     567             :             }
     568             : 
     569           0 :             if( !bValidChartSel )
     570           0 :                 break;
     571             : 
     572             :             // all cells of the (part) table together. Now check if
     573             :             // they're all adjacent
     574             :             size_t n;
     575           0 :             sal_uInt16 nCellCnt = 0;
     576           0 :             long nYPos = LONG_MAX;
     577           0 :             long nXPos = 0;
     578           0 :             long nHeight = 0;
     579             : 
     580           0 :             for( n = 0 ; n < aCellFrms.size(); ++n )
     581             :             {
     582           0 :                 const _Sort_CellFrm& rCF = aCellFrms[ n ];
     583           0 :                 if( (rCF.pFrm->Frm().*fnRect->fnGetTop)() != nYPos )
     584             :                 {
     585             :                     // new row
     586           0 :                     if( n )
     587             :                     {
     588           0 :                         if( USHRT_MAX == nRowCells )        // 1. row change
     589           0 :                             nRowCells = nCellCnt;
     590           0 :                         else if( nRowCells != nCellCnt )
     591             :                         {
     592           0 :                             bValidChartSel = false;
     593           0 :                             break;
     594             :                         }
     595             :                     }
     596           0 :                     nCellCnt = 1;
     597           0 :                     nYPos = (rCF.pFrm->Frm().*fnRect->fnGetTop)();
     598           0 :                     nHeight = (rCF.pFrm->Frm().*fnRect->fnGetHeight)();
     599             : 
     600             :                     nXPos = bRTL ?
     601           0 :                             (rCF.pFrm->Frm().*fnRect->fnGetLeft)() :
     602           0 :                             (rCF.pFrm->Frm().*fnRect->fnGetRight)();
     603             :                 }
     604           0 :                 else if( nXPos == ( bRTL ?
     605           0 :                                     (rCF.pFrm->Frm().*fnRect->fnGetRight)() :
     606           0 :                                     (rCF.pFrm->Frm().*fnRect->fnGetLeft)() ) &&
     607           0 :                          nHeight == (rCF.pFrm->Frm().*fnRect->fnGetHeight)() )
     608             :                 {
     609           0 :                     nXPos += ( bRTL ? (-1) : 1 ) *
     610           0 :                              (rCF.pFrm->Frm().*fnRect->fnGetWidth)();
     611           0 :                     ++nCellCnt;
     612             :                 }
     613             :                 else
     614             :                 {
     615           0 :                     bValidChartSel = false;
     616           0 :                     break;
     617             :                 }
     618             :             }
     619           0 :             if( bValidChartSel )
     620             :             {
     621           0 :                 if( USHRT_MAX == nRowCells )
     622           0 :                     nRowCells = nCellCnt;
     623           0 :                 else if( nRowCells != nCellCnt )
     624           0 :                     bValidChartSel = false;
     625             :             }
     626           0 :         }
     627             : 
     628           0 :         if( bTblIsValid )
     629           0 :             break;
     630             : 
     631             :         // otherwise quickly "calculate" table layout and start over
     632           0 :         SwTabFrm *pTable = aUnions.front().GetTable();
     633           0 :         for( i = 0; i < aUnions.size(); ++i )
     634             :         {
     635           0 :             if( pTable->IsValid() )
     636           0 :                 pTable->InvalidatePos();
     637           0 :             pTable->SetONECalcLowers();
     638           0 :             pTable->Calc();
     639           0 :             pTable->SetCompletePaint();
     640           0 :             if( 0 == (pTable = pTable->GetFollow()) )
     641           0 :                 break;
     642             :         }
     643           0 :         --nLoopMax;
     644             :     } while( true );
     645             : 
     646             :     OSL_ENSURE( nLoopMax, "table layout is still invalid!" );
     647             : 
     648           0 :     return bValidChartSel ? sal_True : sal_False;
     649             : }
     650             : 
     651           0 : sal_Bool IsFrmInTblSel( const SwRect& rUnion, const SwFrm* pCell )
     652             : {
     653             :     OSL_ENSURE( pCell->IsCellFrm(), "Frame without Gazelle" );
     654             : 
     655           0 :     if( pCell->FindTabFrm()->IsVertical() )
     656           0 :         return ( rUnion.Right() >= pCell->Frm().Right() &&
     657           0 :                  rUnion.Left() <= pCell->Frm().Left() &&
     658           0 :             (( rUnion.Top() <= pCell->Frm().Top()+20 &&
     659           0 :                rUnion.Bottom() > pCell->Frm().Top() ) ||
     660           0 :              ( rUnion.Top() >= pCell->Frm().Top() &&
     661           0 :                rUnion.Bottom() < pCell->Frm().Bottom() )) ? sal_True : sal_False );
     662             : 
     663             :     return (
     664           0 :         rUnion.Top() <= pCell->Frm().Top() &&
     665           0 :         rUnion.Bottom() >= pCell->Frm().Bottom() &&
     666             : 
     667           0 :         (( rUnion.Left() <= pCell->Frm().Left()+20 &&
     668           0 :            rUnion.Right() > pCell->Frm().Left() ) ||
     669             : 
     670           0 :          ( rUnion.Left() >= pCell->Frm().Left() &&
     671           0 :            rUnion.Right() < pCell->Frm().Right() )) ? sal_True : sal_False );
     672             : }
     673             : 
     674           0 : sal_Bool GetAutoSumSel( const SwCrsrShell& rShell, SwCellFrms& rBoxes )
     675             : {
     676           0 :     SwShellCrsr* pCrsr = rShell.m_pCurCrsr;
     677           0 :     if ( rShell.IsTableMode() )
     678           0 :         pCrsr = rShell.m_pTblCrsr;
     679             : 
     680           0 :     const SwLayoutFrm *pStart = pCrsr->GetCntntNode()->getLayoutFrm( rShell.GetLayout(),
     681           0 :                       &pCrsr->GetPtPos() )->GetUpper(),
     682           0 :                       *pEnd   = pCrsr->GetCntntNode(false)->getLayoutFrm( rShell.GetLayout(),
     683           0 :                       &pCrsr->GetMkPos() )->GetUpper();
     684             : 
     685           0 :     const SwLayoutFrm* pSttCell = pStart;
     686           0 :     while( pSttCell && !pSttCell->IsCellFrm() )
     687           0 :         pSttCell = pSttCell->GetUpper();
     688             : 
     689             :     // First, compute tables and rectangles
     690           0 :     SwSelUnions aUnions;
     691             : 
     692             :     // by default, first test above and then to the left
     693           0 :     ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_COL );
     694             : 
     695           0 :     bool bTstRow = true, bFound = false;
     696             :     sal_uInt16 i;
     697             : 
     698             :     // 1. check if box above contains value/formula
     699           0 :     for( i = 0; i < aUnions.size(); ++i )
     700             :     {
     701           0 :         SwSelUnion *pUnion = &aUnions[i];
     702           0 :         const SwTabFrm *pTable = pUnion->GetTable();
     703             : 
     704             :         // Skip any repeated headlines in the follow:
     705           0 :         const SwLayoutFrm* pRow = pTable->IsFollow() ?
     706             :                                   pTable->GetFirstNonHeadlineRow() :
     707           0 :                                   (const SwLayoutFrm*)pTable->Lower();
     708             : 
     709           0 :         while( pRow )
     710             :         {
     711           0 :             if( pRow->Frm().IsOver( pUnion->GetUnion() ) )
     712             :             {
     713           0 :                 const SwCellFrm* pUpperCell = 0;
     714           0 :                 const SwLayoutFrm *pCell = pRow->FirstCell();
     715             : 
     716           0 :                 while( pCell && pRow->IsAnLower( pCell ) )
     717             :                 {
     718           0 :                     if( pCell == pSttCell )
     719             :                     {
     720           0 :                         sal_uInt16 nWhichId = 0;
     721           0 :                         for( size_t n = rBoxes.size(); n; )
     722           0 :                             if( USHRT_MAX != ( nWhichId = rBoxes[ --n ]
     723           0 :                                 ->GetTabBox()->IsFormulaOrValueBox() ))
     724           0 :                                 break;
     725             : 
     726             :                         // all boxes together, do not check the
     727             :                         // row, if a formula or value was found
     728           0 :                         bTstRow = 0 == nWhichId || USHRT_MAX == nWhichId;
     729           0 :                         bFound = true;
     730           0 :                         break;
     731             :                     }
     732             : 
     733             :                     OSL_ENSURE( pCell->IsCellFrm(), "Frame without cell" );
     734           0 :                     if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
     735           0 :                         pUpperCell = (SwCellFrm*)pCell;
     736             : 
     737           0 :                     if( pCell->GetNext() )
     738             :                     {
     739           0 :                         pCell = (const SwLayoutFrm*)pCell->GetNext();
     740           0 :                         if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
     741           0 :                             pCell = pCell->FirstCell();
     742             :                     }
     743             :                     else
     744           0 :                         pCell = ::lcl_FindNextCellFrm( pCell );
     745             :                 }
     746             : 
     747           0 :                 if( pUpperCell )
     748           0 :                     rBoxes.push_back( const_cast< SwCellFrm* >(pUpperCell) );
     749             :             }
     750           0 :             if( bFound )
     751             :             {
     752           0 :                 i = aUnions.size();
     753           0 :                 break;
     754             :             }
     755           0 :             pRow = (const SwLayoutFrm*)pRow->GetNext();
     756             :         }
     757             :     }
     758             : 
     759             :     // 2. check if box on left contains value/formula
     760           0 :     if( bTstRow )
     761             :     {
     762           0 :         bFound = false;
     763             : 
     764           0 :         rBoxes.clear();
     765           0 :         aUnions.clear();
     766           0 :         ::MakeSelUnions( aUnions, pStart, pEnd, nsSwTblSearchType::TBLSEARCH_ROW );
     767             : 
     768           0 :         for( i = 0; i < aUnions.size(); ++i )
     769             :         {
     770           0 :             SwSelUnion *pUnion = &aUnions[i];
     771           0 :             const SwTabFrm *pTable = pUnion->GetTable();
     772             : 
     773             :             // Skip any repeated headlines in the follow:
     774           0 :             const SwLayoutFrm* pRow = pTable->IsFollow() ?
     775             :                                       pTable->GetFirstNonHeadlineRow() :
     776           0 :                                       (const SwLayoutFrm*)pTable->Lower();
     777             : 
     778           0 :             while( pRow )
     779             :             {
     780           0 :                 if( pRow->Frm().IsOver( pUnion->GetUnion() ) )
     781             :                 {
     782           0 :                     const SwLayoutFrm *pCell = pRow->FirstCell();
     783             : 
     784           0 :                     while( pCell && pRow->IsAnLower( pCell ) )
     785             :                     {
     786           0 :                         if( pCell == pSttCell )
     787             :                         {
     788           0 :                             sal_uInt16 nWhichId = 0;
     789           0 :                             for( size_t n = rBoxes.size(); n; )
     790           0 :                                 if( USHRT_MAX != ( nWhichId = rBoxes[ --n ]
     791           0 :                                     ->GetTabBox()->IsFormulaOrValueBox() ))
     792           0 :                                     break;
     793             : 
     794             :                             // all boxes together, do not check the
     795             :                             // row if a formula or value was found
     796           0 :                             bFound = 0 != nWhichId && USHRT_MAX != nWhichId;
     797           0 :                             bTstRow = false;
     798           0 :                             break;
     799             :                         }
     800             : 
     801             :                         OSL_ENSURE( pCell->IsCellFrm(), "Frame without cell" );
     802           0 :                         if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
     803             :                         {
     804           0 :                             SwCellFrm* pC = (SwCellFrm*)pCell;
     805           0 :                             rBoxes.push_back( pC );
     806             :                         }
     807           0 :                         if( pCell->GetNext() )
     808             :                         {
     809           0 :                             pCell = (const SwLayoutFrm*)pCell->GetNext();
     810           0 :                             if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
     811           0 :                                 pCell = pCell->FirstCell();
     812             :                         }
     813             :                         else
     814           0 :                             pCell = ::lcl_FindNextCellFrm( pCell );
     815             :                     }
     816             :                 }
     817           0 :                 if( !bTstRow )
     818             :                 {
     819           0 :                     i = aUnions.size();
     820           0 :                     break;
     821             :                 }
     822             : 
     823           0 :                 pRow = (const SwLayoutFrm*)pRow->GetNext();
     824             :             }
     825             :         }
     826             :     }
     827             : 
     828           0 :     return bFound ? sal_True : sal_False;
     829             : }
     830             : 
     831           0 : sal_Bool HasProtectedCells( const SwSelBoxes& rBoxes )
     832             : {
     833           0 :     sal_Bool bRet = sal_False;
     834           0 :     for (size_t n = 0; n < rBoxes.size(); ++n)
     835             :     {
     836           0 :         if( rBoxes[ n ]->GetFrmFmt()->GetProtect().IsCntntProtected() )
     837             :         {
     838           0 :             bRet = sal_True;
     839           0 :             break;
     840             :         }
     841             :     }
     842           0 :     return bRet;
     843             : }
     844             : 
     845           0 : _CmpLPt::_CmpLPt( const Point& rPt, const SwTableBox* pBox, bool bVertical )
     846           0 :     : aPos( rPt ), pSelBox( pBox ), bVert( bVertical )
     847           0 : {}
     848             : 
     849           0 : static void lcl_InsTblBox( SwTableNode* pTblNd, SwDoc* pDoc, SwTableBox* pBox,
     850             :                         sal_uInt16 nInsPos, sal_uInt16 nCnt = 1 )
     851             : {
     852             :     OSL_ENSURE( pBox->GetSttNd(), "Box without Start-Node" );
     853           0 :     SwCntntNode* pCNd = pDoc->GetNodes()[ pBox->GetSttIdx() + 1 ]
     854           0 :                                 ->GetCntntNode();
     855           0 :     if( pCNd && pCNd->IsTxtNode() )
     856           0 :         pDoc->GetNodes().InsBoxen( pTblNd, pBox->GetUpper(),
     857           0 :                 (SwTableBoxFmt*)pBox->GetFrmFmt(),
     858             :                 ((SwTxtNode*)pCNd)->GetTxtColl(),
     859           0 :                 pCNd->GetpSwAttrSet(),
     860           0 :                 nInsPos, nCnt );
     861             :     else
     862           0 :         pDoc->GetNodes().InsBoxen( pTblNd, pBox->GetUpper(),
     863           0 :                 (SwTableBoxFmt*)pBox->GetFrmFmt(),
     864           0 :                 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl(), 0,
     865           0 :                 nInsPos, nCnt );
     866           0 : }
     867             : 
     868           0 : sal_Bool IsEmptyBox( const SwTableBox& rBox, SwPaM& rPam )
     869             : {
     870           0 :     rPam.GetPoint()->nNode = *rBox.GetSttNd()->EndOfSectionNode();
     871           0 :     rPam.Move( fnMoveBackward, fnGoCntnt );
     872           0 :     rPam.SetMark();
     873           0 :     rPam.GetPoint()->nNode = *rBox.GetSttNd();
     874           0 :     rPam.Move( fnMoveForward, fnGoCntnt );
     875           0 :     sal_Bool bRet = *rPam.GetMark() == *rPam.GetPoint()
     876           0 :         && ( rBox.GetSttNd()->GetIndex() + 1 == rPam.GetPoint()->nNode.GetIndex() );
     877             : 
     878           0 :     if( bRet )
     879             :     {
     880             :         // now check for paragraph bound flyes
     881           0 :         const SwFrmFmts& rFmts = *rPam.GetDoc()->GetSpzFrmFmts();
     882           0 :         sal_uLong nSttIdx = rPam.GetPoint()->nNode.GetIndex(),
     883           0 :               nEndIdx = rBox.GetSttNd()->EndOfSectionIndex(),
     884             :               nIdx;
     885             : 
     886           0 :         for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
     887             :         {
     888           0 :             const SwFmtAnchor& rAnchor = rFmts[n]->GetAnchor();
     889           0 :             const SwPosition* pAPos = rAnchor.GetCntntAnchor();
     890           0 :             if (pAPos &&
     891           0 :                 ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
     892           0 :                  (FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
     893           0 :                 nSttIdx <= ( nIdx = pAPos->nNode.GetIndex() ) &&
     894             :                 nIdx < nEndIdx )
     895             :             {
     896           0 :                 bRet = sal_False;
     897           0 :                 break;
     898             :             }
     899             :         }
     900             :     }
     901           0 :     return bRet;
     902             : }
     903             : 
     904           0 : void GetMergeSel( const SwPaM& rPam, SwSelBoxes& rBoxes,
     905             :                 SwTableBox** ppMergeBox, SwUndoTblMerge* pUndo )
     906             : {
     907           0 :     rBoxes.clear();
     908             : 
     909             :     OSL_ENSURE( rPam.GetCntntNode() && rPam.GetCntntNode( false ),
     910             :             "Tabselection not on Cnt." );
     911             : 
     912             : //JP 24.09.96:  Merge with repeating TableHeadLines does not work properly.
     913             : //              Why not use point 0,0? Then it is assured the first
     914             : //              headline is contained.
     915           0 :     Point aPt( 0, 0 );
     916             : 
     917           0 :     const SwCntntNode* pCntNd = rPam.GetCntntNode();
     918           0 :     const SwLayoutFrm *pStart = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
     919           0 :                                                         &aPt )->GetUpper();
     920           0 :     pCntNd = rPam.GetCntntNode(false);
     921           0 :     const SwLayoutFrm *pEnd = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
     922           0 :                                                         &aPt )->GetUpper();
     923             : 
     924             :     // First, compute tables and rectangles
     925           0 :     SwSelUnions aUnions;
     926           0 :     ::MakeSelUnions( aUnions, pStart, pEnd );
     927           0 :     if( aUnions.empty() )
     928           0 :         return;
     929             : 
     930           0 :     const SwTable *pTable = aUnions.front().GetTable()->GetTable();
     931           0 :     SwDoc* pDoc = (SwDoc*)pStart->GetFmt()->GetDoc();
     932           0 :     SwTableNode* pTblNd = (SwTableNode*)pTable->GetTabSortBoxes()[ 0 ]->
     933           0 :                                         GetSttNd()->FindTableNode();
     934             : 
     935           0 :     _MergePos aPosArr;      // Sort-Array with the frame positions
     936             :     long nWidth;
     937           0 :     SwTableBox* pLastBox = 0;
     938             : 
     939           0 :     SWRECTFN( pStart->GetUpper() )
     940             : 
     941           0 :     for ( sal_uInt16 i = 0; i < aUnions.size(); ++i )
     942             :     {
     943           0 :         const SwTabFrm *pTabFrm = aUnions[i].GetTable();
     944             : 
     945           0 :         SwRect &rUnion = aUnions[i].GetUnion();
     946             : 
     947             :         // Skip any repeated headlines in the follow:
     948           0 :         const SwLayoutFrm* pRow = pTabFrm->IsFollow() ?
     949             :                                   pTabFrm->GetFirstNonHeadlineRow() :
     950           0 :                                   (const SwLayoutFrm*)pTabFrm->Lower();
     951             : 
     952           0 :         while ( pRow )
     953             :         {
     954           0 :             if ( pRow->Frm().IsOver( rUnion ) )
     955             :             {
     956           0 :                 const SwLayoutFrm *pCell = pRow->FirstCell();
     957             : 
     958           0 :                 while ( pCell && pRow->IsAnLower( pCell ) )
     959             :                 {
     960             :                     OSL_ENSURE( pCell->IsCellFrm(), "Frame without cell" );
     961             :                     // overlap in full width?
     962           0 :                     if( rUnion.Top() <= pCell->Frm().Top() &&
     963           0 :                         rUnion.Bottom() >= pCell->Frm().Bottom() )
     964             :                     {
     965           0 :                         SwTableBox* pBox =(SwTableBox*)((SwCellFrm*)pCell)->GetTabBox();
     966             : 
     967             :                         // only overlap to the right?
     968           0 :                         if( ( rUnion.Left() - COLFUZZY ) <= pCell->Frm().Left() &&
     969           0 :                             ( rUnion.Right() - COLFUZZY ) > pCell->Frm().Left() )
     970             :                         {
     971           0 :                             if( ( rUnion.Right() + COLFUZZY ) < pCell->Frm().Right() )
     972             :                             {
     973             :                                 sal_uInt16 nInsPos = pBox->GetUpper()->
     974           0 :                                                     GetTabBoxes().GetPos( pBox )+1;
     975           0 :                                 lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos );
     976           0 :                                 pBox->ClaimFrmFmt();
     977             :                                 SwFmtFrmSize aNew(
     978           0 :                                         pBox->GetFrmFmt()->GetFrmSize() );
     979           0 :                                 nWidth = rUnion.Right() - pCell->Frm().Left();
     980           0 :                                 nWidth = nWidth * aNew.GetWidth() /
     981           0 :                                          pCell->Frm().Width();
     982           0 :                                 long nTmpWidth = aNew.GetWidth() - nWidth;
     983           0 :                                 aNew.SetWidth( nWidth );
     984           0 :                                 pBox->GetFrmFmt()->SetFmtAttr( aNew );
     985             :                                 // this box is selected
     986           0 :                                 pLastBox = pBox;
     987           0 :                                 rBoxes.insert( pBox );
     988             :                                 aPosArr.insert(
     989           0 :                                     _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(),
     990           0 :                                     pBox, bVert ) );
     991             : 
     992           0 :                                 pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
     993           0 :                                 aNew.SetWidth( nTmpWidth );
     994           0 :                                 pBox->ClaimFrmFmt();
     995           0 :                                 pBox->GetFrmFmt()->SetFmtAttr( aNew );
     996             : 
     997           0 :                                 if( pUndo )
     998           0 :                                     pUndo->AddNewBox( pBox->GetSttIdx() );
     999             :                             }
    1000             :                             else
    1001             :                             {
    1002             :                                 // this box is selected
    1003           0 :                                 pLastBox = pBox;
    1004           0 :                                 rBoxes.insert( pBox );
    1005             : #if OSL_DEBUG_LEVEL > 1
    1006             :                                 Point aInsPoint( (pCell->Frm().*fnRect->fnGetPos)() );
    1007             : #endif
    1008             :                                 aPosArr.insert(
    1009           0 :                                     _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(),
    1010           0 :                                     pBox, bVert ) );
    1011             :                             }
    1012             :                         }
    1013             :                         // overlapping on left- or right-side
    1014           0 :                         else if( ( rUnion.Left() - COLFUZZY ) >= pCell->Frm().Left() &&
    1015           0 :                                 ( rUnion.Right() + COLFUZZY ) < pCell->Frm().Right() )
    1016             :                         {
    1017           0 :                             sal_uInt16 nInsPos = pBox->GetUpper()->GetTabBoxes().GetPos(
    1018           0 :                                             pBox )+1;
    1019           0 :                             lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos, 2 );
    1020           0 :                             pBox->ClaimFrmFmt();
    1021             :                             SwFmtFrmSize aNew(
    1022           0 :                                         pBox->GetFrmFmt()->GetFrmSize() );
    1023           0 :                             long nLeft = rUnion.Left() - pCell->Frm().Left();
    1024           0 :                             nLeft = nLeft * aNew.GetWidth() /
    1025           0 :                                     pCell->Frm().Width();
    1026           0 :                             long nRight = pCell->Frm().Right() - rUnion.Right();
    1027           0 :                             nRight = nRight * aNew.GetWidth() /
    1028           0 :                                      pCell->Frm().Width();
    1029           0 :                             nWidth = aNew.GetWidth() - nLeft - nRight;
    1030             : 
    1031           0 :                             aNew.SetWidth( nLeft );
    1032           0 :                             pBox->GetFrmFmt()->SetFmtAttr( aNew );
    1033             : 
    1034             :                             {
    1035             :                             const SfxPoolItem* pItem;
    1036           0 :                             if( SFX_ITEM_SET == pBox->GetFrmFmt()->GetAttrSet()
    1037           0 :                                         .GetItemState( RES_BOX, false, &pItem ))
    1038             :                             {
    1039           0 :                                 SvxBoxItem aBox( *(SvxBoxItem*)pItem );
    1040           0 :                                 aBox.SetLine( 0, BOX_LINE_RIGHT );
    1041           0 :                                 pBox->GetFrmFmt()->SetFmtAttr( aBox );
    1042             :                             }
    1043             :                             }
    1044             : 
    1045           0 :                             pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
    1046           0 :                             aNew.SetWidth( nWidth );
    1047           0 :                             pBox->ClaimFrmFmt();
    1048           0 :                             pBox->GetFrmFmt()->SetFmtAttr( aNew );
    1049             : 
    1050           0 :                             if( pUndo )
    1051           0 :                                 pUndo->AddNewBox( pBox->GetSttIdx() );
    1052             : 
    1053             :                             // this box is selected
    1054           0 :                             pLastBox = pBox;
    1055           0 :                             rBoxes.insert( pBox );
    1056             :                             aPosArr.insert(
    1057           0 :                                 _CmpLPt( (pCell->Frm().*fnRect->fnGetPos)(),
    1058           0 :                                 pBox, bVert ) );
    1059             : 
    1060           0 :                             pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos+1 ];
    1061           0 :                             aNew.SetWidth( nRight );
    1062           0 :                             pBox->ClaimFrmFmt();
    1063           0 :                             pBox->GetFrmFmt()->SetFmtAttr( aNew );
    1064             : 
    1065           0 :                             if( pUndo )
    1066           0 :                                 pUndo->AddNewBox( pBox->GetSttIdx() );
    1067             :                         }
    1068             :                        // is right side of box part of the selected area?
    1069           0 :                         else if( ( pCell->Frm().Right() - COLFUZZY ) < rUnion.Right() &&
    1070           0 :                                  ( pCell->Frm().Right() - COLFUZZY ) > rUnion.Left() &&
    1071           0 :                                  ( pCell->Frm().Left() + COLFUZZY ) < rUnion.Left() )
    1072             :                         {
    1073             :                             // then we should insert a new box and adjust the widths
    1074           0 :                             sal_uInt16 nInsPos = pBox->GetUpper()->GetTabBoxes().GetPos(
    1075           0 :                                             pBox )+1;
    1076           0 :                             lcl_InsTblBox( pTblNd, pDoc, pBox, nInsPos, 1 );
    1077             : 
    1078           0 :                             SwFmtFrmSize aNew(pBox->GetFrmFmt()->GetFrmSize() );
    1079           0 :                             long nLeft = rUnion.Left() - pCell->Frm().Left(),
    1080           0 :                                 nRight = pCell->Frm().Right() - rUnion.Left();
    1081             : 
    1082           0 :                             nLeft = nLeft * aNew.GetWidth() /
    1083           0 :                                     pCell->Frm().Width();
    1084           0 :                             nRight = nRight * aNew.GetWidth() /
    1085           0 :                                     pCell->Frm().Width();
    1086             : 
    1087           0 :                             aNew.SetWidth( nLeft );
    1088           0 :                             pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
    1089             : 
    1090             :                                 // this box is selected
    1091           0 :                             pBox = pBox->GetUpper()->GetTabBoxes()[ nInsPos ];
    1092           0 :                             aNew.SetWidth( nRight );
    1093           0 :                             pBox->ClaimFrmFmt();
    1094           0 :                             pBox->GetFrmFmt()->SetFmtAttr( aNew );
    1095             : 
    1096           0 :                             pLastBox = pBox;
    1097           0 :                             rBoxes.insert( pBox );
    1098             :                             aPosArr.insert( _CmpLPt( Point( rUnion.Left(),
    1099           0 :                                                 pCell->Frm().Top()), pBox, bVert ));
    1100             : 
    1101           0 :                             if( pUndo )
    1102           0 :                                 pUndo->AddNewBox( pBox->GetSttIdx() );
    1103             :                         }
    1104             :                     }
    1105           0 :                     if ( pCell->GetNext() )
    1106             :                     {
    1107           0 :                         pCell = (const SwLayoutFrm*)pCell->GetNext();
    1108             :                         // --> Check if table cell is not empty
    1109           0 :                         if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
    1110           0 :                             pCell = pCell->FirstCell();
    1111             :                     }
    1112             :                     else
    1113           0 :                         pCell = ::lcl_FindNextCellFrm( pCell );
    1114             :                 }
    1115             :             }
    1116           0 :             pRow = (const SwLayoutFrm*)pRow->GetNext();
    1117             :         }
    1118             :     }
    1119             : 
    1120             :     // no SSelection / no boxes found
    1121           0 :     if( 1 >= rBoxes.size() )
    1122           0 :         return;
    1123             : 
    1124             :     // now search all horizontally adjacent boxes and connect
    1125             :     // their contents with blanks. All vertically adjacent will be tied
    1126             :     // together as paragraphs
    1127             : 
    1128             :     // 1. Solution: map array and all on same Y-level
    1129             :     //      are separated with blanks
    1130             :     //      all others are separated with paragraphs
    1131           0 :     bool bCalcWidth = true;
    1132           0 :     const SwTableBox* pFirstBox = aPosArr[ 0 ].pSelBox;
    1133             : 
    1134             :     // JP 27.03.98:  Optimise - if boxes on one row are empty,
    1135             :     //              then do not insert blanks or carriage returns
    1136             :     //Block to assure SwPaM, SwPosition are deleted from stack
    1137             :     {
    1138           0 :         SwPaM aPam( pDoc->GetNodes() );
    1139             : 
    1140             : #if defined( DEL_ONLY_EMPTY_LINES )
    1141             :         nWidth = pFirstBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1142             :         sal_Bool bEmptyLine = sal_True;
    1143             :         sal_uInt16 n, nSttPos = 0;
    1144             : 
    1145             :         for( n = 0; n < aPosArr.Count(); ++n )
    1146             :         {
    1147             :             const _CmpLPt& rPt = aPosArr[ n ];
    1148             :             if( n && aPosArr[ n - 1 ].Y() == rPt.Y() )  // same Y level?
    1149             :             {
    1150             :                 if( bEmptyLine && !IsEmptyBox( *rPt.pSelBox, aPam ))
    1151             :                     bEmptyLine = sal_False;
    1152             :                 if( bCalcWidth )
    1153             :                     nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1154             :             }
    1155             :             else
    1156             :             {
    1157             :                 if( bCalcWidth && n )
    1158             :                     bCalcWidth = false;     // one line is ready
    1159             : 
    1160             :                 if( bEmptyLine && nSttPos < n )
    1161             :                 {
    1162             :                     // now complete line is empty and should not
    1163             :                     // be filled with blanks and be inserted as paragraph
    1164             :                     if( pUndo )
    1165             :                         for( sal_uInt16 i = nSttPos; i < n; ++i )
    1166             :                             pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
    1167             : 
    1168             :                     aPosArr.Remove( nSttPos, n - nSttPos );
    1169             :                     n = nSttPos;
    1170             :                 }
    1171             :                 else
    1172             :                     nSttPos = n;
    1173             : 
    1174             :                 bEmptyLine = IsEmptyBox( *aPosArr[n].pSelBox, aPam );
    1175             :             }
    1176             :         }
    1177             :         if( bEmptyLine && nSttPos < n )
    1178             :         {
    1179             :             if( pUndo )
    1180             :                 for( sal_uInt16 i = nSttPos; i < n; ++i )
    1181             :                     pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
    1182             :             aPosArr.Remove( nSttPos, n - nSttPos );
    1183             :         }
    1184             : #elif defined( DEL_EMPTY_BOXES_AT_START_AND_END )
    1185             : 
    1186             :         nWidth = pFirstBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1187             :         sal_uInt16 n, nSttPos = 0, nSEndPos = 0, nESttPos = 0;
    1188             : 
    1189             :         for( n = 0; n < aPosArr.Count(); ++n )
    1190             :         {
    1191             :             const _CmpLPt& rPt = aPosArr[ n ];
    1192             :             if( n && aPosArr[ n - 1 ].Y() == rPt.Y() )  // same Y level?
    1193             :             {
    1194             :                 sal_Bool bEmptyBox = IsEmptyBox( *rPt.pSelBox, aPam );
    1195             :                 if( bEmptyBox )
    1196             :                 {
    1197             :                     if( nSEndPos == n )     // beginning is empty
    1198             :                         nESttPos = ++nSEndPos;
    1199             :                 }
    1200             :                 else                        // end could be empty
    1201             :                     nESttPos = n+1;
    1202             : 
    1203             :                 if( bCalcWidth )
    1204             :                     nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1205             :             }
    1206             :             else
    1207             :             {
    1208             :                 if( bCalcWidth && n )
    1209             :                     bCalcWidth = false;     // one line ready
    1210             : 
    1211             :                 // first those at the beginning
    1212             :                 if( nSttPos < nSEndPos )
    1213             :                 {
    1214             :                     // now the beginning of the line is empty and should
    1215             :                     // not be filled with blanks
    1216             :                     if( pUndo )
    1217             :                         for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
    1218             :                             pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
    1219             : 
    1220             :                     sal_uInt16 nCnt = nSEndPos - nSttPos;
    1221             :                     aPosArr.Remove( nSttPos, nCnt );
    1222             :                     nESttPos -= nCnt;
    1223             :                     n -= nCnt;
    1224             :                 }
    1225             : 
    1226             :                 if( nESttPos < n )
    1227             :                 {
    1228             :                     // now the beginning of the line is empty and should
    1229             :                     // not be filled with blanks
    1230             :                     if( pUndo )
    1231             :                         for( sal_uInt16 i = nESttPos; i < n; ++i )
    1232             :                             pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
    1233             : 
    1234             :                     sal_uInt16 nCnt = n - nESttPos;
    1235             :                     aPosArr.Remove( nESttPos, nCnt );
    1236             :                     n -= nCnt;
    1237             :                 }
    1238             : 
    1239             :                 nSttPos = nSEndPos = nESttPos = n;
    1240             :                 if( IsEmptyBox( *aPosArr[n].pSelBox, aPam ))
    1241             :                     ++nSEndPos;
    1242             :                 else
    1243             :                     ++nESttPos;
    1244             :             }
    1245             :         }
    1246             : 
    1247             :         // first those at the beginning
    1248             :         if( nSttPos < nSEndPos )
    1249             :         {
    1250             :             // now the beginning of the line is empty and should
    1251             :             // not be filled with blanks
    1252             :             if( pUndo )
    1253             :                 for( sal_uInt16 i = nSttPos; i < nSEndPos; ++i )
    1254             :                     pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
    1255             : 
    1256             :             sal_uInt16 nCnt = nSEndPos - nSttPos;
    1257             :             aPosArr.Remove( nSttPos, nCnt );
    1258             :             nESttPos -= nCnt;
    1259             :             n -= nCnt;
    1260             :         }
    1261             :         if( nESttPos < n )
    1262             :         {
    1263             :             // now the beginning of the line is empty and should
    1264             :             // not be filled with blanks
    1265             :             if( pUndo )
    1266             :                 for( sal_uInt16 i = nESttPos; i < n; ++i )
    1267             :                     pUndo->SaveCollection( *aPosArr[ i ].pSelBox );
    1268             : 
    1269             :             sal_uInt16 nCnt = n - nESttPos;
    1270             :             aPosArr.Remove( nESttPos, nCnt );
    1271             :         }
    1272             : #else
    1273             : // DEL_ALL_EMPTY_BOXES
    1274             : 
    1275           0 :         nWidth = 0;
    1276           0 :         long nY = !aPosArr.empty() ?
    1277             :                     ( bVert ?
    1278           0 :                       aPosArr[ 0 ].X() :
    1279           0 :                       aPosArr[ 0 ].Y() ) :
    1280           0 :                   0;
    1281             : 
    1282           0 :         for( sal_uInt16 n = 0; n < aPosArr.size(); ++n )
    1283             :         {
    1284           0 :             const _CmpLPt& rPt = aPosArr[ n ];
    1285           0 :             if( bCalcWidth )
    1286             :             {
    1287           0 :                 if( nY == ( bVert ? rPt.X() : rPt.Y() ) ) // same Y level?
    1288           0 :                     nWidth += rPt.pSelBox->GetFrmFmt()->GetFrmSize().GetWidth();
    1289             :                 else
    1290           0 :                     bCalcWidth = false;     // one line ready
    1291             :             }
    1292             : 
    1293           0 :             if( IsEmptyBox( *rPt.pSelBox, aPam ) )
    1294             :             {
    1295           0 :                 if( pUndo )
    1296           0 :                     pUndo->SaveCollection( *rPt.pSelBox );
    1297             : 
    1298           0 :                 aPosArr.erase( aPosArr.begin() + n );
    1299           0 :                 --n;
    1300             :             }
    1301           0 :         }
    1302             : #endif
    1303             :     }
    1304             : 
    1305             :     // first create new box
    1306             :     {
    1307           0 :         SwTableBox* pTmpBox = rBoxes[0];
    1308           0 :         SwTableLine* pInsLine = pTmpBox->GetUpper();
    1309           0 :         sal_uInt16 nInsPos = pInsLine->GetTabBoxes().GetPos( pTmpBox );
    1310             : 
    1311           0 :         lcl_InsTblBox( pTblNd, pDoc, pTmpBox, nInsPos );
    1312           0 :         (*ppMergeBox) = pInsLine->GetTabBoxes()[ nInsPos ];
    1313           0 :         pInsLine->GetTabBoxes().erase( pInsLine->GetTabBoxes().begin() + nInsPos );  // remove again
    1314           0 :         (*ppMergeBox)->SetUpper( 0 );
    1315           0 :         (*ppMergeBox)->ClaimFrmFmt();
    1316             : 
    1317             :         // define the border: the upper/left side of the first box,
    1318             :         // the lower/right side of the last box:
    1319           0 :         if( pLastBox && pFirstBox )
    1320             :         {
    1321           0 :             SvxBoxItem aBox( pFirstBox->GetFrmFmt()->GetBox() );
    1322           0 :             const SvxBoxItem& rBox = pLastBox->GetFrmFmt()->GetBox();
    1323           0 :             aBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT );
    1324           0 :             aBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM );
    1325           0 :             if( aBox.GetLeft() || aBox.GetTop() ||
    1326           0 :                 aBox.GetRight() || aBox.GetBottom() )
    1327           0 :                 (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( aBox );
    1328             :         }
    1329             :     }
    1330             : 
    1331             :     //Block to delete  SwPaM, SwPosition from stack
    1332           0 :     if( !aPosArr.empty() )
    1333             :     {
    1334           0 :         SwTxtNode* pTxtNd = 0;
    1335           0 :         SwPosition aInsPos( *(*ppMergeBox)->GetSttNd() );
    1336           0 :         SwNodeIndex& rInsPosNd = aInsPos.nNode;
    1337             : 
    1338           0 :         SwPaM aPam( aInsPos );
    1339             : 
    1340           0 :         for( sal_uInt16 n = 0; n < aPosArr.size(); ++n )
    1341             :         {
    1342           0 :             const _CmpLPt& rPt = aPosArr[ n ];
    1343           0 :             aPam.GetPoint()->nNode.Assign( *rPt.pSelBox->GetSttNd()->
    1344           0 :                                             EndOfSectionNode(), -1 );
    1345           0 :             SwCntntNode* pCNd = aPam.GetCntntNode();
    1346           0 :             aPam.GetPoint()->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
    1347             : 
    1348           0 :             SwNodeIndex aSttNdIdx( *rPt.pSelBox->GetSttNd(), 1 );
    1349             :             // one node should be kept in the box (otherwise the
    1350             :             // section would be deleted during a move)
    1351           0 :             bool const bUndo(pDoc->GetIDocumentUndoRedo().DoesUndo());
    1352           0 :             if( pUndo )
    1353             :             {
    1354           0 :                 pDoc->GetIDocumentUndoRedo().DoUndo(false);
    1355             :             }
    1356           0 :             pDoc->AppendTxtNode( *aPam.GetPoint() );
    1357           0 :             if( pUndo )
    1358             :             {
    1359           0 :                 pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
    1360             :             }
    1361           0 :             SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
    1362           0 :             ++rInsPosNd;
    1363           0 :             if( pUndo )
    1364           0 :                 pUndo->MoveBoxCntnt( pDoc, aRg, rInsPosNd );
    1365             :             else
    1366             :             {
    1367             :                 pDoc->MoveNodeRange( aRg, rInsPosNd,
    1368           0 :                     IDocumentContentOperations::DOC_MOVEDEFAULT );
    1369             :             }
    1370             :             // where is now aInsPos ??
    1371             : 
    1372           0 :             if( bCalcWidth )
    1373           0 :                 bCalcWidth = false;     // one line is ready
    1374             : 
    1375             :             // skip the first TextNode
    1376           0 :             rInsPosNd.Assign( pDoc->GetNodes(),
    1377           0 :                             rInsPosNd.GetNode().EndOfSectionIndex() - 2 );
    1378           0 :             pTxtNd = rInsPosNd.GetNode().GetTxtNode();
    1379           0 :             if( pTxtNd )
    1380           0 :                 aInsPos.nContent.Assign(pTxtNd, pTxtNd->GetTxt().getLength());
    1381           0 :         }
    1382             : 
    1383             :         // the MergeBox should contain the complete text
    1384             :         // now erase the initial TextNode
    1385             :         OSL_ENSURE( (*ppMergeBox)->GetSttIdx()+2 <
    1386             :                 (*ppMergeBox)->GetSttNd()->EndOfSectionIndex(),
    1387             :                     "empty box" );
    1388           0 :         SwNodeIndex aIdx( *(*ppMergeBox)->GetSttNd()->EndOfSectionNode(), -1 );
    1389           0 :         pDoc->GetNodes().Delete( aIdx, 1 );
    1390             :     }
    1391             : 
    1392             :     // set width of the box
    1393           0 :     (*ppMergeBox)->GetFrmFmt()->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
    1394           0 :     if( pUndo )
    1395           0 :         pUndo->AddNewBox( (*ppMergeBox)->GetSttIdx() );
    1396             : }
    1397             : 
    1398             : static bool lcl_CheckCol(_FndBox const&, bool* pPara);
    1399             : 
    1400           0 : static bool lcl_CheckRow( const _FndLine& rFndLine, bool* pPara )
    1401             : {
    1402           0 :     for (_FndBoxes::const_iterator it = rFndLine.GetBoxes().begin();
    1403           0 :          it != rFndLine.GetBoxes().end(); ++it)
    1404             :     {
    1405           0 :         lcl_CheckCol(*it, pPara);
    1406             :     }
    1407           0 :     return *pPara;
    1408             : }
    1409             : 
    1410           0 : static bool lcl_CheckCol( _FndBox const& rFndBox, bool* pPara )
    1411             : {
    1412           0 :     if (!rFndBox.GetBox()->GetSttNd())
    1413             :     {
    1414           0 :         if (rFndBox.GetLines().size() !=
    1415           0 :             rFndBox.GetBox()->GetTabLines().size())
    1416             :         {
    1417           0 :             *pPara = false;
    1418             :         }
    1419             :         else
    1420             :         {
    1421           0 :             BOOST_FOREACH( _FndLine const& rFndLine, rFndBox.GetLines() )
    1422           0 :                 lcl_CheckRow( rFndLine, pPara );
    1423             :         }
    1424             :     }
    1425             :     // is box protected ??
    1426           0 :     else if (rFndBox.GetBox()->GetFrmFmt()->GetProtect().IsCntntProtected())
    1427           0 :         *pPara = false;
    1428           0 :     return *pPara;
    1429             : }
    1430             : 
    1431           0 : sal_uInt16 CheckMergeSel( const SwPaM& rPam )
    1432             : {
    1433           0 :     SwSelBoxes aBoxes;
    1434             : //JP 24.09.96:  Merge with repeating TableHeadLines does not work properly.
    1435             : //              Why not use point 0,0? Then it is assured the first
    1436             : //              headline is contained.
    1437             : 
    1438           0 :     Point aPt;
    1439           0 :     const SwCntntNode* pCntNd = rPam.GetCntntNode();
    1440           0 :     const SwLayoutFrm *pStart = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
    1441           0 :                                                         &aPt )->GetUpper();
    1442           0 :     pCntNd = rPam.GetCntntNode(false);
    1443           0 :     const SwLayoutFrm *pEnd = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
    1444           0 :                                                     &aPt )->GetUpper();
    1445           0 :     GetTblSel( pStart, pEnd, aBoxes, 0 );
    1446           0 :     return CheckMergeSel( aBoxes );
    1447             : }
    1448             : 
    1449           0 : sal_uInt16 CheckMergeSel( const SwSelBoxes& rBoxes )
    1450             : {
    1451           0 :     sal_uInt16 eRet = TBLMERGE_NOSELECTION;
    1452           0 :     if( !rBoxes.empty() )
    1453             :     {
    1454           0 :         eRet = TBLMERGE_OK;
    1455             : 
    1456           0 :         _FndBox aFndBox( 0, 0 );
    1457           0 :         _FndPara aPara( rBoxes, &aFndBox );
    1458           0 :         const SwTableNode* pTblNd = aPara.rBoxes[0]->GetSttNd()->FindTableNode();
    1459           0 :         ForEach_FndLineCopyCol( (SwTableLines&)pTblNd->GetTable().GetTabLines(), &aPara );
    1460           0 :         if( !aFndBox.GetLines().empty() )
    1461             :         {
    1462           0 :             bool bMergeSelOk = true;
    1463           0 :             _FndBox* pFndBox = &aFndBox;
    1464           0 :             _FndLine* pFndLine = 0;
    1465           0 :             while( pFndBox && 1 == pFndBox->GetLines().size() )
    1466             :             {
    1467           0 :                 pFndLine = &pFndBox->GetLines().front();
    1468           0 :                 if( 1 == pFndLine->GetBoxes().size() )
    1469           0 :                     pFndBox = &pFndLine->GetBoxes().front();
    1470             :                 else
    1471           0 :                     pFndBox = 0;
    1472             :             }
    1473           0 :             if( pFndBox )
    1474             :             {
    1475           0 :                 for (_FndLines::const_iterator it = pFndBox->GetLines().begin(),
    1476           0 :                         end = pFndBox->GetLines().end(); it != end; ++it)
    1477             :                 {
    1478           0 :                     lcl_CheckRow(*it, &bMergeSelOk);
    1479             :                 }
    1480             :             }
    1481           0 :             else if( pFndLine )
    1482             :             {
    1483           0 :                 for (_FndBoxes::const_iterator it = pFndLine->GetBoxes().begin(),
    1484           0 :                         end = pFndLine->GetBoxes().end(); it != end; ++it)
    1485             :                 {
    1486           0 :                     lcl_CheckCol(*it, &bMergeSelOk);
    1487             :                 }
    1488             :             }
    1489           0 :             if( !bMergeSelOk )
    1490           0 :                 eRet = TBLMERGE_TOOCOMPLEX;
    1491             :         }
    1492             :         else
    1493           0 :             eRet = TBLMERGE_NOSELECTION;
    1494             :     }
    1495           0 :     return eRet;
    1496             : }
    1497             : 
    1498           0 : static SwTwips lcl_CalcWish( const SwLayoutFrm *pCell, long nWish,
    1499             :                                                 const long nAct )
    1500             : {
    1501           0 :     const SwLayoutFrm *pTmp = pCell;
    1502           0 :     if ( !nWish )
    1503           0 :         nWish = 1;
    1504             : 
    1505           0 :     const sal_Bool bRTL = pCell->IsRightToLeft();
    1506             :     SwTwips nRet = bRTL ?
    1507           0 :         nAct - pCell->Frm().Width() :
    1508           0 :         0;
    1509             : 
    1510           0 :     while ( pTmp )
    1511             :     {
    1512           0 :         while ( pTmp->GetPrev() )
    1513             :         {
    1514           0 :             pTmp = (SwLayoutFrm*)pTmp->GetPrev();
    1515           0 :             long nTmp = pTmp->GetFmt()->GetFrmSize().GetWidth();
    1516           0 :             nRet += ( bRTL ? ( -1 ) : 1 ) * nTmp * nAct / nWish;
    1517             :         }
    1518           0 :         pTmp = pTmp->GetUpper()->GetUpper();
    1519           0 :         if ( pTmp && !pTmp->IsCellFrm() )
    1520           0 :             pTmp = 0;
    1521             :     }
    1522           0 :     return nRet;
    1523             : }
    1524             : 
    1525           0 : static void lcl_FindStartEndRow( const SwLayoutFrm *&rpStart,
    1526             :                              const SwLayoutFrm *&rpEnd,
    1527             :                              const int bChkProtected )
    1528             : {
    1529             :     // Put Start at beginning of a row.
    1530             :     // Put End at the end of its row.
    1531           0 :     rpStart = (SwLayoutFrm*)rpStart->GetUpper()->Lower();
    1532           0 :     while ( rpEnd->GetNext() )
    1533           0 :         rpEnd = (SwLayoutFrm*)rpEnd->GetNext();
    1534             : 
    1535           0 :     std::deque<const SwLayoutFrm *> aSttArr, aEndArr;
    1536             :     const SwLayoutFrm *pTmp;
    1537           0 :     for( pTmp = rpStart; (FRM_CELL|FRM_ROW) & pTmp->GetType();
    1538           0 :                 pTmp = pTmp->GetUpper() )
    1539             :     {
    1540           0 :         aSttArr.push_front( pTmp );
    1541             :     }
    1542           0 :     for( pTmp = rpEnd; (FRM_CELL|FRM_ROW) & pTmp->GetType();
    1543           0 :                 pTmp = pTmp->GetUpper() )
    1544             :     {
    1545           0 :         aEndArr.push_front( pTmp );
    1546             :     }
    1547             : 
    1548           0 :     for( sal_uInt16 n = 0; n < aEndArr.size() && n < aSttArr.size(); ++n )
    1549           0 :         if( aSttArr[ n ] != aEndArr[ n ] )
    1550             :         {
    1551             :             // first unequal line or box - all odds are
    1552           0 :             if( n & 1 )                 // 1, 3, 5, ... are boxes
    1553             :             {
    1554           0 :                 rpStart = aSttArr[ n ];
    1555           0 :                 rpEnd = aEndArr[ n ];
    1556             :             }
    1557             :             else                                // 0, 2, 4, ... are lines
    1558             :             {
    1559             :                 // check if start & end line are the first & last Line of the
    1560             :                 // box. If not return these cells.
    1561             :                 // Else the hole line with all Boxes has to be deleted.
    1562           0 :                 rpStart = aSttArr[ n+1 ];
    1563           0 :                 rpEnd = aEndArr[ n+1 ];
    1564           0 :                 if( n )
    1565             :                 {
    1566           0 :                     const SwCellFrm* pCellFrm = (SwCellFrm*)aSttArr[ n-1 ];
    1567             :                     const SwTableLines& rLns = pCellFrm->
    1568           0 :                                                 GetTabBox()->GetTabLines();
    1569           0 :                     if( rLns[ 0 ] == ((SwRowFrm*)aSttArr[ n ])->GetTabLine() &&
    1570           0 :                         rLns[ rLns.size() - 1 ] ==
    1571           0 :                                     ((SwRowFrm*)aEndArr[ n ])->GetTabLine() )
    1572             :                     {
    1573           0 :                         rpStart = rpEnd = pCellFrm;
    1574           0 :                         while ( rpStart->GetPrev() )
    1575           0 :                             rpStart = (SwLayoutFrm*)rpStart->GetPrev();
    1576           0 :                         while ( rpEnd->GetNext() )
    1577           0 :                             rpEnd = (SwLayoutFrm*)rpEnd->GetNext();
    1578             :                     }
    1579             :                 }
    1580             :             }
    1581           0 :             break;
    1582             :         }
    1583             : 
    1584           0 :     if( !bChkProtected )    // protected cell ?
    1585           0 :         return;
    1586             : 
    1587             :     // Beginning and end should not be in protected cells
    1588           0 :     while ( rpStart->GetFmt()->GetProtect().IsCntntProtected() )
    1589           0 :         rpStart = (SwLayoutFrm*)rpStart->GetNext();
    1590           0 :     while ( rpEnd->GetFmt()->GetProtect().IsCntntProtected() )
    1591           0 :         rpEnd = (SwLayoutFrm*)rpEnd->GetPrev();
    1592             : }
    1593             : 
    1594           0 : static void lcl_FindStartEndCol( const SwLayoutFrm *&rpStart,
    1595             :                              const SwLayoutFrm *&rpEnd,
    1596             :                              const int bChkProtected )
    1597             : {
    1598             :     // Beginning and end vertical till the border of the table;
    1599             :     // Consider the whole table, including master and follows.
    1600             :     // In order to start we need the mother-tableFrm
    1601           0 :     if( !rpStart )
    1602           0 :         return;
    1603           0 :     const SwTabFrm *pOrg = rpStart->FindTabFrm();
    1604           0 :     const SwTabFrm *pTab = pOrg;
    1605             : 
    1606           0 :     SWRECTFN( pTab )
    1607             : 
    1608           0 :     sal_Bool bRTL = pTab->IsRightToLeft();
    1609           0 :     const long nTmpWish = pOrg->GetFmt()->GetFrmSize().GetWidth();
    1610           0 :     const long nWish = ( nTmpWish > 0 ) ? nTmpWish : 1;
    1611             : 
    1612           0 :     while ( pTab->IsFollow() )
    1613             :     {
    1614           0 :         const SwFrm *pTmp = pTab->FindPrev();
    1615             :         OSL_ENSURE( pTmp->IsTabFrm(), "Predecessor of Follow is not Master." );
    1616           0 :         pTab = (const SwTabFrm*)pTmp;
    1617             :     }
    1618             : 
    1619           0 :     SwTwips nSX  = 0;
    1620           0 :     SwTwips nSX2 = 0;
    1621             : 
    1622           0 :     if ( pTab->GetTable()->IsNewModel() )
    1623             :     {
    1624           0 :         nSX  = (rpStart->Frm().*fnRect->fnGetLeft )();
    1625           0 :         nSX2 = (rpStart->Frm().*fnRect->fnGetRight)();
    1626             :     }
    1627             :     else
    1628             :     {
    1629           0 :         const SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
    1630           0 :         nSX = ::lcl_CalcWish( rpStart, nWish, nPrtWidth ) + (pTab->*fnRect->fnGetPrtLeft)();
    1631           0 :         nSX2 = nSX + (rpStart->GetFmt()->GetFrmSize().GetWidth() * nPrtWidth / nWish);
    1632             :     }
    1633             : 
    1634           0 :     const SwLayoutFrm *pTmp = pTab->FirstCell();
    1635             : 
    1636           0 :     while ( pTmp &&
    1637           0 :             (!pTmp->IsCellFrm() ||
    1638           0 :              ( ( ! bRTL && (pTmp->Frm().*fnRect->fnGetLeft)() < nSX &&
    1639           0 :                            (pTmp->Frm().*fnRect->fnGetRight)()< nSX2 ) ||
    1640           0 :                (   bRTL && (pTmp->Frm().*fnRect->fnGetLeft)() > nSX &&
    1641           0 :                            (pTmp->Frm().*fnRect->fnGetRight)()> nSX2 ) ) ) )
    1642           0 :         pTmp = pTmp->GetNextLayoutLeaf();
    1643             : 
    1644           0 :     if ( pTmp )
    1645           0 :         rpStart = pTmp;
    1646             : 
    1647           0 :     pTab = pOrg;
    1648             : 
    1649           0 :     const SwTabFrm* pLastValidTab = pTab;
    1650           0 :     while ( pTab->GetFollow() )
    1651             :     {
    1652             : 
    1653             :         // Check if pTab->GetFollow() is a valid follow table:
    1654             :         // Only follow tables with at least on non-FollowFlowLine
    1655             :         // should be considered.
    1656             : 
    1657           0 :         if ( pTab->HasFollowFlowLine() )
    1658             :         {
    1659           0 :             pTab = pTab->GetFollow();
    1660           0 :             const SwFrm* pTmpRow = pTab->GetFirstNonHeadlineRow();
    1661           0 :             if ( pTmpRow && pTmpRow->GetNext() )
    1662           0 :                 pLastValidTab = pTab;
    1663             :         }
    1664             :         else
    1665           0 :             pLastValidTab = pTab = pTab->GetFollow();
    1666             :     }
    1667           0 :     pTab = pLastValidTab;
    1668             : 
    1669           0 :     SwTwips nEX = 0;
    1670             : 
    1671           0 :     if ( pTab->GetTable()->IsNewModel() )
    1672             :     {
    1673           0 :         nEX = (rpEnd->Frm().*fnRect->fnGetLeft )();
    1674             :     }
    1675             :     else
    1676             :     {
    1677           0 :         const SwTwips nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
    1678           0 :         nEX = ::lcl_CalcWish( rpEnd, nWish, nPrtWidth ) + (pTab->*fnRect->fnGetPrtLeft)();
    1679             :     }
    1680             : 
    1681           0 :     const SwCntntFrm* pLastCntnt = pTab->FindLastCntnt();
    1682           0 :     rpEnd = pLastCntnt ? pLastCntnt->GetUpper() : 0;
    1683             :     // --> Made code robust. If pTab does not have a lower,
    1684             :     // we would crash here.
    1685           0 :     if ( !pLastCntnt ) return;
    1686             : 
    1687           0 :     while( !rpEnd->IsCellFrm() )
    1688           0 :         rpEnd = rpEnd->GetUpper();
    1689             : 
    1690           0 :     while ( (   bRTL && (rpEnd->Frm().*fnRect->fnGetLeft)() < nEX ) ||
    1691           0 :             ( ! bRTL && (rpEnd->Frm().*fnRect->fnGetLeft)() > nEX ) )
    1692             :     {
    1693           0 :         const SwLayoutFrm* pTmpLeaf = rpEnd->GetPrevLayoutLeaf();
    1694           0 :         if( !pTmpLeaf || !pTab->IsAnLower( pTmpLeaf ) )
    1695           0 :             break;
    1696           0 :         rpEnd = pTmpLeaf;
    1697             :     }
    1698             : 
    1699           0 :     if( !bChkProtected )    // check for protected cell ?
    1700           0 :         return;
    1701             : 
    1702             :     // Beginning and end should not be in protected cells.
    1703             :     // If necessary we should search backwards again
    1704           0 :     while ( rpStart->GetFmt()->GetProtect().IsCntntProtected() )
    1705             :     {
    1706           0 :         const SwLayoutFrm *pTmpLeaf = rpStart;
    1707           0 :         pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
    1708           0 :         while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() > nEX ) // first skip line
    1709           0 :             pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
    1710           0 :         while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() < nSX &&
    1711           0 :                             (pTmpLeaf->Frm().*fnRect->fnGetRight)()< nSX2 )
    1712           0 :             pTmpLeaf = pTmpLeaf->GetNextLayoutLeaf();
    1713           0 :         const SwTabFrm *pTmpTab = rpStart->FindTabFrm();
    1714           0 :         if ( !pTmpTab->IsAnLower( pTmpLeaf ) )
    1715             :         {
    1716           0 :             pTmpTab = pTmpTab->GetFollow();
    1717           0 :             rpStart = pTmpTab->FirstCell();
    1718           0 :             while ( (rpStart->Frm().*fnRect->fnGetLeft)() < nSX &&
    1719           0 :                     (rpStart->Frm().*fnRect->fnGetRight)()< nSX2 )
    1720           0 :                 rpStart = rpStart->GetNextLayoutLeaf();
    1721             :         }
    1722             :         else
    1723           0 :             rpStart = pTmpLeaf;
    1724             :     }
    1725           0 :     while ( rpEnd->GetFmt()->GetProtect().IsCntntProtected() )
    1726             :     {
    1727           0 :         const SwLayoutFrm *pTmpLeaf = rpEnd;
    1728           0 :         pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
    1729           0 :         while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() < nEX )//erstmal die Zeile ueberspr.
    1730           0 :             pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
    1731           0 :         while ( pTmpLeaf && (pTmpLeaf->Frm().*fnRect->fnGetLeft)() > nEX )
    1732           0 :             pTmpLeaf = pTmpLeaf->GetPrevLayoutLeaf();
    1733           0 :         const SwTabFrm *pTmpTab = rpEnd->FindTabFrm();
    1734           0 :         if ( !pTmpLeaf || !pTmpTab->IsAnLower( pTmpLeaf ) )
    1735             :         {
    1736           0 :             pTmpTab = (const SwTabFrm*)pTmpTab->FindPrev();
    1737             :             OSL_ENSURE( pTmpTab->IsTabFrm(), "Predecessor of Follow not Master.");
    1738           0 :             rpEnd = pTmpTab->FindLastCntnt()->GetUpper();
    1739           0 :             while( !rpEnd->IsCellFrm() )
    1740           0 :                 rpEnd = rpEnd->GetUpper();
    1741           0 :             while ( (rpEnd->Frm().*fnRect->fnGetLeft)() > nEX )
    1742           0 :                 rpEnd = rpEnd->GetPrevLayoutLeaf();
    1743             :         }
    1744             :         else
    1745           0 :             rpEnd = pTmpLeaf;
    1746             :     }
    1747             : }
    1748             : 
    1749           0 : void MakeSelUnions( SwSelUnions& rUnions, const SwLayoutFrm *pStart,
    1750             :                     const SwLayoutFrm *pEnd, const SwTblSearchType eSearchType )
    1751             : {
    1752           0 :     while ( pStart && !pStart->IsCellFrm() )
    1753           0 :         pStart = pStart->GetUpper();
    1754           0 :     while ( pEnd && !pEnd->IsCellFrm() )
    1755           0 :         pEnd = pEnd->GetUpper();
    1756             : 
    1757           0 :     if ( !pStart || !pEnd )
    1758             :     {
    1759             :         OSL_FAIL( "MakeSelUnions with pStart or pEnd not in CellFrm" );
    1760           0 :         return;
    1761             :     }
    1762             : 
    1763           0 :     const SwTabFrm *pTable = pStart->FindTabFrm();
    1764           0 :     const SwTabFrm *pEndTable = pEnd->FindTabFrm();
    1765           0 :     if( !pTable || !pEndTable )
    1766           0 :         return;
    1767           0 :     bool bExchange = false;
    1768             : 
    1769           0 :     if ( pTable != pEndTable )
    1770             :     {
    1771           0 :         if ( !pTable->IsAnFollow( pEndTable ) )
    1772             :         {
    1773             :             OSL_ENSURE( pEndTable->IsAnFollow( pTable ), "Tabchain in knots." );
    1774           0 :             bExchange = true;
    1775             :         }
    1776             :     }
    1777             :     else
    1778             :     {
    1779           0 :         SWRECTFN( pTable )
    1780           0 :         long nSttTop = (pStart->Frm().*fnRect->fnGetTop)();
    1781           0 :         long nEndTop = (pEnd->Frm().*fnRect->fnGetTop)();
    1782           0 :         if( nSttTop == nEndTop )
    1783             :         {
    1784           0 :             if( (pStart->Frm().*fnRect->fnGetLeft)() >
    1785           0 :                 (pEnd->Frm().*fnRect->fnGetLeft)() )
    1786           0 :                 bExchange = true;
    1787             :         }
    1788           0 :         else if( bVert == ( nSttTop < nEndTop ) )
    1789           0 :             bExchange = true;
    1790             :     }
    1791           0 :     if ( bExchange )
    1792             :     {
    1793           0 :         const SwLayoutFrm *pTmp = pStart;
    1794           0 :         pStart = pEnd;
    1795           0 :         pEnd = pTmp;
    1796             :         // do no resort pTable and pEndTable, set new below
    1797             :         // MA: 28. Dec. 93 Bug: 5190
    1798             :     }
    1799             : 
    1800             :     // Beginning and end now nicely sorted, if required we
    1801             :     // should move them
    1802           0 :     if( nsSwTblSearchType::TBLSEARCH_ROW == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) )
    1803           0 :         ::lcl_FindStartEndRow( pStart, pEnd, nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType );
    1804           0 :     else if( nsSwTblSearchType::TBLSEARCH_COL == ((~nsSwTblSearchType::TBLSEARCH_PROTECT ) & eSearchType ) )
    1805           0 :         ::lcl_FindStartEndCol( pStart, pEnd, nsSwTblSearchType::TBLSEARCH_PROTECT & eSearchType );
    1806             : 
    1807           0 :     if ( !pEnd ) return; // Made code robust.
    1808             : 
    1809             :     // retrieve again, as they have been moved
    1810           0 :     pTable = pStart->FindTabFrm();
    1811           0 :     pEndTable = pEnd->FindTabFrm();
    1812             : 
    1813           0 :     const long nStSz = pStart->GetFmt()->GetFrmSize().GetWidth();
    1814           0 :     const long nEdSz = pEnd->GetFmt()->GetFrmSize().GetWidth();
    1815           0 :     const long nWish = std::max( 1L, pTable->GetFmt()->GetFrmSize().GetWidth() );
    1816           0 :     while ( pTable )
    1817             :     {
    1818           0 :         SWRECTFN( pTable )
    1819           0 :         const long nOfst = (pTable->*fnRect->fnGetPrtLeft)();
    1820           0 :         const long nPrtWidth = (pTable->Prt().*fnRect->fnGetWidth)();
    1821           0 :         long nSt1 = ::lcl_CalcWish( pStart, nWish, nPrtWidth ) + nOfst;
    1822           0 :         long nEd1 = ::lcl_CalcWish( pEnd,   nWish, nPrtWidth ) + nOfst;
    1823             : 
    1824           0 :         if ( nSt1 <= nEd1 )
    1825           0 :             nEd1 += (long)((nEdSz * nPrtWidth) / nWish) - 1;
    1826             :         else
    1827           0 :             nSt1 += (long)((nStSz * nPrtWidth) / nWish) - 1;
    1828             : 
    1829             :         long nSt2;
    1830             :         long nEd2;
    1831           0 :         if( pTable->IsAnLower( pStart ) )
    1832           0 :             nSt2 = (pStart->Frm().*fnRect->fnGetTop)();
    1833             :         else
    1834           0 :             nSt2 = (pTable->Frm().*fnRect->fnGetTop)();
    1835           0 :         if( pTable->IsAnLower( pEnd ) )
    1836           0 :             nEd2 = (pEnd->Frm().*fnRect->fnGetBottom)();
    1837             :         else
    1838           0 :             nEd2 = (pTable->Frm().*fnRect->fnGetBottom)();
    1839           0 :         Point aSt, aEd;
    1840           0 :         if( nSt1 > nEd1 )
    1841             :         {
    1842           0 :             long nTmp = nSt1;
    1843           0 :             nSt1 = nEd1;
    1844           0 :             nEd1 = nTmp;
    1845             :         }
    1846           0 :         if( nSt2 > nEd2 )
    1847             :         {
    1848           0 :             long nTmp = nSt2;
    1849           0 :             nSt2 = nEd2;
    1850           0 :             nEd2 = nTmp;
    1851             :         }
    1852           0 :         if( bVert )
    1853             :         {
    1854           0 :             aSt = Point( nSt2, nSt1 );
    1855           0 :             aEd = Point( nEd2, nEd1 );
    1856             :         }
    1857             :         else
    1858             :         {
    1859           0 :             aSt = Point( nSt1, nSt2 );
    1860           0 :             aEd = Point( nEd1, nEd2 );
    1861             :         }
    1862             : 
    1863           0 :         const Point aDiff( aEd - aSt );
    1864           0 :         SwRect aUnion( aSt, Size( aDiff.X(), aDiff.Y() ) );
    1865           0 :         aUnion.Justify();
    1866             : 
    1867           0 :         if( !(nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT & eSearchType ))
    1868             :         {
    1869             :             // Unfortunately the union contains rounding errors now, therefore
    1870             :             // erroneous results could occur during split/merge.
    1871             :             // To prevent these we will determine the first and last row
    1872             :             // within the union and use their values for a new union
    1873           0 :             const SwLayoutFrm* pRow = pTable->IsFollow() ?
    1874             :                                       pTable->GetFirstNonHeadlineRow() :
    1875           0 :                                       (const SwLayoutFrm*)pTable->Lower();
    1876             : 
    1877           0 :             while ( pRow && !pRow->Frm().IsOver( aUnion ) )
    1878           0 :                 pRow = (SwLayoutFrm*)pRow->GetNext();
    1879             : 
    1880             :             // #i31976#
    1881             :             // A follow flow row may contain emtpy cells. These are not
    1882             :             // considered by FirstCell(). Therefore we have to find
    1883             :             // the first cell manually:
    1884           0 :             const SwFrm* pTmpCell = 0;
    1885           0 :             if ( pTable->IsFollow() && pRow && pRow->IsInFollowFlowRow() )
    1886             :             {
    1887           0 :                 const SwFrm* pTmpRow = pRow;
    1888           0 :                 while ( pTmpRow && pTmpRow->IsRowFrm() )
    1889             :                 {
    1890           0 :                     pTmpCell = static_cast<const SwRowFrm*>(pTmpRow)->Lower();
    1891           0 :                     pTmpRow  = static_cast<const SwCellFrm*>(pTmpCell)->Lower();
    1892             :                 }
    1893             :                 OSL_ENSURE( !pTmpCell || pTmpCell->IsCellFrm(), "Lower of rowframe != cellframe?!" );
    1894             :             }
    1895             : 
    1896             :             const SwLayoutFrm* pFirst = pTmpCell ?
    1897             :                                         static_cast<const SwLayoutFrm*>(pTmpCell) :
    1898             :                                         pRow ?
    1899             :                                         pRow->FirstCell() :
    1900           0 :                                         0;
    1901             : 
    1902           0 :             while ( pFirst && !::IsFrmInTblSel( aUnion, pFirst ) )
    1903             :             {
    1904           0 :                 if ( pFirst->GetNext() )
    1905             :                 {
    1906           0 :                     pFirst = (const SwLayoutFrm*)pFirst->GetNext();
    1907           0 :                     if ( pFirst->Lower() && pFirst->Lower()->IsRowFrm() )
    1908           0 :                         pFirst = pFirst->FirstCell();
    1909             :                 }
    1910             :                 else
    1911           0 :                     pFirst = ::lcl_FindNextCellFrm( pFirst );
    1912             :             }
    1913           0 :             const SwLayoutFrm* pLast = 0;
    1914           0 :             const SwFrm* pLastCntnt = pTable->FindLastCntnt();
    1915           0 :             if ( pLastCntnt )
    1916           0 :                 pLast = ::lcl_FindCellFrm( pLastCntnt->GetUpper() );
    1917             : 
    1918           0 :             while ( pLast && !::IsFrmInTblSel( aUnion, pLast ) )
    1919           0 :                 pLast = ::lcl_FindCellFrm( pLast->GetPrevLayoutLeaf() );
    1920             : 
    1921           0 :             if ( pFirst && pLast ) //Robust
    1922             :             {
    1923           0 :                 aUnion = pFirst->Frm();
    1924           0 :                 aUnion.Union( pLast->Frm() );
    1925             :             }
    1926             :             else
    1927           0 :                 aUnion.Width( 0 );
    1928             :         }
    1929             : 
    1930           0 :         if( (aUnion.*fnRect->fnGetWidth)() )
    1931             :         {
    1932           0 :             SwSelUnion *pTmp = new SwSelUnion( aUnion, (SwTabFrm*)pTable );
    1933           0 :             rUnions.push_back( pTmp );
    1934             :         }
    1935             : 
    1936           0 :         pTable = pTable->GetFollow();
    1937           0 :         if ( pTable != pEndTable && pEndTable->IsAnFollow( pTable ) )
    1938           0 :             pTable = 0;
    1939             :     }
    1940             : }
    1941             : 
    1942           0 : sal_Bool CheckSplitCells( const SwCrsrShell& rShell, sal_uInt16 nDiv,
    1943             :                         const SwTblSearchType eSearchType )
    1944             : {
    1945           0 :     if( !rShell.IsTableMode() )
    1946           0 :         rShell.GetCrsr();
    1947             : 
    1948           0 :     return CheckSplitCells( *rShell.getShellCrsr(false), nDiv, eSearchType );
    1949             : }
    1950             : 
    1951           0 : sal_Bool CheckSplitCells( const SwCursor& rCrsr, sal_uInt16 nDiv,
    1952             :                         const SwTblSearchType eSearchType )
    1953             : {
    1954           0 :     if( 1 >= nDiv )
    1955           0 :         return sal_False;
    1956             : 
    1957           0 :     sal_uInt16 nMinValue = nDiv * MINLAY;
    1958             : 
    1959             :     // Get start and end cell
    1960           0 :     Point aPtPos, aMkPos;
    1961           0 :     const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr);
    1962           0 :     if( pShCrsr )
    1963             :     {
    1964           0 :         aPtPos = pShCrsr->GetPtPos();
    1965           0 :         aMkPos = pShCrsr->GetMkPos();
    1966             :     }
    1967             : 
    1968           0 :     const SwCntntNode* pCntNd = rCrsr.GetCntntNode();
    1969           0 :     const SwLayoutFrm *pStart = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
    1970           0 :                                                         &aPtPos )->GetUpper();
    1971           0 :     pCntNd = rCrsr.GetCntntNode(false);
    1972           0 :     const SwLayoutFrm *pEnd = pCntNd->getLayoutFrm( pCntNd->GetDoc()->GetCurrentLayout(),
    1973           0 :                                 &aMkPos )->GetUpper();
    1974             : 
    1975           0 :     SWRECTFN( pStart->GetUpper() )
    1976             : 
    1977             :     // First, compute tables and rectangles
    1978           0 :     SwSelUnions aUnions;
    1979             : 
    1980           0 :     ::MakeSelUnions( aUnions, pStart, pEnd, eSearchType );
    1981             : 
    1982             :     // now search boxes for each entry and emit
    1983           0 :     for ( sal_uInt16 i = 0; i < aUnions.size(); ++i )
    1984             :     {
    1985           0 :         SwSelUnion *pUnion = &aUnions[i];
    1986           0 :         const SwTabFrm *pTable = pUnion->GetTable();
    1987             : 
    1988             :         // Skip any repeated headlines in the follow:
    1989           0 :         const SwLayoutFrm* pRow = pTable->IsFollow() ?
    1990             :                                   pTable->GetFirstNonHeadlineRow() :
    1991           0 :                                   (const SwLayoutFrm*)pTable->Lower();
    1992             : 
    1993           0 :         while ( pRow )
    1994             :         {
    1995           0 :             if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
    1996             :             {
    1997           0 :                 const SwLayoutFrm *pCell = pRow->FirstCell();
    1998             : 
    1999           0 :                 while ( pCell && pRow->IsAnLower( pCell ) )
    2000             :                 {
    2001             :                     OSL_ENSURE( pCell->IsCellFrm(), "Frame without cell" );
    2002           0 :                     if( ::IsFrmInTblSel( pUnion->GetUnion(), pCell ) )
    2003             :                     {
    2004           0 :                         if( (pCell->Frm().*fnRect->fnGetWidth)() < nMinValue )
    2005           0 :                             return sal_False;
    2006             :                     }
    2007             : 
    2008           0 :                     if ( pCell->GetNext() )
    2009             :                     {
    2010           0 :                         pCell = (const SwLayoutFrm*)pCell->GetNext();
    2011           0 :                         if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
    2012           0 :                             pCell = pCell->FirstCell();
    2013             :                     }
    2014             :                     else
    2015           0 :                         pCell = ::lcl_FindNextCellFrm( pCell );
    2016             :                 }
    2017             :             }
    2018           0 :             pRow = (const SwLayoutFrm*)pRow->GetNext();
    2019             :         }
    2020             :     }
    2021           0 :     return sal_True;
    2022             : }
    2023             : 
    2024             : // These Classes copy the current table selections (rBoxes),
    2025             : // into a new structure, retaining the table structure
    2026             : // new: SS for targeted erasing/restoring of the layout
    2027             : 
    2028           0 : static void lcl_InsertRow( SwTableLine &rLine, SwLayoutFrm *pUpper, SwFrm *pSibling )
    2029             : {
    2030           0 :     SwRowFrm *pRow = new SwRowFrm( rLine, pUpper );
    2031           0 :     if ( pUpper->IsTabFrm() && ((SwTabFrm*)pUpper)->IsFollow() )
    2032             :     {
    2033           0 :         SwTabFrm* pTabFrm = (SwTabFrm*)pUpper;
    2034           0 :         pTabFrm->FindMaster()->InvalidatePos(); //can absorb the line
    2035             : 
    2036           0 :         if ( pSibling && pTabFrm->IsInHeadline( *pSibling ) )
    2037             :         {
    2038             :             // Skip any repeated headlines in the follow:
    2039           0 :             pSibling = pTabFrm->GetFirstNonHeadlineRow();
    2040             :         }
    2041             :     }
    2042           0 :     pRow->Paste( pUpper, pSibling );
    2043           0 :     pRow->RegistFlys();
    2044           0 : }
    2045             : 
    2046           0 : static void _FndBoxCopyCol( SwTableBox* pBox, _FndPara* pFndPara )
    2047             : {
    2048           0 :     _FndBox* pFndBox = new _FndBox( pBox, pFndPara->pFndLine );
    2049           0 :     if( pBox->GetTabLines().size() )
    2050             :     {
    2051           0 :         _FndPara aPara( *pFndPara, pFndBox );
    2052           0 :         ForEach_FndLineCopyCol( pFndBox->GetBox()->GetTabLines(), &aPara );
    2053           0 :         if( pFndBox->GetLines().empty() )
    2054             :         {
    2055           0 :             delete pFndBox;
    2056           0 :             return;
    2057             :         }
    2058             :     }
    2059             :     else
    2060             :     {
    2061           0 :         if( pFndPara->rBoxes.find( pBox ) == pFndPara->rBoxes.end())
    2062             :         {
    2063           0 :             delete pFndBox;
    2064           0 :             return;
    2065             :         }
    2066             :     }
    2067           0 :     pFndPara->pFndLine->GetBoxes().push_back( pFndBox );
    2068             : }
    2069             : 
    2070           0 : static void _FndLineCopyCol( SwTableLine* pLine, _FndPara* pFndPara )
    2071             : {
    2072           0 :     _FndLine* pFndLine = new _FndLine( pLine, pFndPara->pFndBox );
    2073           0 :     _FndPara aPara( *pFndPara, pFndLine );
    2074           0 :     for( SwTableBoxes::iterator it = pFndLine->GetLine()->GetTabBoxes().begin();
    2075           0 :              it != pFndLine->GetLine()->GetTabBoxes().end(); ++it)
    2076           0 :         _FndBoxCopyCol(*it, &aPara );
    2077           0 :     if( pFndLine->GetBoxes().size() )
    2078             :     {
    2079           0 :         pFndPara->pFndBox->GetLines().push_back( pFndLine );
    2080             :     }
    2081             :     else
    2082           0 :         delete pFndLine;
    2083           0 : }
    2084             : 
    2085           0 : void ForEach_FndLineCopyCol(SwTableLines& rLines, _FndPara* pFndPara )
    2086             : {
    2087           0 :     for( SwTableLines::iterator it = rLines.begin(); it != rLines.end(); ++it )
    2088           0 :         _FndLineCopyCol( *it, pFndPara );
    2089           0 : }
    2090             : 
    2091           0 : void _FndBox::SetTableLines( const SwSelBoxes &rBoxes, const SwTable &rTable )
    2092             : {
    2093             :     // Set pointers to lines before and after the area to process.
    2094             :     // If the first/last lines are contained in the area, then the pointers
    2095             :     // are 0. We first search for the positions of the first/last affected
    2096             :     // lines in array of the SwTable. In order to use 0 for 'no line'
    2097             :     // we adjust the positions by 1.
    2098             : 
    2099           0 :     sal_uInt16 nStPos = USHRT_MAX;
    2100           0 :     sal_uInt16 nEndPos= 0;
    2101             : 
    2102           0 :     for (size_t i = 0; i < rBoxes.size(); ++i)
    2103             :     {
    2104           0 :         SwTableLine *pLine = rBoxes[i]->GetUpper();
    2105           0 :         while ( pLine->GetUpper() )
    2106           0 :             pLine = pLine->GetUpper()->GetUpper();
    2107           0 :         const sal_uInt16 nPos = rTable.GetTabLines().GetPos(
    2108           0 :                     (const SwTableLine*&)pLine ) + 1;
    2109             : 
    2110             :         OSL_ENSURE( nPos != USHRT_MAX, "TableLine not found." );
    2111             : 
    2112           0 :         if( nStPos > nPos )
    2113           0 :             nStPos = nPos;
    2114             : 
    2115           0 :         if( nEndPos < nPos )
    2116           0 :             nEndPos = nPos;
    2117             :     }
    2118           0 :     if ( nStPos > 1 )
    2119           0 :         pLineBefore = rTable.GetTabLines()[nStPos - 2];
    2120           0 :     if ( nEndPos < rTable.GetTabLines().size() )
    2121           0 :         pLineBehind = rTable.GetTabLines()[nEndPos];
    2122           0 : }
    2123             : 
    2124           0 : void _FndBox::SetTableLines( const SwTable &rTable )
    2125             : {
    2126             :     // Set pointers to lines before and after the area to process.
    2127             :     // If the first/last lines are contained in the area, then the pointers
    2128             :     // are 0. The positions of the first/last affected lines in the array
    2129             :     // of the SwTable are in FndBox. In order to use 0 for 'no line'
    2130             :     // we adjust the positions by 1.
    2131             : 
    2132           0 :     if( GetLines().empty() )
    2133           0 :         return;
    2134             : 
    2135           0 :     SwTableLine* pTmpLine = GetLines().front().GetLine();
    2136           0 :     sal_uInt16 nPos = rTable.GetTabLines().GetPos( pTmpLine );
    2137             :     OSL_ENSURE( USHRT_MAX != nPos, "Line steht nicht in der Tabelle" );
    2138           0 :     if( nPos )
    2139           0 :         pLineBefore = rTable.GetTabLines()[ nPos - 1 ];
    2140             : 
    2141           0 :     pTmpLine = GetLines().back().GetLine();
    2142           0 :     nPos = rTable.GetTabLines().GetPos( pTmpLine );
    2143             :     OSL_ENSURE( USHRT_MAX != nPos, "Line steht nicht in der Tabelle" );
    2144           0 :     if( ++nPos < rTable.GetTabLines().size() )
    2145           0 :         pLineBehind = rTable.GetTabLines()[nPos];
    2146             : }
    2147             : 
    2148           0 : inline void UnsetFollow( SwFlowFrm *pTab )
    2149             : {
    2150           0 :     pTab->m_pPrecede = 0;
    2151           0 : }
    2152             : 
    2153             : //When bAccTableDispose is FALSE,the acc table should not be disposed.
    2154             : //void _FndBox::DelFrms( SwTable &rTable )
    2155           0 : void _FndBox::DelFrms( SwTable &rTable,sal_Bool bAccTableDispose )
    2156             : {
    2157             :     // All lines between pLineBefore and pLineBehind should be cut
    2158             :     // from the layout and erased.
    2159             :     // If this creates empty Follows we should destroy these.
    2160             :     // If a master is destroyed, the follow should become master.
    2161             :     // Always a TabFrm should remain.
    2162             : 
    2163           0 :     sal_uInt16 nStPos = 0;
    2164           0 :     sal_uInt16 nEndPos= rTable.GetTabLines().size() - 1;
    2165           0 :     if( rTable.IsNewModel() && pLineBefore )
    2166           0 :         rTable.CheckRowSpan( pLineBefore, true );
    2167           0 :     if ( pLineBefore )
    2168             :     {
    2169           0 :         nStPos = rTable.GetTabLines().GetPos(
    2170           0 :                         (const SwTableLine*&)pLineBefore );
    2171             :         OSL_ENSURE( nStPos != USHRT_MAX, "The fox stole the line!" );
    2172           0 :         ++nStPos;
    2173             :     }
    2174           0 :     if( rTable.IsNewModel() && pLineBehind )
    2175           0 :         rTable.CheckRowSpan( pLineBehind, false );
    2176           0 :     if ( pLineBehind )
    2177             :     {
    2178           0 :         nEndPos = rTable.GetTabLines().GetPos(
    2179           0 :                         (const SwTableLine*&)pLineBehind );
    2180             :         OSL_ENSURE( nEndPos != USHRT_MAX, "The fox stole the line!" );
    2181           0 :         --nEndPos;
    2182             :     }
    2183             : 
    2184           0 :     for ( sal_uInt16 i = nStPos; i <= nEndPos; ++i)
    2185             :     {
    2186           0 :         SwFrmFmt *pFmt = rTable.GetTabLines()[i]->GetFrmFmt();
    2187           0 :         SwIterator<SwRowFrm,SwFmt> aIter( *pFmt );
    2188           0 :         for ( SwRowFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
    2189             :         {
    2190           0 :                 if ( pFrm->GetTabLine() == rTable.GetTabLines()[i] )
    2191             :                 {
    2192           0 :                     bool bDel = true;
    2193           0 :                     SwTabFrm *pUp = !pFrm->GetPrev() && !pFrm->GetNext() ?
    2194           0 :                                             (SwTabFrm*)pFrm->GetUpper() : 0;
    2195           0 :                     if ( !pUp )
    2196             :                     {
    2197             :                         const sal_uInt16 nRepeat =
    2198           0 :                                 ((SwTabFrm*)pFrm->GetUpper())->GetTable()->GetRowsToRepeat();
    2199           0 :                         if ( nRepeat > 0 &&
    2200           0 :                              ((SwTabFrm*)pFrm->GetUpper())->IsFollow() )
    2201             :                         {
    2202           0 :                             if ( !pFrm->GetNext() )
    2203             :                             {
    2204             :                                 SwRowFrm* pFirstNonHeadline =
    2205           0 :                                     ((SwTabFrm*)pFrm->GetUpper())->GetFirstNonHeadlineRow();
    2206           0 :                                 if ( pFirstNonHeadline == pFrm )
    2207             :                                 {
    2208           0 :                                     pUp = (SwTabFrm*)pFrm->GetUpper();
    2209             :                                 }
    2210             :                             }
    2211             :                         }
    2212             :                     }
    2213           0 :                     if ( pUp )
    2214             :                     {
    2215           0 :                         SwTabFrm *pFollow = pUp->GetFollow();
    2216           0 :                         SwTabFrm *pPrev   = pUp->IsFollow() ? pUp : 0;
    2217           0 :                         if ( pPrev )
    2218             :                         {
    2219           0 :                             SwFrm *pTmp = pPrev->FindPrev();
    2220             :                             OSL_ENSURE( pTmp->IsTabFrm(),
    2221             :                                     "Predecessor of Follow is no Master.");
    2222           0 :                             pPrev = (SwTabFrm*)pTmp;
    2223             :                         }
    2224           0 :                         if ( pPrev )
    2225             :                         {
    2226           0 :                             pPrev->SetFollow( pFollow );
    2227             :                             // #i60340# Do not transfer the
    2228             :                             // flag from pUp to pPrev. pUp may still have the
    2229             :                             // flag set although there is not more follow flow
    2230             :                             // line associated with pUp.
    2231           0 :                             pPrev->SetFollowFlowLine( sal_False );
    2232             :                         }
    2233           0 :                         else if ( pFollow )
    2234           0 :                             ::UnsetFollow( pFollow );
    2235             : 
    2236             :                         // A TableFrm should always remain!
    2237           0 :                         if ( pPrev || pFollow )
    2238             :                         {
    2239             :                             // OD 26.08.2003 #i18103# - if table is in a section,
    2240             :                             // lock the section, to avoid its delete.
    2241             :                             {
    2242           0 :                                 SwSectionFrm* pSctFrm = pUp->FindSctFrm();
    2243           0 :                                 bool bOldSectLock = false;
    2244           0 :                                 if ( pSctFrm )
    2245             :                                 {
    2246           0 :                                     bOldSectLock = pSctFrm->IsColLocked();
    2247           0 :                                     pSctFrm->ColLock();
    2248             :                                 }
    2249           0 :                                 pUp->Cut();
    2250           0 :                                 if ( pSctFrm && !bOldSectLock )
    2251             :                                 {
    2252           0 :                                     pSctFrm->ColUnlock();
    2253             :                                 }
    2254             :                             }
    2255           0 :                             delete pUp;
    2256           0 :                             bDel = false; // Row goes to /dev/null.
    2257             :                         }
    2258             :                     }
    2259           0 :                     if ( bDel )
    2260             :                     {
    2261           0 :                         SwFrm* pTabFrm = pFrm->GetUpper();
    2262           0 :                         if ( pTabFrm->IsTabFrm() &&
    2263           0 :                             !pFrm->GetNext() &&
    2264           0 :                              ((SwTabFrm*)pTabFrm)->GetFollow() )
    2265             :                         {
    2266             :                             // We do not delete the follow flow line,
    2267             :                             // this will be done automatically in the
    2268             :                             // next turn.
    2269           0 :                             ((SwTabFrm*)pTabFrm)->SetFollowFlowLine( sal_False );
    2270             :                         }
    2271             :                         //Set acc table dispose state
    2272           0 :                         pFrm->SetAccTableDispose( bAccTableDispose );
    2273           0 :                         pFrm->Cut();
    2274             :                         //Set acc table dispose state to default value.
    2275           0 :                         pFrm->SetAccTableDispose( true );
    2276           0 :                         delete pFrm;
    2277             :                     }
    2278             :                 }
    2279             :         }
    2280           0 :     }
    2281           0 : }
    2282             : 
    2283           0 : static bool lcl_IsLineOfTblFrm( const SwTabFrm& rTable, const SwFrm& rChk )
    2284             : {
    2285           0 :     const SwTabFrm* pTblFrm = rChk.FindTabFrm();
    2286           0 :     if( pTblFrm->IsFollow() )
    2287           0 :         pTblFrm = pTblFrm->FindMaster( true );
    2288           0 :     return &rTable == pTblFrm;
    2289             : }
    2290             : 
    2291             : /*
    2292             :  * lcl_UpdateRepeatedHeadlines
    2293             :  */
    2294           0 : static void lcl_UpdateRepeatedHeadlines( SwTabFrm& rTabFrm, bool bCalcLowers )
    2295             : {
    2296             :     OSL_ENSURE( rTabFrm.IsFollow(), "lcl_UpdateRepeatedHeadlines called for non-follow tab" );
    2297             : 
    2298             :     // Delete remaining headlines:
    2299           0 :     SwRowFrm* pLower = 0;
    2300           0 :     while ( 0 != ( pLower = (SwRowFrm*)rTabFrm.Lower() ) && pLower->IsRepeatedHeadline() )
    2301             :     {
    2302           0 :         pLower->Cut();
    2303           0 :         delete pLower;
    2304             :     }
    2305             : 
    2306             :     // Insert fresh set of headlines:
    2307           0 :     pLower = (SwRowFrm*)rTabFrm.Lower();
    2308           0 :     SwTable& rTable = *rTabFrm.GetTable();
    2309           0 :     const sal_uInt16 nRepeat = rTable.GetRowsToRepeat();
    2310           0 :     for ( sal_uInt16 nIdx = 0; nIdx < nRepeat; ++nIdx )
    2311             :     {
    2312           0 :         SwRowFrm* pHeadline = new SwRowFrm( *rTable.GetTabLines()[ nIdx ], &rTabFrm );
    2313           0 :         pHeadline->SetRepeatedHeadline( true );
    2314           0 :         pHeadline->Paste( &rTabFrm, pLower );
    2315           0 :         pHeadline->RegistFlys();
    2316             :     }
    2317             : 
    2318           0 :     if ( bCalcLowers )
    2319           0 :         rTabFrm.SetCalcLowers();
    2320           0 : }
    2321             : 
    2322           0 : void _FndBox::MakeFrms( SwTable &rTable )
    2323             : {
    2324             :     // All lines between pLineBefore and pLineBehind should be re-generated in layout.
    2325             :     // And this for all instances of a table (for example in header/footer).
    2326           0 :     sal_uInt16 nStPos = 0;
    2327           0 :     sal_uInt16 nEndPos= rTable.GetTabLines().size() - 1;
    2328           0 :     if ( pLineBefore )
    2329             :     {
    2330           0 :         nStPos = rTable.GetTabLines().GetPos(
    2331           0 :                         (const SwTableLine*&)pLineBefore );
    2332             :         OSL_ENSURE( nStPos != USHRT_MAX, "Fox stole the line!" );
    2333           0 :         ++nStPos;
    2334             : 
    2335             :     }
    2336           0 :     if ( pLineBehind )
    2337             :     {
    2338           0 :         nEndPos = rTable.GetTabLines().GetPos(
    2339           0 :                         (const SwTableLine*&)pLineBehind );
    2340             :         OSL_ENSURE( nEndPos != USHRT_MAX, "Fox stole the line!" );
    2341           0 :         --nEndPos;
    2342             :     }
    2343             :     // now big insert operation for all tables.
    2344           0 :     SwIterator<SwTabFrm,SwFmt> aTabIter( *rTable.GetFrmFmt() );
    2345           0 :     for ( SwTabFrm *pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
    2346             :     {
    2347           0 :         if ( !pTable->IsFollow() )
    2348             :         {
    2349           0 :             SwRowFrm  *pSibling = 0;
    2350           0 :             SwFrm  *pUpperFrm  = 0;
    2351             :             int i;
    2352           0 :             for ( i = rTable.GetTabLines().size()-1;
    2353           0 :                     i >= 0 && !pSibling; --i )
    2354             :             {
    2355             :                 SwTableLine *pLine = pLineBehind ? pLineBehind :
    2356           0 :                                                     rTable.GetTabLines()[static_cast<sal_uInt16>(i)];
    2357           0 :                 SwIterator<SwRowFrm,SwFmt> aIter( *pLine->GetFrmFmt() );
    2358           0 :                 pSibling = aIter.First();
    2359           0 :                 while ( pSibling && (
    2360           0 :                             pSibling->GetTabLine() != pLine ||
    2361           0 :                             !lcl_IsLineOfTblFrm( *pTable, *pSibling ) ||
    2362           0 :                             pSibling->IsRepeatedHeadline() ||
    2363             :                             // #i53647# If !pLineBehind,
    2364             :                             // IsInSplitTableRow() should be checked.
    2365           0 :                             ( pLineBehind && pSibling->IsInFollowFlowRow() ) ||
    2366           0 :                             (!pLineBehind && pSibling->IsInSplitTableRow() ) ) )
    2367             :                 {
    2368           0 :                     pSibling = aIter.Next();
    2369             :                 }
    2370           0 :             }
    2371           0 :             if ( pSibling )
    2372             :             {
    2373           0 :                 pUpperFrm = pSibling->GetUpper();
    2374           0 :                 if ( !pLineBehind )
    2375           0 :                     pSibling = 0;
    2376             :             }
    2377             :             else
    2378             : // ???? or is this the last Follow of the table ????
    2379           0 :                 pUpperFrm = pTable;
    2380             : 
    2381           0 :             for ( i = nStPos; (sal_uInt16)i <= nEndPos; ++i )
    2382           0 :                 ::lcl_InsertRow( *rTable.GetTabLines()[static_cast<sal_uInt16>(i)],
    2383           0 :                                 (SwLayoutFrm*)pUpperFrm, pSibling );
    2384           0 :             if ( pUpperFrm->IsTabFrm() )
    2385           0 :                 ((SwTabFrm*)pUpperFrm)->SetCalcLowers();
    2386             :         }
    2387           0 :         else if ( rTable.GetRowsToRepeat() > 0 )
    2388             :         {
    2389             :             // Insert new headlines:
    2390           0 :             lcl_UpdateRepeatedHeadlines( *pTable, true );
    2391             :         }
    2392           0 :     }
    2393           0 : }
    2394             : 
    2395           0 : void _FndBox::MakeNewFrms( SwTable &rTable, const sal_uInt16 nNumber,
    2396             :                                             const sal_Bool bBehind )
    2397             : {
    2398             :     // Create Frms for newly inserted lines
    2399             :     // bBehind == sal_True:  before  pLineBehind
    2400             :     //         == sal_False: after   pLineBefore
    2401             :     const sal_uInt16 nBfPos = pLineBefore ?
    2402           0 :         rTable.GetTabLines().GetPos( (const SwTableLine*&)pLineBefore ) :
    2403           0 :         USHRT_MAX;
    2404             :     const sal_uInt16 nBhPos = pLineBehind ?
    2405           0 :         rTable.GetTabLines().GetPos( (const SwTableLine*&)pLineBehind ) :
    2406           0 :         USHRT_MAX;
    2407             : 
    2408             :     //nNumber: how often did we insert
    2409             :     //nCnt:    how many were inserted nNumber times
    2410             : 
    2411             :     const sal_uInt16 nCnt =
    2412           0 :         ((nBhPos != USHRT_MAX ? nBhPos : rTable.GetTabLines().size()) -
    2413           0 :          (nBfPos != USHRT_MAX ? nBfPos + 1 : 0)) / (nNumber + 1);
    2414             : 
    2415             :     // search the Master-TabFrm
    2416           0 :     SwIterator<SwTabFrm,SwFmt> aTabIter( *rTable.GetFrmFmt() );
    2417             :     SwTabFrm *pTable;
    2418           0 :     for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
    2419             :     {
    2420           0 :         if( !pTable->IsFollow() )
    2421             :         {
    2422           0 :             SwRowFrm* pSibling = 0;
    2423           0 :             SwLayoutFrm *pUpperFrm   = 0;
    2424           0 :             if ( bBehind )
    2425             :             {
    2426           0 :                 if ( pLineBehind )
    2427             :                 {
    2428           0 :                     SwIterator<SwRowFrm,SwFmt> aIter( *pLineBehind->GetFrmFmt() );
    2429           0 :                     pSibling = aIter.First();
    2430           0 :                     while ( pSibling && (
    2431             :                                 // only consider row frames associated with pLineBehind:
    2432           0 :                                 pSibling->GetTabLine() != pLineBehind ||
    2433             :                                 // only consider row frames that are in pTables Master-Follow chain:
    2434           0 :                                 !lcl_IsLineOfTblFrm( *pTable, *pSibling ) ||
    2435             :                                 // only consider row frames that are not repeated headlines:
    2436           0 :                                 pSibling->IsRepeatedHeadline() ||
    2437             :                                 // only consider row frames that are not follow flow rows
    2438           0 :                                 pSibling->IsInFollowFlowRow() ) )
    2439             :                     {
    2440           0 :                           pSibling = aIter.Next();
    2441           0 :                     }
    2442             :                 }
    2443           0 :                 if ( pSibling )
    2444           0 :                     pUpperFrm = pSibling->GetUpper();
    2445             :                 else
    2446             :                 {
    2447           0 :                     while( pTable->GetFollow() )
    2448           0 :                         pTable = pTable->GetFollow();
    2449           0 :                     pUpperFrm = pTable;
    2450             :                 }
    2451             :                 const sal_uInt16 nMax = nBhPos != USHRT_MAX ?
    2452           0 :                                     nBhPos : rTable.GetTabLines().size();
    2453             : 
    2454           0 :                 sal_uInt16 i = nBfPos != USHRT_MAX ? nBfPos + 1 + nCnt : nCnt;
    2455             : 
    2456           0 :                 for ( ; i < nMax; ++i )
    2457           0 :                     ::lcl_InsertRow( *rTable.GetTabLines()[i], pUpperFrm, pSibling );
    2458           0 :                 if ( pUpperFrm->IsTabFrm() )
    2459           0 :                     ((SwTabFrm*)pUpperFrm)->SetCalcLowers();
    2460             :             }
    2461             :             else // insert before
    2462             :             {
    2463             :                 sal_uInt16 i;
    2464             : 
    2465             :                 // We are looking for the frame that is behind the row frame
    2466             :                 // that should be inserted.
    2467           0 :                 for ( i = 0; !pSibling; ++i )
    2468             :                 {
    2469           0 :                     SwTableLine* pLine = pLineBefore ? pLineBefore : rTable.GetTabLines()[i];
    2470             : 
    2471           0 :                     SwIterator<SwRowFrm,SwFmt> aIter( *pLine->GetFrmFmt() );
    2472           0 :                     pSibling = aIter.First();
    2473             : 
    2474           0 :                     while ( pSibling && (
    2475             :                             // only consider row frames associated with pLineBefore:
    2476           0 :                             pSibling->GetTabLine() != pLine ||
    2477             :                             // only consider row frames that are in pTables Master-Follow chain:
    2478           0 :                             !lcl_IsLineOfTblFrm( *pTable, *pSibling ) ||
    2479             :                             // only consider row frames that are not repeated headlines:
    2480           0 :                             pSibling->IsRepeatedHeadline() ||
    2481             :                             // 1. case: pLineBefore == 0:
    2482             :                             // only consider row frames that are not follow flow rows
    2483             :                             // 2. case: pLineBefore != 0:
    2484             :                             // only consider row frames that are not split table rows
    2485             :                             // #i37476# If !pLineBefore,
    2486             :                             // check IsInFollowFlowRow instead of IsInSplitTableRow.
    2487           0 :                             ( ( !pLineBefore && pSibling->IsInFollowFlowRow() ) ||
    2488           0 :                               (  pLineBefore && pSibling->IsInSplitTableRow() ) ) ) )
    2489             :                     {
    2490           0 :                         pSibling = aIter.Next();
    2491             :                     }
    2492           0 :                 }
    2493             : 
    2494           0 :                 pUpperFrm = pSibling->GetUpper();
    2495           0 :                 if ( pLineBefore )
    2496           0 :                     pSibling = (SwRowFrm*) pSibling->GetNext();
    2497             : 
    2498             :                 sal_uInt16 nMax = nBhPos != USHRT_MAX ?
    2499             :                                     nBhPos - nCnt :
    2500           0 :                                     rTable.GetTabLines().size() - nCnt;
    2501             : 
    2502           0 :                 i = nBfPos != USHRT_MAX ? nBfPos + 1 : 0;
    2503           0 :                 for ( ; i < nMax; ++i )
    2504           0 :                     ::lcl_InsertRow( *rTable.GetTabLines()[i],
    2505           0 :                                 pUpperFrm, pSibling );
    2506           0 :                 if ( pUpperFrm->IsTabFrm() )
    2507           0 :                     ((SwTabFrm*)pUpperFrm)->SetCalcLowers();
    2508             :             }
    2509             :         }
    2510             :     }
    2511             : 
    2512             :     // If necessary headlines should be processed. In order to
    2513             :     // not to fragment good code, we interate once more.
    2514           0 :     const sal_uInt16 nRowsToRepeat = rTable.GetRowsToRepeat();
    2515           0 :     if ( nRowsToRepeat > 0 &&
    2516           0 :          ( ( !bBehind && ( nBfPos == USHRT_MAX || nBfPos + 1 < nRowsToRepeat ) ) ||
    2517           0 :            (  bBehind && ( ( nBfPos == USHRT_MAX && nRowsToRepeat > 1 ) || nBfPos + 2 < nRowsToRepeat ) ) ) )
    2518             :     {
    2519           0 :         for ( pTable = aTabIter.First(); pTable; pTable = aTabIter.Next() )
    2520             :         {
    2521           0 :             if ( pTable->Lower() )
    2522             :             {
    2523           0 :                 if ( pTable->IsFollow() )
    2524             :                 {
    2525           0 :                     lcl_UpdateRepeatedHeadlines( *pTable, true );
    2526             :                 }
    2527             : 
    2528             :                 OSL_ENSURE( ((SwRowFrm*)pTable->Lower())->GetTabLine() ==
    2529             :                         rTable.GetTabLines()[0], "MakeNewFrms: Table corruption!" );
    2530             :             }
    2531             :         }
    2532           0 :     }
    2533           0 : }
    2534             : 
    2535           0 : sal_Bool _FndBox::AreLinesToRestore( const SwTable &rTable ) const
    2536             : {
    2537             :     // Should we call MakeFrms here?
    2538             : 
    2539           0 :     if ( !pLineBefore && !pLineBehind && rTable.GetTabLines().size() )
    2540           0 :         return sal_True;
    2541             : 
    2542             :     sal_uInt16 nBfPos;
    2543           0 :     if(pLineBefore)
    2544             :     {
    2545           0 :         const SwTableLine* rLBefore = (const SwTableLine*)pLineBefore;
    2546           0 :         nBfPos = rTable.GetTabLines().GetPos( rLBefore );
    2547             :     }
    2548             :     else
    2549           0 :         nBfPos = USHRT_MAX;
    2550             : 
    2551             :     sal_uInt16 nBhPos;
    2552           0 :     if(pLineBehind)
    2553             :     {
    2554           0 :         const SwTableLine* rLBehind = (const SwTableLine*)pLineBehind;
    2555           0 :         nBhPos = rTable.GetTabLines().GetPos( rLBehind );
    2556             :     }
    2557             :     else
    2558           0 :         nBhPos = USHRT_MAX;
    2559             : 
    2560           0 :     if ( nBfPos == nBhPos ) // Should never occur.
    2561             :     {
    2562             :         OSL_FAIL( "Table, erase but not on any area !?!" );
    2563           0 :         return sal_False;
    2564             :     }
    2565             : 
    2566           0 :     if ( rTable.GetRowsToRepeat() > 0 )
    2567             :     {
    2568             :         // oops: should the repeated headline have been deleted??
    2569           0 :         SwIterator<SwTabFrm,SwFmt> aIter( *rTable.GetFrmFmt() );
    2570           0 :         for( SwTabFrm* pTable = aIter.First(); pTable; pTable = aIter.Next() )
    2571             :         {
    2572           0 :             if( pTable->IsFollow() )
    2573             :             {
    2574             :                 // Insert new headlines:
    2575           0 :                 lcl_UpdateRepeatedHeadlines( *pTable, false );
    2576             :             }
    2577           0 :         }
    2578             :     }
    2579             : 
    2580             :     // Some adjacent lines at the beginning of the table have been deleted:
    2581           0 :     if ( nBfPos == USHRT_MAX && nBhPos == 0 )
    2582           0 :         return sal_False;
    2583             : 
    2584             :     // Some adjacent lines at the end of the table have been deleted:
    2585           0 :     if ( nBhPos == USHRT_MAX && nBfPos == (rTable.GetTabLines().size() - 1) )
    2586           0 :         return sal_False;
    2587             : 
    2588             :     // Some adjacent lines in the middle of the table have been deleted:
    2589           0 :     if ( nBfPos != USHRT_MAX && nBhPos != USHRT_MAX && (nBfPos + 1) == nBhPos )
    2590           0 :         return sal_False;
    2591             : 
    2592             :     // The structure of the deleted lines is more complex due to split lines.
    2593             :     // A call of MakeFrms() is necessary.
    2594           0 :     return sal_True;
    2595             : }
    2596             : 
    2597             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10