Files
libreoffice/sw/source/core/doc/tblrwcl.cxx

4711 lines
169 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 23:08:29 +00:00
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:08:29 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
2000-09-18 23:08:29 +00:00
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
2000-09-18 23:08:29 +00:00
*
************************************************************************/
#include <com/sun/star/text/HoriOrientation.hpp>
#include <com/sun/star/chart2/XChartDocument.hpp>
2000-09-18 23:08:29 +00:00
#include <hintids.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/protitem.hxx>
#include <editeng/boxitem.hxx>
2001-07-05 09:34:53 +00:00
#include <tools/fract.hxx>
2000-09-18 23:08:29 +00:00
#include <fmtfsize.hxx>
#include <fmtornt.hxx>
#include <doc.hxx>
#include <cntfrm.hxx>
#include <tabfrm.hxx>
#include <frmtool.hxx>
#include <pam.hxx>
#include <swtable.hxx>
#include <ndtxt.hxx>
#include <tblsel.hxx>
#include <fldbas.hxx>
#include <swundo.hxx>
#include <rowfrm.hxx>
#include <ddefld.hxx>
#include <hints.hxx>
#include <UndoTable.hxx>
2000-09-18 23:08:29 +00:00
#include <cellatr.hxx>
#include <mvsave.hxx>
#include <swtblfmt.hxx>
#include <swddetbl.hxx>
#include <poolfmt.hxx>
#include <tblrwcl.hxx>
#include <unochart.hxx>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <switerator.hxx>
2000-09-18 23:08:29 +00:00
using namespace com::sun::star;
using namespace com::sun::star::uno;
2000-09-18 23:08:29 +00:00
#define COLFUZZY 20
#define ROWFUZZY 10
2000-09-18 23:08:29 +00:00
using namespace ::com::sun::star;
#ifdef DBG_UTIL
#define CHECK_TABLE(t) (t).CheckConsistency();
#else
#define CHECK_TABLE(t)
#endif
2000-09-18 23:08:29 +00:00
typedef SwTableLine* SwTableLinePtr;
SV_DECL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr, 16 )
2000-09-18 23:08:29 +00:00
SV_IMPL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr );
2012-02-15 13:19:06 +01:00
// In order to set the Frame Formats for the Boxes, it's enough to look
// up the current one in the array. If it's already there return the new one.
2000-09-18 23:08:29 +00:00
struct _CpyTabFrm
{
union {
2012-02-15 13:19:06 +01:00
SwTableBoxFmt *pFrmFmt; // for CopyCol
SwTwips nSize; // for DelCol
2000-09-18 23:08:29 +00:00
} Value;
SwTableBoxFmt *pNewFrmFmt;
_CpyTabFrm( SwTableBoxFmt* pAktFrmFmt ) : pNewFrmFmt( 0 )
{ Value.pFrmFmt = pAktFrmFmt; }
_CpyTabFrm& operator=( const _CpyTabFrm& );
sal_Bool operator==( const _CpyTabFrm& rCpyTabFrm ) const
{ return (sal_uLong)Value.nSize == (sal_uLong)rCpyTabFrm.Value.nSize; }
sal_Bool operator<( const _CpyTabFrm& rCpyTabFrm ) const
{ return (sal_uLong)Value.nSize < (sal_uLong)rCpyTabFrm.Value.nSize; }
2000-09-18 23:08:29 +00:00
};
struct CR_SetBoxWidth
{
SwSelBoxes aBoxes;
SwSortTableLines aLines;
std::vector<sal_uInt16> aLinesWidth;
2000-09-18 23:08:29 +00:00
SwShareBoxFmts aShareFmts;
SwTableNode* pTblNd;
SwUndoTblNdsChg* pUndo;
SwTwips nDiff, nSide, nMaxSize, nLowerDiff;
TblChgMode nMode;
sal_uInt16 nTblWidth, nRemainWidth, nBoxWidth;
sal_Bool bBigger, bLeft, bSplittBox, bAnyBoxFnd;
2000-09-18 23:08:29 +00:00
CR_SetBoxWidth( sal_uInt16 eType, SwTwips nDif, SwTwips nSid, SwTwips nTblW,
2000-09-18 23:08:29 +00:00
SwTwips nMax, SwTableNode* pTNd )
: pTblNd( pTNd ),
nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 ),
nTblWidth( (sal_uInt16)nTblW ), nRemainWidth( 0 ), nBoxWidth( 0 ),
bSplittBox( sal_False ), bAnyBoxFnd( sal_False )
2000-09-18 23:08:29 +00:00
{
bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff );
bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
2000-09-18 23:08:29 +00:00
nMode = pTblNd->GetTable().GetTblChgMode();
}
CR_SetBoxWidth( const CR_SetBoxWidth& rCpy )
: pTblNd( rCpy.pTblNd ),
pUndo( rCpy.pUndo ),
nDiff( rCpy.nDiff ), nSide( rCpy.nSide ),
nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ),
nMode( rCpy.nMode ), nTblWidth( rCpy.nTblWidth ),
nRemainWidth( rCpy.nRemainWidth ), nBoxWidth( rCpy.nBoxWidth ),
bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft ),
bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
2000-09-18 23:08:29 +00:00
{
aLines.Insert( &rCpy.aLines );
aLinesWidth = rCpy.aLinesWidth;
2000-09-18 23:08:29 +00:00
}
SwUndoTblNdsChg* CreateUndo( SwUndoId eUndoType )
2000-09-18 23:08:29 +00:00
{
return pUndo = new SwUndoTblNdsChg( eUndoType, aBoxes, *pTblNd );
2000-09-18 23:08:29 +00:00
}
void LoopClear()
{
nLowerDiff = 0; nRemainWidth = 0;
}
void AddBoxWidth( const SwTableBox& rBox, sal_uInt16 nWidth )
2000-09-18 23:08:29 +00:00
{
SwTableLinePtr p = (SwTableLine*)rBox.GetUpper();
sal_uInt16 nFndPos;
2000-09-18 23:08:29 +00:00
if( aLines.Insert( p, nFndPos ))
aLinesWidth.insert( aLinesWidth.begin()+nFndPos, nWidth );
2000-09-18 23:08:29 +00:00
else
aLinesWidth[ nFndPos ] = aLinesWidth[ nFndPos ] + nWidth;
2000-09-18 23:08:29 +00:00
}
sal_uInt16 GetBoxWidth( const SwTableLine& rLn ) const
2000-09-18 23:08:29 +00:00
{
SwTableLinePtr p = (SwTableLine*)&rLn;
sal_uInt16 nFndPos;
2000-09-18 23:08:29 +00:00
if( aLines.Seek_Entry( p, &nFndPos ) )
nFndPos = aLinesWidth[ nFndPos ];
else
nFndPos = 0;
return nFndPos;
}
};
sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck );
sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck );
sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck );
sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck );
sal_Bool lcl_DelSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck );
sal_Bool lcl_DelOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck );
typedef sal_Bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, sal_Bool );
2000-09-18 23:08:29 +00:00
#ifdef DBG_UTIL
2000-09-18 23:08:29 +00:00
void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize );
#define CHECKBOXWIDTH \
{ \
SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); \
for( sal_uInt16 nTmp = 0; nTmp < aLines.Count(); ++nTmp ) \
::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \
2000-09-18 23:08:29 +00:00
}
#define CHECKTABLELAYOUT \
{ \
for ( sal_uInt16 i = 0; i < GetTabLines().Count(); ++i ) \
{ \
SwFrmFmt* pFmt = GetTabLines()[i]->GetFrmFmt(); \
SwIterator<SwRowFrm,SwFmt> aIter( *pFmt ); \
for (SwRowFrm* pFrm=aIter.First(); pFrm; pFrm=aIter.Next())\
{ \
if ( pFrm->GetTabLine() == GetTabLines()[i] ) \
{ \
OSL_ENSURE( pFrm->GetUpper()->IsTabFrm(), \
"Table layout does not match table structure" ); \
} \
} \
} \
}
2000-09-18 23:08:29 +00:00
#else
#define CHECKBOXWIDTH
#define CHECKTABLELAYOUT
2000-09-18 23:08:29 +00:00
#endif // DBG_UTIL
2000-09-18 23:08:29 +00:00
struct CR_SetLineHeight
{
SwSelBoxes aBoxes;
SwShareBoxFmts aShareFmts;
SwTableNode* pTblNd;
SwUndoTblNdsChg* pUndo;
SwTwips nMaxSpace, nMaxHeight;
TblChgMode nMode;
sal_uInt16 nLines;
sal_Bool bBigger, bTop, bSplittBox, bAnyBoxFnd;
2000-09-18 23:08:29 +00:00
CR_SetLineHeight( sal_uInt16 eType, SwTableNode* pTNd )
: pTblNd( pTNd ), pUndo( 0 ),
nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ),
bSplittBox( sal_False ), bAnyBoxFnd( sal_False )
2000-09-18 23:08:29 +00:00
{
bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff );
bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER );
if( eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL )
2000-09-18 23:08:29 +00:00
bBigger = !bBigger;
nMode = pTblNd->GetTable().GetTblChgMode();
}
CR_SetLineHeight( const CR_SetLineHeight& rCpy )
: pTblNd( rCpy.pTblNd ), pUndo( rCpy.pUndo ),
nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ),
nMode( rCpy.nMode ), nLines( rCpy.nLines ),
2000-09-18 23:08:29 +00:00
bBigger( rCpy.bBigger ), bTop( rCpy.bTop ),
bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd )
2000-09-18 23:08:29 +00:00
{}
SwUndoTblNdsChg* CreateUndo( SwUndoId nUndoType )
2000-09-18 23:08:29 +00:00
{
return pUndo = new SwUndoTblNdsChg( nUndoType, aBoxes, *pTblNd );
}
};
sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
SwTwips nDist, sal_Bool bCheck );
sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
SwTwips nDist, sal_Bool bCheck );
sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
SwTwips nDist, sal_Bool bCheck );
2000-09-18 23:08:29 +00:00
typedef sal_Bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, sal_Bool );
2000-09-18 23:08:29 +00:00
_CpyTabFrm& _CpyTabFrm::operator=( const _CpyTabFrm& rCpyTabFrm )
{
pNewFrmFmt = rCpyTabFrm.pNewFrmFmt;
Value = rCpyTabFrm.Value;
return *this;
}
SV_DECL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm, 0 )
2000-09-18 23:08:29 +00:00
SV_IMPL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm )
void lcl_DelCpyTabFrmFmts( _CpyTabFrm& rArr );
struct _CpyPara
{
boost::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths;
2000-09-18 23:08:29 +00:00
SwDoc* pDoc;
SwTableNode* pTblNd;
_CpyTabFrms& rTabFrmArr;
SwTableLine* pInsLine;
SwTableBox* pInsBox;
2012-02-15 13:19:06 +01:00
sal_uLong nOldSize, nNewSize; // in order to correct the size attributes
sal_uLong nMinLeft, nMaxRight;
sal_uInt16 nCpyCnt, nInsPos;
sal_uInt16 nLnIdx, nBoxIdx;
sal_uInt8 nDelBorderFlag;
sal_Bool bCpyCntnt;
_CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, _CpyTabFrms& rFrmArr,
sal_Bool bCopyContent = sal_True )
: pDoc( pNd->GetDoc() ), pTblNd( pNd ), rTabFrmArr(rFrmArr),
pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0),
nMinLeft(ULONG_MAX), nMaxRight(0),
nCpyCnt(nCopies), nInsPos(0),
nLnIdx(0), nBoxIdx(0),
nDelBorderFlag(0), bCpyCntnt( bCopyContent )
2000-09-18 23:08:29 +00:00
{}
_CpyPara( const _CpyPara& rPara, SwTableLine* pLine )
: pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
2000-09-18 23:08:29 +00:00
rTabFrmArr(rPara.rTabFrmArr), pInsLine(pLine), pInsBox(rPara.pInsBox),
nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ),
nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0),
nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ),
nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
2000-09-18 23:08:29 +00:00
{}
_CpyPara( const _CpyPara& rPara, SwTableBox* pBox )
: pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd),
2000-09-18 23:08:29 +00:00
rTabFrmArr(rPara.rTabFrmArr), pInsLine(rPara.pInsLine), pInsBox(pBox),
nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize),
nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ),
nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx),
nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt )
2000-09-18 23:08:29 +00:00
{}
void SetBoxWidth( SwTableBox* pBox );
};
static void lcl_CopyRow(_FndLine & rFndLine, _CpyPara *const pCpyPara);
static void lcl_CopyCol( _FndBox & rFndBox, _CpyPara *const pCpyPara)
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Look up the Frame Format in the Frame Format Array
SwTableBox* pBox = rFndBox.GetBox();
2000-09-18 23:08:29 +00:00
_CpyTabFrm aFindFrm( (SwTableBoxFmt*)pBox->GetFrmFmt() );
sal_uInt16 nFndPos;
2000-09-18 23:08:29 +00:00
if( pCpyPara->nCpyCnt )
{
if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
{
2012-02-15 13:19:06 +01:00
// For nested copying, also save the new Format as an old one.
2000-09-18 23:08:29 +00:00
SwTableBoxFmt* pNewFmt = (SwTableBoxFmt*)pBox->ClaimFrmFmt();
2012-02-15 13:19:06 +01:00
// Find the selected Boxes in the Line:
_FndLine const* pCmpLine = NULL;
2000-09-18 23:08:29 +00:00
SwFmtFrmSize aFrmSz( pNewFmt->GetFrmSize() );
CWS-TOOLING: integrate CWS bjm02 2009-08-12 Bjoern Michaelsen #i101879# moved officeversion from envelope body to requestbody 2009-08-11 Bjoern Michaelsen #i103732# reverting changeset f3f527950572 2009-08-10 Bjoern Michaelsen cws bjm02: merging local minibranches 2009-08-10 Bjoern Michaelsen #i104128# remove additional duplication in svx headers, remove license header merge conflicts in svx headers 2009-08-10 Bjoern Michaelsen #i100484# fixed buildbreaker on win32 2009-08-10 Bjoern Michaelsen #i104128# remove duplication in svx headers 2009-08-04 Bjoern Michaelsen #i103913# fixed bookmark updating when moving numbered para 2009-08-03 Bjoern Michaelsen #i101879# include officeversion/productname in soaprequest 2009-07-31 Bjoern Michaelsen #i84926# Selecting all in blockmode automatically falls back to std mode 2009-07-31 Bjoern Michaelsen #i100484# operation on 'pCmpLine' may be undefined, thanks cmc 2009-07-29 Bjoern Michaelsen #i103059# fixing crash on empty enumeration 2009-07-29 Bjoern Michaelsen #i98659# fixing typo in usagetracking option tabpage 2009-07-29 Bjoern Michaelsen #i103732# not triggering loading of oooimprovement dll if usage tracking is disabled 2009-07-29 Bjoern Michaelsen #i103036# stlunosequence can be use simple array-pointers as iterators, fixing used type in xmloff 2009-07-29 Bjoern Michaelsen #i103036# stlunosequence can be use simple array-pointers as iterators 2009-07-29 Bjoern Michaelsen #i103182# completely removing unused functions in extensions/oooimprovement 2009-07-28 Bjoern Michaelsen cws bjm02: merged changes from master up to milestone DEV300_m53 2009-06-29 Bjoern Michaelsen #i103182# commenting out getFailedAttempts(..) for future use 2009-06-29 Bjoern Michaelsen #i103183# removed unused function sw::mark::CrossRefBookmark::IsLegalName(..) 2009-06-29 Bjoern Michaelsen #i103182# removing unused functions in extensions/oooimprovement 2009-06-24 Bjoern Michaelsen #i103059# not using enumeration for getByName/getByIndex 2009-06-24 Bjoern Michaelsen #i103059# not using enumeration for hasByName/GetCount/hasElements for performance reasons 2009-06-24 Bjoern Michaelsen #i103036# stlunosequence can be use simple array-pointers as iterators 2009-08-27 releng CWS-TOOLING: integrate CWS hr65 2009-08-26 Jens-Heiner Rechtien #i104521#: implement 'setcurrent'; document --hg option to 'create' 2009-08-26 Jens-Heiner Rechtien #i104521#: SOAP method setSCMName() doesn't return a value 2009-08-26 Jens-Heiner Rechtien #i104521#: implement [set|get]_scm() 2009-08-26 Jens-Heiner Rechtien #i104521#: implement --hg switch to 'cws create' 2009-08-27 vg CWS-TOOLING: integrate CWS hr64_DEV300 2009-07-21 13:24:57 +0200 hr r274189 : #i99576#: re-enable optimization for tabcont.cxx 2009-07-21 13:17:18 +0200 hr r274188 : #i99592: disable -xspace optimization for Solaris x86 and SunStudio 12, due to some mis-optimzation in sc and elsewhere. SunStudio 12 update 1 is OK, but needs a few unrelated changes which will be implemented in DEV300 code line 2009-08-27 releng CWS-TOOLING: integrate CWS sw32bf02 2009-08-25 15:52:04 +0200 hde r275366 : reactived testcases hit by issue 102752 2009-08-21 13:52:17 +0200 od r275245 : #i102921# delete files whose deletion has been forgotten in cws impress172 2009-08-21 11:20:47 +0200 od r275225 : CWS-TOOLING: rebase CWS sw32bf02 to trunk@275001 (milestone: DEV300:m55) 2009-08-20 16:21:30 +0200 od r275191 : #i92511# method <lcl_MoveAllLowerObjs(..)> - invalidation of cache for object rectangle inclusive spaces is needed. 2009-08-20 15:50:40 +0200 od r275188 : #i96726# method <SwPagePreView::DocSzChgd(..)> - trigger recalculation of page preview layout even if the count of pages is not changing 2009-08-20 12:37:32 +0200 od r275172 : #i100466# correction for showing and hiding redlines 2009-08-18 13:25:18 +0200 od r275100 : #i103817# method <XMLTextImportHelper::SetStyleAndAttrs(..) - assure that a heading applies the outline style, if no other list style is applied. 2009-08-18 13:21:38 +0200 od r275098 : #i103817# allow the outline style - list style for outline numbering - to be set directly at the paragraph 2009-08-17 14:13:02 +0200 od r275052 : #i103684# add missing documentation for new optional OutlineLevel attribute introduced in OOo 3.1 2009-08-17 14:00:25 +0200 od r275049 : #i100481# method <XMLTextFrameContext_Impl::CreateChildContext(..)># - correct condition for handling embedded documents and embedded math objects 2009-08-12 14:11:34 +0200 od r274891 : #i97379# assure that columns are not applied to fly frames, which represent graphics or embedded objects 2009-08-12 12:51:43 +0200 od r274889 : #i101870# method <SwTxtNode::_MakeNewTxtNode(..)> - perform action on different paragraph styles before applying new paragraph style 2009-08-12 12:24:44 +0200 od r274888 : #i101092# method <ViewShell::Paint(..)> - encapsulate paint of document background and document into pre and post drawing layer paint calls 2009-08-12 11:38:48 +0200 od r274886 : #i98766# minor adjustment in order to be warning free under Mac port builds 2009-08-12 11:33:54 +0200 od r274885 : #i99267# method <SwTabFrm::MakeAll()> - reset <bSplit> after forward move to assure that follows can be joined, if further space is available. 2009-08-12 11:11:49 +0200 od r274882 : #i98766# method <ViewShell::SmoothScroll(..) - disable smooth scroll for Mac port builds 2009-08-10 12:17:58 +0200 od r274801 : CWS-TOOLING: rebase CWS sw32bf02 to trunk@274622 (milestone: DEV300:m54) 2009-07-21 16:56:45 +0200 od r274206 : #i103685# method <SwTxtFormatter::NewTabPortion(..)> - adjust condition to apply automatic tab stop at left margin correctly in case that tab stops are not relative to indent 2009-07-10 11:53:53 +0200 od r273883 : #i102752 method <SwDrawContact::Modify(..)> - assure that a ShapePropertyChangeNotifier exists 2009-07-07 12:01:58 +0200 mst r273788 : #i103304# apply patch by dtardon to fix bogus conditional 2009-07-07 09:01:13 +0200 od r273767 : CWS-TOOLING: rebase CWS sw32bf02 to trunk@273468 (milestone: DEV300:m51) 2009-08-27 vg CWS-TOOLING: integrate CWS native264_DEV300 2009-08-13 11:58:58 +0200 is r274928 : #i104200# update to jre6u16 2009-08-27 vg CWS-TOOLING: integrate CWS automationdev300m54tables 2009-08-14 13:01:05 +0200 wg r274976 : i104224 2009-08-14 13:00:28 +0200 wg r274975 : i104224 2009-08-14 12:12:34 +0200 wg r274974 : i104222 2009-08-13 14:28:13 +0200 wg r274944 : i104205 2009-08-13 14:27:40 +0200 wg r274943 : i104205 2009-08-13 14:26:36 +0200 wg r274942 : i104205
2009-08-27 15:54:55 +00:00
bool bDiffCount = false;
if( pBox->GetTabLines().Count() )
{
pCmpLine = &rFndBox.GetLines().front();
if ( pCmpLine->GetBoxes().size() != pCmpLine->GetLine()->GetTabBoxes().Count() )
CWS-TOOLING: integrate CWS bjm02 2009-08-12 Bjoern Michaelsen #i101879# moved officeversion from envelope body to requestbody 2009-08-11 Bjoern Michaelsen #i103732# reverting changeset f3f527950572 2009-08-10 Bjoern Michaelsen cws bjm02: merging local minibranches 2009-08-10 Bjoern Michaelsen #i104128# remove additional duplication in svx headers, remove license header merge conflicts in svx headers 2009-08-10 Bjoern Michaelsen #i100484# fixed buildbreaker on win32 2009-08-10 Bjoern Michaelsen #i104128# remove duplication in svx headers 2009-08-04 Bjoern Michaelsen #i103913# fixed bookmark updating when moving numbered para 2009-08-03 Bjoern Michaelsen #i101879# include officeversion/productname in soaprequest 2009-07-31 Bjoern Michaelsen #i84926# Selecting all in blockmode automatically falls back to std mode 2009-07-31 Bjoern Michaelsen #i100484# operation on 'pCmpLine' may be undefined, thanks cmc 2009-07-29 Bjoern Michaelsen #i103059# fixing crash on empty enumeration 2009-07-29 Bjoern Michaelsen #i98659# fixing typo in usagetracking option tabpage 2009-07-29 Bjoern Michaelsen #i103732# not triggering loading of oooimprovement dll if usage tracking is disabled 2009-07-29 Bjoern Michaelsen #i103036# stlunosequence can be use simple array-pointers as iterators, fixing used type in xmloff 2009-07-29 Bjoern Michaelsen #i103036# stlunosequence can be use simple array-pointers as iterators 2009-07-29 Bjoern Michaelsen #i103182# completely removing unused functions in extensions/oooimprovement 2009-07-28 Bjoern Michaelsen cws bjm02: merged changes from master up to milestone DEV300_m53 2009-06-29 Bjoern Michaelsen #i103182# commenting out getFailedAttempts(..) for future use 2009-06-29 Bjoern Michaelsen #i103183# removed unused function sw::mark::CrossRefBookmark::IsLegalName(..) 2009-06-29 Bjoern Michaelsen #i103182# removing unused functions in extensions/oooimprovement 2009-06-24 Bjoern Michaelsen #i103059# not using enumeration for getByName/getByIndex 2009-06-24 Bjoern Michaelsen #i103059# not using enumeration for hasByName/GetCount/hasElements for performance reasons 2009-06-24 Bjoern Michaelsen #i103036# stlunosequence can be use simple array-pointers as iterators 2009-08-27 releng CWS-TOOLING: integrate CWS hr65 2009-08-26 Jens-Heiner Rechtien #i104521#: implement 'setcurrent'; document --hg option to 'create' 2009-08-26 Jens-Heiner Rechtien #i104521#: SOAP method setSCMName() doesn't return a value 2009-08-26 Jens-Heiner Rechtien #i104521#: implement [set|get]_scm() 2009-08-26 Jens-Heiner Rechtien #i104521#: implement --hg switch to 'cws create' 2009-08-27 vg CWS-TOOLING: integrate CWS hr64_DEV300 2009-07-21 13:24:57 +0200 hr r274189 : #i99576#: re-enable optimization for tabcont.cxx 2009-07-21 13:17:18 +0200 hr r274188 : #i99592: disable -xspace optimization for Solaris x86 and SunStudio 12, due to some mis-optimzation in sc and elsewhere. SunStudio 12 update 1 is OK, but needs a few unrelated changes which will be implemented in DEV300 code line 2009-08-27 releng CWS-TOOLING: integrate CWS sw32bf02 2009-08-25 15:52:04 +0200 hde r275366 : reactived testcases hit by issue 102752 2009-08-21 13:52:17 +0200 od r275245 : #i102921# delete files whose deletion has been forgotten in cws impress172 2009-08-21 11:20:47 +0200 od r275225 : CWS-TOOLING: rebase CWS sw32bf02 to trunk@275001 (milestone: DEV300:m55) 2009-08-20 16:21:30 +0200 od r275191 : #i92511# method <lcl_MoveAllLowerObjs(..)> - invalidation of cache for object rectangle inclusive spaces is needed. 2009-08-20 15:50:40 +0200 od r275188 : #i96726# method <SwPagePreView::DocSzChgd(..)> - trigger recalculation of page preview layout even if the count of pages is not changing 2009-08-20 12:37:32 +0200 od r275172 : #i100466# correction for showing and hiding redlines 2009-08-18 13:25:18 +0200 od r275100 : #i103817# method <XMLTextImportHelper::SetStyleAndAttrs(..) - assure that a heading applies the outline style, if no other list style is applied. 2009-08-18 13:21:38 +0200 od r275098 : #i103817# allow the outline style - list style for outline numbering - to be set directly at the paragraph 2009-08-17 14:13:02 +0200 od r275052 : #i103684# add missing documentation for new optional OutlineLevel attribute introduced in OOo 3.1 2009-08-17 14:00:25 +0200 od r275049 : #i100481# method <XMLTextFrameContext_Impl::CreateChildContext(..)># - correct condition for handling embedded documents and embedded math objects 2009-08-12 14:11:34 +0200 od r274891 : #i97379# assure that columns are not applied to fly frames, which represent graphics or embedded objects 2009-08-12 12:51:43 +0200 od r274889 : #i101870# method <SwTxtNode::_MakeNewTxtNode(..)> - perform action on different paragraph styles before applying new paragraph style 2009-08-12 12:24:44 +0200 od r274888 : #i101092# method <ViewShell::Paint(..)> - encapsulate paint of document background and document into pre and post drawing layer paint calls 2009-08-12 11:38:48 +0200 od r274886 : #i98766# minor adjustment in order to be warning free under Mac port builds 2009-08-12 11:33:54 +0200 od r274885 : #i99267# method <SwTabFrm::MakeAll()> - reset <bSplit> after forward move to assure that follows can be joined, if further space is available. 2009-08-12 11:11:49 +0200 od r274882 : #i98766# method <ViewShell::SmoothScroll(..) - disable smooth scroll for Mac port builds 2009-08-10 12:17:58 +0200 od r274801 : CWS-TOOLING: rebase CWS sw32bf02 to trunk@274622 (milestone: DEV300:m54) 2009-07-21 16:56:45 +0200 od r274206 : #i103685# method <SwTxtFormatter::NewTabPortion(..)> - adjust condition to apply automatic tab stop at left margin correctly in case that tab stops are not relative to indent 2009-07-10 11:53:53 +0200 od r273883 : #i102752 method <SwDrawContact::Modify(..)> - assure that a ShapePropertyChangeNotifier exists 2009-07-07 12:01:58 +0200 mst r273788 : #i103304# apply patch by dtardon to fix bogus conditional 2009-07-07 09:01:13 +0200 od r273767 : CWS-TOOLING: rebase CWS sw32bf02 to trunk@273468 (milestone: DEV300:m51) 2009-08-27 vg CWS-TOOLING: integrate CWS native264_DEV300 2009-08-13 11:58:58 +0200 is r274928 : #i104200# update to jre6u16 2009-08-27 vg CWS-TOOLING: integrate CWS automationdev300m54tables 2009-08-14 13:01:05 +0200 wg r274976 : i104224 2009-08-14 13:00:28 +0200 wg r274975 : i104224 2009-08-14 12:12:34 +0200 wg r274974 : i104222 2009-08-13 14:28:13 +0200 wg r274944 : i104205 2009-08-13 14:27:40 +0200 wg r274943 : i104205 2009-08-13 14:26:36 +0200 wg r274942 : i104205
2009-08-27 15:54:55 +00:00
bDiffCount = true;
}
if( bDiffCount )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// The first Line should be enough
_FndBoxes const& rFndBoxes = pCmpLine->GetBoxes();
2000-09-18 23:08:29 +00:00
long nSz = 0;
for( sal_uInt16 n = rFndBoxes.size(); n; )
{
nSz += rFndBoxes[--n].GetBox()->
GetFrmFmt()->GetFrmSize().GetWidth();
}
2000-09-18 23:08:29 +00:00
aFrmSz.SetWidth( aFrmSz.GetWidth() -
nSz / ( pCpyPara->nCpyCnt + 1 ) );
pNewFmt->SetFmtAttr( aFrmSz );
2000-09-18 23:08:29 +00:00
aFrmSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) );
2012-02-15 13:19:06 +01:00
// Create a new Format for the new Box, specifying it's size.
2000-09-18 23:08:29 +00:00
aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pNewFmt->GetDoc()->
MakeTableLineFmt();
*aFindFrm.pNewFrmFmt = *pNewFmt;
aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
2000-09-18 23:08:29 +00:00
}
else
{
aFrmSz.SetWidth( aFrmSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) );
pNewFmt->SetFmtAttr( aFrmSz );
2000-09-18 23:08:29 +00:00
aFindFrm.pNewFrmFmt = pNewFmt;
pCpyPara->rTabFrmArr.Insert( aFindFrm );
aFindFrm.Value.pFrmFmt = pNewFmt;
pCpyPara->rTabFrmArr.Insert( aFindFrm );
}
}
else
{
aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
pBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
}
}
else
{
if( pCpyPara->nDelBorderFlag &&
pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
else
aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
}
if (!rFndBox.GetLines().empty())
2000-09-18 23:08:29 +00:00
{
pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
rFndBox.GetLines().size(), pCpyPara->pInsLine );
2000-09-18 23:08:29 +00:00
pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++);
_CpyPara aPara( *pCpyPara, pBox );
aPara.nDelBorderFlag &= 7;
BOOST_FOREACH( _FndLine & rFndLine, rFndBox.GetLines() )
lcl_CopyRow( rFndLine, &aPara );
2000-09-18 23:08:29 +00:00
}
else
{
::_InsTblBox( pCpyPara->pDoc, pCpyPara->pTblNd, pCpyPara->pInsLine,
aFindFrm.pNewFrmFmt, pBox, pCpyPara->nInsPos++ );
const _FndBoxes& rFndBxs = rFndBox.GetUpper()->GetBoxes();
2000-09-18 23:08:29 +00:00
if( 8 > pCpyPara->nDelBorderFlag
? pCpyPara->nDelBorderFlag
: &rFndBox == &rFndBxs[rFndBxs.size() - 1] )
2000-09-18 23:08:29 +00:00
{
const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
if( 8 > pCpyPara->nDelBorderFlag
? rBoxItem.GetTop()
: rBoxItem.GetRight() )
{
aFindFrm.Value.pFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
SvxBoxItem aNew( rBoxItem );
if( 8 > pCpyPara->nDelBorderFlag )
aNew.SetLine( 0, BOX_LINE_TOP );
else
aNew.SetLine( 0, BOX_LINE_RIGHT );
if( 1 == pCpyPara->nDelBorderFlag ||
8 == pCpyPara->nDelBorderFlag )
{
2012-02-15 13:19:06 +01:00
// For all Boxes that delete TopBorderLine, we copy after that
2000-09-18 23:08:29 +00:00
pBox = pCpyPara->pInsLine->GetTabBoxes()[
pCpyPara->nInsPos - 1 ];
}
aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
2012-02-15 13:19:06 +01:00
// Else we copy before that and the first Line keeps the TopLine
// and we remove it at the original
pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
2000-09-18 23:08:29 +00:00
if( !pCpyPara->nCpyCnt )
pCpyPara->rTabFrmArr.Insert( aFindFrm );
}
}
}
}
static void lcl_CopyRow(_FndLine& rFndLine, _CpyPara *const pCpyPara)
2000-09-18 23:08:29 +00:00
{
SwTableLine* pNewLine = new SwTableLine(
(SwTableLineFmt*)rFndLine.GetLine()->GetFrmFmt(),
rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
2000-09-18 23:08:29 +00:00
if( pCpyPara->pInsBox )
{
pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
}
else
{
pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
pCpyPara->nInsPos++ );
}
_CpyPara aPara( *pCpyPara, pNewLine );
for (_FndBoxes::iterator it = rFndLine.GetBoxes().begin();
it != rFndLine.GetBoxes().end(); ++it)
{
lcl_CopyCol(*it, &aPara);
}
2000-09-18 23:08:29 +00:00
pCpyPara->nDelBorderFlag &= 0xf8;
}
void lcl_InsCol( _FndLine* pFndLn, _CpyPara& rCpyPara, sal_uInt16 nCpyCnt,
sal_Bool bBehind )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Bug 29124: Not only copy in the BaseLines. If possible, we go down as far as possible
2000-09-18 23:08:29 +00:00
_FndBox* pFBox;
if( 1 == pFndLn->GetBoxes().size() &&
!( pFBox = &pFndLn->GetBoxes()[0] )->GetBox()->GetSttNd() )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// A Box with multiple Lines, so insert into these Lines
for( sal_uInt16 n = 0; n < pFBox->GetLines().size(); ++n )
lcl_InsCol( &pFBox->GetLines()[ n ], rCpyPara, nCpyCnt, bBehind );
2000-09-18 23:08:29 +00:00
}
else
{
rCpyPara.pInsLine = pFndLn->GetLine();
SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ?
pFndLn->GetBoxes().size()-1 : 0 ].GetBox();
2000-09-18 23:08:29 +00:00
rCpyPara.nInsPos = pFndLn->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
if( bBehind )
++rCpyPara.nInsPos;
for( sal_uInt16 n = 0; n < nCpyCnt; ++n )
2000-09-18 23:08:29 +00:00
{
if( n + 1 == nCpyCnt && bBehind )
rCpyPara.nDelBorderFlag = 9;
else
rCpyPara.nDelBorderFlag = 8;
for (_FndBoxes::iterator it = pFndLn->GetBoxes().begin();
it != pFndLn->GetBoxes().end(); ++it)
{
lcl_CopyCol(*it, &rCpyPara);
}
2000-09-18 23:08:29 +00:00
}
}
}
2002-11-15 08:31:09 +00:00
SwRowFrm* GetRowFrm( SwTableLine& rLine )
{
SwIterator<SwRowFrm,SwFmt> aIter( *rLine.GetFrmFmt() );
for( SwRowFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
if( pFrm->GetTabLine() == &rLine )
return pFrm;
2002-11-15 08:31:09 +00:00
return 0;
}
sal_Bool SwTable::InsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind )
2000-09-18 23:08:29 +00:00
{
OSL_ENSURE( rBoxes.Count() && nCnt, "No valid Box List" );
SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
2000-09-18 23:08:29 +00:00
if( !pTblNd )
return sal_False;
2000-09-18 23:08:29 +00:00
sal_Bool bRes = sal_True;
if( IsNewModel() )
bRes = NewInsertCol( pDoc, rBoxes, nCnt, bBehind );
else
{
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
_FndBox aFndBox( 0, 0 );
{
_FndPara aPara( rBoxes, &aFndBox );
GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
}
if( aFndBox.GetLines().empty() )
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find Lines for the layout update
aFndBox.SetTableLines( *this );
aFndBox.DelFrms( *this );
// TL_CHART2: nothing to be done since chart2 currently does not want to
// get notified about new rows/cols.
2000-09-18 23:08:29 +00:00
_CpyTabFrms aTabFrmArr;
_CpyPara aCpyPara( pTblNd, nCnt, aTabFrmArr );
2000-09-18 23:08:29 +00:00
for( sal_uInt16 n = 0; n < aFndBox.GetLines().size(); ++n )
lcl_InsCol( &aFndBox.GetLines()[ n ], aCpyPara, nCnt, bBehind );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// clean up this Line's structure once again, generally all of them
GCLines();
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Update Layout
aFndBox.MakeFrms( *this );
CHECKBOXWIDTH;
CHECKTABLELAYOUT;
bRes = sal_True;
}
SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
if (pPCD && nCnt)
pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
pDoc->UpdateCharts( GetFrmFmt()->GetName() );
return bRes;
2000-09-18 23:08:29 +00:00
}
sal_Bool SwTable::_InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
sal_uInt16 nCnt, sal_Bool bBehind )
2000-09-18 23:08:29 +00:00
{
OSL_ENSURE( pDoc && rBoxes.Count() && nCnt, "No valid Box List" );
SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
2000-09-18 23:08:29 +00:00
if( !pTblNd )
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
_FndBox aFndBox( 0, 0 );
{
_FndPara aPara( rBoxes, &aFndBox );
GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
}
if( aFndBox.GetLines().empty() )
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
2000-09-18 23:08:29 +00:00
_FndBox* pFndBox = &aFndBox;
{
_FndLine* pFndLine;
while( 1 == pFndBox->GetLines().size() &&
1 == ( pFndLine = &pFndBox->GetLines()[ 0 ])->GetBoxes().size() )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Don't go down too far! One Line with Box needs to remain!
_FndBox* pTmpBox = &pFndLine->GetBoxes().front();
if( !pTmpBox->GetLines().empty() )
2000-09-18 23:08:29 +00:00
pFndBox = pTmpBox;
else
break;
}
}
2012-02-15 13:19:06 +01:00
// Find Lines for the layout update
const sal_Bool bLayout = !IsNewModel() &&
0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() );
2000-09-18 23:08:29 +00:00
if ( bLayout )
{
aFndBox.SetTableLines( *this );
if( pFndBox != &aFndBox )
aFndBox.DelFrms( *this );
// TL_CHART2: nothing to be done since chart2 currently does not want to
// get notified about new rows/cols.
2000-09-18 23:08:29 +00:00
}
_CpyTabFrms aTabFrmArr;
_CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
SwTableLine* pLine = pFndBox->GetLines()[ bBehind ?
pFndBox->GetLines().size()-1 : 0 ].GetLine();
2000-09-18 23:08:29 +00:00
if( &aFndBox == pFndBox )
aCpyPara.nInsPos = GetTabLines().C40_GETPOS( SwTableLine, pLine );
else
{
aCpyPara.pInsBox = pFndBox->GetBox();
aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().C40_GETPOS( SwTableLine, pLine );
}
if( bBehind )
{
++aCpyPara.nInsPos;
aCpyPara.nDelBorderFlag = 1;
}
else
aCpyPara.nDelBorderFlag = 2;
for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
2000-09-18 23:08:29 +00:00
{
if( bBehind )
aCpyPara.nDelBorderFlag = 1;
BOOST_FOREACH( _FndLine& rFndLine, pFndBox->GetLines() )
lcl_CopyRow( rFndLine, &aCpyPara );
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// clean up this Line's structure once again, generally all of them
2000-09-18 23:08:29 +00:00
if( !pDoc->IsInReading() )
GCLines();
2012-02-15 13:19:06 +01:00
// Update Layout
2000-09-18 23:08:29 +00:00
if ( bLayout )
{
if( pFndBox != &aFndBox )
aFndBox.MakeFrms( *this );
else
aFndBox.MakeNewFrms( *this, nCnt, bBehind );
}
CHECKBOXWIDTH;
CHECKTABLELAYOUT;
SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
if (pPCD && nCnt)
pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind );
pDoc->UpdateCharts( GetFrmFmt()->GetName() );
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara );
sal_Bool _FndBoxAppendRowBox( const SwTableBox*& rpBox, void* pPara )
{
_FndPara* pFndPara = (_FndPara*)pPara;
_FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine );
if( rpBox->GetTabLines().Count() )
{
_FndPara aPara( *pFndPara, pFndBox );
pFndBox->GetBox()->GetTabLines().ForEach( &_FndBoxAppendRowLine, &aPara );
if( pFndBox->GetLines().empty() )
delete pFndBox;
}
else
pFndPara->pFndLine->GetBoxes().push_back( pFndBox );
return sal_True;
}
sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara )
{
_FndPara* pFndPara = (_FndPara*)pPara;
_FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox );
_FndPara aPara( *pFndPara, pFndLine );
pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxAppendRowBox, &aPara );
if( pFndLine->GetBoxes().size() )
{
pFndPara->pFndBox->GetLines().push_back( pFndLine );
}
else
delete pFndLine;
return sal_True;
}
sal_Bool SwTable::AppendRow( SwDoc* pDoc, sal_uInt16 nCnt )
2000-09-18 23:08:29 +00:00
{
SwTableNode* pTblNd = (SwTableNode*)aSortCntBoxes[0]->GetSttNd()->FindTableNode();
if( !pTblNd )
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
_FndBox aFndBox( 0, 0 );
{
const SwTableLine* pLLine = GetTabLines()[ GetTabLines().Count()-1 ];
2012-02-15 13:19:06 +01:00
const SwSelBoxes* pBxs = 0; // Dummy!!!
_FndPara aPara( *pBxs, &aFndBox );
_FndBoxAppendRowLine( pLLine, &aPara );
}
if( aFndBox.GetLines().empty() )
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find Lines for the Layout update
bool bLayout = 0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() );
2000-09-18 23:08:29 +00:00
if( bLayout )
{
aFndBox.SetTableLines( *this );
// TL_CHART2: nothing to be done since chart2 currently does not want to
// get notified about new rows/cols.
2000-09-18 23:08:29 +00:00
}
_CpyTabFrms aTabFrmArr;
_CpyPara aCpyPara( pTblNd, 0, aTabFrmArr );
aCpyPara.nInsPos = GetTabLines().Count();
aCpyPara.nDelBorderFlag = 1;
for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt )
2000-09-18 23:08:29 +00:00
{
aCpyPara.nDelBorderFlag = 1;
BOOST_FOREACH( _FndLine& rFndLine, aFndBox.GetLines() )
lcl_CopyRow( rFndLine, &aCpyPara );
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// Clean up this Line's structure once again, generally all of them
2000-09-18 23:08:29 +00:00
if( !pDoc->IsInReading() )
GCLines();
2012-02-15 13:19:06 +01:00
// Update Layout
2000-09-18 23:08:29 +00:00
if ( bLayout )
{
aFndBox.MakeNewFrms( *this, nCnt, sal_True );
2000-09-18 23:08:29 +00:00
}
// TL_CHART2: need to inform chart of probably changed cell names
pDoc->UpdateCharts( GetFrmFmt()->GetName() );
CHECKBOXWIDTH;
CHECKTABLELAYOUT;
return sal_True;
2000-09-18 23:08:29 +00:00
}
void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
sal_Bool bFirst, SwShareBoxFmts& rShareFmts );
2000-09-18 23:08:29 +00:00
void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const long nOffset,
sal_Bool bFirst, SwShareBoxFmts& rShareFmts )
2000-09-18 23:08:29 +00:00
{
for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
::lcl_LastBoxSetWidth( rLines[i]->GetTabBoxes(), nOffset, bFirst,
rShareFmts );
2000-09-18 23:08:29 +00:00
}
void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset,
sal_Bool bFirst, SwShareBoxFmts& rShareFmts )
2000-09-18 23:08:29 +00:00
{
SwTableBox& rBox = *rBoxes[ bFirst ? 0 : rBoxes.Count() - 1 ];
2000-09-18 23:08:29 +00:00
if( !rBox.GetSttNd() )
::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset,
bFirst, rShareFmts );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Adapt the Box
2011-11-23 13:12:43 +00:00
const SwFrmFmt *pBoxFmt = rBox.GetFrmFmt();
2000-09-18 23:08:29 +00:00
SwFmtFrmSize aNew( pBoxFmt->GetFrmSize() );
aNew.SetWidth( aNew.GetWidth() + nOffset );
SwFrmFmt *pFmt = rShareFmts.GetFormat( *pBoxFmt, aNew );
if( pFmt )
rBox.ChgFrmFmt( (SwTableBoxFmt*)pFmt );
else
{
pFmt = rBox.ClaimFrmFmt();
pFmt->LockModify();
pFmt->SetFmtAttr( aNew );
2000-09-18 23:08:29 +00:00
pFmt->UnlockModify();
rShareFmts.AddFormat( *pBoxFmt, *pFmt );
}
}
void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* pUndo,
sal_Bool bCalcNewSize, const sal_Bool bCorrBorder,
2000-09-18 23:08:29 +00:00
SwShareBoxFmts* pShareFmts )
{
do {
SwTwips nBoxSz = bCalcNewSize ?
pBox->GetFrmFmt()->GetFrmSize().GetWidth() : 0;
SwTableLine* pLine = pBox->GetUpper();
SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox );
2000-09-18 23:08:29 +00:00
SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper();
2012-02-15 13:19:06 +01:00
// Special treatment for the border:
2000-09-18 23:08:29 +00:00
if( bCorrBorder && 1 < rTblBoxes.Count() )
{
sal_Bool bChgd = sal_False;
2000-09-18 23:08:29 +00:00
const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
if( rBoxItem.GetLeft() || rBoxItem.GetRight() )
{
2012-02-15 13:19:06 +01:00
// JP 02.04.97: 1st part for Bug 36271
// First the left/right edges
2000-09-18 23:08:29 +00:00
if( nDelPos + 1 < rTblBoxes.Count() )
{
SwTableBox* pNxtBox = rTblBoxes[ nDelPos + 1 ];
const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
SwTableBox* pPrvBox = nDelPos ? rTblBoxes[ nDelPos - 1 ] : 0;
if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() &&
( !pPrvBox || !pPrvBox->GetFrmFmt()->GetBox().GetRight()) )
{
SvxBoxItem aTmp( rNxtBoxItem );
aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
: rBoxItem.GetRight(),
BOX_LINE_LEFT );
if( pShareFmts )
pShareFmts->SetAttr( *pNxtBox, aTmp );
else
pNxtBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
bChgd = sal_True;
2000-09-18 23:08:29 +00:00
}
}
if( !bChgd && nDelPos )
{
SwTableBox* pPrvBox = rTblBoxes[ nDelPos - 1 ];
const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
SwTableBox* pNxtBox = nDelPos + 1 < rTblBoxes.Count()
? rTblBoxes[ nDelPos + 1 ] : 0;
if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() &&
( !pNxtBox || !pNxtBox->GetFrmFmt()->GetBox().GetLeft()) )
{
SvxBoxItem aTmp( rPrvBoxItem );
aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft()
: rBoxItem.GetRight(),
BOX_LINE_RIGHT );
if( pShareFmts )
pShareFmts->SetAttr( *pPrvBox, aTmp );
else
pPrvBox->ClaimFrmFmt()->SetFmtAttr( aTmp );
2000-09-18 23:08:29 +00:00
}
}
}
}
2012-02-15 13:19:06 +01:00
// Delete the Box first, then the Nodes!
2000-09-18 23:08:29 +00:00
SwStartNode* pSttNd = (SwStartNode*)pBox->GetSttNd();
if( pShareFmts )
pShareFmts->RemoveFormat( *rTblBoxes[ nDelPos ]->GetFrmFmt() );
rTblBoxes.DeleteAndDestroy( nDelPos );
if( pSttNd )
{
2012-02-15 13:19:06 +01:00
// Has the UndoObject been prepared to save the Section?
if( pUndo && pUndo->IsDelBox() )
2000-09-18 23:08:29 +00:00
((SwUndoTblNdsChg*)pUndo)->SaveSection( pSttNd );
else
pSttNd->GetDoc()->DeleteSection( pSttNd );
}
2012-02-15 13:19:06 +01:00
// Also delete the Line?
2000-09-18 23:08:29 +00:00
if( rTblBoxes.Count() )
{
2012-02-15 13:19:06 +01:00
// Then adapt the Frame-SSize
sal_Bool bLastBox = nDelPos == rTblBoxes.Count();
if( bLastBox )
2000-09-18 23:08:29 +00:00
--nDelPos;
pBox = rTblBoxes[nDelPos];
if( bCalcNewSize )
{
SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
aNew.SetWidth( aNew.GetWidth() + nBoxSz );
if( pShareFmts )
pShareFmts->SetSize( *pBox, aNew );
else
pBox->ClaimFrmFmt()->SetFmtAttr( aNew );
2000-09-18 23:08:29 +00:00
if( !pBox->GetSttNd() )
{
2012-02-15 13:19:06 +01:00
// We need to this recursively in all Lines in all Cells!
2000-09-18 23:08:29 +00:00
SwShareBoxFmts aShareFmts;
::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz,
!bLastBox,
2000-09-18 23:08:29 +00:00
pShareFmts ? *pShareFmts
: aShareFmts );
}
}
2012-02-15 13:19:06 +01:00
break; // Stop deleting
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// Delete the Line from the Table/Box
2000-09-18 23:08:29 +00:00
if( !pUpperBox )
{
2012-02-15 13:19:06 +01:00
// Also delete the Line from the Table
2000-09-18 23:08:29 +00:00
nDelPos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine );
if( pShareFmts )
pShareFmts->RemoveFormat( *rTbl.GetTabLines()[ nDelPos ]->GetFrmFmt() );
rTbl.GetTabLines().DeleteAndDestroy( nDelPos );
2012-02-15 13:19:06 +01:00
break; // we cannot delete more
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// finally also delete the Line
2000-09-18 23:08:29 +00:00
pBox = pUpperBox;
nDelPos = pBox->GetTabLines().C40_GETPOS( SwTableLine, pLine );
if( pShareFmts )
pShareFmts->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrmFmt() );
pBox->GetTabLines().DeleteAndDestroy( nDelPos );
} while( !pBox->GetTabLines().Count() );
}
SwTableBox* lcl_FndNxtPrvDelBox( const SwTableLines& rTblLns,
SwTwips nBoxStt, SwTwips nBoxWidth,
sal_uInt16 nLinePos, sal_Bool bNxt,
SwSelBoxes* pAllDelBoxes, sal_uInt16* pCurPos )
2000-09-18 23:08:29 +00:00
{
SwTableBox* pFndBox = 0;
do {
if( bNxt )
++nLinePos;
else
--nLinePos;
SwTableLine* pLine = rTblLns[ nLinePos ];
SwTwips nFndBoxWidth = 0;
SwTwips nFndWidth = nBoxStt + nBoxWidth;
sal_uInt16 nBoxCnt = pLine->GetTabBoxes().Count();
2000-09-18 23:08:29 +00:00
pFndBox = pLine->GetTabBoxes()[ 0 ];
for( sal_uInt16 n = 0; 0 < nFndWidth && n < nBoxCnt; ++n )
2000-09-18 23:08:29 +00:00
{
pFndBox = pLine->GetTabBoxes()[ n ];
nFndWidth -= (nFndBoxWidth = pFndBox->GetFrmFmt()->
GetFrmSize().GetWidth());
}
2012-02-15 13:19:06 +01:00
// Find the first ContentBox
2000-09-18 23:08:29 +00:00
while( !pFndBox->GetSttNd() )
{
const SwTableLines& rLowLns = pFndBox->GetTabLines();
if( bNxt )
pFndBox = rLowLns[ 0 ]->GetTabBoxes()[ 0 ];
else
pFndBox = rLowLns[ rLowLns.Count() - 1 ]->GetTabBoxes()[ 0 ];
}
if( Abs( nFndWidth ) > COLFUZZY ||
Abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY )
pFndBox = 0;
else if( pAllDelBoxes )
{
2012-02-15 13:19:06 +01:00
// If the predecessor will also be deleted, there's nothing to do
sal_uInt16 nFndPos;
if( !pAllDelBoxes->Seek_Entry( pFndBox, &nFndPos ) )
2000-09-18 23:08:29 +00:00
break;
2012-02-15 13:19:06 +01:00
// else, we keep on searching.
// We do not need to recheck the Box, however
2011-11-23 13:12:43 +00:00
pFndBox = 0;
if( nFndPos <= *pCurPos )
--*pCurPos;
pAllDelBoxes->Remove( nFndPos );
2000-09-18 23:08:29 +00:00
}
} while( bNxt ? ( nLinePos + 1 < rTblLns.Count() ) : nLinePos );
return pFndBox;
}
void lcl_SaveUpperLowerBorder( SwTable& rTbl, const SwTableBox& rBox,
SwShareBoxFmts& rShareFmts,
SwSelBoxes* pAllDelBoxes = 0,
sal_uInt16* pCurPos = 0 )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
//JP 16.04.97: 2. part for Bug 36271
sal_Bool bChgd = sal_False;
2000-09-18 23:08:29 +00:00
const SwTableLine* pLine = rBox.GetUpper();
const SwTableBoxes& rTblBoxes = pLine->GetTabBoxes();
const SwTableBox* pUpperBox = &rBox;
sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pUpperBox );
2000-09-18 23:08:29 +00:00
pUpperBox = rBox.GetUpper()->GetUpper();
const SvxBoxItem& rBoxItem = rBox.GetFrmFmt()->GetBox();
2012-02-15 13:19:06 +01:00
// then the top/bottom edges
2000-09-18 23:08:29 +00:00
if( rBoxItem.GetTop() || rBoxItem.GetBottom() )
{
bChgd = sal_False;
2000-09-18 23:08:29 +00:00
const SwTableLines* pTblLns;
if( pUpperBox )
pTblLns = &pUpperBox->GetTabLines();
else
pTblLns = &rTbl.GetTabLines();
sal_uInt16 nLnPos = pTblLns->GetPos( pLine );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Calculate the attribute position of the top-be-deleted Box and then
// search in the top/bottom Line of the respective counterparts.
2000-09-18 23:08:29 +00:00
SwTwips nBoxStt = 0;
for( sal_uInt16 n = 0; n < nDelPos; ++n )
2000-09-18 23:08:29 +00:00
nBoxStt += rTblBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
SwTwips nBoxWidth = rBox.GetFrmFmt()->GetFrmSize().GetWidth();
SwTableBox *pPrvBox = 0, *pNxtBox = 0;
2012-02-15 13:19:06 +01:00
if( nLnPos ) // Predecessor?
2000-09-18 23:08:29 +00:00
pPrvBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
nLnPos, sal_False, pAllDelBoxes, pCurPos );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
if( nLnPos + 1 < pTblLns->Count() ) // Successor?
2000-09-18 23:08:29 +00:00
pNxtBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth,
nLnPos, sal_True, pAllDelBoxes, pCurPos );
2000-09-18 23:08:29 +00:00
if( pNxtBox && pNxtBox->GetSttNd() )
{
const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox();
if( !rNxtBoxItem.GetTop() && ( !pPrvBox ||
!pPrvBox->GetFrmFmt()->GetBox().GetBottom()) )
{
SvxBoxItem aTmp( rNxtBoxItem );
aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
: rBoxItem.GetBottom(),
BOX_LINE_TOP );
rShareFmts.SetAttr( *pNxtBox, aTmp );
bChgd = sal_True;
2000-09-18 23:08:29 +00:00
}
}
if( !bChgd && pPrvBox && pPrvBox->GetSttNd() )
{
const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox();
if( !rPrvBoxItem.GetTop() && ( !pNxtBox ||
!pNxtBox->GetFrmFmt()->GetBox().GetTop()) )
{
SvxBoxItem aTmp( rPrvBoxItem );
aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop()
: rBoxItem.GetBottom(),
BOX_LINE_BOTTOM );
rShareFmts.SetAttr( *pPrvBox, aTmp );
}
}
}
}
sal_Bool SwTable::DeleteSel(
SwDoc* pDoc
,
const SwSelBoxes& rBoxes,
const SwSelBoxes* pMerged, SwUndo* pUndo,
const sal_Bool bDelMakeFrms, const sal_Bool bCorrBorder )
2000-09-18 23:08:29 +00:00
{
OSL_ENSURE( pDoc, "No doc?" );
SwTableNode* pTblNd = 0;
if( rBoxes.Count() )
{
pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
if( !pTblNd )
return sal_False;
}
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find Lines for the Layout update
2000-09-18 23:08:29 +00:00
_FndBox aFndBox( 0, 0 );
if ( bDelMakeFrms )
{
if( pMerged && pMerged->Count() )
aFndBox.SetTableLines( *pMerged, *this );
else if( rBoxes.Count() )
aFndBox.SetTableLines( rBoxes, *this );
2000-09-18 23:08:29 +00:00
aFndBox.DelFrms( *this );
}
SwShareBoxFmts aShareFmts;
2012-02-15 13:19:06 +01:00
// First switch the Border, then delete
2000-09-18 23:08:29 +00:00
if( bCorrBorder )
{
SwSelBoxes aBoxes;
aBoxes.Insert( &rBoxes );
for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFmts,
&aBoxes, &n );
2000-09-18 23:08:29 +00:00
}
PrepareDelBoxes( rBoxes );
SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
2012-02-15 13:19:06 +01:00
// Delete boxes from last to first
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
{
sal_uInt16 nIdx = rBoxes.Count() - 1 - n;
2012-02-15 13:19:06 +01:00
// First adapt the data-sequence for chart if necessary
// (needed to move the implementation cursor properly to it's new
// position which can't be done properly if the cell is already gone)
if (pPCD && pTblNd)
pPCD->DeleteBox( &pTblNd->GetTable(), *rBoxes[nIdx] );
// ... then delete the boxes
_DeleteBox( *this, rBoxes[nIdx], pUndo, sal_True, bCorrBorder, &aShareFmts );
}
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// then clean up the structure of all Lines
2000-09-18 23:08:29 +00:00
GCLines();
if( bDelMakeFrms && aFndBox.AreLinesToRestore( *this ) )
aFndBox.MakeFrms( *this );
// TL_CHART2: now inform chart that sth has changed
pDoc->UpdateCharts( GetFrmFmt()->GetName() );
CHECKTABLELAYOUT;
CHECK_TABLE( *this );
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool SwTable::OldSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt,
sal_Bool bSameHeight )
2000-09-18 23:08:29 +00:00
{
OSL_ENSURE( pDoc && rBoxes.Count() && nCnt, "No valid values" );
SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
2000-09-18 23:08:29 +00:00
if( !pTblNd )
return sal_False;
2000-09-18 23:08:29 +00:00
// TL_CHART2: splitting/merging of a number of cells or rows will usually make
// the table too complex to be handled with chart.
// Thus we tell the charts to use their own data provider and forget about this table
pDoc->CreateChartInternalDataProviders( this );
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
2000-09-18 23:08:29 +00:00
2002-11-15 08:31:09 +00:00
// If the rows should get the same (min) height, we first have
// to store the old row heights before deleting the frames
long* pRowHeights = 0;
2002-11-15 08:31:09 +00:00
if ( bSameHeight )
{
pRowHeights = new long[ rBoxes.Count() ];
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2002-11-15 08:31:09 +00:00
{
SwTableBox* pSelBox = *( rBoxes.GetData() + n );
2002-11-15 08:31:09 +00:00
const SwRowFrm* pRow = GetRowFrm( *pSelBox->GetUpper() );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pRow, "Where is the SwTableLine's Frame?" );
2002-11-15 08:31:09 +00:00
SWRECTFN( pRow )
pRowHeights[ n ] = (pRow->Frm().*fnRect->fnGetHeight)();
2002-11-15 08:31:09 +00:00
}
}
2012-02-15 13:19:06 +01:00
// Find Lines for the Layout update
2000-09-18 23:08:29 +00:00
_FndBox aFndBox( 0, 0 );
aFndBox.SetTableLines( rBoxes, *this );
aFndBox.DelFrms( *this );
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
SwTableBox* pSelBox = *( rBoxes.GetData() + n );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pSelBox, "Box is not within the Table" );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Insert nCnt new Lines into the Box
2000-09-18 23:08:29 +00:00
SwTableLine* pInsLine = pSelBox->GetUpper();
SwTableBoxFmt* pFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
2012-02-15 13:19:06 +01:00
// Respect the Line's height, reset if needed
2000-09-18 23:08:29 +00:00
SwFmtFrmSize aFSz( pInsLine->GetFrmFmt()->GetFrmSize() );
if ( bSameHeight && ATT_VAR_SIZE == aFSz.GetHeightSizeType() )
aFSz.SetHeightSizeType( ATT_MIN_SIZE );
2002-11-15 08:31:09 +00:00
sal_Bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight;
2002-11-15 08:31:09 +00:00
if ( bChgLineSz )
aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) /
2002-11-15 08:31:09 +00:00
(nCnt + 1) );
2000-09-18 23:08:29 +00:00
SwTableBox* pNewBox = new SwTableBox( pFrmFmt, nCnt, pInsLine );
sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
2012-02-15 13:19:06 +01:00
pInsLine->GetTabBoxes().Remove( nBoxPos ); // delete old ones
2000-09-18 23:08:29 +00:00
pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox, nBoxPos );
2012-02-15 13:19:06 +01:00
// Delete background/border attribute
SwTableBox* pLastBox = pSelBox; // To distribute the TextNodes!
// If Areas are contained in the Box, it stays as is
// !! If this is changed we need to adapt the Undo, too !!!
sal_Bool bMoveNodes = sal_True;
2000-09-18 23:08:29 +00:00
{
sal_uLong nSttNd = pLastBox->GetSttIdx() + 1,
2000-09-18 23:08:29 +00:00
nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex();
while( nSttNd < nEndNd )
if( !pDoc->GetNodes()[ nSttNd++ ]->IsTxtNode() )
{
bMoveNodes = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
SwTableBoxFmt* pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt();
sal_Bool bChkBorder = 0 != pCpyBoxFrmFmt->GetBox().GetTop();
2000-09-18 23:08:29 +00:00
if( bChkBorder )
pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
for( sal_uInt16 i = 0; i <= nCnt; ++i )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Create a new Line in the new Box
2000-09-18 23:08:29 +00:00
SwTableLine* pNewLine = new SwTableLine(
(SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pNewBox );
if( bChgLineSz )
{
pNewLine->ClaimFrmFmt()->SetFmtAttr( aFSz );
2000-09-18 23:08:29 +00:00
}
pNewBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, i );
2012-02-15 13:19:06 +01:00
// then a new Box in the Line
if( !i ) // hang up the original Box
2000-09-18 23:08:29 +00:00
{
pSelBox->SetUpper( pNewLine );
pNewLine->GetTabBoxes().C40_INSERT( SwTableBox, pSelBox, 0 );
}
else
{
::_InsTblBox( pDoc, pTblNd, pNewLine, pCpyBoxFrmFmt,
pLastBox, 0 );
if( bChkBorder )
{
pCpyBoxFrmFmt = (SwTableBoxFmt*)pNewLine->GetTabBoxes()[ 0 ]->ClaimFrmFmt();
SvxBoxItem aTmp( pCpyBoxFrmFmt->GetBox() );
aTmp.SetLine( 0, BOX_LINE_TOP );
pCpyBoxFrmFmt->SetFmtAttr( aTmp );
bChkBorder = sal_False;
2000-09-18 23:08:29 +00:00
}
if( bMoveNodes )
{
const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode();
if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() )
{
2012-02-15 13:19:06 +01:00
// Move TextNodes
2000-09-18 23:08:29 +00:00
SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd );
2012-02-15 13:19:06 +01:00
pLastBox = pNewLine->GetTabBoxes()[0]; // reset
2000-09-18 23:08:29 +00:00
SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 );
pDoc->GetNodes()._MoveNodes(aRg, pDoc->GetNodes(), aInsPos, sal_False);
2012-02-15 13:19:06 +01:00
pDoc->GetNodes().Delete( aInsPos, 1 ); // delete the empty one
2000-09-18 23:08:29 +00:00
}
}
}
}
2012-02-15 13:19:06 +01:00
// In Boxes with Lines, we can only have Size/Fillorder
2000-09-18 23:08:29 +00:00
pFrmFmt = (SwTableBoxFmt*)pNewBox->ClaimFrmFmt();
pFrmFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
pFrmFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
2000-09-18 23:08:29 +00:00
}
delete[] pRowHeights;
GCLines();
2000-09-18 23:08:29 +00:00
aFndBox.MakeFrms( *this );
2000-09-18 23:08:29 +00:00
CHECKBOXWIDTH
CHECKTABLELAYOUT
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool SwTable::SplitCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt )
2000-09-18 23:08:29 +00:00
{
OSL_ENSURE( pDoc && rBoxes.Count() && nCnt, "No valid values" );
SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
2000-09-18 23:08:29 +00:00
if( !pTblNd )
return sal_False;
2000-09-18 23:08:29 +00:00
// TL_CHART2: splitting/merging of a number of cells or rows will usually make
// the table too complex to be handled with chart.
// Thus we tell the charts to use their own data provider and forget about this table
pDoc->CreateChartInternalDataProviders( this );
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
SwSelBoxes aSelBoxes;
aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count());
ExpandSelection( aSelBoxes );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find Lines for the Layout update
2000-09-18 23:08:29 +00:00
_FndBox aFndBox( 0, 0 );
aFndBox.SetTableLines( aSelBoxes, *this );
2000-09-18 23:08:29 +00:00
aFndBox.DelFrms( *this );
_CpyTabFrms aFrmArr;
SvPtrarr aLastBoxArr;
sal_uInt16 nFndPos;
for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
SwTableBox* pSelBox = *( aSelBoxes.GetData() + n );
OSL_ENSURE( pSelBox, "Box steht nicht in der Tabelle" );
2000-09-18 23:08:29 +00:00
// We don't want to split small table cells into very very small cells
if( pSelBox->GetFrmFmt()->GetFrmSize().GetWidth()/( nCnt + 1 ) < 10 )
continue;
2012-02-15 13:19:06 +01:00
// Then split the nCnt Box up into nCnt Boxes
2000-09-18 23:08:29 +00:00
SwTableLine* pInsLine = pSelBox->GetUpper();
sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find the Frame Format in the Frame Format Array
2000-09-18 23:08:29 +00:00
SwTableBoxFmt* pLastBoxFmt;
_CpyTabFrm aFindFrm( (SwTableBoxFmt*)pSelBox->GetFrmFmt() );
if( !aFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
{
2012-02-15 13:19:06 +01:00
// Change the FrmFmt
2000-09-18 23:08:29 +00:00
aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt();
SwTwips nBoxSz = aFindFrm.pNewFrmFmt->GetFrmSize().GetWidth();
SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 );
aFindFrm.pNewFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
2000-09-18 23:08:29 +00:00
nNewBoxSz, 0 ) );
aFrmArr.Insert( aFindFrm );
pLastBoxFmt = aFindFrm.pNewFrmFmt;
if( nBoxSz != ( nNewBoxSz * (nCnt + 1)))
{
2012-02-15 13:19:06 +01:00
// We have a remainder, so we need to define an own Format
// for the last Box.
2000-09-18 23:08:29 +00:00
pLastBoxFmt = new SwTableBoxFmt( *aFindFrm.pNewFrmFmt );
pLastBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE,
2000-09-18 23:08:29 +00:00
nBoxSz - ( nNewBoxSz * nCnt ), 0 ) );
}
void* p = pLastBoxFmt;
aLastBoxArr.Insert( p, nFndPos );
}
else
{
aFindFrm = aFrmArr[ nFndPos ];
pSelBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt );
pLastBoxFmt = (SwTableBoxFmt*)aLastBoxArr[ nFndPos ];
}
2012-02-15 13:19:06 +01:00
// Insert the Boxes at the Position
for( sal_uInt16 i = 1; i < nCnt; ++i )
2000-09-18 23:08:29 +00:00
::_InsTblBox( pDoc, pTblNd, pInsLine, aFindFrm.pNewFrmFmt,
2012-02-15 13:19:06 +01:00
pSelBox, nBoxPos + i ); // insert after
2000-09-18 23:08:29 +00:00
::_InsTblBox( pDoc, pTblNd, pInsLine, pLastBoxFmt,
2012-02-15 13:19:06 +01:00
pSelBox, nBoxPos + nCnt ); // insert after
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Special treatment for the Border:
const SvxBoxItem& aSelBoxItem = aFindFrm.pNewFrmFmt->GetBox();
if( aSelBoxItem.GetRight() )
2000-09-18 23:08:29 +00:00
{
pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrmFmt();
SvxBoxItem aTmp( aSelBoxItem );
2000-09-18 23:08:29 +00:00
aTmp.SetLine( 0, BOX_LINE_RIGHT );
aFindFrm.pNewFrmFmt->SetFmtAttr( aTmp );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Remove the Format from the "cache"
for( sal_uInt16 i = aFrmArr.Count(); i; )
2000-09-18 23:08:29 +00:00
{
const _CpyTabFrm& rCTF = aFrmArr[ --i ];
if( rCTF.pNewFrmFmt == aFindFrm.pNewFrmFmt ||
rCTF.Value.pFrmFmt == aFindFrm.pNewFrmFmt )
{
aFrmArr.Remove( i );
aLastBoxArr.Remove( i );
}
}
}
}
2012-02-15 13:19:06 +01:00
// Update Layout
2000-09-18 23:08:29 +00:00
aFndBox.MakeFrms( *this );
2000-09-18 23:08:29 +00:00
CHECKBOXWIDTH
CHECKTABLELAYOUT
return sal_True;
2000-09-18 23:08:29 +00:00
}
/*
----------------------- >> MERGE << ------------------------
2012-02-15 13:19:06 +01:00
Algorithm:
If we only have one Line in the _FndBox, take this Line and test
the Box count:
- If we have more than one Box, we merge on Box level, meaning
the new Box will be as wide as the old ones.
- All Lines that are above/under the Area, are inserted into
the Box as Line + Box.
- All Lines that come before/after the Area, are inserted into
the Boxes Left/Right.
2000-09-18 23:08:29 +00:00
----------------------- >> MERGE << ------------------------
*/
void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd,
2000-09-18 23:08:29 +00:00
SwTableLines& rLines,
SwTableBox* pInsBox,
sal_uInt16 nPos = USHRT_MAX )
2000-09-18 23:08:29 +00:00
{
for( sal_uInt16 n = nStt; n < nEnd; ++n )
2000-09-18 23:08:29 +00:00
rLines[n]->SetUpper( pInsBox );
if( USHRT_MAX == nPos )
nPos = pInsBox->GetTabLines().Count();
pInsBox->GetTabLines().Insert( &rLines, nPos, nStt, nEnd );
rLines.Remove( nStt, nEnd - nStt );
}
void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd,
2000-09-18 23:08:29 +00:00
SwTableBoxes& rBoxes,
SwTableLine* pInsLine,
sal_uInt16 nPos = USHRT_MAX )
2000-09-18 23:08:29 +00:00
{
for( sal_uInt16 n = nStt; n < nEnd; ++n )
2000-09-18 23:08:29 +00:00
rBoxes[n]->SetUpper( pInsLine );
if( USHRT_MAX == nPos )
nPos = pInsLine->GetTabBoxes().Count();
pInsLine->GetTabBoxes().Insert( &rBoxes, nPos, nStt, nEnd );
rBoxes.Remove( nStt, nEnd - nStt );
}
void lcl_CalcWidth( SwTableBox* pBox )
{
2012-02-15 13:19:06 +01:00
// Assertion: Every Line in the Box is as large
2000-09-18 23:08:29 +00:00
SwFrmFmt* pFmt = pBox->ClaimFrmFmt();
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pBox->GetTabLines().Count(), "Box does not have any Lines" );
2000-09-18 23:08:29 +00:00
SwTableLine* pLine = pBox->GetTabLines()[0];
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pLine, "Box is not within a Line" );
2000-09-18 23:08:29 +00:00
long nWidth = 0;
for( sal_uInt16 n = 0; n < pLine->GetTabBoxes().Count(); ++n )
2000-09-18 23:08:29 +00:00
nWidth += pLine->GetTabBoxes()[n]->GetFrmFmt()->GetFrmSize().GetWidth();
pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 ));
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Boxes with Lines can only have Size/Fillorder
pFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 );
pFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 );
2000-09-18 23:08:29 +00:00
}
struct _InsULPara
{
SwTableNode* pTblNd;
SwTableLine* pInsLine;
SwTableBox* pInsBox;
2012-02-15 13:19:06 +01:00
sal_Bool bUL_LR : 1; // Upper-Lower(sal_True) or Left-Right(sal_False) ?
sal_Bool bUL : 1; // Upper-Left(sal_True) or Lower-Right(sal_False) ?
2000-09-18 23:08:29 +00:00
SwTableBox* pLeftBox;
SwTableBox* pRightBox;
SwTableBox* pMergeBox;
_InsULPara( SwTableNode* pTNd, sal_Bool bUpperLower, sal_Bool bUpper,
2000-09-18 23:08:29 +00:00
SwTableBox* pLeft, SwTableBox* pMerge, SwTableBox* pRight,
SwTableLine* pLine=0, SwTableBox* pBox=0 )
: pTblNd( pTNd ), pInsLine( pLine ), pInsBox( pBox ),
pLeftBox( pLeft ), pRightBox( pRight ), pMergeBox( pMerge )
2000-09-18 23:08:29 +00:00
{ bUL_LR = bUpperLower; bUL = bUpper; }
void SetLeft( SwTableBox* pBox=0 )
{ bUL_LR = sal_False; bUL = sal_True; if( pBox ) pInsBox = pBox; }
2000-09-18 23:08:29 +00:00
void SetRight( SwTableBox* pBox=0 )
{ bUL_LR = sal_False; bUL = sal_False; if( pBox ) pInsBox = pBox; }
2000-09-18 23:08:29 +00:00
void SetUpper( SwTableLine* pLine=0 )
{ bUL_LR = sal_True; bUL = sal_True; if( pLine ) pInsLine = pLine; }
2000-09-18 23:08:29 +00:00
void SetLower( SwTableLine* pLine=0 )
{ bUL_LR = sal_True; bUL = sal_False; if( pLine ) pInsLine = pLine; }
2000-09-18 23:08:29 +00:00
};
static void lcl_Merge_MoveLine(_FndLine & rFndLine, _InsULPara *const pULPara);
static void lcl_Merge_MoveBox(_FndBox & rFndBox, _InsULPara *const pULPara)
2000-09-18 23:08:29 +00:00
{
SwTableBoxes* pBoxes;
sal_uInt16 nStt = 0, nEnd = rFndBox.GetLines().size();
sal_uInt16 nInsPos = USHRT_MAX;
2000-09-18 23:08:29 +00:00
if( !pULPara->bUL_LR ) // Left/Right
{
sal_uInt16 nPos;
SwTableBox* pFndTableBox = rFndBox.GetBox();
pBoxes = &pFndTableBox->GetUpper()->GetTabBoxes();
2000-09-18 23:08:29 +00:00
if( pULPara->bUL ) // Left ?
{
2012-02-15 13:19:06 +01:00
// if there are Boxes before it, move them
if( 0 != ( nPos = pBoxes->C40_GETPOS( SwTableBox, pFndTableBox )) )
2000-09-18 23:08:29 +00:00
lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine );
}
else // Right
2012-02-15 13:19:06 +01:00
// if there are Boxes behind it, move them
if( (nPos = pBoxes->C40_GETPOS( SwTableBox, pFndTableBox )) +1 < pBoxes->Count() )
2000-09-18 23:08:29 +00:00
{
nInsPos = pULPara->pInsLine->GetTabBoxes().Count();
lcl_CpyBoxes( nPos+1, pBoxes->Count(),
*pBoxes, pULPara->pInsLine );
}
}
2012-02-15 13:19:06 +01:00
// Upper/Lower and still deeper?
else if (!rFndBox.GetLines().empty())
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Only search the Line from which we need to move
nStt = pULPara->bUL ? 0 : rFndBox.GetLines().size()-1;
2000-09-18 23:08:29 +00:00
nEnd = nStt+1;
}
pBoxes = &pULPara->pInsLine->GetTabBoxes();
2012-02-15 13:19:06 +01:00
// Is there still a level to step down to?
if (rFndBox.GetBox()->GetTabLines().Count())
2000-09-18 23:08:29 +00:00
{
SwTableBox* pBox = new SwTableBox(
static_cast<SwTableBoxFmt*>(rFndBox.GetBox()->GetFrmFmt()),
0, pULPara->pInsLine );
2000-09-18 23:08:29 +00:00
_InsULPara aPara( *pULPara );
aPara.pInsBox = pBox;
for (_FndLines::iterator it = rFndBox.GetLines().begin() + nStt;
it != rFndBox.GetLines().begin() + nEnd; ++it )
{
lcl_Merge_MoveLine(*it, &aPara );
}
2000-09-18 23:08:29 +00:00
if( pBox->GetTabLines().Count() )
{
if( USHRT_MAX == nInsPos )
nInsPos = pBoxes->Count();
pBoxes->C40_INSERT( SwTableBox, pBox, nInsPos );
2012-02-15 13:19:06 +01:00
lcl_CalcWidth( pBox ); // calculate the Box's width
2000-09-18 23:08:29 +00:00
}
else
delete pBox;
}
}
static void lcl_Merge_MoveLine(_FndLine& rFndLine, _InsULPara *const pULPara)
2000-09-18 23:08:29 +00:00
{
SwTableLines* pLines;
sal_uInt16 nStt = 0, nEnd = rFndLine.GetBoxes().size();
sal_uInt16 nInsPos = USHRT_MAX;
2000-09-18 23:08:29 +00:00
if( pULPara->bUL_LR ) // UpperLower ?
{
sal_uInt16 nPos;
SwTableLine* pFndLn = (SwTableLine*)rFndLine.GetLine();
2000-09-18 23:08:29 +00:00
pLines = pFndLn->GetUpper() ?
&pFndLn->GetUpper()->GetTabLines() :
&pULPara->pTblNd->GetTable().GetTabLines();
SwTableBox* pLBx = rFndLine.GetBoxes().front().GetBox();
SwTableBox* pRBx = rFndLine.GetBoxes().back().GetBox();
sal_uInt16 nLeft = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pLBx );
sal_uInt16 nRight = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pRBx );
2000-09-18 23:08:29 +00:00
if( !nLeft || nRight == pFndLn->GetTabBoxes().Count() )
{
if( pULPara->bUL ) // Upper ?
{
2012-02-15 13:19:06 +01:00
// If there are Lines before it, move them
2000-09-18 23:08:29 +00:00
if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox );
}
else
2012-02-15 13:19:06 +01:00
// If there are Lines after it, move them
2000-09-18 23:08:29 +00:00
if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
{
nInsPos = pULPara->pInsBox->GetTabLines().Count();
lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
pULPara->pInsBox );
}
}
else if( nLeft )
{
2012-02-15 13:19:06 +01:00
// There are still Boxes on the left side, so put the Left-
// and Merge-Box into one Box and Line, insert before/after
// a Line with a Box, into which the upper/lower Lines are
// inserted
2000-09-18 23:08:29 +00:00
SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper();
SwTableBox* pLMBox = new SwTableBox(
(SwTableBoxFmt*)pULPara->pLeftBox->GetFrmFmt(), 0, pInsLine );
SwTableLine* pLMLn = new SwTableLine(
(SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pLMBox );
pLMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
2000-09-18 23:08:29 +00:00
pLMBox->GetTabLines().C40_INSERT( SwTableLine, pLMLn, 0 );
lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn );
pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLMBox, 0 );
if( pULPara->bUL ) // Upper ?
{
2012-02-15 13:19:06 +01:00
// If there are Lines before it, move them
2000-09-18 23:08:29 +00:00
if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 );
}
else
2012-02-15 13:19:06 +01:00
// If there are Lines after it, move them
2000-09-18 23:08:29 +00:00
if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
pLMBox );
2012-02-15 13:19:06 +01:00
lcl_CalcWidth( pLMBox ); // calculate the Box's width
2000-09-18 23:08:29 +00:00
}
else if( nRight+1 < pFndLn->GetTabBoxes().Count() )
{
2012-02-15 13:19:06 +01:00
// There are still Boxes on the right, so put the Right-
// and Merge-Box into one Box and Line, insert before/after
// a Line with a Box, into which the upper/lower Lines are
// inserted
2000-09-18 23:08:29 +00:00
SwTableLine* pInsLine = pULPara->pRightBox->GetUpper();
SwTableBox* pRMBox;
if( pULPara->pLeftBox->GetUpper() == pInsLine )
{
pRMBox = new SwTableBox(
(SwTableBoxFmt*)pULPara->pRightBox->GetFrmFmt(), 0, pInsLine );
SwTableLine* pRMLn = new SwTableLine(
(SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pRMBox );
pRMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
2000-09-18 23:08:29 +00:00
pRMBox->GetTabLines().C40_INSERT( SwTableLine, pRMLn, 0 );
lcl_CpyBoxes( 1, 3, pInsLine->GetTabBoxes(), pRMLn );
pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
}
else
{
2012-02-15 13:19:06 +01:00
// Left and Merge have been merged, so also move Right into the Line
2000-09-18 23:08:29 +00:00
pInsLine = pULPara->pLeftBox->GetUpper();
sal_uInt16 nMvPos = pULPara->pRightBox->GetUpper()->GetTabBoxes().
2000-09-18 23:08:29 +00:00
C40_GETPOS( SwTableBox, pULPara->pRightBox );
lcl_CpyBoxes( nMvPos, nMvPos+1,
pULPara->pRightBox->GetUpper()->GetTabBoxes(),
pInsLine );
pRMBox = pInsLine->GetUpper();
2012-02-15 13:19:06 +01:00
// If there are already Lines, then these need to go into a new Line and Box
2000-09-18 23:08:29 +00:00
nMvPos = pRMBox->GetTabLines().C40_GETPOS( SwTableLine, pInsLine );
if( pULPara->bUL ? nMvPos
: nMvPos+1 < pRMBox->GetTabLines().Count() )
{
2012-02-15 13:19:06 +01:00
// Merge all Lines into a new Line and Box
2000-09-18 23:08:29 +00:00
SwTableLine* pNewLn = new SwTableLine(
(SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pRMBox );
pNewLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
2000-09-18 23:08:29 +00:00
pRMBox->GetTabLines().C40_INSERT( SwTableLine, pNewLn,
pULPara->bUL ? nMvPos : nMvPos+1 );
pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 );
sal_uInt16 nPos1, nPos2;
2000-09-18 23:08:29 +00:00
if( pULPara->bUL )
nPos1 = 0,
nPos2 = nMvPos;
else
nPos1 = nMvPos+2,
nPos2 = pNewLn->GetUpper()->GetTabLines().Count();
lcl_CpyLines( nPos1, nPos2,
pNewLn->GetUpper()->GetTabLines(), pRMBox );
2012-02-15 13:19:06 +01:00
lcl_CalcWidth( pRMBox ); // calculate the Box's width
2000-09-18 23:08:29 +00:00
pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn );
pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox,
pNewLn->GetTabBoxes().Count() );
}
}
if( pULPara->bUL ) // Upper ?
{
2012-02-15 13:19:06 +01:00
// If there are Lines before it, move them
2000-09-18 23:08:29 +00:00
if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) )
lcl_CpyLines( 0, nPos, *pLines, pRMBox, 0 );
}
else
2012-02-15 13:19:06 +01:00
// If there are Lines after it, move them
2000-09-18 23:08:29 +00:00
if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() )
lcl_CpyLines( nPos+1, pLines->Count(), *pLines,
pRMBox );
2012-02-15 13:19:06 +01:00
lcl_CalcWidth( pRMBox ); // calculate the Box's width
2000-09-18 23:08:29 +00:00
}
else {
2012-02-15 13:19:06 +01:00
OSL_FAIL( "So ... what do we do now?" );
}
2000-09-18 23:08:29 +00:00
}
// Left/Right
else
{
2012-02-15 13:19:06 +01:00
// Find only the Line from which we need to move
nStt = pULPara->bUL ? 0 : rFndLine.GetBoxes().size()-1;
2000-09-18 23:08:29 +00:00
nEnd = nStt+1;
}
pLines = &pULPara->pInsBox->GetTabLines();
SwTableLine* pNewLine = new SwTableLine(
(SwTableLineFmt*)rFndLine.GetLine()->GetFrmFmt(), 0, pULPara->pInsBox );
2000-09-18 23:08:29 +00:00
_InsULPara aPara( *pULPara ); // kopieren
aPara.pInsLine = pNewLine;
_FndBoxes & rLineBoxes = rFndLine.GetBoxes();
for (_FndBoxes::iterator it = rLineBoxes.begin() + nStt;
it != rLineBoxes.begin() + nEnd; ++it)
{
lcl_Merge_MoveBox(*it, &aPara);
}
2000-09-18 23:08:29 +00:00
if( pNewLine->GetTabBoxes().Count() )
{
if( USHRT_MAX == nInsPos )
nInsPos = pLines->Count();
pLines->C40_INSERT( SwTableLine, pNewLine, nInsPos );
}
else
delete pNewLine;
}
sal_Bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes,
SwTableBox* pMergeBox, SwUndoTblMerge* pUndo )
2000-09-18 23:08:29 +00:00
{
OSL_ENSURE( rBoxes.Count() && pMergeBox, "no valid values" );
SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode();
2000-09-18 23:08:29 +00:00
if( !pTblNd )
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
_FndBox aFndBox( 0, 0 );
{
_FndPara aPara( rBoxes, &aFndBox );
GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
}
if( aFndBox.GetLines().empty() )
return sal_False;
2000-09-18 23:08:29 +00:00
// TL_CHART2: splitting/merging of a number of cells or rows will usually make
// the table too complex to be handled with chart.
// Thus we tell the charts to use their own data provider and forget about this table
pDoc->CreateChartInternalDataProviders( this );
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
2000-09-18 23:08:29 +00:00
if( pUndo )
pUndo->SetSelBoxes( rBoxes );
2012-02-15 13:19:06 +01:00
// Find Lines for the Layout update
2000-09-18 23:08:29 +00:00
aFndBox.SetTableLines( *this );
aFndBox.DelFrms( *this );
_FndBox* pFndBox = &aFndBox;
while( 1 == pFndBox->GetLines().size() &&
1 == pFndBox->GetLines().front().GetBoxes().size() )
{
pFndBox = &pFndBox->GetLines().front().GetBoxes().front();
}
2000-09-18 23:08:29 +00:00
SwTableLine* pInsLine = new SwTableLine(
(SwTableLineFmt*)pFndBox->GetLines().front().GetLine()->GetFrmFmt(), 0,
2000-09-18 23:08:29 +00:00
!pFndBox->GetUpper() ? 0 : pFndBox->GetBox() );
pInsLine->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Add the new Line
2000-09-18 23:08:29 +00:00
SwTableLines* pLines = pFndBox->GetUpper() ?
&pFndBox->GetBox()->GetTabLines() : &GetTabLines();
SwTableLine* pNewLine = pFndBox->GetLines().front().GetLine();
sal_uInt16 nInsPos = pLines->C40_GETPOS( SwTableLine, pNewLine );
2000-09-18 23:08:29 +00:00
pLines->C40_INSERT( SwTableLine, pInsLine, nInsPos );
SwTableBox* pLeftBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
SwTableBox* pRightBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine );
2000-09-18 23:08:29 +00:00
pMergeBox->SetUpper( pInsLine );
pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLeftBox, 0 );
pLeftBox->ClaimFrmFmt();
2000-09-18 23:08:29 +00:00
pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pMergeBox, 1 );
pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRightBox, 2 );
pRightBox->ClaimFrmFmt();
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// This contains all Lines that are above the selected Area,
// thus they form a Upper/Lower Line
_InsULPara aPara( pTblNd, sal_True, sal_True, pLeftBox, pMergeBox, pRightBox, pInsLine );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Move the overlapping upper/lower Lines of the selected Area
_FndBoxes& rLineBoxes = pFndBox->GetLines().front().GetBoxes();
for (_FndBoxes::iterator it = rLineBoxes.begin(); it != rLineBoxes.end(); ++it)
{
lcl_Merge_MoveBox(*it, &aPara);
}
2000-09-18 23:08:29 +00:00
aPara.SetLower( pInsLine );
sal_uInt16 nEnd = pFndBox->GetLines().size()-1;
rLineBoxes = pFndBox->GetLines()[nEnd].GetBoxes();
for (_FndBoxes::iterator it = rLineBoxes.begin(); it != rLineBoxes.end(); ++it)
{
lcl_Merge_MoveBox(*it, &aPara);
}
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Move the Boxes extending into the selected Area from left/right
aPara.SetLeft( pLeftBox );
BOOST_FOREACH(_FndLine& rFndLine, pFndBox->GetLines() )
lcl_Merge_MoveLine( rFndLine, &aPara );
2000-09-18 23:08:29 +00:00
aPara.SetRight( pRightBox );
BOOST_FOREACH(_FndLine& rFndLine, pFndBox->GetLines() )
lcl_Merge_MoveLine( rFndLine, &aPara );
2000-09-18 23:08:29 +00:00
if( !pLeftBox->GetTabLines().Count() )
_DeleteBox( *this, pLeftBox, 0, sal_False, sal_False );
2000-09-18 23:08:29 +00:00
else
{
2012-02-15 13:19:06 +01:00
lcl_CalcWidth( pLeftBox ); // calculate the Box's width
if( pUndo && pLeftBox->GetSttNd() )
pUndo->AddNewBox( pLeftBox->GetSttIdx() );
2000-09-18 23:08:29 +00:00
}
if( !pRightBox->GetTabLines().Count() )
_DeleteBox( *this, pRightBox, 0, sal_False, sal_False );
2000-09-18 23:08:29 +00:00
else
{
2012-02-15 13:19:06 +01:00
lcl_CalcWidth( pRightBox ); // calculate the Box's width
if( pUndo && pRightBox->GetSttNd() )
pUndo->AddNewBox( pRightBox->GetSttIdx() );
2000-09-18 23:08:29 +00:00
}
DeleteSel( pDoc, rBoxes, 0, 0, sal_False, sal_False );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Clean up this Line's structure once again, generally all of them
2000-09-18 23:08:29 +00:00
GCLines();
GetTabLines()[0]->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
aFndBox.MakeFrms( *this );
2000-09-18 23:08:29 +00:00
CHECKBOXWIDTH
CHECKTABLELAYOUT
return sal_True;
2000-09-18 23:08:29 +00:00
}
void lcl_CheckRowSpan( SwTable &rTbl )
{
sal_uInt16 nLineCount = rTbl.GetTabLines().Count();
sal_uInt16 nMaxSpan = nLineCount;
long nMinSpan = 1;
while( nMaxSpan )
{
SwTableLine* pLine = rTbl.GetTabLines()[ nLineCount - nMaxSpan ];
for( sal_uInt16 nBox = 0; nBox < pLine->GetTabBoxes().Count(); ++nBox )
{
SwTableBox* pBox = pLine->GetTabBoxes()[nBox];
long nRowSpan = pBox->getRowSpan();
if( nRowSpan > nMaxSpan )
pBox->setRowSpan( nMaxSpan );
else if( nRowSpan < nMinSpan )
pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan );
}
--nMaxSpan;
nMinSpan = -nMaxSpan;
}
}
sal_uInt16 lcl_GetBoxOffset( const _FndBox& rBox )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Find the first Box
2000-09-18 23:08:29 +00:00
const _FndBox* pFirstBox = &rBox;
while( !pFirstBox->GetLines().empty() )
pFirstBox = &pFirstBox->GetLines().front().GetBoxes().front();
2000-09-18 23:08:29 +00:00
sal_uInt16 nRet = 0;
2012-02-15 13:19:06 +01:00
// Calculate the position relative to above via the Lines
2000-09-18 23:08:29 +00:00
const SwTableBox* pBox = pFirstBox->GetBox();
do {
const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes();
const SwTableBox* pCmp;
for( sal_uInt16 n = 0; pBox != ( pCmp = rBoxes[ n ] ); ++n )
nRet = nRet + (sal_uInt16) pCmp->GetFrmFmt()->GetFrmSize().GetWidth();
2000-09-18 23:08:29 +00:00
pBox = pBox->GetUpper()->GetUpper();
} while( pBox );
return nRet;
}
sal_uInt16 lcl_GetLineWidth( const _FndLine& rLine )
2000-09-18 23:08:29 +00:00
{
sal_uInt16 nRet = 0;
for( sal_uInt16 n = rLine.GetBoxes().size(); n; )
{
nRet = nRet + static_cast<sal_uInt16>(rLine.GetBoxes()[--n].GetBox()
->GetFrmFmt()->GetFrmSize().GetWidth());
}
2000-09-18 23:08:29 +00:00
return nRet;
}
void lcl_CalcNewWidths( const _FndLines& rFndLines, _CpyPara& rPara )
{
rPara.pWidths.reset();
sal_uInt16 nLineCount = rFndLines.size();
if( nLineCount )
{
rPara.pWidths = boost::shared_ptr< std::vector< std::vector< sal_uLong > > >
( new std::vector< std::vector< sal_uLong > >( nLineCount ));
// First we collect information about the left/right borders of all
// selected cells
for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
{
std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
const _FndLine *pFndLine = &rFndLines[ nLine ];
if( pFndLine && pFndLine->GetBoxes().size() )
{
const SwTableLine *pLine = pFndLine->GetLine();
if( pLine && pLine->GetTabBoxes().Count() )
{
sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count();
sal_uLong nPos = 0;
// The first selected box...
const SwTableBox *const pSel =
pFndLine->GetBoxes().front().GetBox();
sal_uInt16 nBox = 0;
// Sum up the width of all boxes before the first selected box
while( nBox < nBoxCount )
{
SwTableBox* pBox = pLine->GetTabBoxes()[nBox++];
if( pBox != pSel )
nPos += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
else
break;
}
2012-02-15 13:19:06 +01:00
// nPos is now the left border of the first selected box
if( rPara.nMinLeft > nPos )
rPara.nMinLeft = nPos;
nBoxCount = pFndLine->GetBoxes().size();
rWidth = std::vector< sal_uLong >( nBoxCount+2 );
rWidth[ 0 ] = nPos;
// Add now the widths of all selected boxes and store
// the positions in the vector
for( nBox = 0; nBox < nBoxCount; )
{
nPos += pFndLine->GetBoxes()[nBox]
.GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
rWidth[ ++nBox ] = nPos;
}
// nPos: The right border of the last selected box
if( rPara.nMaxRight < nPos )
rPara.nMaxRight = nPos;
if( nPos <= rWidth[ 0 ] )
rWidth.clear();
}
}
}
}
// Second step: calculate the new widths for the copied cells
sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft;
if( nSelSize )
{
for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
{
std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ];
sal_uInt16 nCount = (sal_uInt16)rWidth.size();
if( nCount > 2 )
{
rWidth[ nCount - 1 ] = rPara.nMaxRight;
sal_uLong nLastPos = 0;
for( sal_uInt16 nBox = 0; nBox < nCount; ++nBox )
{
sal_uInt64 nNextPos = rWidth[ nBox ];
nNextPos -= rPara.nMinLeft;
nNextPos *= rPara.nNewSize;
nNextPos /= nSelSize;
rWidth[ nBox ] = (sal_uLong)(nNextPos - nLastPos);
nLastPos = (sal_uLong)nNextPos;
}
}
}
}
}
static void
lcl_CopyLineToDoc(_FndLine const& rpFndLn, _CpyPara *const pCpyPara);
static void lcl_CopyBoxToDoc(_FndBox const& rFndBox, _CpyPara *const pCpyPara)
2000-09-18 23:08:29 +00:00
{
// Calculation of new size
sal_uLong nRealSize;
sal_uLong nDummy1 = 0;
sal_uLong nDummy2 = 0;
if( pCpyPara->pTblNd->GetTable().IsNewModel() )
2000-09-18 23:08:29 +00:00
{
if( pCpyPara->nBoxIdx == 1 )
nDummy1 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][0];
nRealSize = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++];
if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx].size()-1 )
nDummy2 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx];
2000-09-18 23:08:29 +00:00
}
else
2000-09-18 23:08:29 +00:00
{
nRealSize = pCpyPara->nNewSize;
nRealSize *= rFndBox.GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
nRealSize /= pCpyPara->nOldSize;
2000-09-18 23:08:29 +00:00
}
sal_uLong nSize;
bool bDummy = nDummy1 > 0;
if( bDummy )
nSize = nDummy1;
2000-09-18 23:08:29 +00:00
else
{
nSize = nRealSize;
nRealSize = 0;
}
do
{
2012-02-15 13:19:06 +01:00
// Find the Frame Format in the list of all Frame Formats
_CpyTabFrm aFindFrm(static_cast<SwTableBoxFmt*>(rFndBox.GetBox()->GetFrmFmt()));
2000-09-18 23:08:29 +00:00
SwFmtFrmSize aFrmSz;
sal_uInt16 nFndPos;
if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ) ||
( aFrmSz = ( aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]).pNewFrmFmt->
GetFrmSize()).GetWidth() != (SwTwips)nSize )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// It doesn't exist yet, so copy it
aFindFrm.pNewFrmFmt = pCpyPara->pDoc->MakeTableBoxFmt();
aFindFrm.pNewFrmFmt->CopyAttrs( *rFndBox.GetBox()->GetFrmFmt() );
if( !pCpyPara->bCpyCntnt )
aFindFrm.pNewFrmFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
aFrmSz.SetWidth( nSize );
aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz );
pCpyPara->rTabFrmArr.Insert( aFindFrm );
}
2000-09-18 23:08:29 +00:00
SwTableBox* pBox;
if (!rFndBox.GetLines().empty())
{
pBox = new SwTableBox( aFindFrm.pNewFrmFmt,
rFndBox.GetLines().size(), pCpyPara->pInsLine );
pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++ );
_CpyPara aPara( *pCpyPara, pBox );
2012-02-15 13:19:06 +01:00
aPara.nNewSize = nSize; // get the size
BOOST_FOREACH(_FndLine const& rFndLine, rFndBox.GetLines())
lcl_CopyLineToDoc( rFndLine, &aPara );
}
else
{
2012-02-15 13:19:06 +01:00
// Create an empty Box
pCpyPara->pDoc->GetNodes().InsBoxen( pCpyPara->pTblNd, pCpyPara->pInsLine,
aFindFrm.pNewFrmFmt,
(SwTxtFmtColl*)pCpyPara->pDoc->GetDfltTxtFmtColl(),
0, pCpyPara->nInsPos );
pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ];
if( bDummy )
pBox->setDummyFlag( true );
else if( pCpyPara->bCpyCntnt )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Copy the content into this empty Box
pBox->setRowSpan(rFndBox.GetBox()->getRowSpan());
2012-02-15 13:19:06 +01:00
// We can also copy formulas and values, if we copy the content
2000-09-18 23:08:29 +00:00
{
SfxItemSet aBoxAttrSet( pCpyPara->pDoc->GetAttrPool(),
RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
aBoxAttrSet.Put(rFndBox.GetBox()->GetFrmFmt()->GetAttrSet());
if( aBoxAttrSet.Count() )
2000-09-18 23:08:29 +00:00
{
const SfxPoolItem* pItem;
SvNumberFormatter* pN = pCpyPara->pDoc->GetNumberFormatter( sal_False );
if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
{
sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
if( nNewIdx != nOldIdx )
aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
}
pBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
2000-09-18 23:08:29 +00:00
}
}
SwDoc* pFromDoc = rFndBox.GetBox()->GetFrmFmt()->GetDoc();
SwNodeRange aCpyRg( *rFndBox.GetBox()->GetSttNd(), 1,
*rFndBox.GetBox()->GetSttNd()->EndOfSectionNode() );
SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 );
pFromDoc->CopyWithFlyInFly( aCpyRg, 0, aInsIdx, sal_False );
2012-02-15 13:19:06 +01:00
// Delete the initial TextNode
pCpyPara->pDoc->GetNodes().Delete( aInsIdx, 1 );
2000-09-18 23:08:29 +00:00
}
++pCpyPara->nInsPos;
}
if( nRealSize )
{
bDummy = false;
nSize = nRealSize;
nRealSize = 0;
}
else
{
bDummy = true;
nSize = nDummy2;
nDummy2 = 0;
2000-09-18 23:08:29 +00:00
}
}
while( nSize );
2000-09-18 23:08:29 +00:00
}
static void
lcl_CopyLineToDoc(const _FndLine& rFndLine, _CpyPara *const pCpyPara)
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Find the Frame Format in the list of all Frame Formats
_CpyTabFrm aFindFrm( (SwTableBoxFmt*)rFndLine.GetLine()->GetFrmFmt() );
sal_uInt16 nFndPos;
2000-09-18 23:08:29 +00:00
if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ))
{
2012-02-15 13:19:06 +01:00
// It doesn't exist yet, so copy it
2000-09-18 23:08:29 +00:00
aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pCpyPara->pDoc->MakeTableLineFmt();
aFindFrm.pNewFrmFmt->CopyAttrs( *rFndLine.GetLine()->GetFrmFmt() );
2000-09-18 23:08:29 +00:00
pCpyPara->rTabFrmArr.Insert( aFindFrm );
}
else
aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ];
SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)aFindFrm.pNewFrmFmt,
rFndLine.GetBoxes().size(), pCpyPara->pInsBox );
2000-09-18 23:08:29 +00:00
if( pCpyPara->pInsBox )
{
pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ );
}
else
{
pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
pCpyPara->nInsPos++ );
}
_CpyPara aPara( *pCpyPara, pNewLine );
if( pCpyPara->pTblNd->GetTable().IsNewModel() )
{
aPara.nOldSize = 0; // will not be used
aPara.nBoxIdx = 1;
}
else if( rFndLine.GetBoxes().size() ==
rFndLine.GetLine()->GetTabBoxes().Count() )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Get the Parent's size
2000-09-18 23:08:29 +00:00
const SwFrmFmt* pFmt;
if( rFndLine.GetLine()->GetUpper() )
pFmt = rFndLine.GetLine()->GetUpper()->GetFrmFmt();
2000-09-18 23:08:29 +00:00
else
pFmt = pCpyPara->pTblNd->GetTable().GetFrmFmt();
aPara.nOldSize = pFmt->GetFrmSize().GetWidth();
}
else
2012-02-15 13:19:06 +01:00
// Calculate it
for( sal_uInt16 n = 0; n < rFndLine.GetBoxes().size(); ++n )
{
aPara.nOldSize += rFndLine.GetBoxes()[n]
.GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
}
2000-09-18 23:08:29 +00:00
const _FndBoxes& rBoxes = rFndLine.GetBoxes();
for (_FndBoxes::const_iterator it = rBoxes.begin(); it != rBoxes.end(); ++it)
lcl_CopyBoxToDoc(*it, &aPara);
if( pCpyPara->pTblNd->GetTable().IsNewModel() )
++pCpyPara->nLnIdx;
2000-09-18 23:08:29 +00:00
}
sal_Bool SwTable::CopyHeadlineIntoTable( SwTableNode& rTblNd )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
2000-09-18 23:08:29 +00:00
SwSelBoxes aSelBoxes;
SwTableBox* pBox = GetTabSortBoxes()[ 0 ];
pBox = GetTblBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
SelLineFromBox( pBox, aSelBoxes, sal_True );
2000-09-18 23:08:29 +00:00
_FndBox aFndBox( 0, 0 );
{
_FndPara aPara( aSelBoxes, &aFndBox );
((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
}
if( aFndBox.GetLines().empty() )
return sal_False;
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Convert Table formulas to their relative representation
2000-09-18 23:08:29 +00:00
SwTableFmlUpdate aMsgHnt( this );
aMsgHnt.eFlags = TBL_RELBOXNAME;
GetFrmFmt()->GetDoc()->UpdateTblFlds( &aMsgHnt );
}
_CpyTabFrms aCpyFmt;
_CpyPara aPara( &rTblNd, 1, aCpyFmt, sal_True );
2000-09-18 23:08:29 +00:00
aPara.nNewSize = aPara.nOldSize = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
2012-02-15 13:19:06 +01:00
// Copy
if( IsNewModel() )
lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
BOOST_FOREACH( _FndLine& rFndLine, aFndBox.GetLines() )
lcl_CopyLineToDoc( rFndLine, &aPara );
if( rTblNd.GetTable().IsNewModel() )
{ // The copied line must not contain any row span attributes > 1
SwTableLine* pLine = rTblNd.GetTable().GetTabLines()[0];
sal_uInt16 nColCount = pLine->GetTabBoxes().Count();
OSL_ENSURE( nColCount, "Empty Table Line" );
for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol )
{
SwTableBox* pTableBox = pLine->GetTabBoxes()[nCurrCol];
OSL_ENSURE( pTableBox, "Missing Table Box" );
pTableBox->setRowSpan( 1 );
}
}
2000-09-18 23:08:29 +00:00
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool SwTable::MakeCopy( SwDoc* pInsDoc, const SwPosition& rPos,
const SwSelBoxes& rSelBoxes, sal_Bool bCpyNds,
sal_Bool bCpyName ) const
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
_FndBox aFndBox( 0, 0 );
{
_FndPara aPara( rSelBoxes, &aFndBox );
((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
}
if( aFndBox.GetLines().empty() )
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// First copy the PoolTemplates for the Table, so that the Tables are
// actually copied and have valid values.
2000-09-18 23:08:29 +00:00
SwDoc* pSrcDoc = GetFrmFmt()->GetDoc();
if( pSrcDoc != pInsDoc )
{
pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE ) );
pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN ) );
}
SwTable* pNewTbl = (SwTable*)pInsDoc->InsertTable(
SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ),
rPos, 1, 1, GetFrmFmt()->GetHoriOrient().GetHoriOrient(),
0, 0, sal_False, IsNewModel() );
2000-09-18 23:08:29 +00:00
if( !pNewTbl )
return sal_False;
2000-09-18 23:08:29 +00:00
SwNodeIndex aIdx( rPos.nNode, -1 );
SwTableNode* pTblNd = aIdx.GetNode().FindTableNode();
aIdx++;
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pTblNd, "Where is the TableNode now?" );
2000-09-18 23:08:29 +00:00
pTblNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
2000-09-18 23:08:29 +00:00
if( IS_TYPE( SwDDETable, this ))
{
2012-02-15 13:19:06 +01:00
// A DDE-Table is being copied
// Does the new Document actually have it's FieldType?
2000-09-18 23:08:29 +00:00
SwFieldType* pFldType = pInsDoc->InsertFldType(
*((SwDDETable*)this)->GetDDEFldType() );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pFldType, "unknown FieldType" );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Change the Table Pointer at the Node
2000-09-18 23:08:29 +00:00
pNewTbl = new SwDDETable( *pNewTbl,
(SwDDEFieldType*)pFldType );
pTblNd->SetNewTable( pNewTbl, sal_False );
2000-09-18 23:08:29 +00:00
}
pNewTbl->GetFrmFmt()->CopyAttrs( *GetFrmFmt() );
pNewTbl->SetTblChgMode( GetTblChgMode() );
2012-02-15 13:19:06 +01:00
// Destroy the already created Frames
2000-09-18 23:08:29 +00:00
pTblNd->DelFrms();
{
2012-02-15 13:19:06 +01:00
// Conver the Table formulas to their relative representation
2000-09-18 23:08:29 +00:00
SwTableFmlUpdate aMsgHnt( this );
aMsgHnt.eFlags = TBL_RELBOXNAME;
pSrcDoc->UpdateTblFlds( &aMsgHnt );
}
SwTblNumFmtMerge aTNFM( *pSrcDoc, *pInsDoc );
2012-02-15 13:19:06 +01:00
// Also copy Names or enforce a new unique one
2000-09-18 23:08:29 +00:00
if( bCpyName )
pNewTbl->GetFrmFmt()->SetName( GetFrmFmt()->GetName() );
_CpyTabFrms aCpyFmt;
_CpyPara aPara( pTblNd, 1, aCpyFmt, bCpyNds );
aPara.nNewSize = aPara.nOldSize = GetFrmFmt()->GetFrmSize().GetWidth();
if( IsNewModel() )
lcl_CalcNewWidths( aFndBox.GetLines(), aPara );
2012-02-15 13:19:06 +01:00
// Copy
BOOST_FOREACH( _FndLine& rFndLine, aFndBox.GetLines() )
lcl_CopyLineToDoc( rFndLine, &aPara );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Set the "right" margin above/below
2000-09-18 23:08:29 +00:00
{
_FndLine* pFndLn = &aFndBox.GetLines().front();
2000-09-18 23:08:29 +00:00
SwTableLine* pLn = pFndLn->GetLine();
const SwTableLine* pTmp = pLn;
sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp );
2000-09-18 23:08:29 +00:00
if( USHRT_MAX != nLnPos && nLnPos )
{
2012-02-15 13:19:06 +01:00
// There is a Line before it
SwCollectTblLineBoxes aLnPara( sal_False, HEADLINE_BORDERCOPY );
2000-09-18 23:08:29 +00:00
pLn = GetTabLines()[ nLnPos - 1 ];
pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
lcl_GetLineWidth( *pFndLn )) )
{
aLnPara.SetValues( sal_True );
2000-09-18 23:08:29 +00:00
pLn = pNewTbl->GetTabLines()[ 0 ];
pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
}
}
pFndLn = &aFndBox.GetLines().back();
2000-09-18 23:08:29 +00:00
pLn = pFndLn->GetLine();
pTmp = pLn;
nLnPos = GetTabLines().GetPos( pTmp );
if( nLnPos < GetTabLines().Count() - 1 )
{
2012-02-15 13:19:06 +01:00
// There is a Line following it
SwCollectTblLineBoxes aLnPara( sal_True, HEADLINE_BORDERCOPY );
2000-09-18 23:08:29 +00:00
pLn = GetTabLines()[ nLnPos + 1 ];
pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara );
if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ),
lcl_GetLineWidth( *pFndLn )) )
{
aLnPara.SetValues( sal_False );
2000-09-18 23:08:29 +00:00
pLn = pNewTbl->GetTabLines()[ pNewTbl->GetTabLines().Count()-1 ];
pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara );
}
}
}
2012-02-15 13:19:06 +01:00
// We need to delete the initial Box
2000-09-18 23:08:29 +00:00
_DeleteBox( *pNewTbl, pNewTbl->GetTabLines()[
pNewTbl->GetTabLines().Count() - 1 ]->GetTabBoxes()[0],
0, sal_False, sal_False );
2000-09-18 23:08:29 +00:00
if( pNewTbl->IsNewModel() )
lcl_CheckRowSpan( *pNewTbl );
2012-02-15 13:19:06 +01:00
// Clean up
2000-09-18 23:08:29 +00:00
pNewTbl->GCLines();
2012-02-15 13:19:06 +01:00
pTblNd->MakeFrms( &aIdx ); // re-generate the Frames
CHECKTABLELAYOUT
return sal_True;
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// Find the next Box with content from this Line
2000-09-18 23:08:29 +00:00
SwTableBox* SwTableLine::FindNextBox( const SwTable& rTbl,
const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
const SwTableLine* pLine = this; // for M800
2000-09-18 23:08:29 +00:00
SwTableBox* pBox;
sal_uInt16 nFndPos;
2000-09-18 23:08:29 +00:00
if( GetTabBoxes().Count() && pSrchBox &&
USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
nFndPos + 1 != GetTabBoxes().Count() )
{
pBox = GetTabBoxes()[ nFndPos + 1 ];
while( pBox->GetTabLines().Count() )
pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
return pBox;
}
if( GetUpper() )
{
nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
// Is there another Line?
2000-09-18 23:08:29 +00:00
if( nFndPos+1 >= GetUpper()->GetTabLines().Count() )
return GetUpper()->GetUpper()->FindNextBox( rTbl, GetUpper(), bOvrTblLns );
pLine = GetUpper()->GetTabLines()[nFndPos+1];
}
2012-02-15 13:19:06 +01:00
else if( bOvrTblLns ) // Over a Table's the "BaseLines"??
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Search for the next Line in the Table
2000-09-18 23:08:29 +00:00
nFndPos = rTbl.GetTabLines().GetPos( pLine );
if( nFndPos + 1 >= rTbl.GetTabLines().Count() )
2012-02-15 13:19:06 +01:00
return 0; // there are no more Boxes
2000-09-18 23:08:29 +00:00
pLine = rTbl.GetTabLines()[ nFndPos+1 ];
}
else
return 0;
if( pLine->GetTabBoxes().Count() )
{
pBox = pLine->GetTabBoxes()[0];
while( pBox->GetTabLines().Count() )
pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
return pBox;
}
return pLine->FindNextBox( rTbl, 0, bOvrTblLns );
}
2012-02-15 13:19:06 +01:00
// Find the previous Box from this Line
2000-09-18 23:08:29 +00:00
SwTableBox* SwTableLine::FindPreviousBox( const SwTable& rTbl,
const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
const SwTableLine* pLine = this; // for M800
2000-09-18 23:08:29 +00:00
SwTableBox* pBox;
sal_uInt16 nFndPos;
2000-09-18 23:08:29 +00:00
if( GetTabBoxes().Count() && pSrchBox &&
USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) &&
nFndPos )
{
pBox = GetTabBoxes()[ nFndPos - 1 ];
while( pBox->GetTabLines().Count() )
{
pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
}
return pBox;
}
if( GetUpper() )
{
nFndPos = GetUpper()->GetTabLines().GetPos( pLine );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( USHRT_MAX != nFndPos, "Line is not in the Table" );
// Is there another Line?
2000-09-18 23:08:29 +00:00
if( !nFndPos )
return GetUpper()->GetUpper()->FindPreviousBox( rTbl, GetUpper(), bOvrTblLns );
pLine = GetUpper()->GetTabLines()[nFndPos-1];
}
2012-02-15 13:19:06 +01:00
else if( bOvrTblLns ) // Over a Table's the "BaseLines"??
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Search for the next Line in the Table
2000-09-18 23:08:29 +00:00
nFndPos = rTbl.GetTabLines().GetPos( pLine );
if( !nFndPos )
2012-02-15 13:19:06 +01:00
return 0; // there are no more Boxes
2000-09-18 23:08:29 +00:00
pLine = rTbl.GetTabLines()[ nFndPos-1 ];
}
else
return 0;
if( pLine->GetTabBoxes().Count() )
{
pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
while( pBox->GetTabLines().Count() )
{
pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1];
pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1];
}
return pBox;
}
return pLine->FindPreviousBox( rTbl, 0, bOvrTblLns );
}
2012-02-15 13:19:06 +01:00
// Find the next Box with content from this Line
2000-09-18 23:08:29 +00:00
SwTableBox* SwTableBox::FindNextBox( const SwTable& rTbl,
const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
2000-09-18 23:08:29 +00:00
{
if( !pSrchBox && !GetTabLines().Count() )
return (SwTableBox*)this;
return GetUpper()->FindNextBox( rTbl, pSrchBox ? pSrchBox : this,
bOvrTblLns );
}
2012-02-15 13:19:06 +01:00
// Find the next Box with content from this Line
2000-09-18 23:08:29 +00:00
SwTableBox* SwTableBox::FindPreviousBox( const SwTable& rTbl,
const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const
2000-09-18 23:08:29 +00:00
{
if( !pSrchBox && !GetTabLines().Count() )
return (SwTableBox*)this;
return GetUpper()->FindPreviousBox( rTbl, pSrchBox ? pSrchBox : this,
bOvrTblLns );
}
sal_Bool lcl_BoxSetHeadCondColl( const SwTableBox*& rpBox, void* )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// We need to adapt the paragraphs with conditional templates in the HeadLine
2000-09-18 23:08:29 +00:00
const SwStartNode* pSttNd = rpBox->GetSttNd();
if( pSttNd )
pSttNd->CheckSectionCondColl();
else
((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_LineSetHeadCondColl, 0 );
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool lcl_LineSetHeadCondColl( const SwTableLine*& rpLine, void* )
2000-09-18 23:08:29 +00:00
{
((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 );
return sal_True;
2000-09-18 23:08:29 +00:00
}
SwTwips lcl_GetDistance( SwTableBox* pBox, sal_Bool bLeft )
2000-09-18 23:08:29 +00:00
{
sal_Bool bFirst = sal_True;
2000-09-18 23:08:29 +00:00
SwTwips nRet = 0;
SwTableLine* pLine;
while( pBox && 0 != ( pLine = pBox->GetUpper() ) )
{
sal_uInt16 nStt = 0, nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
2000-09-18 23:08:29 +00:00
if( bFirst && !bLeft )
++nPos;
bFirst = sal_False;
2000-09-18 23:08:29 +00:00
while( nStt < nPos )
nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrmFmt()
->GetFrmSize().GetWidth();
pBox = pLine->GetUpper();
}
return nRet;
}
sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
SwTableBox* pBox = rBoxes[ n ];
SwFrmFmt* pFmt = pBox->GetFrmFmt();
const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
SwTwips nWidth = rSz.GetWidth();
sal_Bool bGreaterBox = sal_False;
2000-09-18 23:08:29 +00:00
if( bCheck )
{
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
if( !::lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam,
nDist, sal_True ))
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Collect all "ContentBoxes"
if( ( 0 != ( bGreaterBox = TBLFIX_CHGABS != rParam.nMode && ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
( !rParam.bBigger && ( Abs( nDist + (( rParam.nMode && rParam.bLeft ) ? 0 : nWidth ) - rParam.nSide ) < COLFUZZY ) ) )
2000-09-18 23:08:29 +00:00
{
rParam.bAnyBoxFnd = sal_True;
2000-09-18 23:08:29 +00:00
SwTwips nLowerDiff;
if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
{
2012-02-15 13:19:06 +01:00
// The "other Boxes" have been adapted, so change by this value
2000-09-18 23:08:29 +00:00
nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
nLowerDiff *= rParam.nDiff;
nLowerDiff /= rParam.nMaxSize;
nLowerDiff = rParam.nDiff - nLowerDiff;
}
else
nLowerDiff = rParam.nDiff;
if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY )
return sal_False;
2000-09-18 23:08:29 +00:00
}
}
else
{
SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
{
rParam.nLowerDiff = 0;
lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, nDist, sal_False );
2000-09-18 23:08:29 +00:00
if( nLowerDiff < rParam.nLowerDiff )
nLowerDiff = rParam.nLowerDiff;
}
rParam.nLowerDiff = nOldLower;
if( nLowerDiff ||
( 0 != ( bGreaterBox = !nOldLower && TBLFIX_CHGABS != rParam.nMode &&
( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) ||
( Abs( nDist + ( (rParam.nMode && rParam.bLeft) ? 0 : nWidth )
- rParam.nSide ) < COLFUZZY ))
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// This column contains the Cursor - so decrease/increase
2000-09-18 23:08:29 +00:00
SwFmtFrmSize aNew( rSz );
if( !nLowerDiff )
{
if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode )
{
2012-02-15 13:19:06 +01:00
// The "other Boxes" have been adapted, so change by this value
2000-09-18 23:08:29 +00:00
nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide;
nLowerDiff *= rParam.nDiff;
nLowerDiff /= rParam.nMaxSize;
nLowerDiff = rParam.nDiff - nLowerDiff;
}
else
nLowerDiff = rParam.nDiff;
}
rParam.nLowerDiff += nLowerDiff;
if( rParam.bBigger )
aNew.SetWidth( nWidth + nLowerDiff );
else
aNew.SetWidth( nWidth - nLowerDiff );
rParam.aShareFmts.SetSize( *pBox, aNew );
break;
}
}
if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
break;
nDist += nWidth;
2012-02-15 13:19:06 +01:00
// If it gets bigger, then that's it
2000-09-18 23:08:29 +00:00
if( ( TBLFIX_CHGABS == rParam.nMode || !rParam.bLeft ) &&
nDist >= rParam.nSide )
break;
}
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
SwTableBox* pBox = rBoxes[ n ];
SwFrmFmt* pFmt = pBox->GetFrmFmt();
const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
SwTwips nWidth = rSz.GetWidth();
if( bCheck )
{
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
if( !::lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ],
rParam, nDist, sal_True ))
return sal_False;
2000-09-18 23:08:29 +00:00
if( rParam.bBigger && ( TBLFIX_CHGABS == rParam.nMode
? Abs( nDist - rParam.nSide ) < COLFUZZY
: ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
: nDist >= rParam.nSide - COLFUZZY )) )
{
rParam.bAnyBoxFnd = sal_True;
2000-09-18 23:08:29 +00:00
SwTwips nDiff;
2012-02-15 13:19:06 +01:00
if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// calculate relative
2000-09-18 23:08:29 +00:00
nDiff = nWidth;
nDiff *= rParam.nDiff;
nDiff /= rParam.nMaxSize;
}
else
nDiff = rParam.nDiff;
if( nWidth < nDiff || nWidth - nDiff < MINLAY )
return sal_False;
2000-09-18 23:08:29 +00:00
}
}
else
{
SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
{
rParam.nLowerDiff = 0;
lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], rParam,
nDist, sal_False );
2000-09-18 23:08:29 +00:00
if( nLowerDiff < rParam.nLowerDiff )
nLowerDiff = rParam.nLowerDiff;
}
rParam.nLowerDiff = nOldLower;
if( nLowerDiff ||
( TBLFIX_CHGABS == rParam.nMode
? Abs( nDist - rParam.nSide ) < COLFUZZY
: ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY
: nDist >= rParam.nSide - COLFUZZY)
) )
{
SwFmtFrmSize aNew( rSz );
if( !nLowerDiff )
{
2012-02-15 13:19:06 +01:00
if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// calculate relative
2000-09-18 23:08:29 +00:00
nLowerDiff = nWidth;
nLowerDiff *= rParam.nDiff;
nLowerDiff /= rParam.nMaxSize;
}
else
nLowerDiff = rParam.nDiff;
}
rParam.nLowerDiff += nLowerDiff;
if( rParam.bBigger )
aNew.SetWidth( nWidth - nLowerDiff );
else
aNew.SetWidth( nWidth + nLowerDiff );
rParam.aShareFmts.SetSize( *pBox, aNew );
}
}
nDist += nWidth;
if( ( TBLFIX_CHGABS == rParam.nMode || rParam.bLeft ) &&
nDist > rParam.nSide )
break;
}
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
sal_uInt16 n, nCmp;
2000-09-18 23:08:29 +00:00
for( n = 0; n < rBoxes.Count(); ++n )
{
SwTableBox* pBox = rBoxes[ n ];
SwTableBoxFmt* pFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
SwTwips nWidth = rSz.GetWidth();
if( bCheck )
{
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
if( !::lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam,
nDist, sal_True ))
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Collect all "ContentBoxes"
2000-09-18 23:08:29 +00:00
if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
- rParam.nSide ) < COLFUZZY )
nCmp = 1;
else if( nDist + ( rParam.bLeft ? 0 : nWidth/2 ) > rParam.nSide )
nCmp = 2;
else
nCmp = 0;
if( nCmp )
{
rParam.bAnyBoxFnd = sal_True;
2000-09-18 23:08:29 +00:00
if( pFmt->GetProtect().IsCntntProtected() )
return sal_False;
2000-09-18 23:08:29 +00:00
if( rParam.bSplittBox &&
nWidth - rParam.nDiff <= COLFUZZY +
2012-02-15 13:19:06 +01:00
( 567 / 2 /*leave room for at least 0.5 cm*/) )
return sal_False;
2000-09-18 23:08:29 +00:00
if( pBox->GetSttNd() )
rParam.aBoxes.Insert( pBox );
2000-09-18 23:08:29 +00:00
break;
}
}
else
{
SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
{
rParam.nLowerDiff = 0;
lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, nDist, sal_False );
2000-09-18 23:08:29 +00:00
if( nLowerDiff < rParam.nLowerDiff )
nLowerDiff = rParam.nLowerDiff;
}
rParam.nLowerDiff = nOldLower;
if( nLowerDiff )
nCmp = 1;
else if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth )
- rParam.nSide ) < COLFUZZY )
nCmp = 2;
else if( nDist + nWidth / 2 > rParam.nSide )
nCmp = 3;
else
nCmp = 0;
if( nCmp )
{
2012-02-15 13:19:06 +01:00
// This column contains the Cursor - so decrease/increase
2000-09-18 23:08:29 +00:00
if( 1 == nCmp )
{
if( !rParam.bSplittBox )
{
2012-02-15 13:19:06 +01:00
// the current Box on
2000-09-18 23:08:29 +00:00
SwFmtFrmSize aNew( rSz );
aNew.SetWidth( nWidth + rParam.nDiff );
rParam.aShareFmts.SetSize( *pBox, aNew );
}
}
else
{
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pBox->GetSttNd(), "This must be an EndBox!");
2000-09-18 23:08:29 +00:00
if( !rParam.bLeft && 3 != nCmp )
++n;
::_InsTblBox( pFmt->GetDoc(), rParam.pTblNd,
pLine, pFmt, pBox, n );
SwTableBox* pNewBox = rBoxes[ n ];
SwFmtFrmSize aNew( rSz );
aNew.SetWidth( rParam.nDiff );
rParam.aShareFmts.SetSize( *pNewBox, aNew );
2012-02-15 13:19:06 +01:00
// Special case: There is no space in the other Boxes, but in the Cell
2000-09-18 23:08:29 +00:00
if( rParam.bSplittBox )
{
2012-02-15 13:19:06 +01:00
// the current Box on
SwFmtFrmSize aNewSize( rSz );
aNewSize.SetWidth( nWidth - rParam.nDiff );
rParam.aShareFmts.SetSize( *pBox, aNewSize );
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// Special treatment for the Border
// The right one needs to be removed
2000-09-18 23:08:29 +00:00
{
const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox();
if( rBoxItem.GetRight() )
{
SvxBoxItem aTmp( rBoxItem );
aTmp.SetLine( 0, BOX_LINE_RIGHT );
rParam.aShareFmts.SetAttr( rParam.bLeft
? *pNewBox
: *pBox, aTmp );
}
}
}
rParam.nLowerDiff = rParam.nDiff;
break;
}
}
if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide )
break;
nDist += nWidth;
}
return sal_True;
2000-09-18 23:08:29 +00:00
}
sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Special case: There is no space in the other Boxes, but in the cell
2000-09-18 23:08:29 +00:00
if( rParam.bSplittBox )
return sal_True;
2000-09-18 23:08:29 +00:00
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
sal_uInt16 n;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Table fixed, proportional
2000-09-18 23:08:29 +00:00
if( !rParam.nRemainWidth && TBLFIX_CHGPROP == rParam.nMode )
{
2012-02-15 13:19:06 +01:00
// Find the right width to which the relative width adjustment
// corresponds to
2000-09-18 23:08:29 +00:00
SwTwips nTmpDist = nDist;
for( n = 0; n < rBoxes.Count(); ++n )
{
SwTwips nWidth = rBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth();
if( (nTmpDist + nWidth / 2 ) > rParam.nSide )
{
rParam.nRemainWidth = rParam.bLeft
? sal_uInt16(nTmpDist)
: sal_uInt16(rParam.nTblWidth - nTmpDist);
2000-09-18 23:08:29 +00:00
break;
}
nTmpDist += nWidth;
}
}
for( n = 0; n < rBoxes.Count(); ++n )
{
SwTableBox* pBox = rBoxes[ n ];
SwFrmFmt* pFmt = pBox->GetFrmFmt();
const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
SwTwips nWidth = rSz.GetWidth();
if( bCheck )
{
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
if( !::lcl_InsOtherBox( pBox->GetTabLines()[ i ],
rParam, nDist, sal_True ))
return sal_False;
2000-09-18 23:08:29 +00:00
if(
rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
(TBLFIX_CHGABS != rParam.nMode ||
2010-11-04 13:05:15 +01:00
(n < rBoxes.Count() &&
2010-09-30 18:34:49 +02:00
(nDist + nWidth + rBoxes[ n+1 ]->
GetFrmFmt()->GetFrmSize().GetWidth() / 2)
2010-11-04 13:05:15 +01:00
> rParam.nSide) ))
2000-09-18 23:08:29 +00:00
: (nDist + nWidth / 2 ) > rParam.nSide
)
{
rParam.bAnyBoxFnd = sal_True;
2000-09-18 23:08:29 +00:00
SwTwips nDiff;
2012-02-15 13:19:06 +01:00
if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2000-09-18 23:08:29 +00:00
{
// relativ berechnen
nDiff = nWidth;
nDiff *= rParam.nDiff;
nDiff /= rParam.nRemainWidth;
if( nWidth < nDiff || nWidth - nDiff < MINLAY )
return sal_False;
2000-09-18 23:08:29 +00:00
}
else
{
nDiff = rParam.nDiff;
2012-02-15 13:19:06 +01:00
// See if the left or right Box is big enough to give up space.
// We're inserting a Box before or after.
2000-09-18 23:08:29 +00:00
SwTwips nTmpWidth = nWidth;
if( rParam.bLeft && pBox->GetUpper()->GetUpper() )
{
const SwTableBox* pTmpBox = pBox;
sal_uInt16 nBoxPos = n;
2000-09-18 23:08:29 +00:00
while( !nBoxPos && pTmpBox->GetUpper()->GetUpper() )
{
pTmpBox = pTmpBox->GetUpper()->GetUpper();
nBoxPos = pTmpBox->GetUpper()->GetTabBoxes().GetPos( pTmpBox );
}
// if( nBoxPos )
nTmpWidth = pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
// else
// nTmpWidth = 0;
}
if( nTmpWidth < nDiff || nTmpWidth - nDiff < MINLAY )
return sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
}
else
{
SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff;
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
{
rParam.nLowerDiff = 0;
lcl_InsOtherBox( pBox->GetTabLines()[ i ], rParam,
nDist, sal_False );
2000-09-18 23:08:29 +00:00
if( nLowerDiff < rParam.nLowerDiff )
nLowerDiff = rParam.nLowerDiff;
}
rParam.nLowerDiff = nOldLower;
if( nLowerDiff ||
(rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide &&
(TBLFIX_CHGABS != rParam.nMode ||
2010-11-04 13:05:15 +01:00
(n < rBoxes.Count() &&
2010-09-30 18:34:49 +02:00
(nDist + nWidth + rBoxes[ n+1 ]->
GetFrmFmt()->GetFrmSize().GetWidth() / 2)
2010-11-04 13:05:15 +01:00
> rParam.nSide) ))
2000-09-18 23:08:29 +00:00
: (nDist + nWidth / 2 ) > rParam.nSide ))
{
if( !nLowerDiff )
{
2012-02-15 13:19:06 +01:00
if( TBLFIX_CHGPROP == rParam.nMode ) // Table fixed, proportional
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Calculate relatively
2000-09-18 23:08:29 +00:00
nLowerDiff = nWidth;
nLowerDiff *= rParam.nDiff;
nLowerDiff /= rParam.nRemainWidth;
}
else
nLowerDiff = rParam.nDiff;
}
SwFmtFrmSize aNew( rSz );
rParam.nLowerDiff += nLowerDiff;
if( rParam.bBigger )
aNew.SetWidth( nWidth - nLowerDiff );
else
aNew.SetWidth( nWidth + nLowerDiff );
rParam.aShareFmts.SetSize( *pBox, aNew );
if( TBLFIX_CHGABS == rParam.nMode )
break;
}
}
nDist += nWidth;
}
return sal_True;
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// The position comparison's result
// POS_BEFORE, // Box comes before
// POS_BEHIND, // Box comes after
// POS_INSIDE, // Box is completely wthin start/end
// POS_OUTSIDE, // Box overlaps start/end completely
// POS_EQUAL, // Box and start/end are the same
// POS_OVERLAP_BEFORE, // Box overlapps the start
// POS_OVERLAP_BEHIND // Box overlapps the end
SwComparePosition _CheckBoxInRange( sal_uInt16 nStt, sal_uInt16 nEnd,
sal_uInt16 nBoxStt, sal_uInt16 nBoxEnd )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Still treat COLFUZZY!
2000-09-18 23:08:29 +00:00
SwComparePosition nRet;
if( nBoxStt + COLFUZZY < nStt )
{
if( nBoxEnd > nStt + COLFUZZY )
{
if( nBoxEnd >= nEnd + COLFUZZY )
nRet = POS_OUTSIDE;
else
nRet = POS_OVERLAP_BEFORE;
}
else
nRet = POS_BEFORE;
}
else if( nEnd > nBoxStt + COLFUZZY )
{
if( nEnd + COLFUZZY >= nBoxEnd )
{
if( COLFUZZY > Abs( long(nEnd) - long(nBoxEnd) ) &&
COLFUZZY > Abs( long(nStt) - long(nBoxStt) ) )
nRet = POS_EQUAL;
else
nRet = POS_INSIDE;
}
else
nRet = POS_OVERLAP_BEHIND;
}
else
nRet = POS_BEHIND;
return nRet;
}
void lcl_DelSelBox_CorrLowers( SwTableLine& rLine, CR_SetBoxWidth& rParam,
SwTwips nWidth )
{
2012-02-15 13:19:06 +01:00
// 1. step: Calculate own width
2000-09-18 23:08:29 +00:00
SwTableBoxes& rBoxes = rLine.GetTabBoxes();
SwTwips nBoxWidth = 0;
sal_uInt16 n;
2000-09-18 23:08:29 +00:00
for( n = rBoxes.Count(); n; )
2000-09-18 23:08:29 +00:00
nBoxWidth += rBoxes[ --n ]->GetFrmFmt()->GetFrmSize().GetWidth();
if( COLFUZZY < Abs( nWidth - nBoxWidth ))
{
2012-02-15 13:19:06 +01:00
// Thus, they need to be adjusted
2000-09-18 23:08:29 +00:00
for( n = rBoxes.Count(); n; )
{
SwTableBox* pBox = rBoxes[ --n ];
SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() );
long nDiff = aNew.GetWidth();
nDiff *= nWidth;
nDiff /= nBoxWidth;
aNew.SetWidth( nDiff );
rParam.aShareFmts.SetSize( *pBox, aNew );
if( !pBox->GetSttNd() )
{
2012-02-15 13:19:06 +01:00
// Has Lower itself, so also adjust that
for( sal_uInt16 i = pBox->GetTabLines().Count(); i; )
2000-09-18 23:08:29 +00:00
::lcl_DelSelBox_CorrLowers( *pBox->GetTabLines()[ --i ],
rParam, nDiff );
}
}
}
}
void lcl_ChgBoxSize( SwTableBox& rBox, CR_SetBoxWidth& rParam,
const SwFmtFrmSize& rOldSz,
sal_uInt16& rDelWidth, SwTwips nDist )
2000-09-18 23:08:29 +00:00
{
2010-12-01 13:03:57 +01:00
long nDiff = 0;
sal_Bool bSetSize = sal_False;
2000-09-18 23:08:29 +00:00
switch( rParam.nMode )
{
2012-02-15 13:19:06 +01:00
case TBLFIX_CHGABS: // Fixed width table, change neighbor
2000-09-18 23:08:29 +00:00
nDiff = rDelWidth + rParam.nLowerDiff;
bSetSize = sal_True;
2000-09-18 23:08:29 +00:00
break;
2012-02-15 13:19:06 +01:00
case TBLFIX_CHGPROP: // Fixed width table, change all neighbors
2000-09-18 23:08:29 +00:00
if( !rParam.nRemainWidth )
{
2012-02-15 13:19:06 +01:00
// Calculate
2000-09-18 23:08:29 +00:00
if( rParam.bLeft )
rParam.nRemainWidth = sal_uInt16(nDist);
2000-09-18 23:08:29 +00:00
else
rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist);
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// Calculate relatively
2000-09-18 23:08:29 +00:00
nDiff = rOldSz.GetWidth();
nDiff *= rDelWidth + rParam.nLowerDiff;
nDiff /= rParam.nRemainWidth;
bSetSize = sal_True;
2000-09-18 23:08:29 +00:00
break;
2012-02-15 13:19:06 +01:00
case TBLVAR_CHGABS: // Variable table, change all neighbors
2000-09-18 23:08:29 +00:00
if( COLFUZZY < Abs( rParam.nBoxWidth -
( rDelWidth + rParam.nLowerDiff )))
{
nDiff = rDelWidth + rParam.nLowerDiff - rParam.nBoxWidth;
if( 0 < nDiff )
rDelWidth = rDelWidth - sal_uInt16(nDiff);
2000-09-18 23:08:29 +00:00
else
rDelWidth = rDelWidth + sal_uInt16(-nDiff);
bSetSize = sal_True;
2000-09-18 23:08:29 +00:00
}
break;
}
if( bSetSize )
{
SwFmtFrmSize aNew( rOldSz );
aNew.SetWidth( aNew.GetWidth() + nDiff );
rParam.aShareFmts.SetSize( rBox, aNew );
2012-02-15 13:19:06 +01:00
// Change the Lower once again
for( sal_uInt16 i = rBox.GetTabLines().Count(); i; )
2000-09-18 23:08:29 +00:00
::lcl_DelSelBox_CorrLowers( *rBox.GetTabLines()[ --i ], rParam,
aNew.GetWidth() );
}
}
sal_Bool lcl_DeleteBox_Rekursiv( CR_SetBoxWidth& rParam, SwTableBox& rBox,
sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
sal_Bool bRet = sal_True;
2000-09-18 23:08:29 +00:00
if( rBox.GetSttNd() )
{
if( bCheck )
{
rParam.bAnyBoxFnd = sal_True;
2000-09-18 23:08:29 +00:00
if( rBox.GetFrmFmt()->GetProtect().IsCntntProtected() )
bRet = sal_False;
2000-09-18 23:08:29 +00:00
else
{
SwTableBox* pBox = &rBox;
rParam.aBoxes.Insert( pBox );
2000-09-18 23:08:29 +00:00
}
}
else
::_DeleteBox( rParam.pTblNd->GetTable(), &rBox,
rParam.pUndo, sal_False, sal_True, &rParam.aShareFmts );
2000-09-18 23:08:29 +00:00
}
else
{
2012-02-15 13:19:06 +01:00
// We need to delete these sequentially via the ContentBoxes
for( sal_uInt16 i = rBox.GetTabLines().Count(); i; )
2000-09-18 23:08:29 +00:00
{
SwTableLine& rLine = *rBox.GetTabLines()[ --i ];
for( sal_uInt16 n = rLine.GetTabBoxes().Count(); n; )
2000-09-18 23:08:29 +00:00
if( !::lcl_DeleteBox_Rekursiv( rParam,
*rLine.GetTabBoxes()[ --n ], bCheck ))
return sal_False;
2000-09-18 23:08:29 +00:00
}
}
return bRet;
}
sal_Bool lcl_DelSelBox( SwTableLine* pTabLine, CR_SetBoxWidth& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
sal_uInt16 n, nCntEnd, nBoxChkStt, nBoxChkEnd, nDelWidth = 0;
2000-09-18 23:08:29 +00:00
if( rParam.bLeft )
{
n = rBoxes.Count();
nCntEnd = 0;
nBoxChkStt = (sal_uInt16)rParam.nSide;
nBoxChkEnd = static_cast<sal_uInt16>(rParam.nSide + rParam.nBoxWidth);
2000-09-18 23:08:29 +00:00
}
else
{
n = 0;
nCntEnd = rBoxes.Count();
nBoxChkStt = static_cast<sal_uInt16>(rParam.nSide - rParam.nBoxWidth);
nBoxChkEnd = (sal_uInt16)rParam.nSide;
2000-09-18 23:08:29 +00:00
}
while( n != nCntEnd )
{
SwTableBox* pBox;
if( rParam.bLeft )
pBox = rBoxes[ --n ];
else
pBox = rBoxes[ n++ ];
SwFrmFmt* pFmt = pBox->GetFrmFmt();
const SwFmtFrmSize& rSz = pFmt->GetFrmSize();
long nWidth = rSz.GetWidth();
sal_Bool bDelBox = sal_False, bChgLowers = sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Test the Box width and react accordingly
2000-09-18 23:08:29 +00:00
SwComparePosition ePosType = ::_CheckBoxInRange(
nBoxChkStt, nBoxChkEnd,
sal_uInt16(rParam.bLeft ? nDist - nWidth : nDist),
sal_uInt16(rParam.bLeft ? nDist : nDist + nWidth));
2000-09-18 23:08:29 +00:00
switch( ePosType )
{
case POS_BEFORE:
if( bCheck )
{
if( rParam.bLeft )
return sal_True;
2000-09-18 23:08:29 +00:00
}
else if( rParam.bLeft )
{
::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
if( TBLFIX_CHGABS == rParam.nMode )
n = nCntEnd;
}
break;
case POS_BEHIND:
if( bCheck )
{
if( !rParam.bLeft )
return sal_True;
2000-09-18 23:08:29 +00:00
}
else if( !rParam.bLeft )
{
::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
if( TBLFIX_CHGABS == rParam.nMode )
n = nCntEnd;
}
break;
2012-02-15 13:19:06 +01:00
case POS_OUTSIDE: // Box fully overlaps start/end
case POS_INSIDE: // Box is completely within start/end
case POS_EQUAL: // Box and start/end are the same
bDelBox = sal_True;
2000-09-18 23:08:29 +00:00
break;
2012-02-15 13:19:06 +01:00
case POS_OVERLAP_BEFORE: // Box overlaps the start
2000-09-18 23:08:29 +00:00
if( nBoxChkStt <= ( nDist + (rParam.bLeft ? - nWidth / 2
: nWidth / 2 )))
{
if( !pBox->GetSttNd() )
bChgLowers = sal_True;
2000-09-18 23:08:29 +00:00
else
bDelBox = sal_True;
2000-09-18 23:08:29 +00:00
}
else if( !bCheck && rParam.bLeft )
{
if( !pBox->GetSttNd() )
bChgLowers = sal_True;
2000-09-18 23:08:29 +00:00
else
{
::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist );
if( TBLFIX_CHGABS == rParam.nMode )
n = nCntEnd;
}
}
break;
2012-02-15 13:19:06 +01:00
case POS_OVERLAP_BEHIND: // Box overlaps the end
2000-09-18 23:08:29 +00:00
// JP 10.02.99:
2012-02-15 13:19:06 +01:00
// Delete generally or (like in OVERLAP_BEFORE) only delete the one who reaches up to the half into the delete Box?
2000-09-18 23:08:29 +00:00
if( !pBox->GetSttNd() )
bChgLowers = sal_True;
2000-09-18 23:08:29 +00:00
else
bDelBox = sal_True;
2000-09-18 23:08:29 +00:00
break;
default: break;
2000-09-18 23:08:29 +00:00
}
if( bDelBox )
{
nDelWidth = nDelWidth + sal_uInt16(nWidth);
2000-09-18 23:08:29 +00:00
if( bCheck )
{
2012-02-15 13:19:06 +01:00
// The last/first Box can only be deleted for the variable Table,
// if it's as large as the change in the Table.
2000-09-18 23:08:29 +00:00
if( (( TBLVAR_CHGABS != rParam.nMode ||
nDelWidth != rParam.nBoxWidth ) &&
COLFUZZY > Abs( rParam.bLeft
? nWidth - nDist
: (nDist + nWidth - rParam.nTblWidth )))
|| !::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ) )
return sal_False;
2000-09-18 23:08:29 +00:00
if( pFmt->GetProtect().IsCntntProtected() )
return sal_False;
2000-09-18 23:08:29 +00:00
}
else
{
::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck );
if( !rParam.bLeft )
--n, --nCntEnd;
}
}
else if( bChgLowers )
{
sal_Bool bFirst = sal_True, bCorrLowers = sal_False;
2000-09-18 23:08:29 +00:00
long nLowerDiff = 0;
long nOldLower = rParam.nLowerDiff;
sal_uInt16 nOldRemain = rParam.nRemainWidth;
sal_uInt16 i;
2000-09-18 23:08:29 +00:00
for( i = pBox->GetTabLines().Count(); i; )
2000-09-18 23:08:29 +00:00
{
rParam.nLowerDiff = nDelWidth + nOldLower;
rParam.nRemainWidth = nOldRemain;
SwTableLine* pLine = pBox->GetTabLines()[ --i ];
if( !::lcl_DelSelBox( pLine, rParam, nDist, bCheck ))
return sal_False;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Do the Box and its Lines still exist?
2000-09-18 23:08:29 +00:00
if( n < rBoxes.Count() &&
pBox == rBoxes[ rParam.bLeft ? n : n-1 ] &&
i < pBox->GetTabLines().Count() &&
pLine == pBox->GetTabLines()[ i ] )
{
if( !bFirst && !bCorrLowers &&
COLFUZZY < Abs( nLowerDiff - rParam.nLowerDiff ) )
bCorrLowers = sal_True;
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// The largest deletion width counts, but only if we don't
// delete the whole Line
2000-09-18 23:08:29 +00:00
if( nLowerDiff < rParam.nLowerDiff )
nLowerDiff = rParam.nLowerDiff;
bFirst = sal_False;
2000-09-18 23:08:29 +00:00
}
}
rParam.nLowerDiff = nOldLower;
rParam.nRemainWidth = nOldRemain;
2012-02-15 13:19:06 +01:00
// Did we delete all Boxes? Then the deletion width = the Box width, of course
2000-09-18 23:08:29 +00:00
if( !nLowerDiff )
nLowerDiff = nWidth;
2012-02-15 13:19:06 +01:00
// Adjust deletion width!
nDelWidth = nDelWidth + sal_uInt16(nLowerDiff);
2000-09-18 23:08:29 +00:00
if( !bCheck )
{
2012-02-15 13:19:06 +01:00
// Has the Box already been removed?
2000-09-18 23:08:29 +00:00
if( n > rBoxes.Count() ||
pBox != rBoxes[ ( rParam.bLeft ? n : n-1 ) ] )
{
2012-02-15 13:19:06 +01:00
// Then change the loop variable when deleting to the right
2000-09-18 23:08:29 +00:00
if( !rParam.bLeft )
--n, --nCntEnd;
}
else
{
2012-02-15 13:19:06 +01:00
// Or else we need to adapt the Box's size
2000-09-18 23:08:29 +00:00
SwFmtFrmSize aNew( rSz );
sal_Bool bCorrRel = sal_False;
2000-09-18 23:08:29 +00:00
if( TBLVAR_CHGABS != rParam.nMode )
{
switch( ePosType )
{
2012-02-15 13:19:06 +01:00
case POS_OVERLAP_BEFORE: // Box overlaps the start
2000-09-18 23:08:29 +00:00
if( TBLFIX_CHGPROP == rParam.nMode )
bCorrRel = rParam.bLeft;
else if( rParam.bLeft ) // TBLFIX_CHGABS
{
nLowerDiff = nLowerDiff - nDelWidth;
bCorrLowers = sal_True;
2000-09-18 23:08:29 +00:00
n = nCntEnd;
}
break;
2012-02-15 13:19:06 +01:00
case POS_OVERLAP_BEHIND: // Box overlaps the end
2000-09-18 23:08:29 +00:00
if( TBLFIX_CHGPROP == rParam.nMode )
bCorrRel = !rParam.bLeft;
else if( !rParam.bLeft ) // TBLFIX_CHGABS
{
nLowerDiff = nLowerDiff - nDelWidth;
bCorrLowers = sal_True;
2000-09-18 23:08:29 +00:00
n = nCntEnd;
}
break;
default:
2012-02-15 13:19:06 +01:00
OSL_ENSURE( !pBox, "we should never reach this!" );
2000-09-18 23:08:29 +00:00
break;
}
}
if( bCorrRel )
{
if( !rParam.nRemainWidth )
{
2012-02-15 13:19:06 +01:00
// Calculate
2000-09-18 23:08:29 +00:00
if( rParam.bLeft )
rParam.nRemainWidth = sal_uInt16(nDist - nLowerDiff);
2000-09-18 23:08:29 +00:00
else
rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist
2000-09-18 23:08:29 +00:00
- nLowerDiff );
}
long nDiff = aNew.GetWidth() - nLowerDiff;
nDiff *= nDelWidth + rParam.nLowerDiff;
nDiff /= rParam.nRemainWidth;
aNew.SetWidth( aNew.GetWidth() - nLowerDiff + nDiff );
}
else
aNew.SetWidth( aNew.GetWidth() - nLowerDiff );
rParam.aShareFmts.SetSize( *pBox, aNew );
if( bCorrLowers )
{
2012-02-15 13:19:06 +01:00
// Adapt the Lower once again
2000-09-18 23:08:29 +00:00
for( i = pBox->GetTabLines().Count(); i; )
::lcl_DelSelBox_CorrLowers( *pBox->
GetTabLines()[ --i ], rParam, aNew.GetWidth() );
}
}
}
}
if( rParam.bLeft )
nDist -= nWidth;
else
nDist += nWidth;
}
rParam.nLowerDiff = nDelWidth;
return sal_True;
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// Dummy function for the method SetColWidth
sal_Bool lcl_DelOtherBox( SwTableLine* , CR_SetBoxWidth& , SwTwips , sal_Bool )
2000-09-18 23:08:29 +00:00
{
return sal_True;
2000-09-18 23:08:29 +00:00
}
void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam )
{
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
SwTableBox* pBox = rBoxes[ n ];
SwFmtFrmSize aSz( pBox->GetFrmFmt()->GetFrmSize() );
SwTwips nWidth = aSz.GetWidth();
nWidth *= rParam.nDiff;
nWidth /= rParam.nMaxSize;
aSz.SetWidth( nWidth );
rParam.aShareFmts.SetSize( *pBox, aSz );
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
::lcl_AjustLines( pBox->GetTabLines()[ i ], rParam );
}
}
#ifdef DBG_UTIL
2000-09-18 23:08:29 +00:00
void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize )
{
const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
SwTwips nAktSize = 0;
2012-02-15 13:19:06 +01:00
// See if the tables have a correct width
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
const SwTableBox* pBox = rBoxes[ n ];
const SwTwips nBoxW = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
2000-09-18 23:08:29 +00:00
nAktSize += nBoxW;
for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
_CheckBoxWidth( *pBox->GetTabLines()[ i ], nBoxW );
}
if( Abs( nAktSize - nSize ) > ( COLFUZZY * rBoxes.Count() ) )
{
2012-02-15 13:19:06 +01:00
OSL_FAIL( "Line's Boxes are too small or too large" );
2000-09-18 23:08:29 +00:00
}
}
#endif
_FndBox* lcl_SaveInsDelData( CR_SetBoxWidth& rParam, SwUndo** ppUndo,
SwTableSortBoxes& rTmpLst, SwTwips nDistStt )
{
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
2000-09-18 23:08:29 +00:00
SwTable& rTbl = rParam.pTblNd->GetTable();
if( !rParam.aBoxes.Count() )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Get the Boxes
2000-09-18 23:08:29 +00:00
if( rParam.bBigger )
for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n )
::lcl_DelSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True );
2000-09-18 23:08:29 +00:00
else
for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n )
::lcl_InsSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True );
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// Prevent deleting the whole Table
if( rParam.bBigger && rParam.aBoxes.Count() == rTbl.GetTabSortBoxes().Count() )
2000-09-18 23:08:29 +00:00
return 0;
_FndBox* pFndBox = new _FndBox( 0, 0 );
2000-09-18 23:08:29 +00:00
if( rParam.bBigger )
pFndBox->SetTableLines( rParam.aBoxes, rTbl );
else
{
_FndPara aPara( rParam.aBoxes, pFndBox );
rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
OSL_ENSURE( pFndBox->GetLines().size(), "Where are the Boxes" );
2000-09-18 23:08:29 +00:00
pFndBox->SetTableLines( rTbl );
if( ppUndo )
rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
}
2012-02-15 13:19:06 +01:00
// Find Lines for the Layout update
2000-09-18 23:08:29 +00:00
pFndBox->DelFrms( rTbl );
// TL_CHART2: this function gest called from SetColWidth exclusively,
// thus it is currently speculated that nothing needs to be done here.
// Note: that SetColWidth is currently not completely understood though :-(
2000-09-18 23:08:29 +00:00
return pFndBox;
}
sal_Bool SwTable::SetColWidth( SwTableBox& rAktBox, sal_uInt16 eType,
2000-09-18 23:08:29 +00:00
SwTwips nAbsDiff, SwTwips nRelDiff, SwUndo** ppUndo )
{
2012-02-15 13:19:06 +01:00
SetHTMLTableLayout( 0 ); // Delete HTML Layout
2000-09-18 23:08:29 +00:00
const SwFmtFrmSize& rSz = GetFrmFmt()->GetFrmSize();
const SvxLRSpaceItem& rLR = GetFrmFmt()->GetLRSpace();
2012-02-15 13:19:06 +01:00
_FndBox* pFndBox = 0; // for insertion/deletion
SwTableSortBoxes aTmpLst( 0 ); // for Undo
sal_Bool bBigger,
bRet = sal_False,
bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) ||
nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ),
bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
sal_uInt16 n;
sal_uLong nBoxIdx = rAktBox.GetSttIdx();
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Get the current Box's edge
// Only needed for manipulating the width
const SwTwips nDist = ::lcl_GetDistance( &rAktBox, bLeft );
SwTwips nDistStt = 0;
2000-09-18 23:08:29 +00:00
CR_SetBoxWidth aParam( eType, nRelDiff, nDist, rSz.GetWidth(),
bLeft ? nDist : rSz.GetWidth() - nDist,
(SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
bBigger = aParam.bBigger;
FN_lcl_SetBoxWidth fnSelBox, fnOtherBox;
if( bInsDel )
{
if( bBigger )
{
fnSelBox = lcl_DelSelBox;
fnOtherBox = lcl_DelOtherBox;
aParam.nBoxWidth = (sal_uInt16)rAktBox.GetFrmFmt()->GetFrmSize().GetWidth();
2000-09-18 23:08:29 +00:00
if( bLeft )
nDistStt = rSz.GetWidth();
}
else
{
fnSelBox = lcl_InsSelBox;
fnOtherBox = lcl_InsOtherBox;
}
}
else
{
fnSelBox = lcl_SetSelBoxWidth;
fnOtherBox = lcl_SetOtherBoxWidth;
}
switch( eType & 0xff )
{
case nsTblChgWidthHeightType::WH_COL_RIGHT:
case nsTblChgWidthHeightType::WH_COL_LEFT:
2000-09-18 23:08:29 +00:00
if( TBLVAR_CHGABS == eTblChgMode )
{
if( bInsDel )
bBigger = !bBigger;
2012-02-15 13:19:06 +01:00
// First test if we have room at all
sal_Bool bChgLRSpace = sal_True;
2000-09-18 23:08:29 +00:00
if( bBigger )
{
if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
2000-09-18 23:08:29 +00:00
!rSz.GetWidthPercent() )
{
bRet = rSz.GetWidth() < USHRT_MAX - nRelDiff;
bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff
: rLR.GetRight() >= nAbsDiff;
}
else
bRet = bLeft ? rLR.GetLeft() >= nAbsDiff
: rLR.GetRight() >= nAbsDiff;
if( !bRet && bInsDel &&
2012-02-15 13:19:06 +01:00
// Is the room on the other side?
2000-09-18 23:08:29 +00:00
( bLeft ? rLR.GetRight() >= nAbsDiff
: rLR.GetLeft() >= nAbsDiff ))
{
bRet = sal_True; bLeft = !bLeft;
2000-09-18 23:08:29 +00:00
}
if( !bRet )
{
2012-02-15 13:19:06 +01:00
// Then call itself recursively; only with another mode (proportional)
2000-09-18 23:08:29 +00:00
TblChgMode eOld = eTblChgMode;
eTblChgMode = TBLFIX_CHGPROP;
bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
ppUndo );
eTblChgMode = eOld;
return bRet;
}
}
else
{
bRet = sal_True;
2000-09-18 23:08:29 +00:00
for( n = 0; n < aLines.Count(); ++n )
{
aParam.LoopClear();
if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
2000-09-18 23:08:29 +00:00
{
bRet = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
}
if( bRet )
{
if( bInsDel )
{
pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
aTmpLst, nDistStt );
if( aParam.bBigger && aParam.aBoxes.Count() ==
aSortCntBoxes.Count() )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// This whole Table is to be deleted!
2000-09-18 23:08:29 +00:00
GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
return sal_False;
2000-09-18 23:08:29 +00:00
}
if( ppUndo )
*ppUndo = aParam.CreateUndo(
aParam.bBigger ? UNDO_COL_DELETE
2000-09-18 23:08:29 +00:00
: UNDO_TABLE_INSCOL );
}
else if( ppUndo )
*ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
2000-09-18 23:08:29 +00:00
long nFrmWidth = LONG_MAX;
LockModify();
SwFmtFrmSize aSz( rSz );
SvxLRSpaceItem aLR( rLR );
if( bBigger )
{
2012-02-15 13:19:06 +01:00
// If the Table does not have any room to grow, we need to create some!
2000-09-18 23:08:29 +00:00
if( aSz.GetWidth() + nRelDiff > USHRT_MAX )
{
2012-02-15 13:19:06 +01:00
// Break down to USHRT_MAX / 2
2000-09-18 23:08:29 +00:00
CR_SetBoxWidth aTmpPara( 0, aSz.GetWidth() / 2,
0, aSz.GetWidth(), aSz.GetWidth(), aParam.pTblNd );
for( sal_uInt16 nLn = 0; nLn < aLines.Count(); ++nLn )
::lcl_AjustLines( aLines[ nLn ], aTmpPara );
2000-09-18 23:08:29 +00:00
aSz.SetWidth( aSz.GetWidth() / 2 );
aParam.nDiff = nRelDiff /= 2;
aParam.nSide /= 2;
aParam.nMaxSize /= 2;
}
if( bLeft )
aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) );
2000-09-18 23:08:29 +00:00
else
aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) );
2000-09-18 23:08:29 +00:00
}
else if( bLeft )
aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) );
2000-09-18 23:08:29 +00:00
else
aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) );
2000-09-18 23:08:29 +00:00
if( bChgLRSpace )
GetFrmFmt()->SetFmtAttr( aLR );
2000-09-18 23:08:29 +00:00
const SwFmtHoriOrient& rHOri = GetFrmFmt()->GetHoriOrient();
if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() ||
(text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) ||
(text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight()))
2000-09-18 23:08:29 +00:00
{
SwFmtHoriOrient aHOri( rHOri );
aHOri.SetHoriOrient( text::HoriOrientation::NONE );
GetFrmFmt()->SetFmtAttr( aHOri );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// If the Table happens to contain relative values (USHORT_MAX),
// we need to convert them to absolute ones now.
// Bug 61494
if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) &&
2000-09-18 23:08:29 +00:00
!rSz.GetWidthPercent() )
{
SwTabFrm* pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() );
2000-09-18 23:08:29 +00:00
if( pTabFrm &&
pTabFrm->Prt().Width() != rSz.GetWidth() )
{
nFrmWidth = pTabFrm->Prt().Width();
if( bBigger )
nFrmWidth += nAbsDiff;
else
nFrmWidth -= nAbsDiff;
}
}
}
if( bBigger )
aSz.SetWidth( aSz.GetWidth() + nRelDiff );
else
aSz.SetWidth( aSz.GetWidth() - nRelDiff );
if( rSz.GetWidthPercent() )
aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) /
( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft())));
2000-09-18 23:08:29 +00:00
GetFrmFmt()->SetFmtAttr( aSz );
aParam.nTblWidth = sal_uInt16( aSz.GetWidth() );
2000-09-18 23:08:29 +00:00
UnlockModify();
for( n = aLines.Count(); n; )
{
--n;
aParam.LoopClear();
(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// If the Table happens to contain relative values (USHORT_MAX),
// we need to convert them to absolute ones now.
// Bug 61494
2000-09-18 23:08:29 +00:00
if( LONG_MAX != nFrmWidth )
{
SwFmtFrmSize aAbsSz( aSz );
aAbsSz.SetWidth( nFrmWidth );
GetFrmFmt()->SetFmtAttr( aAbsSz );
2000-09-18 23:08:29 +00:00
}
}
}
else if( bInsDel ||
( bLeft ? nDist : Abs( rSz.GetWidth() - nDist ) > COLFUZZY ) )
{
bRet = sal_True;
2000-09-18 23:08:29 +00:00
if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
aParam.bBigger = !bBigger;
2012-02-15 13:19:06 +01:00
// First test if we have room at all
2000-09-18 23:08:29 +00:00
if( bInsDel )
{
if( aParam.bBigger )
{
for( n = 0; n < aLines.Count(); ++n )
{
aParam.LoopClear();
if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
2000-09-18 23:08:29 +00:00
{
bRet = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
}
else
{
if( 0 != ( bRet = bLeft ? nDist != 0
: ( rSz.GetWidth() - nDist ) > COLFUZZY ) )
2000-09-18 23:08:29 +00:00
{
for( n = 0; n < aLines.Count(); ++n )
{
aParam.LoopClear();
if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True ))
2000-09-18 23:08:29 +00:00
{
bRet = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
if( bRet && !aParam.bAnyBoxFnd )
bRet = sal_False;
2000-09-18 23:08:29 +00:00
}
if( !bRet && rAktBox.GetFrmFmt()->GetFrmSize().GetWidth()
- nRelDiff > COLFUZZY +
2012-02-15 13:19:06 +01:00
( 567 / 2 /*leave room for at least 0.5 cm*/) )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Consume the space from the current Cell
aParam.bSplittBox = sal_True;
2012-02-15 13:19:06 +01:00
// We also need to test this!
bRet = sal_True;
2000-09-18 23:08:29 +00:00
for( n = 0; n < aLines.Count(); ++n )
{
aParam.LoopClear();
if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
2000-09-18 23:08:29 +00:00
{
bRet = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
}
}
}
else if( aParam.bBigger )
{
for( n = 0; n < aLines.Count(); ++n )
{
aParam.LoopClear();
if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True ))
2000-09-18 23:08:29 +00:00
{
bRet = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
}
else
{
for( n = 0; n < aLines.Count(); ++n )
{
aParam.LoopClear();
if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True ))
2000-09-18 23:08:29 +00:00
{
bRet = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
}
2012-02-15 13:19:06 +01:00
// If true, set it
2000-09-18 23:08:29 +00:00
if( bRet )
{
CR_SetBoxWidth aParam1( aParam );
if( bInsDel )
{
aParam1.bBigger = !aParam.bBigger;
pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo,
aTmpLst, nDistStt );
if( ppUndo )
*ppUndo = aParam.CreateUndo(
aParam.bBigger ? UNDO_TABLE_DELBOX
: UNDO_TABLE_INSCOL );
}
else if( ppUndo )
*ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
2000-09-18 23:08:29 +00:00
if( bInsDel
? ( TBLFIX_CHGABS == eTblChgMode ? bLeft : bLeft )
: ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
{
for( n = aLines.Count(); n; )
{
--n;
aParam.LoopClear();
aParam1.LoopClear();
(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
(*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False );
2000-09-18 23:08:29 +00:00
}
}
else
for( n = aLines.Count(); n; )
{
--n;
aParam.LoopClear();
aParam1.LoopClear();
(*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False );
(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False );
2000-09-18 23:08:29 +00:00
}
}
}
break;
case nsTblChgWidthHeightType::WH_CELL_RIGHT:
case nsTblChgWidthHeightType::WH_CELL_LEFT:
2000-09-18 23:08:29 +00:00
if( TBLVAR_CHGABS == eTblChgMode )
{
2012-02-15 13:19:06 +01:00
// Then call itself recursively; only with another mode (proportional)
2000-09-18 23:08:29 +00:00
TblChgMode eOld = eTblChgMode;
eTblChgMode = TBLFIX_CHGABS;
bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff,
ppUndo );
eTblChgMode = eOld;
return bRet;
}
else if( bInsDel || ( bLeft ? nDist
: (rSz.GetWidth() - nDist) > COLFUZZY ))
{
if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel )
aParam.bBigger = !bBigger;
2012-02-15 13:19:06 +01:00
// First, see if there is enough room at all
2000-09-18 23:08:29 +00:00
SwTableBox* pBox = &rAktBox;
SwTableLine* pLine = rAktBox.GetUpper();
while( pLine->GetUpper() )
{
sal_uInt16 nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox );
2000-09-18 23:08:29 +00:00
if( bLeft ? nPos : nPos + 1 != pLine->GetTabBoxes().Count() )
break;
pBox = pLine->GetUpper();
pLine = pBox->GetUpper();
}
if( pLine->GetUpper() )
{
2012-02-15 13:19:06 +01:00
// We need to correct the distance once again!
aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), sal_True );
2000-09-18 23:08:29 +00:00
if( bLeft )
aParam.nMaxSize = aParam.nSide;
else
aParam.nMaxSize = pLine->GetUpper()->GetFrmFmt()->
GetFrmSize().GetWidth() - aParam.nSide;
}
2012-02-15 13:19:06 +01:00
// First, see if there is enough room at all
2000-09-18 23:08:29 +00:00
if( bInsDel )
{
if( 0 != ( bRet = bLeft ? nDist != 0
2000-09-18 23:08:29 +00:00
: ( rSz.GetWidth() - nDist ) > COLFUZZY ) &&
!aParam.bBigger )
{
bRet = (*fnOtherBox)( pLine, aParam, 0, sal_True );
2000-09-18 23:08:29 +00:00
if( bRet && !aParam.bAnyBoxFnd )
bRet = sal_False;
2000-09-18 23:08:29 +00:00
}
if( !bRet && !aParam.bBigger && rAktBox.GetFrmFmt()->
GetFrmSize().GetWidth() - nRelDiff > COLFUZZY +
2012-02-15 13:19:06 +01:00
( 567 / 2 /*leave room for at least 0.5 cm*/) )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// Consume the room from the current Cell
aParam.bSplittBox = sal_True;
bRet = sal_True;
2000-09-18 23:08:29 +00:00
}
}
else
{
FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox;
bRet = (*fnTmp)( pLine, aParam, nDistStt, sal_True );
2000-09-18 23:08:29 +00:00
}
2012-02-15 13:19:06 +01:00
// If true, set it
2000-09-18 23:08:29 +00:00
if( bRet )
{
CR_SetBoxWidth aParam1( aParam );
if( bInsDel )
{
aParam1.bBigger = !aParam.bBigger;
pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst, nDistStt );
if( ppUndo )
*ppUndo = aParam.CreateUndo(
aParam.bBigger ? UNDO_TABLE_DELBOX
: UNDO_TABLE_INSCOL );
}
else if( ppUndo )
*ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
2000-09-18 23:08:29 +00:00
if( bInsDel
? ( TBLFIX_CHGABS == eTblChgMode ? (bBigger && bLeft) : bLeft )
: ( TBLFIX_CHGABS != eTblChgMode && bLeft ) )
{
(*fnSelBox)( pLine, aParam, nDistStt, sal_False );
(*fnOtherBox)( pLine, aParam1, nDistStt, sal_False );
2000-09-18 23:08:29 +00:00
}
else
{
(*fnOtherBox)( pLine, aParam1, nDistStt, sal_False );
(*fnSelBox)( pLine, aParam, nDistStt, sal_False );
2000-09-18 23:08:29 +00:00
}
}
}
break;
}
if( pFndBox )
{
2012-02-15 13:19:06 +01:00
// Clean up the structure of all Lines
2000-09-18 23:08:29 +00:00
GCLines();
2012-02-15 13:19:06 +01:00
// Update Layout
2000-09-18 23:08:29 +00:00
if( !bBigger || pFndBox->AreLinesToRestore( *this ) )
pFndBox->MakeFrms( *this );
// TL_CHART2: it is currently unclear if sth has to be done here.
// The function name hints that nothing needs to be done, on the other
// hand there is a case where sth gets deleted. :-(
2000-09-18 23:08:29 +00:00
delete pFndBox;
if( ppUndo && *ppUndo )
{
aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType,
2000-09-18 23:08:29 +00:00
nAbsDiff, nRelDiff );
if( !aParam.bBigger )
aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
}
}
if( bRet )
{
CHECKBOXWIDTH
CHECKTABLELAYOUT
2000-09-18 23:08:29 +00:00
}
return bRet;
}
_FndBox* lcl_SaveInsDelData( CR_SetLineHeight& rParam, SwUndo** ppUndo,
SwTableSortBoxes& rTmpLst )
{
2012-02-15 13:19:06 +01:00
// Find all Boxes/Lines
2000-09-18 23:08:29 +00:00
SwTable& rTbl = rParam.pTblNd->GetTable();
OSL_ENSURE( rParam.aBoxes.Count(), "We can't go on without Boxes!" );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Prevent deleting the whole Table
if( !rParam.bBigger && rParam.aBoxes.Count() == rTbl.GetTabSortBoxes().Count() )
2000-09-18 23:08:29 +00:00
return 0;
_FndBox* pFndBox = new _FndBox( 0, 0 );
2000-09-18 23:08:29 +00:00
if( !rParam.bBigger )
pFndBox->SetTableLines( rParam.aBoxes, rTbl );
else
{
_FndPara aPara( rParam.aBoxes, pFndBox );
rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
OSL_ENSURE( pFndBox->GetLines().size(), "Where are the Boxes?" );
2000-09-18 23:08:29 +00:00
pFndBox->SetTableLines( rTbl );
if( ppUndo )
rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
}
2012-02-15 13:19:06 +01:00
// Find Lines for the Layout update
2000-09-18 23:08:29 +00:00
pFndBox->DelFrms( rTbl );
// TL_CHART2: it is currently unclear if sth has to be done here.
2000-09-18 23:08:29 +00:00
return pFndBox;
}
void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight,
sal_Bool bMinSize )
2000-09-18 23:08:29 +00:00
{
SwLayoutFrm* pLineFrm = GetRowFrm( rLine );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine?" );
2000-09-18 23:08:29 +00:00
SwFrmFmt* pFmt = rLine.ClaimFrmFmt();
SwTwips nMyNewH, nMyOldH = pLineFrm->Frm().Height();
2012-02-15 13:19:06 +01:00
if( !nOldHeight ) // the BaseLine and absolute
2000-09-18 23:08:29 +00:00
nMyNewH = nMyOldH + nNewHeight;
else
{
2012-02-15 13:19:06 +01:00
// Calculate as exactly as possible
2000-09-18 23:08:29 +00:00
Fraction aTmp( nMyOldH );
aTmp *= Fraction( nNewHeight, nOldHeight );
2012-02-15 13:19:06 +01:00
aTmp += Fraction( 1, 2 ); // round up if needed
2000-09-18 23:08:29 +00:00
nMyNewH = aTmp;
}
SwFrmSize eSize = ATT_MIN_SIZE;
if( !bMinSize &&
( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrm ) + ROWFUZZY ))
2000-09-18 23:08:29 +00:00
eSize = ATT_FIX_SIZE;
pFmt->SetFmtAttr( SwFmtFrmSize( eSize, 0, nMyNewH ) );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// First adapt all internal ones
2000-09-18 23:08:29 +00:00
SwTableBoxes& rBoxes = rLine.GetTabBoxes();
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
SwTableBox& rBox = *rBoxes[ n ];
for( sal_uInt16 i = 0; i < rBox.GetTabLines().Count(); ++i )
2000-09-18 23:08:29 +00:00
SetLineHeight( *rBox.GetTabLines()[ i ], nMyOldH, nMyNewH, bMinSize );
}
}
sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
sal_Bool bRet = sal_True;
2000-09-18 23:08:29 +00:00
if( !bCheck )
{
2012-02-15 13:19:06 +01:00
// Set line height
2000-09-18 23:08:29 +00:00
SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist,
rParam.bBigger );
}
else if( !rParam.bBigger )
{
2012-02-15 13:19:06 +01:00
// Calculate the new relative size by means of the old one
2000-09-18 23:08:29 +00:00
SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine?" );
2000-09-18 23:08:29 +00:00
SwTwips nRstHeight = CalcRowRstHeight( pLineFrm );
if( (nRstHeight + ROWFUZZY) < nDist )
bRet = sal_False;
2000-09-18 23:08:29 +00:00
}
return bRet;
}
sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
sal_Bool bRet = sal_True;
2000-09-18 23:08:29 +00:00
if( bCheck )
{
if( rParam.bBigger )
{
2012-02-15 13:19:06 +01:00
// Calculate the new relative size by means of the old one
2000-09-18 23:08:29 +00:00
SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine?" );
2000-09-18 23:08:29 +00:00
if( TBLFIX_CHGPROP == rParam.nMode )
{
nDist *= pLineFrm->Frm().Height();
nDist /= rParam.nMaxHeight;
}
bRet = nDist <= CalcRowRstHeight( pLineFrm );
}
}
else
{
2012-02-15 13:19:06 +01:00
// Set line height
// pLine is the following/preceeding, thus adjust it
2000-09-18 23:08:29 +00:00
if( TBLFIX_CHGPROP == rParam.nMode )
{
SwLayoutFrm* pLineFrm = GetRowFrm( *pLine );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine??" );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Calculate the new relative size by means of the old one
// If the selected Box get bigger, adjust via the max space else
// via the max height.
2000-09-18 23:08:29 +00:00
if( 1 /*!rParam.bBigger*/ )
{
nDist *= pLineFrm->Frm().Height();
nDist /= rParam.nMaxHeight;
}
else
{
2012-02-15 13:19:06 +01:00
// Calculate the new relative size by means of the old one
2000-09-18 23:08:29 +00:00
nDist *= CalcRowRstHeight( pLineFrm );
nDist /= rParam.nMaxSpace;
}
}
SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist,
!rParam.bBigger );
}
return bRet;
}
sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam,
SwTwips nDist, sal_Bool bCheck )
2000-09-18 23:08:29 +00:00
{
sal_Bool bRet = sal_True;
2000-09-18 23:08:29 +00:00
if( !bCheck )
{
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
SwDoc* pDoc = pLine->GetFrmFmt()->GetDoc();
if( !rParam.bBigger )
{
sal_uInt16 n;
for( n = rBoxes.Count(); n; )
2000-09-18 23:08:29 +00:00
::lcl_SaveUpperLowerBorder( rParam.pTblNd->GetTable(),
*rBoxes[ --n ],
rParam.aShareFmts );
for( n = rBoxes.Count(); n; )
::_DeleteBox( rParam.pTblNd->GetTable(),
rBoxes[ --n ], rParam.pUndo, sal_False,
sal_False, &rParam.aShareFmts );
2000-09-18 23:08:29 +00:00
}
else
{
2012-02-15 13:19:06 +01:00
// Insert Line
2000-09-18 23:08:29 +00:00
SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)pLine->GetFrmFmt(),
rBoxes.Count(), pLine->GetUpper() );
SwTableLines* pLines;
if( pLine->GetUpper() )
pLines = &pLine->GetUpper()->GetTabLines();
else
pLines = &rParam.pTblNd->GetTable().GetTabLines();
sal_uInt16 nPos = pLines->C40_GETPOS( SwTableLine, pLine );
2000-09-18 23:08:29 +00:00
if( !rParam.bTop )
++nPos;
pLines->C40_INSERT( SwTableLine, pNewLine, nPos );
SwFrmFmt* pNewFmt = pNewLine->ClaimFrmFmt();
pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE, 0, nDist ) );
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// And once again calculate the Box count
2000-09-18 23:08:29 +00:00
SwTableBoxes& rNewBoxes = pNewLine->GetTabBoxes();
for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
SwTwips nWidth = 0;
SwTableBox* pOld = rBoxes[ n ];
if( !pOld->GetSttNd() )
{
2012-02-15 13:19:06 +01:00
// Not a normal content Box, so fall back to the 1st next Box
2000-09-18 23:08:29 +00:00
nWidth = pOld->GetFrmFmt()->GetFrmSize().GetWidth();
while( !pOld->GetSttNd() )
pOld = pOld->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
}
::_InsTblBox( pDoc, rParam.pTblNd, pNewLine,
(SwTableBoxFmt*)pOld->GetFrmFmt(), pOld, n );
2012-02-15 13:19:06 +01:00
// Special treatment for the border:
// The top one needs to be removed
2000-09-18 23:08:29 +00:00
const SvxBoxItem& rBoxItem = pOld->GetFrmFmt()->GetBox();
if( rBoxItem.GetTop() )
{
SvxBoxItem aTmp( rBoxItem );
aTmp.SetLine( 0, BOX_LINE_TOP );
rParam.aShareFmts.SetAttr( rParam.bTop
? *pOld
: *rNewBoxes[ n ], aTmp );
}
if( nWidth )
rParam.aShareFmts.SetAttr( *rNewBoxes[ n ],
SwFmtFrmSize( ATT_FIX_SIZE, nWidth, 0 ) );
}
}
}
else
{
2012-02-15 13:19:06 +01:00
// Collect Boxes!
2000-09-18 23:08:29 +00:00
SwTableBoxes& rBoxes = pLine->GetTabBoxes();
for( sal_uInt16 n = rBoxes.Count(); n; )
2000-09-18 23:08:29 +00:00
{
SwTableBox* pBox = rBoxes[ --n ];
if( pBox->GetFrmFmt()->GetProtect().IsCntntProtected() )
return sal_False;
2000-09-18 23:08:29 +00:00
if( pBox->GetSttNd() )
rParam.aBoxes.Insert( pBox );
2000-09-18 23:08:29 +00:00
else
{
for( sal_uInt16 i = pBox->GetTabLines().Count(); i; )
2000-09-18 23:08:29 +00:00
lcl_InsDelSelLine( pBox->GetTabLines()[ --i ],
rParam, 0, sal_True );
2000-09-18 23:08:29 +00:00
}
}
}
return bRet;
}
sal_Bool SwTable::SetRowHeight( SwTableBox& rAktBox, sal_uInt16 eType,
2000-09-18 23:08:29 +00:00
SwTwips nAbsDiff, SwTwips nRelDiff,SwUndo** ppUndo )
{
SwTableLine* pLine = rAktBox.GetUpper();
SwTableLine* pBaseLine = pLine;
while( pBaseLine->GetUpper() )
pBaseLine = pBaseLine->GetUpper()->GetUpper();
2012-02-15 13:19:06 +01:00
_FndBox* pFndBox = 0; // for insertion/deletion
SwTableSortBoxes aTmpLst( 0 ); // for Undo
sal_Bool bBigger,
bRet = sal_False,
bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) ||
nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ),
bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL );
sal_uInt16 n, nBaseLinePos = GetTabLines().C40_GETPOS( SwTableLine, pBaseLine );
sal_uLong nBoxIdx = rAktBox.GetSttIdx();
2000-09-18 23:08:29 +00:00
CR_SetLineHeight aParam( eType,
(SwTableNode*)rAktBox.GetSttNd()->FindTableNode() );
bBigger = aParam.bBigger;
FN_lcl_SetLineHeight fnSelLine, fnOtherLine = lcl_SetOtherLineHeight;
if( bInsDel )
fnSelLine = lcl_InsDelSelLine;
else
fnSelLine = lcl_SetSelLineHeight;
SwTableLines* pLines = &aLines;
2012-02-15 13:19:06 +01:00
// How do we get to the height?
2000-09-18 23:08:29 +00:00
switch( eType & 0xff )
{
case nsTblChgWidthHeightType::WH_CELL_TOP:
case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
2000-09-18 23:08:29 +00:00
if( pLine == pBaseLine )
2012-02-15 13:19:06 +01:00
break; // it doesn't work then!
2000-09-18 23:08:29 +00:00
2012-02-15 13:19:06 +01:00
// Is a nested Line (Box!)
2000-09-18 23:08:29 +00:00
pLines = &pLine->GetUpper()->GetTabLines();
nBaseLinePos = pLines->C40_GETPOS( SwTableLine, pLine );
pBaseLine = pLine;
2012-02-15 13:19:06 +01:00
// no break!
2000-09-18 23:08:29 +00:00
case nsTblChgWidthHeightType::WH_ROW_TOP:
case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
if( bInsDel && !bBigger ) // By how much does it get higher?
2000-09-18 23:08:29 +00:00
{
nAbsDiff = GetRowFrm( *pBaseLine )->Frm().Height();
}
if( TBLVAR_CHGABS == eTblChgMode )
{
2012-02-15 13:19:06 +01:00
// First test if we have room at all
2000-09-18 23:08:29 +00:00
if( bBigger )
{
bRet = sal_True;
2012-02-15 13:19:06 +01:00
// What's up with Top, Table in a Frame or Header/Footer with fixed width??
2000-09-18 23:08:29 +00:00
if( !bRet )
{
2012-02-15 13:19:06 +01:00
// Then call itself recursively; only with another mode (proportional)
2000-09-18 23:08:29 +00:00
TblChgMode eOld = eTblChgMode;
eTblChgMode = TBLFIX_CHGPROP;
bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
nRelDiff, ppUndo );
eTblChgMode = eOld;
return bRet;
}
}
else
bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
nAbsDiff, sal_True );
2000-09-18 23:08:29 +00:00
if( bRet )
{
if( bInsDel )
{
if( !aParam.aBoxes.Count() )
2000-09-18 23:08:29 +00:00
::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
aParam, 0, sal_True );
2000-09-18 23:08:29 +00:00
pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
2011-02-07 20:21:18 +01:00
// delete complete table when last row is deleted
if( !bBigger &&
aParam.aBoxes.Count() == aSortCntBoxes.Count() )
{
GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes );
return sal_False;
}
2000-09-18 23:08:29 +00:00
if( ppUndo )
*ppUndo = aParam.CreateUndo(
bBigger ? UNDO_TABLE_INSROW
: UNDO_ROW_DELETE );
2000-09-18 23:08:29 +00:00
}
else if( ppUndo )
*ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
2000-09-18 23:08:29 +00:00
(*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
nAbsDiff, sal_False );
2000-09-18 23:08:29 +00:00
}
}
else
{
bRet = sal_True;
sal_uInt16 nStt, nEnd;
2000-09-18 23:08:29 +00:00
if( bTop )
nStt = 0, nEnd = nBaseLinePos;
else
nStt = nBaseLinePos + 1, nEnd = pLines->Count();
2012-02-15 13:19:06 +01:00
// Get the current Lines' height
2000-09-18 23:08:29 +00:00
if( TBLFIX_CHGPROP == eTblChgMode )
{
for( n = nStt; n < nEnd; ++n )
{
SwLayoutFrm* pLineFrm = GetRowFrm( *(*pLines)[ n ] );
2012-02-15 13:19:06 +01:00
OSL_ENSURE( pLineFrm, "Where is the Frame from the SwTableLine??" );
2000-09-18 23:08:29 +00:00
aParam.nMaxSpace += CalcRowRstHeight( pLineFrm );
aParam.nMaxHeight += pLineFrm->Frm().Height();
}
if( bBigger && aParam.nMaxSpace < nAbsDiff )
bRet = sal_False;
2000-09-18 23:08:29 +00:00
}
else
{
if( bTop ? nEnd : nStt < nEnd )
{
if( bTop )
nStt = nEnd - 1;
else
nEnd = nStt + 1;
}
else
bRet = sal_False;
2000-09-18 23:08:29 +00:00
}
if( bRet )
{
if( bBigger )
{
for( n = nStt; n < nEnd; ++n )
{
if( !(*fnOtherLine)( (*pLines)[ n ], aParam,
nAbsDiff, sal_True ))
2000-09-18 23:08:29 +00:00
{
bRet = sal_False;
2000-09-18 23:08:29 +00:00
break;
}
}
}
else
bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
nAbsDiff, sal_True );
2000-09-18 23:08:29 +00:00
}
if( bRet )
{
2012-02-15 13:19:06 +01:00
// Adjust
2000-09-18 23:08:29 +00:00
if( bInsDel )
{
if( !aParam.aBoxes.Count() )
2000-09-18 23:08:29 +00:00
::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ],
aParam, 0, sal_True );
2000-09-18 23:08:29 +00:00
pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst );
if( ppUndo )
*ppUndo = aParam.CreateUndo(
bBigger ? UNDO_TABLE_INSROW
: UNDO_ROW_DELETE );
2000-09-18 23:08:29 +00:00
}
else if( ppUndo )
*ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True );
2000-09-18 23:08:29 +00:00
CR_SetLineHeight aParam1( aParam );
if( TBLFIX_CHGPROP == eTblChgMode && !bBigger &&
!aParam.nMaxSpace )
{
2012-02-15 13:19:06 +01:00
// We need to distribute the space evenly among all the Lines.
// That's why we need their count.
2000-09-18 23:08:29 +00:00
aParam1.nLines = nEnd - nStt;
}
if( bTop )
{
(*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
nAbsDiff, sal_False );
2000-09-18 23:08:29 +00:00
for( n = nStt; n < nEnd; ++n )
(*fnOtherLine)( (*pLines)[ n ], aParam1,
nAbsDiff, sal_False );
2000-09-18 23:08:29 +00:00
}
else
{
for( n = nStt; n < nEnd; ++n )
(*fnOtherLine)( (*pLines)[ n ], aParam1,
nAbsDiff, sal_False );
2000-09-18 23:08:29 +00:00
(*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam,
nAbsDiff, sal_False );
2000-09-18 23:08:29 +00:00
}
}
else
{
2012-02-15 13:19:06 +01:00
// Then call itself recursively; only with another mode (proportional)
2000-09-18 23:08:29 +00:00
TblChgMode eOld = eTblChgMode;
eTblChgMode = TBLVAR_CHGABS;
bRet = SetRowHeight( rAktBox, eType, nAbsDiff,
nRelDiff, ppUndo );
eTblChgMode = eOld;
pFndBox = 0;
}
}
}
break;
}
if( pFndBox )
{
2012-02-15 13:19:06 +01:00
// then clean up the structure of all Lines
2000-09-18 23:08:29 +00:00
GCLines();
2012-02-15 13:19:06 +01:00
// Update Layout
2000-09-18 23:08:29 +00:00
if( bBigger || pFndBox->AreLinesToRestore( *this ) )
pFndBox->MakeFrms( *this );
// TL_CHART2: it is currently unclear if sth has to be done here.
2000-09-18 23:08:29 +00:00
delete pFndBox;
if( ppUndo && *ppUndo )
{
aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType,
2000-09-18 23:08:29 +00:00
nAbsDiff, nRelDiff );
if( bBigger )
aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst );
}
}
CHECKTABLELAYOUT
2000-09-18 23:08:29 +00:00
return bRet;
}
SwFrmFmt* SwShareBoxFmt::GetFormat( long nWidth ) const
{
SwFrmFmt *pRet = 0, *pTmp;
for( sal_uInt16 n = aNewFmts.Count(); n; )
2000-09-18 23:08:29 +00:00
if( ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->GetFrmSize().GetWidth()
== nWidth )
{
pRet = pTmp;
break;
}
return pRet;
}
SwFrmFmt* SwShareBoxFmt::GetFormat( const SfxPoolItem& rItem ) const
{
const SfxPoolItem* pItem;
sal_uInt16 nWhich = rItem.Which();
2000-09-18 23:08:29 +00:00
SwFrmFmt *pRet = 0, *pTmp;
const SfxPoolItem& rFrmSz = pOldFmt->GetFmtAttr( RES_FRM_SIZE, sal_False );
for( sal_uInt16 n = aNewFmts.Count(); n; )
2000-09-18 23:08:29 +00:00
if( SFX_ITEM_SET == ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->
GetItemState( nWhich, sal_False, &pItem ) && *pItem == rItem &&
pTmp->GetFmtAttr( RES_FRM_SIZE, sal_False ) == rFrmSz )
2000-09-18 23:08:29 +00:00
{
pRet = pTmp;
break;
}
return pRet;
}
void SwShareBoxFmt::AddFormat( const SwFrmFmt& rNew )
{
void* pFmt = (void*)&rNew;
aNewFmts.Insert( pFmt, aNewFmts.Count() );
}
sal_Bool SwShareBoxFmt::RemoveFormat( const SwFrmFmt& rFmt )
2000-09-18 23:08:29 +00:00
{
2012-02-15 13:19:06 +01:00
// returns sal_True, if we can delete
2000-09-18 23:08:29 +00:00
if( pOldFmt == &rFmt )
return sal_True;
2000-09-18 23:08:29 +00:00
void* p = (void*)&rFmt;
sal_uInt16 nFnd = aNewFmts.GetPos( p );
2000-09-18 23:08:29 +00:00
if( USHRT_MAX != nFnd )
aNewFmts.Remove( nFnd );
return 0 == aNewFmts.Count();
}
SwShareBoxFmts::~SwShareBoxFmts()
{
}
SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, long nWidth ) const
{
sal_uInt16 nPos;
2000-09-18 23:08:29 +00:00
return Seek_Entry( rFmt, &nPos )
? aShareArr[ nPos ].GetFormat( nWidth )
2000-09-18 23:08:29 +00:00
: 0;
}
SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt,
const SfxPoolItem& rItem ) const
{
sal_uInt16 nPos;
2000-09-18 23:08:29 +00:00
return Seek_Entry( rFmt, &nPos )
? aShareArr[ nPos ].GetFormat( rItem )
2000-09-18 23:08:29 +00:00
: 0;
}
void SwShareBoxFmts::AddFormat( const SwFrmFmt& rOld, const SwFrmFmt& rNew )
{
{
sal_uInt16 nPos;
2000-09-18 23:08:29 +00:00
SwShareBoxFmt* pEntry;
if( !Seek_Entry( rOld, &nPos ))
{
pEntry = new SwShareBoxFmt( rOld );
aShareArr.insert( aShareArr.begin() + nPos, pEntry );
2000-09-18 23:08:29 +00:00
}
else
pEntry = &aShareArr[ nPos ];
2000-09-18 23:08:29 +00:00
pEntry->AddFormat( rNew );
}
}
2000-09-18 23:08:29 +00:00
void SwShareBoxFmts::ChangeFrmFmt( SwTableBox* pBox, SwTableLine* pLn,
SwFrmFmt& rFmt )
{
SwClient aCl;
SwFrmFmt* pOld = 0;
if( pBox )
{
pOld = pBox->GetFrmFmt();
pOld->Add( &aCl );
pBox->ChgFrmFmt( (SwTableBoxFmt*)&rFmt );
}
else if( pLn )
{
pOld = pLn->GetFrmFmt();
pOld->Add( &aCl );
pLn->ChgFrmFmt( (SwTableLineFmt*)&rFmt );
}
if( pOld && pOld->IsLastDepend() )
{
RemoveFormat( *pOld );
delete pOld;
}
}
void SwShareBoxFmts::SetSize( SwTableBox& rBox, const SwFmtFrmSize& rSz )
{
SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
*pRet = GetFormat( *pBoxFmt, rSz.GetWidth() );
if( pRet )
ChangeFrmFmt( &rBox, 0, *pRet );
else
{
pRet = rBox.ClaimFrmFmt();
pRet->SetFmtAttr( rSz );
2000-09-18 23:08:29 +00:00
AddFormat( *pBoxFmt, *pRet );
}
}
void SwShareBoxFmts::SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem )
{
SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(),
*pRet = GetFormat( *pBoxFmt, rItem );
if( pRet )
ChangeFrmFmt( &rBox, 0, *pRet );
else
{
pRet = rBox.ClaimFrmFmt();
pRet->SetFmtAttr( rItem );
2000-09-18 23:08:29 +00:00
AddFormat( *pBoxFmt, *pRet );
}
}
void SwShareBoxFmts::SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem )
{
SwFrmFmt *pLineFmt = rLine.GetFrmFmt(),
*pRet = GetFormat( *pLineFmt, rItem );
if( pRet )
ChangeFrmFmt( 0, &rLine, *pRet );
else
{
pRet = rLine.ClaimFrmFmt();
pRet->SetFmtAttr( rItem );
2000-09-18 23:08:29 +00:00
AddFormat( *pLineFmt, *pRet );
}
}
void SwShareBoxFmts::RemoveFormat( const SwFrmFmt& rFmt )
{
for( sal_uInt16 i = aShareArr.size(); i; )
if( aShareArr[ --i ].RemoveFormat( rFmt ))
aShareArr.erase( aShareArr.begin() + i );
2000-09-18 23:08:29 +00:00
}
sal_Bool SwShareBoxFmts::Seek_Entry( const SwFrmFmt& rFmt, sal_uInt16* pPos ) const
2000-09-18 23:08:29 +00:00
{
sal_uLong nIdx = (sal_uLong)&rFmt;
sal_uInt16 nO = aShareArr.size(), nM, nU = 0;
2000-09-18 23:08:29 +00:00
if( nO > 0 )
{
nO--;
while( nU <= nO )
{
nM = nU + ( nO - nU ) / 2;
sal_uLong nFmt = (sal_uLong)&aShareArr[ nM ].GetOldFormat();
2000-09-18 23:08:29 +00:00
if( nFmt == nIdx )
{
if( pPos )
*pPos = nM;
return sal_True;
2000-09-18 23:08:29 +00:00
}
else if( nFmt < nIdx )
nU = nM + 1;
else if( nM == 0 )
{
if( pPos )
*pPos = nU;
return sal_False;
2000-09-18 23:08:29 +00:00
}
else
nO = nM - 1;
}
}
if( pPos )
*pPos = nU;
return sal_False;
2000-09-18 23:08:29 +00:00
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */