1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/text/HoriOrientation.hpp>
22 #include <com/sun/star/chart2/XChartDocument.hpp>
23 #include <hintids.hxx>
25 #include <editeng/brshitem.hxx>
26 #include <editeng/lrspitem.hxx>
27 #include <editeng/protitem.hxx>
28 #include <editeng/boxitem.hxx>
29 #include <tools/fract.hxx>
30 #include <fmtfsize.hxx>
31 #include <fmtornt.hxx>
35 #include <frmtool.hxx>
37 #include <swtable.hxx>
45 #include <UndoTable.hxx>
46 #include <cellatr.hxx>
48 #include <swtblfmt.hxx>
49 #include <swddetbl.hxx>
50 #include <poolfmt.hxx>
51 #include <tblrwcl.hxx>
52 #include <unochart.hxx>
53 #include <boost/shared_ptr.hpp>
54 #include <boost/foreach.hpp>
55 #include <switerator.hxx>
57 using namespace com::sun::star
;
58 using namespace com::sun::star::uno
;
64 using namespace ::com::sun::star
;
67 #define CHECK_TABLE(t) (t).CheckConsistency();
69 #define CHECK_TABLE(t)
72 typedef std::map
<SwTableLine
*, sal_uInt16
> SwTableLineWidthMap_t
;
74 // In order to set the Frame Formats for the Boxes, it's enough to look
75 // up the current one in the array. If it's already there return the new one.
79 SwTableBoxFmt
*pFrmFmt
; // for CopyCol
80 SwTwips nSize
; // for DelCol
82 SwTableBoxFmt
*pNewFrmFmt
;
84 _CpyTabFrm( SwTableBoxFmt
* pAktFrmFmt
) : pNewFrmFmt( 0 )
85 { Value
.pFrmFmt
= pAktFrmFmt
; }
87 _CpyTabFrm
& operator=( const _CpyTabFrm
& );
89 bool operator==( const _CpyTabFrm
& rCpyTabFrm
) const
90 { return (sal_uLong
)Value
.nSize
== (sal_uLong
)rCpyTabFrm
.Value
.nSize
; }
91 bool operator<( const _CpyTabFrm
& rCpyTabFrm
) const
92 { return (sal_uLong
)Value
.nSize
< (sal_uLong
)rCpyTabFrm
.Value
.nSize
; }
98 SwTableLineWidthMap_t m_LineWidthMap
;
99 SwShareBoxFmts aShareFmts
;
101 SwUndoTblNdsChg
* pUndo
;
102 SwTwips nDiff
, nSide
, nMaxSize
, nLowerDiff
;
104 sal_uInt16 nTblWidth
, nRemainWidth
, nBoxWidth
;
105 bool bBigger
, bLeft
, bSplittBox
, bAnyBoxFnd
;
107 CR_SetBoxWidth( sal_uInt16 eType
, SwTwips nDif
, SwTwips nSid
, SwTwips nTblW
,
108 SwTwips nMax
, SwTableNode
* pTNd
)
110 nDiff( nDif
), nSide( nSid
), nMaxSize( nMax
), nLowerDiff( 0 ),
111 nTblWidth( (sal_uInt16
)nTblW
), nRemainWidth( 0 ), nBoxWidth( 0 ),
112 bSplittBox( false ), bAnyBoxFnd( false )
114 bLeft
= nsTblChgWidthHeightType::WH_COL_LEFT
== ( eType
& 0xff ) ||
115 nsTblChgWidthHeightType::WH_CELL_LEFT
== ( eType
& 0xff );
116 bBigger
= 0 != (eType
& nsTblChgWidthHeightType::WH_FLAG_BIGGER
);
117 nMode
= pTblNd
->GetTable().GetTblChgMode();
119 CR_SetBoxWidth( const CR_SetBoxWidth
& rCpy
)
120 : m_LineWidthMap(rCpy
.m_LineWidthMap
)
122 pTblNd( rCpy
.pTblNd
),
124 nDiff( rCpy
.nDiff
), nSide( rCpy
.nSide
),
125 nMaxSize( rCpy
.nMaxSize
), nLowerDiff( 0 ),
126 nMode( rCpy
.nMode
), nTblWidth( rCpy
.nTblWidth
),
127 nRemainWidth( rCpy
.nRemainWidth
), nBoxWidth( rCpy
.nBoxWidth
),
128 bBigger( rCpy
.bBigger
), bLeft( rCpy
.bLeft
),
129 bSplittBox( rCpy
.bSplittBox
), bAnyBoxFnd( rCpy
.bAnyBoxFnd
)
133 SwUndoTblNdsChg
* CreateUndo( SwUndoId eUndoType
)
135 return pUndo
= new SwUndoTblNdsChg( eUndoType
, m_Boxes
, *pTblNd
);
140 nLowerDiff
= 0; nRemainWidth
= 0;
143 void AddBoxWidth( const SwTableBox
& rBox
, sal_uInt16 nWidth
)
145 SwTableLine
* p
= (SwTableLine
*)rBox
.GetUpper();
146 std::pair
<SwTableLineWidthMap_t::iterator
, bool> aPair
=
147 m_LineWidthMap
.insert(std::make_pair(p
,nWidth
));
150 aPair
.first
->second
+= nWidth
;
154 sal_uInt16
GetBoxWidth( const SwTableLine
& rLn
) const
156 SwTableLine
* p
= (SwTableLine
*)&rLn
;
157 SwTableLineWidthMap_t::const_iterator
const it
= m_LineWidthMap
.find(p
);
158 return (it
!= m_LineWidthMap
.end()) ? it
->second
: 0;
162 static bool lcl_SetSelBoxWidth( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
163 SwTwips nDist
, bool bCheck
);
164 static bool lcl_SetOtherBoxWidth( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
165 SwTwips nDist
, bool bCheck
);
166 static bool lcl_InsSelBox( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
167 SwTwips nDist
, bool bCheck
);
168 static bool lcl_InsOtherBox( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
169 SwTwips nDist
, bool bCheck
);
170 static bool lcl_DelSelBox( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
171 SwTwips nDist
, bool bCheck
);
172 static bool lcl_DelOtherBox( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
173 SwTwips nDist
, bool bCheck
);
175 typedef bool (*FN_lcl_SetBoxWidth
)(SwTableLine
*, CR_SetBoxWidth
&, SwTwips
, bool );
179 void _CheckBoxWidth( const SwTableLine
& rLine
, SwTwips nSize
);
181 #define CHECKBOXWIDTH \
183 SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); \
184 for (size_t nTmp = 0; nTmp < aLines.size(); ++nTmp) \
185 ::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \
188 #define CHECKTABLELAYOUT \
190 for ( sal_uInt16 i = 0; i < GetTabLines().size(); ++i ) \
192 SwFrmFmt* pFmt = GetTabLines()[i]->GetFrmFmt(); \
193 SwIterator<SwRowFrm,SwFmt> aIter( *pFmt ); \
194 for (SwRowFrm* pFrm=aIter.First(); pFrm; pFrm=aIter.Next())\
196 if ( pFrm->GetTabLine() == GetTabLines()[i] ) \
198 OSL_ENSURE( pFrm->GetUpper()->IsTabFrm(), \
199 "Table layout does not match table structure" ); \
207 #define CHECKBOXWIDTH
208 #define CHECKTABLELAYOUT
212 struct CR_SetLineHeight
215 SwShareBoxFmts aShareFmts
;
217 SwUndoTblNdsChg
* pUndo
;
218 SwTwips nMaxSpace
, nMaxHeight
;
221 bool bBigger
, bTop
, bSplittBox
, bAnyBoxFnd
;
223 CR_SetLineHeight( sal_uInt16 eType
, SwTableNode
* pTNd
)
224 : pTblNd( pTNd
), pUndo( 0 ),
225 nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ),
226 bSplittBox( false ), bAnyBoxFnd( false )
228 bTop
= nsTblChgWidthHeightType::WH_ROW_TOP
== ( eType
& 0xff ) || nsTblChgWidthHeightType::WH_CELL_TOP
== ( eType
& 0xff );
229 bBigger
= 0 != (eType
& nsTblChgWidthHeightType::WH_FLAG_BIGGER
);
230 if( eType
& nsTblChgWidthHeightType::WH_FLAG_INSDEL
)
232 nMode
= pTblNd
->GetTable().GetTblChgMode();
234 CR_SetLineHeight( const CR_SetLineHeight
& rCpy
)
235 : pTblNd( rCpy
.pTblNd
), pUndo( rCpy
.pUndo
),
236 nMaxSpace( rCpy
.nMaxSpace
), nMaxHeight( rCpy
.nMaxHeight
),
237 nMode( rCpy
.nMode
), nLines( rCpy
.nLines
),
238 bBigger( rCpy
.bBigger
), bTop( rCpy
.bTop
),
239 bSplittBox( rCpy
.bSplittBox
), bAnyBoxFnd( rCpy
.bAnyBoxFnd
)
242 SwUndoTblNdsChg
* CreateUndo( SwUndoId nUndoType
)
244 return pUndo
= new SwUndoTblNdsChg( nUndoType
, m_Boxes
, *pTblNd
);
248 static bool lcl_SetSelLineHeight( SwTableLine
* pLine
, CR_SetLineHeight
& rParam
,
249 SwTwips nDist
, bool bCheck
);
250 static bool lcl_SetOtherLineHeight( SwTableLine
* pLine
, CR_SetLineHeight
& rParam
,
251 SwTwips nDist
, bool bCheck
);
252 static bool lcl_InsDelSelLine( SwTableLine
* pLine
, CR_SetLineHeight
& rParam
,
253 SwTwips nDist
, bool bCheck
);
255 typedef bool (*FN_lcl_SetLineHeight
)(SwTableLine
*, CR_SetLineHeight
&, SwTwips
, bool );
257 _CpyTabFrm
& _CpyTabFrm::operator=( const _CpyTabFrm
& rCpyTabFrm
)
259 pNewFrmFmt
= rCpyTabFrm
.pNewFrmFmt
;
260 Value
= rCpyTabFrm
.Value
;
264 typedef o3tl::sorted_vector
<_CpyTabFrm
> _CpyTabFrms
;
268 boost::shared_ptr
< std::vector
< std::vector
< sal_uLong
> > > pWidths
;
271 _CpyTabFrms
& rTabFrmArr
;
272 SwTableLine
* pInsLine
;
274 sal_uLong nOldSize
, nNewSize
; // in order to correct the size attributes
275 sal_uLong nMinLeft
, nMaxRight
;
276 sal_uInt16 nCpyCnt
, nInsPos
;
277 sal_uInt16 nLnIdx
, nBoxIdx
;
278 sal_uInt8 nDelBorderFlag
;
281 _CpyPara( SwTableNode
* pNd
, sal_uInt16 nCopies
, _CpyTabFrms
& rFrmArr
,
282 bool bCopyContent
= true )
283 : pDoc( pNd
->GetDoc() ), pTblNd( pNd
), rTabFrmArr(rFrmArr
),
284 pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0),
285 nMinLeft(ULONG_MAX
), nMaxRight(0),
286 nCpyCnt(nCopies
), nInsPos(0),
287 nLnIdx(0), nBoxIdx(0),
288 nDelBorderFlag(0), bCpyCntnt( bCopyContent
)
290 _CpyPara( const _CpyPara
& rPara
, SwTableLine
* pLine
)
291 : pWidths( rPara
.pWidths
), pDoc(rPara
.pDoc
), pTblNd(rPara
.pTblNd
),
292 rTabFrmArr(rPara
.rTabFrmArr
), pInsLine(pLine
), pInsBox(rPara
.pInsBox
),
293 nOldSize(0), nNewSize(rPara
.nNewSize
), nMinLeft( rPara
.nMinLeft
),
294 nMaxRight( rPara
.nMaxRight
), nCpyCnt(rPara
.nCpyCnt
), nInsPos(0),
295 nLnIdx( rPara
.nLnIdx
), nBoxIdx( rPara
.nBoxIdx
),
296 nDelBorderFlag( rPara
.nDelBorderFlag
), bCpyCntnt( rPara
.bCpyCntnt
)
298 _CpyPara( const _CpyPara
& rPara
, SwTableBox
* pBox
)
299 : pWidths( rPara
.pWidths
), pDoc(rPara
.pDoc
), pTblNd(rPara
.pTblNd
),
300 rTabFrmArr(rPara
.rTabFrmArr
), pInsLine(rPara
.pInsLine
), pInsBox(pBox
),
301 nOldSize(rPara
.nOldSize
), nNewSize(rPara
.nNewSize
),
302 nMinLeft( rPara
.nMinLeft
), nMaxRight( rPara
.nMaxRight
),
303 nCpyCnt(rPara
.nCpyCnt
), nInsPos(0), nLnIdx(rPara
.nLnIdx
), nBoxIdx(rPara
.nBoxIdx
),
304 nDelBorderFlag( rPara
.nDelBorderFlag
), bCpyCntnt( rPara
.bCpyCntnt
)
306 void SetBoxWidth( SwTableBox
* pBox
);
309 static void lcl_CopyRow(_FndLine
& rFndLine
, _CpyPara
*const pCpyPara
);
311 static void lcl_CopyCol( _FndBox
& rFndBox
, _CpyPara
*const pCpyPara
)
313 // Look up the Frame Format in the Frame Format Array
314 SwTableBox
* pBox
= rFndBox
.GetBox();
315 _CpyTabFrm
aFindFrm( (SwTableBoxFmt
*)pBox
->GetFrmFmt() );
318 if( pCpyPara
->nCpyCnt
)
320 _CpyTabFrms::const_iterator itFind
= pCpyPara
->rTabFrmArr
.lower_bound( aFindFrm
);
321 nFndPos
= itFind
- pCpyPara
->rTabFrmArr
.begin();
322 if( itFind
== pCpyPara
->rTabFrmArr
.end() || !(*itFind
== aFindFrm
) )
324 // For nested copying, also save the new Format as an old one.
325 SwTableBoxFmt
* pNewFmt
= (SwTableBoxFmt
*)pBox
->ClaimFrmFmt();
327 // Find the selected Boxes in the Line:
328 _FndLine
const* pCmpLine
= NULL
;
329 SwFmtFrmSize
aFrmSz( pNewFmt
->GetFrmSize() );
331 bool bDiffCount
= false;
332 if( pBox
->GetTabLines().size() )
334 pCmpLine
= &rFndBox
.GetLines().front();
335 if ( pCmpLine
->GetBoxes().size() != pCmpLine
->GetLine()->GetTabBoxes().size() )
341 // The first Line should be enough
342 _FndBoxes
const& rFndBoxes
= pCmpLine
->GetBoxes();
344 for( sal_uInt16 n
= rFndBoxes
.size(); n
; )
346 nSz
+= rFndBoxes
[--n
].GetBox()->
347 GetFrmFmt()->GetFrmSize().GetWidth();
349 aFrmSz
.SetWidth( aFrmSz
.GetWidth() -
350 nSz
/ ( pCpyPara
->nCpyCnt
+ 1 ) );
351 pNewFmt
->SetFmtAttr( aFrmSz
);
352 aFrmSz
.SetWidth( nSz
/ ( pCpyPara
->nCpyCnt
+ 1 ) );
354 // Create a new Format for the new Box, specifying it's size.
355 aFindFrm
.pNewFrmFmt
= (SwTableBoxFmt
*)pNewFmt
->GetDoc()->
357 *aFindFrm
.pNewFrmFmt
= *pNewFmt
;
358 aFindFrm
.pNewFrmFmt
->SetFmtAttr( aFrmSz
);
362 aFrmSz
.SetWidth( aFrmSz
.GetWidth() / ( pCpyPara
->nCpyCnt
+ 1 ) );
363 pNewFmt
->SetFmtAttr( aFrmSz
);
365 aFindFrm
.pNewFrmFmt
= pNewFmt
;
366 pCpyPara
->rTabFrmArr
.insert( aFindFrm
);
367 aFindFrm
.Value
.pFrmFmt
= pNewFmt
;
368 pCpyPara
->rTabFrmArr
.insert( aFindFrm
);
373 aFindFrm
= pCpyPara
->rTabFrmArr
[ nFndPos
];
374 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)aFindFrm
.pNewFrmFmt
);
379 _CpyTabFrms::const_iterator itFind
= pCpyPara
->rTabFrmArr
.find( aFindFrm
);
380 if( pCpyPara
->nDelBorderFlag
&&
381 itFind
!= pCpyPara
->rTabFrmArr
.end() )
384 aFindFrm
.pNewFrmFmt
= (SwTableBoxFmt
*)pBox
->GetFrmFmt();
387 if (!rFndBox
.GetLines().empty())
389 pBox
= new SwTableBox( aFindFrm
.pNewFrmFmt
,
390 rFndBox
.GetLines().size(), pCpyPara
->pInsLine
);
391 pCpyPara
->pInsLine
->GetTabBoxes().insert( pCpyPara
->pInsLine
->GetTabBoxes().begin() + pCpyPara
->nInsPos
++, pBox
);
392 _CpyPara
aPara( *pCpyPara
, pBox
);
393 aPara
.nDelBorderFlag
&= 7;
395 BOOST_FOREACH( _FndLine
& rFndLine
, rFndBox
.GetLines() )
396 lcl_CopyRow( rFndLine
, &aPara
);
400 ::_InsTblBox( pCpyPara
->pDoc
, pCpyPara
->pTblNd
, pCpyPara
->pInsLine
,
401 aFindFrm
.pNewFrmFmt
, pBox
, pCpyPara
->nInsPos
++ );
403 const _FndBoxes
& rFndBxs
= rFndBox
.GetUpper()->GetBoxes();
404 if( 8 > pCpyPara
->nDelBorderFlag
405 ? pCpyPara
->nDelBorderFlag
406 : &rFndBox
== &rFndBxs
[rFndBxs
.size() - 1] )
408 const SvxBoxItem
& rBoxItem
= pBox
->GetFrmFmt()->GetBox();
409 if( 8 > pCpyPara
->nDelBorderFlag
411 : rBoxItem
.GetRight() )
413 aFindFrm
.Value
.pFrmFmt
= (SwTableBoxFmt
*)pBox
->GetFrmFmt();
415 SvxBoxItem
aNew( rBoxItem
);
416 if( 8 > pCpyPara
->nDelBorderFlag
)
417 aNew
.SetLine( 0, BOX_LINE_TOP
);
419 aNew
.SetLine( 0, BOX_LINE_RIGHT
);
421 if( 1 == pCpyPara
->nDelBorderFlag
||
422 8 == pCpyPara
->nDelBorderFlag
)
424 // For all Boxes that delete TopBorderLine, we copy after that
425 pBox
= pCpyPara
->pInsLine
->GetTabBoxes()[
426 pCpyPara
->nInsPos
- 1 ];
429 aFindFrm
.pNewFrmFmt
= (SwTableBoxFmt
*)pBox
->GetFrmFmt();
431 // Else we copy before that and the first Line keeps the TopLine
432 // and we remove it at the original
433 pBox
->ClaimFrmFmt()->SetFmtAttr( aNew
);
435 if( !pCpyPara
->nCpyCnt
)
436 pCpyPara
->rTabFrmArr
.insert( aFindFrm
);
442 static void lcl_CopyRow(_FndLine
& rFndLine
, _CpyPara
*const pCpyPara
)
444 SwTableLine
* pNewLine
= new SwTableLine(
445 (SwTableLineFmt
*)rFndLine
.GetLine()->GetFrmFmt(),
446 rFndLine
.GetBoxes().size(), pCpyPara
->pInsBox
);
447 if( pCpyPara
->pInsBox
)
449 SwTableLines
& rLines
= pCpyPara
->pInsBox
->GetTabLines();
450 rLines
.insert( rLines
.begin() + pCpyPara
->nInsPos
++, pNewLine
);
454 SwTableLines
& rLines
= pCpyPara
->pTblNd
->GetTable().GetTabLines();
455 rLines
.insert( rLines
.begin() + pCpyPara
->nInsPos
++, pNewLine
);
458 _CpyPara
aPara( *pCpyPara
, pNewLine
);
459 for (_FndBoxes::iterator it
= rFndLine
.GetBoxes().begin();
460 it
!= rFndLine
.GetBoxes().end(); ++it
)
462 lcl_CopyCol(*it
, &aPara
);
465 pCpyPara
->nDelBorderFlag
&= 0xf8;
468 static void lcl_InsCol( _FndLine
* pFndLn
, _CpyPara
& rCpyPara
, sal_uInt16 nCpyCnt
,
471 // Bug 29124: Not only copy in the BaseLines. If possible, we go down as far as possible
473 if( 1 == pFndLn
->GetBoxes().size() &&
474 !( pFBox
= &pFndLn
->GetBoxes()[0] )->GetBox()->GetSttNd() )
476 // A Box with multiple Lines, so insert into these Lines
477 for( sal_uInt16 n
= 0; n
< pFBox
->GetLines().size(); ++n
)
478 lcl_InsCol( &pFBox
->GetLines()[ n
], rCpyPara
, nCpyCnt
, bBehind
);
482 rCpyPara
.pInsLine
= pFndLn
->GetLine();
483 SwTableBox
* pBox
= pFndLn
->GetBoxes()[ bBehind
?
484 pFndLn
->GetBoxes().size()-1 : 0 ].GetBox();
485 rCpyPara
.nInsPos
= pFndLn
->GetLine()->GetTabBoxes().GetPos( pBox
);
489 for( sal_uInt16 n
= 0; n
< nCpyCnt
; ++n
)
491 if( n
+ 1 == nCpyCnt
&& bBehind
)
492 rCpyPara
.nDelBorderFlag
= 9;
494 rCpyPara
.nDelBorderFlag
= 8;
495 for (_FndBoxes::iterator it
= pFndLn
->GetBoxes().begin();
496 it
!= pFndLn
->GetBoxes().end(); ++it
)
498 lcl_CopyCol(*it
, &rCpyPara
);
504 SwRowFrm
* GetRowFrm( SwTableLine
& rLine
)
506 SwIterator
<SwRowFrm
,SwFmt
> aIter( *rLine
.GetFrmFmt() );
507 for( SwRowFrm
* pFrm
= aIter
.First(); pFrm
; pFrm
= aIter
.Next() )
508 if( pFrm
->GetTabLine() == &rLine
)
513 bool SwTable::InsertCol( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
, sal_uInt16 nCnt
, bool bBehind
)
515 OSL_ENSURE( !rBoxes
.empty() && nCnt
, "No valid Box List" );
516 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
522 bRes
= NewInsertCol( pDoc
, rBoxes
, nCnt
, bBehind
);
525 // Find all Boxes/Lines
526 _FndBox
aFndBox( 0, 0 );
528 _FndPara
aPara( rBoxes
, &aFndBox
);
529 ForEach_FndLineCopyCol( GetTabLines(), &aPara
);
531 if( aFndBox
.GetLines().empty() )
534 SetHTMLTableLayout( 0 ); // Delete HTML Layout
536 // Find Lines for the layout update
537 aFndBox
.SetTableLines( *this );
538 aFndBox
.DelFrms( *this );
540 // TL_CHART2: nothing to be done since chart2 currently does not want to
541 // get notified about new rows/cols.
543 _CpyTabFrms aTabFrmArr
;
544 _CpyPara
aCpyPara( pTblNd
, nCnt
, aTabFrmArr
);
546 for( sal_uInt16 n
= 0; n
< aFndBox
.GetLines().size(); ++n
)
547 lcl_InsCol( &aFndBox
.GetLines()[ n
], aCpyPara
, nCnt
, bBehind
);
549 // clean up this Line's structure once again, generally all of them
553 aFndBox
.MakeFrms( *this );
560 SwChartDataProvider
*pPCD
= pDoc
->GetChartDataProvider();
562 pPCD
->AddRowCols( *this, rBoxes
, nCnt
, bBehind
);
563 pDoc
->UpdateCharts( GetFrmFmt()->GetName() );
568 bool SwTable::_InsertRow( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
,
569 sal_uInt16 nCnt
, bool bBehind
)
571 OSL_ENSURE( pDoc
&& !rBoxes
.empty() && nCnt
, "No valid Box List" );
572 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
576 // Find all Boxes/Lines
577 _FndBox
aFndBox( 0, 0 );
579 _FndPara
aPara( rBoxes
, &aFndBox
);
580 ForEach_FndLineCopyCol( GetTabLines(), &aPara
);
582 if( aFndBox
.GetLines().empty() )
585 SetHTMLTableLayout( 0 ); // Delete HTML Layout
587 _FndBox
* pFndBox
= &aFndBox
;
590 while( 1 == pFndBox
->GetLines().size() &&
591 1 == ( pFndLine
= &pFndBox
->GetLines()[ 0 ])->GetBoxes().size() )
593 // Don't go down too far! One Line with Box needs to remain!
594 _FndBox
* pTmpBox
= &pFndLine
->GetBoxes().front();
595 if( !pTmpBox
->GetLines().empty() )
602 // Find Lines for the layout update
603 const bool bLayout
= !IsNewModel() &&
604 0 != SwIterator
<SwTabFrm
,SwFmt
>::FirstElement( *GetFrmFmt() );
608 aFndBox
.SetTableLines( *this );
609 if( pFndBox
!= &aFndBox
)
610 aFndBox
.DelFrms( *this );
611 // TL_CHART2: nothing to be done since chart2 currently does not want to
612 // get notified about new rows/cols.
615 _CpyTabFrms aTabFrmArr
;
616 _CpyPara
aCpyPara( pTblNd
, 0, aTabFrmArr
);
618 SwTableLine
* pLine
= pFndBox
->GetLines()[ bBehind
?
619 pFndBox
->GetLines().size()-1 : 0 ].GetLine();
620 if( &aFndBox
== pFndBox
)
621 aCpyPara
.nInsPos
= GetTabLines().GetPos( pLine
);
624 aCpyPara
.pInsBox
= pFndBox
->GetBox();
625 aCpyPara
.nInsPos
= pFndBox
->GetBox()->GetTabLines().GetPos( pLine
);
631 aCpyPara
.nDelBorderFlag
= 1;
634 aCpyPara
.nDelBorderFlag
= 2;
636 for( sal_uInt16 nCpyCnt
= 0; nCpyCnt
< nCnt
; ++nCpyCnt
)
639 aCpyPara
.nDelBorderFlag
= 1;
640 BOOST_FOREACH( _FndLine
& rFndLine
, pFndBox
->GetLines() )
641 lcl_CopyRow( rFndLine
, &aCpyPara
);
644 // clean up this Line's structure once again, generally all of them
645 if( !pDoc
->IsInReading() )
651 if( pFndBox
!= &aFndBox
)
652 aFndBox
.MakeFrms( *this );
654 aFndBox
.MakeNewFrms( *this, nCnt
, bBehind
);
660 SwChartDataProvider
*pPCD
= pDoc
->GetChartDataProvider();
662 pPCD
->AddRowCols( *this, rBoxes
, nCnt
, bBehind
);
663 pDoc
->UpdateCharts( GetFrmFmt()->GetName() );
668 void _FndBoxAppendRowLine( SwTableLine
* pLine
, _FndPara
* pFndPara
);
670 static void _FndBoxAppendRowBox( SwTableBox
* pBox
, _FndPara
* pFndPara
)
672 _FndBox
* pFndBox
= new _FndBox( pBox
, pFndPara
->pFndLine
);
673 if( pBox
->GetTabLines().size() )
675 _FndPara
aPara( *pFndPara
, pFndBox
);
676 BOOST_FOREACH( SwTableLine
* pLine
, pFndBox
->GetBox()->GetTabLines() )
677 _FndBoxAppendRowLine( pLine
, &aPara
);
678 if( pFndBox
->GetLines().empty() )
682 pFndPara
->pFndLine
->GetBoxes().push_back( pFndBox
);
685 void _FndBoxAppendRowLine( SwTableLine
* pLine
, _FndPara
* pFndPara
)
687 _FndLine
* pFndLine
= new _FndLine( pLine
, pFndPara
->pFndBox
);
688 _FndPara
aPara( *pFndPara
, pFndLine
);
689 for( SwTableBoxes::iterator it
= pFndLine
->GetLine()->GetTabBoxes().begin();
690 it
!= pFndLine
->GetLine()->GetTabBoxes().end(); ++it
)
691 _FndBoxAppendRowBox(*it
, &aPara
);
692 if( pFndLine
->GetBoxes().size() )
694 pFndPara
->pFndBox
->GetLines().push_back( pFndLine
);
700 bool SwTable::AppendRow( SwDoc
* pDoc
, sal_uInt16 nCnt
)
702 SwTableNode
*const pTblNd
= const_cast<SwTableNode
*>(
703 m_TabSortContentBoxes
[0]->GetSttNd()->FindTableNode());
707 // Find all Boxes/Lines
708 _FndBox
aFndBox( 0, 0 );
710 SwTableLine
* pLLine
= GetTabLines().back();
712 const SwSelBoxes
* pBxs
= 0; // Dummy!!!
713 _FndPara
aPara( *pBxs
, &aFndBox
);
715 _FndBoxAppendRowLine(pLLine
, &aPara
);
717 if( aFndBox
.GetLines().empty() )
720 SetHTMLTableLayout( 0 ); // Delete HTML Layout
722 // Find Lines for the Layout update
723 bool bLayout
= 0 != SwIterator
<SwTabFrm
,SwFmt
>::FirstElement( *GetFrmFmt() );
726 aFndBox
.SetTableLines( *this );
727 // TL_CHART2: nothing to be done since chart2 currently does not want to
728 // get notified about new rows/cols.
731 _CpyTabFrms aTabFrmArr
;
732 _CpyPara
aCpyPara( pTblNd
, 0, aTabFrmArr
);
733 aCpyPara
.nInsPos
= GetTabLines().size();
734 aCpyPara
.nDelBorderFlag
= 1;
736 for( sal_uInt16 nCpyCnt
= 0; nCpyCnt
< nCnt
; ++nCpyCnt
)
738 aCpyPara
.nDelBorderFlag
= 1;
739 BOOST_FOREACH( _FndLine
& rFndLine
, aFndBox
.GetLines() )
740 lcl_CopyRow( rFndLine
, &aCpyPara
);
743 // Clean up this Line's structure once again, generally all of them
744 if( !pDoc
->IsInReading() )
750 aFndBox
.MakeNewFrms( *this, nCnt
, sal_True
);
752 // TL_CHART2: need to inform chart of probably changed cell names
753 pDoc
->UpdateCharts( GetFrmFmt()->GetName() );
761 static void lcl_LastBoxSetWidth( SwTableBoxes
&rBoxes
, const long nOffset
,
762 bool bFirst
, SwShareBoxFmts
& rShareFmts
);
764 static void lcl_LastBoxSetWidthLine( SwTableLines
&rLines
, const long nOffset
,
765 bool bFirst
, SwShareBoxFmts
& rShareFmts
)
767 for ( sal_uInt16 i
= 0; i
< rLines
.size(); ++i
)
768 ::lcl_LastBoxSetWidth( rLines
[i
]->GetTabBoxes(), nOffset
, bFirst
,
772 static void lcl_LastBoxSetWidth( SwTableBoxes
&rBoxes
, const long nOffset
,
773 bool bFirst
, SwShareBoxFmts
& rShareFmts
)
775 SwTableBox
& rBox
= *(bFirst
? rBoxes
.front() : rBoxes
.back());
776 if( !rBox
.GetSttNd() )
777 ::lcl_LastBoxSetWidthLine( rBox
.GetTabLines(), nOffset
,
778 bFirst
, rShareFmts
);
781 const SwFrmFmt
*pBoxFmt
= rBox
.GetFrmFmt();
782 SwFmtFrmSize
aNew( pBoxFmt
->GetFrmSize() );
783 aNew
.SetWidth( aNew
.GetWidth() + nOffset
);
784 SwFrmFmt
*pFmt
= rShareFmts
.GetFormat( *pBoxFmt
, aNew
);
786 rBox
.ChgFrmFmt( (SwTableBoxFmt
*)pFmt
);
789 pFmt
= rBox
.ClaimFrmFmt();
792 pFmt
->SetFmtAttr( aNew
);
793 pFmt
->UnlockModify();
795 rShareFmts
.AddFormat( *pBoxFmt
, *pFmt
);
799 void _DeleteBox( SwTable
& rTbl
, SwTableBox
* pBox
, SwUndo
* pUndo
,
800 bool bCalcNewSize
, const bool bCorrBorder
,
801 SwShareBoxFmts
* pShareFmts
)
804 SwTwips nBoxSz
= bCalcNewSize
?
805 pBox
->GetFrmFmt()->GetFrmSize().GetWidth() : 0;
806 SwTableLine
* pLine
= pBox
->GetUpper();
807 SwTableBoxes
& rTblBoxes
= pLine
->GetTabBoxes();
808 sal_uInt16 nDelPos
= rTblBoxes
.GetPos( pBox
);
809 SwTableBox
* pUpperBox
= pBox
->GetUpper()->GetUpper();
811 // Special treatment for the border:
812 if( bCorrBorder
&& 1 < rTblBoxes
.size() )
815 const SvxBoxItem
& rBoxItem
= pBox
->GetFrmFmt()->GetBox();
817 if( rBoxItem
.GetLeft() || rBoxItem
.GetRight() )
819 // JP 02.04.97: 1st part for Bug 36271
820 // First the left/right edges
821 if( nDelPos
+ 1 < (sal_uInt16
)rTblBoxes
.size() )
823 SwTableBox
* pNxtBox
= rTblBoxes
[ nDelPos
+ 1 ];
824 const SvxBoxItem
& rNxtBoxItem
= pNxtBox
->GetFrmFmt()->GetBox();
826 SwTableBox
* pPrvBox
= nDelPos
? rTblBoxes
[ nDelPos
- 1 ] : 0;
828 if( pNxtBox
->GetSttNd() && !rNxtBoxItem
.GetLeft() &&
829 ( !pPrvBox
|| !pPrvBox
->GetFrmFmt()->GetBox().GetRight()) )
831 SvxBoxItem
aTmp( rNxtBoxItem
);
832 aTmp
.SetLine( rBoxItem
.GetLeft() ? rBoxItem
.GetLeft()
833 : rBoxItem
.GetRight(),
836 pShareFmts
->SetAttr( *pNxtBox
, aTmp
);
838 pNxtBox
->ClaimFrmFmt()->SetFmtAttr( aTmp
);
842 if( !bChgd
&& nDelPos
)
844 SwTableBox
* pPrvBox
= rTblBoxes
[ nDelPos
- 1 ];
845 const SvxBoxItem
& rPrvBoxItem
= pPrvBox
->GetFrmFmt()->GetBox();
847 SwTableBox
* pNxtBox
= nDelPos
+ 1 < (sal_uInt16
)rTblBoxes
.size()
848 ? rTblBoxes
[ nDelPos
+ 1 ] : 0;
850 if( pPrvBox
->GetSttNd() && !rPrvBoxItem
.GetRight() &&
851 ( !pNxtBox
|| !pNxtBox
->GetFrmFmt()->GetBox().GetLeft()) )
853 SvxBoxItem
aTmp( rPrvBoxItem
);
854 aTmp
.SetLine( rBoxItem
.GetLeft() ? rBoxItem
.GetLeft()
855 : rBoxItem
.GetRight(),
858 pShareFmts
->SetAttr( *pPrvBox
, aTmp
);
860 pPrvBox
->ClaimFrmFmt()->SetFmtAttr( aTmp
);
867 // Delete the Box first, then the Nodes!
868 SwStartNode
* pSttNd
= (SwStartNode
*)pBox
->GetSttNd();
870 pShareFmts
->RemoveFormat( *rTblBoxes
[ nDelPos
]->GetFrmFmt() );
871 delete rTblBoxes
[nDelPos
];
872 rTblBoxes
.erase( rTblBoxes
.begin() + nDelPos
);
876 // Has the UndoObject been prepared to save the Section?
877 if( pUndo
&& pUndo
->IsDelBox() )
878 ((SwUndoTblNdsChg
*)pUndo
)->SaveSection( pSttNd
);
880 pSttNd
->GetDoc()->DeleteSection( pSttNd
);
883 // Also delete the Line?
884 if( !rTblBoxes
.empty() )
886 // Then adapt the Frame-SSize
887 bool bLastBox
= nDelPos
== rTblBoxes
.size();
890 pBox
= rTblBoxes
[nDelPos
];
893 SwFmtFrmSize
aNew( pBox
->GetFrmFmt()->GetFrmSize() );
894 aNew
.SetWidth( aNew
.GetWidth() + nBoxSz
);
896 pShareFmts
->SetSize( *pBox
, aNew
);
898 pBox
->ClaimFrmFmt()->SetFmtAttr( aNew
);
900 if( !pBox
->GetSttNd() )
902 // We need to this recursively in all Lines in all Cells!
903 SwShareBoxFmts aShareFmts
;
904 ::lcl_LastBoxSetWidthLine( pBox
->GetTabLines(), nBoxSz
,
906 pShareFmts
? *pShareFmts
910 break; // Stop deleting
912 // Delete the Line from the Table/Box
915 // Also delete the Line from the Table
916 nDelPos
= rTbl
.GetTabLines().GetPos( pLine
);
918 pShareFmts
->RemoveFormat( *rTbl
.GetTabLines()[ nDelPos
]->GetFrmFmt() );
919 delete rTbl
.GetTabLines()[ nDelPos
];
920 rTbl
.GetTabLines().erase( rTbl
.GetTabLines().begin() + nDelPos
);
921 break; // we cannot delete more
924 // finally also delete the Line
926 nDelPos
= pBox
->GetTabLines().GetPos( pLine
);
928 pShareFmts
->RemoveFormat( *pBox
->GetTabLines()[ nDelPos
]->GetFrmFmt() );
929 delete pBox
->GetTabLines()[ nDelPos
];
930 pBox
->GetTabLines().erase( pBox
->GetTabLines().begin() + nDelPos
);
931 } while( pBox
->GetTabLines().empty() );
935 lcl_FndNxtPrvDelBox( const SwTableLines
& rTblLns
,
936 SwTwips nBoxStt
, SwTwips nBoxWidth
,
937 sal_uInt16 nLinePos
, bool bNxt
,
938 SwSelBoxes
* pAllDelBoxes
, size_t *const pCurPos
)
940 SwTableBox
* pFndBox
= 0;
946 SwTableLine
* pLine
= rTblLns
[ nLinePos
];
947 SwTwips nFndBoxWidth
= 0;
948 SwTwips nFndWidth
= nBoxStt
+ nBoxWidth
;
949 sal_uInt16 nBoxCnt
= pLine
->GetTabBoxes().size();
951 pFndBox
= pLine
->GetTabBoxes()[ 0 ];
952 for( sal_uInt16 n
= 0; 0 < nFndWidth
&& n
< nBoxCnt
; ++n
)
954 pFndBox
= pLine
->GetTabBoxes()[ n
];
955 nFndWidth
-= (nFndBoxWidth
= pFndBox
->GetFrmFmt()->
956 GetFrmSize().GetWidth());
959 // Find the first ContentBox
960 while( !pFndBox
->GetSttNd() )
962 const SwTableLines
& rLowLns
= pFndBox
->GetTabLines();
964 pFndBox
= rLowLns
.front()->GetTabBoxes().front();
966 pFndBox
= rLowLns
.back()->GetTabBoxes().front();
969 if( Abs( nFndWidth
) > COLFUZZY
||
970 Abs( nBoxWidth
- nFndBoxWidth
) > COLFUZZY
)
972 else if( pAllDelBoxes
)
974 // If the predecessor will also be deleted, there's nothing to do
975 SwSelBoxes::const_iterator aFndIt
= pAllDelBoxes
->find( pFndBox
);
976 if( aFndIt
== pAllDelBoxes
->end() )
978 size_t const nFndPos
= aFndIt
- pAllDelBoxes
->begin() ;
980 // else, we keep on searching.
981 // We do not need to recheck the Box, however
983 if( nFndPos
<= *pCurPos
)
985 pAllDelBoxes
->erase( pAllDelBoxes
->begin() + nFndPos
);
987 } while( bNxt
? ( nLinePos
+ 1 < (sal_uInt16
)rTblLns
.size() ) : nLinePos
);
992 lcl_SaveUpperLowerBorder( SwTable
& rTbl
, const SwTableBox
& rBox
,
993 SwShareBoxFmts
& rShareFmts
,
994 SwSelBoxes
* pAllDelBoxes
= 0,
995 size_t *const pCurPos
= 0 )
997 //JP 16.04.97: 2. part for Bug 36271
999 const SwTableLine
* pLine
= rBox
.GetUpper();
1000 const SwTableBoxes
& rTblBoxes
= pLine
->GetTabBoxes();
1001 const SwTableBox
* pUpperBox
= &rBox
;
1002 sal_uInt16 nDelPos
= rTblBoxes
.GetPos( pUpperBox
);
1003 pUpperBox
= rBox
.GetUpper()->GetUpper();
1004 const SvxBoxItem
& rBoxItem
= rBox
.GetFrmFmt()->GetBox();
1006 // then the top/bottom edges
1007 if( rBoxItem
.GetTop() || rBoxItem
.GetBottom() )
1010 const SwTableLines
* pTblLns
;
1012 pTblLns
= &pUpperBox
->GetTabLines();
1014 pTblLns
= &rTbl
.GetTabLines();
1016 sal_uInt16 nLnPos
= pTblLns
->GetPos( pLine
);
1018 // Calculate the attribute position of the top-be-deleted Box and then
1019 // search in the top/bottom Line of the respective counterparts.
1020 SwTwips nBoxStt
= 0;
1021 for( sal_uInt16 n
= 0; n
< nDelPos
; ++n
)
1022 nBoxStt
+= rTblBoxes
[ n
]->GetFrmFmt()->GetFrmSize().GetWidth();
1023 SwTwips nBoxWidth
= rBox
.GetFrmFmt()->GetFrmSize().GetWidth();
1025 SwTableBox
*pPrvBox
= 0, *pNxtBox
= 0;
1026 if( nLnPos
) // Predecessor?
1027 pPrvBox
= ::lcl_FndNxtPrvDelBox( *pTblLns
, nBoxStt
, nBoxWidth
,
1028 nLnPos
, false, pAllDelBoxes
, pCurPos
);
1030 if( nLnPos
+ 1 < (sal_uInt16
)pTblLns
->size() ) // Successor?
1031 pNxtBox
= ::lcl_FndNxtPrvDelBox( *pTblLns
, nBoxStt
, nBoxWidth
,
1032 nLnPos
, true, pAllDelBoxes
, pCurPos
);
1034 if( pNxtBox
&& pNxtBox
->GetSttNd() )
1036 const SvxBoxItem
& rNxtBoxItem
= pNxtBox
->GetFrmFmt()->GetBox();
1037 if( !rNxtBoxItem
.GetTop() && ( !pPrvBox
||
1038 !pPrvBox
->GetFrmFmt()->GetBox().GetBottom()) )
1040 SvxBoxItem
aTmp( rNxtBoxItem
);
1041 aTmp
.SetLine( rBoxItem
.GetTop() ? rBoxItem
.GetTop()
1042 : rBoxItem
.GetBottom(),
1044 rShareFmts
.SetAttr( *pNxtBox
, aTmp
);
1048 if( !bChgd
&& pPrvBox
&& pPrvBox
->GetSttNd() )
1050 const SvxBoxItem
& rPrvBoxItem
= pPrvBox
->GetFrmFmt()->GetBox();
1051 if( !rPrvBoxItem
.GetTop() && ( !pNxtBox
||
1052 !pNxtBox
->GetFrmFmt()->GetBox().GetTop()) )
1054 SvxBoxItem
aTmp( rPrvBoxItem
);
1055 aTmp
.SetLine( rBoxItem
.GetTop() ? rBoxItem
.GetTop()
1056 : rBoxItem
.GetBottom(),
1058 rShareFmts
.SetAttr( *pPrvBox
, aTmp
);
1065 bool SwTable::DeleteSel(
1068 const SwSelBoxes
& rBoxes
,
1069 const SwSelBoxes
* pMerged
, SwUndo
* pUndo
,
1070 const bool bDelMakeFrms
, const bool bCorrBorder
)
1072 OSL_ENSURE( pDoc
, "No doc?" );
1073 SwTableNode
* pTblNd
= 0;
1074 if( !rBoxes
.empty() )
1076 pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1081 SetHTMLTableLayout( 0 ); // Delete HTML Layout
1083 // Find Lines for the Layout update
1084 _FndBox
aFndBox( 0, 0 );
1087 if( pMerged
&& !pMerged
->empty() )
1088 aFndBox
.SetTableLines( *pMerged
, *this );
1089 else if( !rBoxes
.empty() )
1090 aFndBox
.SetTableLines( rBoxes
, *this );
1091 aFndBox
.DelFrms( *this );
1094 SwShareBoxFmts aShareFmts
;
1096 // First switch the Border, then delete
1099 SwSelBoxes
aBoxes( rBoxes
);
1100 for (size_t n
= 0; n
< aBoxes
.size(); ++n
)
1102 ::lcl_SaveUpperLowerBorder( *this, *rBoxes
[ n
], aShareFmts
,
1107 PrepareDelBoxes( rBoxes
);
1109 SwChartDataProvider
*pPCD
= pDoc
->GetChartDataProvider();
1110 // Delete boxes from last to first
1111 for (size_t n
= 0; n
< rBoxes
.size(); ++n
)
1113 size_t const nIdx
= rBoxes
.size() - 1 - n
;
1115 // First adapt the data-sequence for chart if necessary
1116 // (needed to move the implementation cursor properly to it's new
1117 // position which can't be done properly if the cell is already gone)
1119 pPCD
->DeleteBox( &pTblNd
->GetTable(), *rBoxes
[nIdx
] );
1121 // ... then delete the boxes
1122 _DeleteBox( *this, rBoxes
[nIdx
], pUndo
, true, bCorrBorder
, &aShareFmts
);
1125 // then clean up the structure of all Lines
1128 if( bDelMakeFrms
&& aFndBox
.AreLinesToRestore( *this ) )
1129 aFndBox
.MakeFrms( *this );
1131 // TL_CHART2: now inform chart that sth has changed
1132 pDoc
->UpdateCharts( GetFrmFmt()->GetName() );
1135 CHECK_TABLE( *this );
1140 bool SwTable::OldSplitRow( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
, sal_uInt16 nCnt
,
1143 OSL_ENSURE( pDoc
&& !rBoxes
.empty() && nCnt
, "No valid values" );
1144 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1148 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1149 // the table too complex to be handled with chart.
1150 // Thus we tell the charts to use their own data provider and forget about this table
1151 pDoc
->CreateChartInternalDataProviders( this );
1153 SetHTMLTableLayout( 0 ); // Delete HTML Layout
1155 // If the rows should get the same (min) height, we first have
1156 // to store the old row heights before deleting the frames
1157 long* pRowHeights
= 0;
1160 pRowHeights
= new long[ rBoxes
.size() ];
1161 for (size_t n
= 0; n
< rBoxes
.size(); ++n
)
1163 SwTableBox
* pSelBox
= rBoxes
[n
];
1164 const SwRowFrm
* pRow
= GetRowFrm( *pSelBox
->GetUpper() );
1165 OSL_ENSURE( pRow
, "Where is the SwTableLine's Frame?" );
1167 pRowHeights
[ n
] = (pRow
->Frm().*fnRect
->fnGetHeight
)();
1171 // Find Lines for the Layout update
1172 _FndBox
aFndBox( 0, 0 );
1173 aFndBox
.SetTableLines( rBoxes
, *this );
1174 aFndBox
.DelFrms( *this );
1176 for (size_t n
= 0; n
< rBoxes
.size(); ++n
)
1178 SwTableBox
* pSelBox
= rBoxes
[n
];
1179 OSL_ENSURE( pSelBox
, "Box is not within the Table" );
1181 // Insert nCnt new Lines into the Box
1182 SwTableLine
* pInsLine
= pSelBox
->GetUpper();
1183 SwTableBoxFmt
* pFrmFmt
= (SwTableBoxFmt
*)pSelBox
->GetFrmFmt();
1185 // Respect the Line's height, reset if needed
1186 SwFmtFrmSize
aFSz( pInsLine
->GetFrmFmt()->GetFrmSize() );
1187 if ( bSameHeight
&& ATT_VAR_SIZE
== aFSz
.GetHeightSizeType() )
1188 aFSz
.SetHeightSizeType( ATT_MIN_SIZE
);
1190 bool bChgLineSz
= 0 != aFSz
.GetHeight() || bSameHeight
;
1192 aFSz
.SetHeight( ( bSameHeight
? pRowHeights
[ n
] : aFSz
.GetHeight() ) /
1195 SwTableBox
* pNewBox
= new SwTableBox( pFrmFmt
, nCnt
, pInsLine
);
1196 sal_uInt16 nBoxPos
= pInsLine
->GetTabBoxes().GetPos( pSelBox
);
1197 pInsLine
->GetTabBoxes()[nBoxPos
] = pNewBox
; // overwrite old one
1199 // Delete background/border attribute
1200 SwTableBox
* pLastBox
= pSelBox
; // To distribute the TextNodes!
1201 // If Areas are contained in the Box, it stays as is
1202 // !! If this is changed we need to adapt the Undo, too !!!
1203 bool bMoveNodes
= true;
1205 sal_uLong nSttNd
= pLastBox
->GetSttIdx() + 1,
1206 nEndNd
= pLastBox
->GetSttNd()->EndOfSectionIndex();
1207 while( nSttNd
< nEndNd
)
1208 if( !pDoc
->GetNodes()[ nSttNd
++ ]->IsTxtNode() )
1215 SwTableBoxFmt
* pCpyBoxFrmFmt
= (SwTableBoxFmt
*)pSelBox
->GetFrmFmt();
1216 bool bChkBorder
= 0 != pCpyBoxFrmFmt
->GetBox().GetTop();
1218 pCpyBoxFrmFmt
= (SwTableBoxFmt
*)pSelBox
->ClaimFrmFmt();
1220 for( sal_uInt16 i
= 0; i
<= nCnt
; ++i
)
1222 // Create a new Line in the new Box
1223 SwTableLine
* pNewLine
= new SwTableLine(
1224 (SwTableLineFmt
*)pInsLine
->GetFrmFmt(), 1, pNewBox
);
1227 pNewLine
->ClaimFrmFmt()->SetFmtAttr( aFSz
);
1230 pNewBox
->GetTabLines().insert( pNewBox
->GetTabLines().begin() + i
, pNewLine
);
1231 // then a new Box in the Line
1232 if( !i
) // hang up the original Box
1234 pSelBox
->SetUpper( pNewLine
);
1235 pNewLine
->GetTabBoxes().insert( pNewLine
->GetTabBoxes().begin(), pSelBox
);
1239 ::_InsTblBox( pDoc
, pTblNd
, pNewLine
, pCpyBoxFrmFmt
,
1244 pCpyBoxFrmFmt
= (SwTableBoxFmt
*)pNewLine
->GetTabBoxes()[ 0 ]->ClaimFrmFmt();
1245 SvxBoxItem
aTmp( pCpyBoxFrmFmt
->GetBox() );
1246 aTmp
.SetLine( 0, BOX_LINE_TOP
);
1247 pCpyBoxFrmFmt
->SetFmtAttr( aTmp
);
1253 const SwNode
* pEndNd
= pLastBox
->GetSttNd()->EndOfSectionNode();
1254 if( pLastBox
->GetSttIdx()+2 != pEndNd
->GetIndex() )
1257 SwNodeRange
aRg( *pLastBox
->GetSttNd(), +2, *pEndNd
);
1258 pLastBox
= pNewLine
->GetTabBoxes()[0]; // reset
1259 SwNodeIndex
aInsPos( *pLastBox
->GetSttNd(), 1 );
1260 pDoc
->GetNodes()._MoveNodes(aRg
, pDoc
->GetNodes(), aInsPos
, sal_False
);
1261 pDoc
->GetNodes().Delete( aInsPos
, 1 ); // delete the empty one
1266 // In Boxes with Lines, we can only have Size/Fillorder
1267 pFrmFmt
= (SwTableBoxFmt
*)pNewBox
->ClaimFrmFmt();
1268 pFrmFmt
->ResetFmtAttr( RES_LR_SPACE
, RES_FRMATR_END
- 1 );
1269 pFrmFmt
->ResetFmtAttr( RES_BOXATR_BEGIN
, RES_BOXATR_END
- 1 );
1272 delete[] pRowHeights
;
1276 aFndBox
.MakeFrms( *this );
1283 bool SwTable::SplitCol( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
, sal_uInt16 nCnt
)
1285 OSL_ENSURE( pDoc
&& !rBoxes
.empty() && nCnt
, "No valid values" );
1286 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1290 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1291 // the table too complex to be handled with chart.
1292 // Thus we tell the charts to use their own data provider and forget about this table
1293 pDoc
->CreateChartInternalDataProviders( this );
1295 SetHTMLTableLayout( 0 ); // Delete HTML Layout
1296 SwSelBoxes
aSelBoxes(rBoxes
);
1297 ExpandSelection( aSelBoxes
);
1299 // Find Lines for the Layout update
1300 _FndBox
aFndBox( 0, 0 );
1301 aFndBox
.SetTableLines( aSelBoxes
, *this );
1302 aFndBox
.DelFrms( *this );
1304 _CpyTabFrms aFrmArr
;
1305 std::vector
<SwTableBoxFmt
*> aLastBoxArr
;
1307 for (size_t n
= 0; n
< aSelBoxes
.size(); ++n
)
1309 SwTableBox
* pSelBox
= aSelBoxes
[n
];
1310 OSL_ENSURE( pSelBox
, "Box steht nicht in der Tabelle" );
1312 // We don't want to split small table cells into very very small cells
1313 if( pSelBox
->GetFrmFmt()->GetFrmSize().GetWidth()/( nCnt
+ 1 ) < 10 )
1316 // Then split the nCnt Box up into nCnt Boxes
1317 SwTableLine
* pInsLine
= pSelBox
->GetUpper();
1318 sal_uInt16 nBoxPos
= pInsLine
->GetTabBoxes().GetPos( pSelBox
);
1320 // Find the Frame Format in the Frame Format Array
1321 SwTableBoxFmt
* pLastBoxFmt
;
1322 _CpyTabFrm
aFindFrm( (SwTableBoxFmt
*)pSelBox
->GetFrmFmt() );
1323 _CpyTabFrms::const_iterator itFind
= aFrmArr
.lower_bound( aFindFrm
);
1324 nFndPos
= itFind
- aFrmArr
.begin();
1325 if( itFind
== aFrmArr
.end() || !(*itFind
== aFindFrm
) )
1327 // Change the FrmFmt
1328 aFindFrm
.pNewFrmFmt
= (SwTableBoxFmt
*)pSelBox
->ClaimFrmFmt();
1329 SwTwips nBoxSz
= aFindFrm
.pNewFrmFmt
->GetFrmSize().GetWidth();
1330 SwTwips nNewBoxSz
= nBoxSz
/ ( nCnt
+ 1 );
1331 aFindFrm
.pNewFrmFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
,
1333 aFrmArr
.insert( aFindFrm
);
1335 pLastBoxFmt
= aFindFrm
.pNewFrmFmt
;
1336 if( nBoxSz
!= ( nNewBoxSz
* (nCnt
+ 1)))
1338 // We have a remainder, so we need to define an own Format
1339 // for the last Box.
1340 pLastBoxFmt
= new SwTableBoxFmt( *aFindFrm
.pNewFrmFmt
);
1341 pLastBoxFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
,
1342 nBoxSz
- ( nNewBoxSz
* nCnt
), 0 ) );
1344 aLastBoxArr
.insert( aLastBoxArr
.begin() + nFndPos
, pLastBoxFmt
);
1348 aFindFrm
= aFrmArr
[ nFndPos
];
1349 pSelBox
->ChgFrmFmt( (SwTableBoxFmt
*)aFindFrm
.pNewFrmFmt
);
1350 pLastBoxFmt
= aLastBoxArr
[ nFndPos
];
1353 // Insert the Boxes at the Position
1354 for( sal_uInt16 i
= 1; i
< nCnt
; ++i
)
1355 ::_InsTblBox( pDoc
, pTblNd
, pInsLine
, aFindFrm
.pNewFrmFmt
,
1356 pSelBox
, nBoxPos
+ i
); // insert after
1358 ::_InsTblBox( pDoc
, pTblNd
, pInsLine
, pLastBoxFmt
,
1359 pSelBox
, nBoxPos
+ nCnt
); // insert after
1361 // Special treatment for the Border:
1362 const SvxBoxItem
& aSelBoxItem
= aFindFrm
.pNewFrmFmt
->GetBox();
1363 if( aSelBoxItem
.GetRight() )
1365 pInsLine
->GetTabBoxes()[ nBoxPos
+ nCnt
]->ClaimFrmFmt();
1367 SvxBoxItem
aTmp( aSelBoxItem
);
1368 aTmp
.SetLine( 0, BOX_LINE_RIGHT
);
1369 aFindFrm
.pNewFrmFmt
->SetFmtAttr( aTmp
);
1371 // Remove the Format from the "cache"
1372 for( sal_uInt16 i
= aFrmArr
.size(); i
; )
1374 const _CpyTabFrm
& rCTF
= aFrmArr
[ --i
];
1375 if( rCTF
.pNewFrmFmt
== aFindFrm
.pNewFrmFmt
||
1376 rCTF
.Value
.pFrmFmt
== aFindFrm
.pNewFrmFmt
)
1378 aFrmArr
.erase( aFrmArr
.begin() + i
);
1379 aLastBoxArr
.erase( aLastBoxArr
.begin() + i
);
1386 aFndBox
.MakeFrms( *this );
1394 ----------------------- >> MERGE << ------------------------
1396 If we only have one Line in the _FndBox, take this Line and test
1398 - If we have more than one Box, we merge on Box level, meaning
1399 the new Box will be as wide as the old ones.
1400 - All Lines that are above/under the Area, are inserted into
1401 the Box as Line + Box.
1402 - All Lines that come before/after the Area, are inserted into
1403 the Boxes Left/Right.
1405 ----------------------- >> MERGE << ------------------------
1407 static void lcl_CpyLines( sal_uInt16 nStt
, sal_uInt16 nEnd
,
1408 SwTableLines
& rLines
,
1409 SwTableBox
* pInsBox
,
1410 sal_uInt16 nPos
= USHRT_MAX
)
1412 for( sal_uInt16 n
= nStt
; n
< nEnd
; ++n
)
1413 rLines
[n
]->SetUpper( pInsBox
);
1414 if( USHRT_MAX
== nPos
)
1415 nPos
= pInsBox
->GetTabLines().size();
1416 pInsBox
->GetTabLines().insert( pInsBox
->GetTabLines().begin() + nPos
,
1417 rLines
.begin() + nStt
, rLines
.begin() + nEnd
);
1418 rLines
.erase( rLines
.begin() + nStt
, rLines
.begin() + nEnd
);
1421 static void lcl_CpyBoxes( sal_uInt16 nStt
, sal_uInt16 nEnd
,
1422 SwTableBoxes
& rBoxes
,
1423 SwTableLine
* pInsLine
,
1424 sal_uInt16 nPos
= USHRT_MAX
)
1426 for( sal_uInt16 n
= nStt
; n
< nEnd
; ++n
)
1427 rBoxes
[n
]->SetUpper( pInsLine
);
1428 if( USHRT_MAX
== nPos
)
1429 nPos
= pInsLine
->GetTabBoxes().size();
1430 pInsLine
->GetTabBoxes().insert( pInsLine
->GetTabBoxes().begin() + nPos
,
1431 rBoxes
.begin() + nStt
, rBoxes
.begin() + nEnd
);
1432 rBoxes
.erase( rBoxes
.begin() + nStt
, rBoxes
.begin() + nEnd
);
1435 static void lcl_CalcWidth( SwTableBox
* pBox
)
1437 // Assertion: Every Line in the Box is as large
1438 SwFrmFmt
* pFmt
= pBox
->ClaimFrmFmt();
1439 OSL_ENSURE( pBox
->GetTabLines().size(), "Box does not have any Lines" );
1441 SwTableLine
* pLine
= pBox
->GetTabLines()[0];
1442 OSL_ENSURE( pLine
, "Box is not within a Line" );
1445 for( sal_uInt16 n
= 0; n
< pLine
->GetTabBoxes().size(); ++n
)
1446 nWidth
+= pLine
->GetTabBoxes()[n
]->GetFrmFmt()->GetFrmSize().GetWidth();
1448 pFmt
->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nWidth
, 0 ));
1450 // Boxes with Lines can only have Size/Fillorder
1451 pFmt
->ResetFmtAttr( RES_LR_SPACE
, RES_FRMATR_END
- 1 );
1452 pFmt
->ResetFmtAttr( RES_BOXATR_BEGIN
, RES_BOXATR_END
- 1 );
1457 SwTableNode
* pTblNd
;
1458 SwTableLine
* pInsLine
;
1459 SwTableBox
* pInsBox
;
1460 bool bUL_LR
: 1; // Upper-Lower(true) or Left-Right(false) ?
1461 bool bUL
: 1; // Upper-Left(true) or Lower-Right(false) ?
1463 SwTableBox
* pLeftBox
;
1464 SwTableBox
* pRightBox
;
1465 SwTableBox
* pMergeBox
;
1467 _InsULPara( SwTableNode
* pTNd
, bool bUpperLower
, bool bUpper
,
1468 SwTableBox
* pLeft
, SwTableBox
* pMerge
, SwTableBox
* pRight
,
1469 SwTableLine
* pLine
=0, SwTableBox
* pBox
=0 )
1470 : pTblNd( pTNd
), pInsLine( pLine
), pInsBox( pBox
),
1471 pLeftBox( pLeft
), pRightBox( pRight
), pMergeBox( pMerge
)
1472 { bUL_LR
= bUpperLower
; bUL
= bUpper
; }
1474 void SetLeft( SwTableBox
* pBox
=0 )
1475 { bUL_LR
= false; bUL
= true; if( pBox
) pInsBox
= pBox
; }
1476 void SetRight( SwTableBox
* pBox
=0 )
1477 { bUL_LR
= false; bUL
= false; if( pBox
) pInsBox
= pBox
; }
1478 void SetUpper( SwTableLine
* pLine
=0 )
1479 { bUL_LR
= true; bUL
= true; if( pLine
) pInsLine
= pLine
; }
1480 void SetLower( SwTableLine
* pLine
=0 )
1481 { bUL_LR
= true; bUL
= false; if( pLine
) pInsLine
= pLine
; }
1484 static void lcl_Merge_MoveLine(_FndLine
& rFndLine
, _InsULPara
*const pULPara
);
1486 static void lcl_Merge_MoveBox(_FndBox
& rFndBox
, _InsULPara
*const pULPara
)
1488 SwTableBoxes
* pBoxes
;
1490 sal_uInt16 nStt
= 0, nEnd
= rFndBox
.GetLines().size();
1491 sal_uInt16 nInsPos
= USHRT_MAX
;
1492 if( !pULPara
->bUL_LR
) // Left/Right
1495 SwTableBox
* pFndTableBox
= rFndBox
.GetBox();
1496 pBoxes
= &pFndTableBox
->GetUpper()->GetTabBoxes();
1497 if( pULPara
->bUL
) // Left ?
1499 // if there are Boxes before it, move them
1500 if( 0 != ( nPos
= pBoxes
->GetPos( pFndTableBox
) ) )
1501 lcl_CpyBoxes( 0, nPos
, *pBoxes
, pULPara
->pInsLine
);
1504 // if there are Boxes behind it, move them
1505 if( (nPos
= pBoxes
->GetPos( pFndTableBox
)) +1 < (sal_uInt16
)pBoxes
->size() )
1507 nInsPos
= pULPara
->pInsLine
->GetTabBoxes().size();
1508 lcl_CpyBoxes( nPos
+1, pBoxes
->size(),
1509 *pBoxes
, pULPara
->pInsLine
);
1512 // Upper/Lower and still deeper?
1513 else if (!rFndBox
.GetLines().empty())
1515 // Only search the Line from which we need to move
1516 nStt
= pULPara
->bUL
? 0 : rFndBox
.GetLines().size()-1;
1520 pBoxes
= &pULPara
->pInsLine
->GetTabBoxes();
1522 // Is there still a level to step down to?
1523 if (rFndBox
.GetBox()->GetTabLines().size())
1525 SwTableBox
* pBox
= new SwTableBox(
1526 static_cast<SwTableBoxFmt
*>(rFndBox
.GetBox()->GetFrmFmt()),
1527 0, pULPara
->pInsLine
);
1528 _InsULPara
aPara( *pULPara
);
1529 aPara
.pInsBox
= pBox
;
1530 for (_FndLines::iterator it
= rFndBox
.GetLines().begin() + nStt
;
1531 it
!= rFndBox
.GetLines().begin() + nEnd
; ++it
)
1533 lcl_Merge_MoveLine(*it
, &aPara
);
1535 if( pBox
->GetTabLines().size() )
1537 if( USHRT_MAX
== nInsPos
)
1538 nInsPos
= pBoxes
->size();
1539 pBoxes
->insert( pBoxes
->begin() + nInsPos
, pBox
);
1540 lcl_CalcWidth( pBox
); // calculate the Box's width
1547 static void lcl_Merge_MoveLine(_FndLine
& rFndLine
, _InsULPara
*const pULPara
)
1549 SwTableLines
* pLines
;
1551 sal_uInt16 nStt
= 0, nEnd
= rFndLine
.GetBoxes().size();
1552 sal_uInt16 nInsPos
= USHRT_MAX
;
1553 if( pULPara
->bUL_LR
) // UpperLower ?
1556 SwTableLine
* pFndLn
= (SwTableLine
*)rFndLine
.GetLine();
1557 pLines
= pFndLn
->GetUpper() ?
1558 &pFndLn
->GetUpper()->GetTabLines() :
1559 &pULPara
->pTblNd
->GetTable().GetTabLines();
1561 SwTableBox
* pLBx
= rFndLine
.GetBoxes().front().GetBox();
1562 SwTableBox
* pRBx
= rFndLine
.GetBoxes().back().GetBox();
1563 sal_uInt16 nLeft
= pFndLn
->GetTabBoxes().GetPos( pLBx
);
1564 sal_uInt16 nRight
= pFndLn
->GetTabBoxes().GetPos( pRBx
);
1566 if( !nLeft
|| nRight
== pFndLn
->GetTabBoxes().size() )
1568 if( pULPara
->bUL
) // Upper ?
1570 // If there are Lines before it, move them
1571 if( 0 != ( nPos
= pLines
->GetPos( pFndLn
)) )
1572 lcl_CpyLines( 0, nPos
, *pLines
, pULPara
->pInsBox
);
1575 // If there are Lines after it, move them
1576 if( (nPos
= pLines
->GetPos( pFndLn
)) + 1 < (sal_uInt16
)pLines
->size() )
1578 nInsPos
= pULPara
->pInsBox
->GetTabLines().size();
1579 lcl_CpyLines( nPos
+1, pLines
->size(), *pLines
,
1585 // There are still Boxes on the left side, so put the Left-
1586 // and Merge-Box into one Box and Line, insert before/after
1587 // a Line with a Box, into which the upper/lower Lines are
1589 SwTableLine
* pInsLine
= pULPara
->pLeftBox
->GetUpper();
1590 SwTableBox
* pLMBox
= new SwTableBox(
1591 (SwTableBoxFmt
*)pULPara
->pLeftBox
->GetFrmFmt(), 0, pInsLine
);
1592 SwTableLine
* pLMLn
= new SwTableLine(
1593 (SwTableLineFmt
*)pInsLine
->GetFrmFmt(), 2, pLMBox
);
1594 pLMLn
->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE
);
1596 pLMBox
->GetTabLines().insert( pLMBox
->GetTabLines().begin(), pLMLn
);
1598 lcl_CpyBoxes( 0, 2, pInsLine
->GetTabBoxes(), pLMLn
);
1600 pInsLine
->GetTabBoxes().insert( pInsLine
->GetTabBoxes().begin(), pLMBox
);
1602 if( pULPara
->bUL
) // Upper ?
1604 // If there are Lines before it, move them
1605 if( 0 != ( nPos
= pLines
->GetPos( pFndLn
)) )
1606 lcl_CpyLines( 0, nPos
, *pLines
, pLMBox
, 0 );
1609 // If there are Lines after it, move them
1610 if( (nPos
= pLines
->GetPos( pFndLn
)) + 1 < (sal_uInt16
)pLines
->size() )
1611 lcl_CpyLines( nPos
+1, pLines
->size(), *pLines
,
1613 lcl_CalcWidth( pLMBox
); // calculate the Box's width
1615 else if( nRight
+1 < (sal_uInt16
)pFndLn
->GetTabBoxes().size() )
1617 // There are still Boxes on the right, so put the Right-
1618 // and Merge-Box into one Box and Line, insert before/after
1619 // a Line with a Box, into which the upper/lower Lines are
1621 SwTableLine
* pInsLine
= pULPara
->pRightBox
->GetUpper();
1623 if( pULPara
->pLeftBox
->GetUpper() == pInsLine
)
1625 pRMBox
= new SwTableBox(
1626 (SwTableBoxFmt
*)pULPara
->pRightBox
->GetFrmFmt(), 0, pInsLine
);
1627 SwTableLine
* pRMLn
= new SwTableLine(
1628 (SwTableLineFmt
*)pInsLine
->GetFrmFmt(), 2, pRMBox
);
1629 pRMLn
->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE
);
1630 pRMBox
->GetTabLines().insert( pRMBox
->GetTabLines().begin(), pRMLn
);
1632 lcl_CpyBoxes( 1, 3, pInsLine
->GetTabBoxes(), pRMLn
);
1634 pInsLine
->GetTabBoxes().insert( pInsLine
->GetTabBoxes().begin(), pRMBox
);
1638 // Left and Merge have been merged, so also move Right into the Line
1639 pInsLine
= pULPara
->pLeftBox
->GetUpper();
1640 sal_uInt16 nMvPos
= pULPara
->pRightBox
->GetUpper()->GetTabBoxes().GetPos(
1641 pULPara
->pRightBox
);
1642 lcl_CpyBoxes( nMvPos
, nMvPos
+1,
1643 pULPara
->pRightBox
->GetUpper()->GetTabBoxes(),
1645 pRMBox
= pInsLine
->GetUpper();
1647 // If there are already Lines, then these need to go into a new Line and Box
1648 nMvPos
= pRMBox
->GetTabLines().GetPos( pInsLine
);
1649 if( pULPara
->bUL
? nMvPos
1650 : nMvPos
+1 < (sal_uInt16
)pRMBox
->GetTabLines().size() )
1652 // Merge all Lines into a new Line and Box
1653 SwTableLine
* pNewLn
= new SwTableLine(
1654 (SwTableLineFmt
*)pInsLine
->GetFrmFmt(), 1, pRMBox
);
1655 pNewLn
->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE
);
1656 pRMBox
->GetTabLines().insert(
1657 pRMBox
->GetTabLines().begin() + (pULPara
->bUL
? nMvPos
: nMvPos
+1),
1659 pRMBox
= new SwTableBox( (SwTableBoxFmt
*)pRMBox
->GetFrmFmt(), 0, pNewLn
);
1660 pNewLn
->GetTabBoxes().insert( pNewLn
->GetTabBoxes().begin(), pRMBox
);
1662 sal_uInt16 nPos1
, nPos2
;
1668 nPos2
= pNewLn
->GetUpper()->GetTabLines().size();
1670 lcl_CpyLines( nPos1
, nPos2
,
1671 pNewLn
->GetUpper()->GetTabLines(), pRMBox
);
1672 lcl_CalcWidth( pRMBox
); // calculate the Box's width
1674 pRMBox
= new SwTableBox( (SwTableBoxFmt
*)pRMBox
->GetFrmFmt(), 0, pNewLn
);
1675 pNewLn
->GetTabBoxes().push_back( pRMBox
);
1678 if( pULPara
->bUL
) // Upper ?
1680 // If there are Lines before it, move them
1681 if( 0 != ( nPos
= pLines
->GetPos( pFndLn
)) )
1682 lcl_CpyLines( 0, nPos
, *pLines
, pRMBox
, 0 );
1685 // If there are Lines after it, move them
1686 if( (nPos
= pLines
->GetPos( pFndLn
)) + 1 < (sal_uInt16
)pLines
->size() )
1687 lcl_CpyLines( nPos
+1, pLines
->size(), *pLines
,
1689 lcl_CalcWidth( pRMBox
); // calculate the Box's width
1692 OSL_FAIL( "So ... what do we do now?" );
1698 // Find only the Line from which we need to move
1699 nStt
= pULPara
->bUL
? 0 : rFndLine
.GetBoxes().size()-1;
1702 pLines
= &pULPara
->pInsBox
->GetTabLines();
1704 SwTableLine
* pNewLine
= new SwTableLine(
1705 (SwTableLineFmt
*)rFndLine
.GetLine()->GetFrmFmt(), 0, pULPara
->pInsBox
);
1706 _InsULPara
aPara( *pULPara
); // kopieren
1707 aPara
.pInsLine
= pNewLine
;
1708 _FndBoxes
& rLineBoxes
= rFndLine
.GetBoxes();
1709 for (_FndBoxes::iterator it
= rLineBoxes
.begin() + nStt
;
1710 it
!= rLineBoxes
.begin() + nEnd
; ++it
)
1712 lcl_Merge_MoveBox(*it
, &aPara
);
1715 if( !pNewLine
->GetTabBoxes().empty() )
1717 if( USHRT_MAX
== nInsPos
)
1718 nInsPos
= pLines
->size();
1719 pLines
->insert( pLines
->begin() + nInsPos
, pNewLine
);
1725 static void lcl_BoxSetHeadCondColl( const SwTableBox
* pBox
);
1727 bool SwTable::OldMerge( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
,
1728 SwTableBox
* pMergeBox
, SwUndoTblMerge
* pUndo
)
1730 OSL_ENSURE( !rBoxes
.empty() && pMergeBox
, "no valid values" );
1731 SwTableNode
* pTblNd
= (SwTableNode
*)rBoxes
[0]->GetSttNd()->FindTableNode();
1735 // Find all Boxes/Lines
1736 _FndBox
aFndBox( 0, 0 );
1738 _FndPara
aPara( rBoxes
, &aFndBox
);
1739 ForEach_FndLineCopyCol( GetTabLines(), &aPara
);
1741 if( aFndBox
.GetLines().empty() )
1744 // TL_CHART2: splitting/merging of a number of cells or rows will usually make
1745 // the table too complex to be handled with chart.
1746 // Thus we tell the charts to use their own data provider and forget about this table
1747 pDoc
->CreateChartInternalDataProviders( this );
1749 SetHTMLTableLayout( 0 ); // Delete HTML Layout
1752 pUndo
->SetSelBoxes( rBoxes
);
1754 // Find Lines for the Layout update
1755 aFndBox
.SetTableLines( *this );
1756 aFndBox
.DelFrms( *this );
1758 _FndBox
* pFndBox
= &aFndBox
;
1759 while( 1 == pFndBox
->GetLines().size() &&
1760 1 == pFndBox
->GetLines().front().GetBoxes().size() )
1762 pFndBox
= &pFndBox
->GetLines().front().GetBoxes().front();
1765 SwTableLine
* pInsLine
= new SwTableLine(
1766 (SwTableLineFmt
*)pFndBox
->GetLines().front().GetLine()->GetFrmFmt(), 0,
1767 !pFndBox
->GetUpper() ? 0 : pFndBox
->GetBox() );
1768 pInsLine
->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE
);
1771 SwTableLines
* pLines
= pFndBox
->GetUpper() ?
1772 &pFndBox
->GetBox()->GetTabLines() : &GetTabLines();
1774 SwTableLine
* pNewLine
= pFndBox
->GetLines().front().GetLine();
1775 sal_uInt16 nInsPos
= pLines
->GetPos( pNewLine
);
1776 pLines
->insert( pLines
->begin() + nInsPos
, pInsLine
);
1778 SwTableBox
* pLeftBox
= new SwTableBox( (SwTableBoxFmt
*)pMergeBox
->GetFrmFmt(), 0, pInsLine
);
1779 SwTableBox
* pRightBox
= new SwTableBox( (SwTableBoxFmt
*)pMergeBox
->GetFrmFmt(), 0, pInsLine
);
1780 pMergeBox
->SetUpper( pInsLine
);
1781 pInsLine
->GetTabBoxes().insert( pInsLine
->GetTabBoxes().begin(), pLeftBox
);
1782 pLeftBox
->ClaimFrmFmt();
1783 pInsLine
->GetTabBoxes().insert( pInsLine
->GetTabBoxes().begin() + 1, pMergeBox
);
1784 pInsLine
->GetTabBoxes().insert( pInsLine
->GetTabBoxes().begin() + 2, pRightBox
);
1785 pRightBox
->ClaimFrmFmt();
1787 // This contains all Lines that are above the selected Area,
1788 // thus they form a Upper/Lower Line
1789 _InsULPara
aPara( pTblNd
, true, true, pLeftBox
, pMergeBox
, pRightBox
, pInsLine
);
1791 // Move the overlapping upper/lower Lines of the selected Area
1792 _FndBoxes
& rLineBoxes
= pFndBox
->GetLines().front().GetBoxes();
1793 for (_FndBoxes::iterator it
= rLineBoxes
.begin(); it
!= rLineBoxes
.end(); ++it
)
1795 lcl_Merge_MoveBox(*it
, &aPara
);
1797 aPara
.SetLower( pInsLine
);
1798 sal_uInt16 nEnd
= pFndBox
->GetLines().size()-1;
1799 rLineBoxes
= pFndBox
->GetLines()[nEnd
].GetBoxes();
1800 for (_FndBoxes::iterator it
= rLineBoxes
.begin(); it
!= rLineBoxes
.end(); ++it
)
1802 lcl_Merge_MoveBox(*it
, &aPara
);
1805 // Move the Boxes extending into the selected Area from left/right
1806 aPara
.SetLeft( pLeftBox
);
1807 BOOST_FOREACH(_FndLine
& rFndLine
, pFndBox
->GetLines() )
1808 lcl_Merge_MoveLine( rFndLine
, &aPara
);
1810 aPara
.SetRight( pRightBox
);
1811 BOOST_FOREACH(_FndLine
& rFndLine
, pFndBox
->GetLines() )
1812 lcl_Merge_MoveLine( rFndLine
, &aPara
);
1814 if( pLeftBox
->GetTabLines().empty() )
1815 _DeleteBox( *this, pLeftBox
, 0, false, false );
1818 lcl_CalcWidth( pLeftBox
); // calculate the Box's width
1819 if( pUndo
&& pLeftBox
->GetSttNd() )
1820 pUndo
->AddNewBox( pLeftBox
->GetSttIdx() );
1822 if( pRightBox
->GetTabLines().empty() )
1823 _DeleteBox( *this, pRightBox
, 0, false, false );
1826 lcl_CalcWidth( pRightBox
); // calculate the Box's width
1827 if( pUndo
&& pRightBox
->GetSttNd() )
1828 pUndo
->AddNewBox( pRightBox
->GetSttIdx() );
1831 DeleteSel( pDoc
, rBoxes
, 0, 0, false, false );
1833 // Clean up this Line's structure once again, generally all of them
1836 for( SwTableBoxes::iterator it
= GetTabLines()[0]->GetTabBoxes().begin();
1837 it
!= GetTabLines()[0]->GetTabBoxes().end(); ++it
)
1838 lcl_BoxSetHeadCondColl(*it
);
1840 aFndBox
.MakeFrms( *this );
1848 static void lcl_CheckRowSpan( SwTable
&rTbl
)
1850 sal_uInt16 nLineCount
= rTbl
.GetTabLines().size();
1851 sal_uInt16 nMaxSpan
= nLineCount
;
1855 SwTableLine
* pLine
= rTbl
.GetTabLines()[ nLineCount
- nMaxSpan
];
1856 for( sal_uInt16 nBox
= 0; nBox
< pLine
->GetTabBoxes().size(); ++nBox
)
1858 SwTableBox
* pBox
= pLine
->GetTabBoxes()[nBox
];
1859 long nRowSpan
= pBox
->getRowSpan();
1860 if( nRowSpan
> nMaxSpan
)
1861 pBox
->setRowSpan( nMaxSpan
);
1862 else if( nRowSpan
< nMinSpan
)
1863 pBox
->setRowSpan( nMinSpan
> 0 ? nMaxSpan
: nMinSpan
);
1866 nMinSpan
= -nMaxSpan
;
1870 static sal_uInt16
lcl_GetBoxOffset( const _FndBox
& rBox
)
1872 // Find the first Box
1873 const _FndBox
* pFirstBox
= &rBox
;
1874 while( !pFirstBox
->GetLines().empty() )
1875 pFirstBox
= &pFirstBox
->GetLines().front().GetBoxes().front();
1877 sal_uInt16 nRet
= 0;
1878 // Calculate the position relative to above via the Lines
1879 const SwTableBox
* pBox
= pFirstBox
->GetBox();
1881 const SwTableBoxes
& rBoxes
= pBox
->GetUpper()->GetTabBoxes();
1882 const SwTableBox
* pCmp
;
1883 for( sal_uInt16 n
= 0; pBox
!= ( pCmp
= rBoxes
[ n
] ); ++n
)
1884 nRet
= nRet
+ (sal_uInt16
) pCmp
->GetFrmFmt()->GetFrmSize().GetWidth();
1885 pBox
= pBox
->GetUpper()->GetUpper();
1890 static sal_uInt16
lcl_GetLineWidth( const _FndLine
& rLine
)
1892 sal_uInt16 nRet
= 0;
1893 for( sal_uInt16 n
= rLine
.GetBoxes().size(); n
; )
1895 nRet
= nRet
+ static_cast<sal_uInt16
>(rLine
.GetBoxes()[--n
].GetBox()
1896 ->GetFrmFmt()->GetFrmSize().GetWidth());
1901 static void lcl_CalcNewWidths( const _FndLines
& rFndLines
, _CpyPara
& rPara
)
1903 rPara
.pWidths
.reset();
1904 sal_uInt16 nLineCount
= rFndLines
.size();
1907 rPara
.pWidths
= boost::shared_ptr
< std::vector
< std::vector
< sal_uLong
> > >
1908 ( new std::vector
< std::vector
< sal_uLong
> >( nLineCount
));
1909 // First we collect information about the left/right borders of all
1911 for( sal_uInt16 nLine
= 0; nLine
< nLineCount
; ++nLine
)
1913 std::vector
< sal_uLong
> &rWidth
= (*rPara
.pWidths
.get())[ nLine
];
1914 const _FndLine
*pFndLine
= &rFndLines
[ nLine
];
1915 if( pFndLine
&& pFndLine
->GetBoxes().size() )
1917 const SwTableLine
*pLine
= pFndLine
->GetLine();
1918 if( pLine
&& !pLine
->GetTabBoxes().empty() )
1920 sal_uInt16 nBoxCount
= pLine
->GetTabBoxes().size();
1922 // The first selected box...
1923 const SwTableBox
*const pSel
=
1924 pFndLine
->GetBoxes().front().GetBox();
1925 sal_uInt16 nBox
= 0;
1926 // Sum up the width of all boxes before the first selected box
1927 while( nBox
< nBoxCount
)
1929 SwTableBox
* pBox
= pLine
->GetTabBoxes()[nBox
++];
1931 nPos
+= pBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1935 // nPos is now the left border of the first selected box
1936 if( rPara
.nMinLeft
> nPos
)
1937 rPara
.nMinLeft
= nPos
;
1938 nBoxCount
= pFndLine
->GetBoxes().size();
1939 rWidth
= std::vector
< sal_uLong
>( nBoxCount
+2 );
1941 // Add now the widths of all selected boxes and store
1942 // the positions in the vector
1943 for( nBox
= 0; nBox
< nBoxCount
; )
1945 nPos
+= pFndLine
->GetBoxes()[nBox
]
1946 .GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
1947 rWidth
[ ++nBox
] = nPos
;
1949 // nPos: The right border of the last selected box
1950 if( rPara
.nMaxRight
< nPos
)
1951 rPara
.nMaxRight
= nPos
;
1952 if( nPos
<= rWidth
[ 0 ] )
1958 // Second step: calculate the new widths for the copied cells
1959 sal_uLong nSelSize
= rPara
.nMaxRight
- rPara
.nMinLeft
;
1962 for( sal_uInt16 nLine
= 0; nLine
< nLineCount
; ++nLine
)
1964 std::vector
< sal_uLong
> &rWidth
= (*rPara
.pWidths
.get())[ nLine
];
1965 sal_uInt16 nCount
= (sal_uInt16
)rWidth
.size();
1968 rWidth
[ nCount
- 1 ] = rPara
.nMaxRight
;
1969 sal_uLong nLastPos
= 0;
1970 for( sal_uInt16 nBox
= 0; nBox
< nCount
; ++nBox
)
1972 sal_uInt64 nNextPos
= rWidth
[ nBox
];
1973 nNextPos
-= rPara
.nMinLeft
;
1974 nNextPos
*= rPara
.nNewSize
;
1975 nNextPos
/= nSelSize
;
1976 rWidth
[ nBox
] = (sal_uLong
)(nNextPos
- nLastPos
);
1977 nLastPos
= (sal_uLong
)nNextPos
;
1985 lcl_CopyLineToDoc(_FndLine
const& rpFndLn
, _CpyPara
*const pCpyPara
);
1987 static void lcl_CopyBoxToDoc(_FndBox
const& rFndBox
, _CpyPara
*const pCpyPara
)
1989 // Calculation of new size
1990 sal_uLong nRealSize
;
1991 sal_uLong nDummy1
= 0;
1992 sal_uLong nDummy2
= 0;
1993 if( pCpyPara
->pTblNd
->GetTable().IsNewModel() )
1995 if( pCpyPara
->nBoxIdx
== 1 )
1996 nDummy1
= (*pCpyPara
->pWidths
.get())[pCpyPara
->nLnIdx
][0];
1997 nRealSize
= (*pCpyPara
->pWidths
.get())[pCpyPara
->nLnIdx
][pCpyPara
->nBoxIdx
++];
1998 if( pCpyPara
->nBoxIdx
== (*pCpyPara
->pWidths
.get())[pCpyPara
->nLnIdx
].size()-1 )
1999 nDummy2
= (*pCpyPara
->pWidths
.get())[pCpyPara
->nLnIdx
][pCpyPara
->nBoxIdx
];
2003 nRealSize
= pCpyPara
->nNewSize
;
2004 nRealSize
*= rFndBox
.GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
2005 nRealSize
/= pCpyPara
->nOldSize
;
2009 bool bDummy
= nDummy1
> 0;
2019 // Find the Frame Format in the list of all Frame Formats
2020 _CpyTabFrm
aFindFrm(static_cast<SwTableBoxFmt
*>(rFndBox
.GetBox()->GetFrmFmt()));
2022 SwFmtFrmSize aFrmSz
;
2023 _CpyTabFrms::const_iterator itFind
= pCpyPara
->rTabFrmArr
.lower_bound( aFindFrm
);
2024 sal_uInt16 nFndPos
= itFind
- pCpyPara
->rTabFrmArr
.begin();
2025 if( itFind
== pCpyPara
->rTabFrmArr
.end() || !(*itFind
== aFindFrm
) ||
2026 ( aFrmSz
= ( aFindFrm
= pCpyPara
->rTabFrmArr
[ nFndPos
]).pNewFrmFmt
->
2027 GetFrmSize()).GetWidth() != (SwTwips
)nSize
)
2029 // It doesn't exist yet, so copy it
2030 aFindFrm
.pNewFrmFmt
= pCpyPara
->pDoc
->MakeTableBoxFmt();
2031 aFindFrm
.pNewFrmFmt
->CopyAttrs( *rFndBox
.GetBox()->GetFrmFmt() );
2032 if( !pCpyPara
->bCpyCntnt
)
2033 aFindFrm
.pNewFrmFmt
->ResetFmtAttr( RES_BOXATR_FORMULA
, RES_BOXATR_VALUE
);
2034 aFrmSz
.SetWidth( nSize
);
2035 aFindFrm
.pNewFrmFmt
->SetFmtAttr( aFrmSz
);
2036 pCpyPara
->rTabFrmArr
.insert( aFindFrm
);
2040 if (!rFndBox
.GetLines().empty())
2042 pBox
= new SwTableBox( aFindFrm
.pNewFrmFmt
,
2043 rFndBox
.GetLines().size(), pCpyPara
->pInsLine
);
2044 pCpyPara
->pInsLine
->GetTabBoxes().insert( pCpyPara
->pInsLine
->GetTabBoxes().begin() + pCpyPara
->nInsPos
++, pBox
);
2045 _CpyPara
aPara( *pCpyPara
, pBox
);
2046 aPara
.nNewSize
= nSize
; // get the size
2047 BOOST_FOREACH(_FndLine
const& rFndLine
, rFndBox
.GetLines())
2048 lcl_CopyLineToDoc( rFndLine
, &aPara
);
2052 // Create an empty Box
2053 pCpyPara
->pDoc
->GetNodes().InsBoxen( pCpyPara
->pTblNd
, pCpyPara
->pInsLine
,
2054 aFindFrm
.pNewFrmFmt
,
2055 (SwTxtFmtColl
*)pCpyPara
->pDoc
->GetDfltTxtFmtColl(),
2056 0, pCpyPara
->nInsPos
);
2057 pBox
= pCpyPara
->pInsLine
->GetTabBoxes()[ pCpyPara
->nInsPos
];
2059 pBox
->setDummyFlag( true );
2060 else if( pCpyPara
->bCpyCntnt
)
2062 // Copy the content into this empty Box
2063 pBox
->setRowSpan(rFndBox
.GetBox()->getRowSpan());
2065 // We can also copy formulas and values, if we copy the content
2067 SfxItemSet
aBoxAttrSet( pCpyPara
->pDoc
->GetAttrPool(),
2068 RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
2069 aBoxAttrSet
.Put(rFndBox
.GetBox()->GetFrmFmt()->GetAttrSet());
2070 if( aBoxAttrSet
.Count() )
2072 const SfxPoolItem
* pItem
;
2073 SvNumberFormatter
* pN
= pCpyPara
->pDoc
->GetNumberFormatter( sal_False
);
2074 if( pN
&& pN
->HasMergeFmtTbl() && SFX_ITEM_SET
== aBoxAttrSet
.
2075 GetItemState( RES_BOXATR_FORMAT
, sal_False
, &pItem
) )
2077 sal_uLong nOldIdx
= ((SwTblBoxNumFormat
*)pItem
)->GetValue();
2078 sal_uLong nNewIdx
= pN
->GetMergeFmtIndex( nOldIdx
);
2079 if( nNewIdx
!= nOldIdx
)
2080 aBoxAttrSet
.Put( SwTblBoxNumFormat( nNewIdx
));
2082 pBox
->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet
);
2085 SwDoc
* pFromDoc
= rFndBox
.GetBox()->GetFrmFmt()->GetDoc();
2086 SwNodeRange
aCpyRg( *rFndBox
.GetBox()->GetSttNd(), 1,
2087 *rFndBox
.GetBox()->GetSttNd()->EndOfSectionNode() );
2088 SwNodeIndex
aInsIdx( *pBox
->GetSttNd(), 1 );
2090 pFromDoc
->CopyWithFlyInFly( aCpyRg
, 0, aInsIdx
, sal_False
);
2091 // Delete the initial TextNode
2092 pCpyPara
->pDoc
->GetNodes().Delete( aInsIdx
, 1 );
2094 ++pCpyPara
->nInsPos
;
2113 lcl_CopyLineToDoc(const _FndLine
& rFndLine
, _CpyPara
*const pCpyPara
)
2115 // Find the Frame Format in the list of all Frame Formats
2116 _CpyTabFrm
aFindFrm( (SwTableBoxFmt
*)rFndLine
.GetLine()->GetFrmFmt() );
2117 _CpyTabFrms::const_iterator itFind
= pCpyPara
->rTabFrmArr
.find( aFindFrm
);
2118 if( itFind
== pCpyPara
->rTabFrmArr
.end() )
2120 // It doesn't exist yet, so copy it
2121 aFindFrm
.pNewFrmFmt
= (SwTableBoxFmt
*)pCpyPara
->pDoc
->MakeTableLineFmt();
2122 aFindFrm
.pNewFrmFmt
->CopyAttrs( *rFndLine
.GetLine()->GetFrmFmt() );
2123 pCpyPara
->rTabFrmArr
.insert( aFindFrm
);
2128 SwTableLine
* pNewLine
= new SwTableLine( (SwTableLineFmt
*)aFindFrm
.pNewFrmFmt
,
2129 rFndLine
.GetBoxes().size(), pCpyPara
->pInsBox
);
2130 if( pCpyPara
->pInsBox
)
2132 SwTableLines
& rLines
= pCpyPara
->pInsBox
->GetTabLines();
2133 rLines
.insert( rLines
.begin() + pCpyPara
->nInsPos
++, pNewLine
);
2137 SwTableLines
& rLines
= pCpyPara
->pTblNd
->GetTable().GetTabLines();
2138 rLines
.insert( rLines
.begin() + pCpyPara
->nInsPos
++, pNewLine
);
2141 _CpyPara
aPara( *pCpyPara
, pNewLine
);
2143 if( pCpyPara
->pTblNd
->GetTable().IsNewModel() )
2145 aPara
.nOldSize
= 0; // will not be used
2148 else if( rFndLine
.GetBoxes().size() ==
2149 rFndLine
.GetLine()->GetTabBoxes().size() )
2151 // Get the Parent's size
2152 const SwFrmFmt
* pFmt
;
2154 if( rFndLine
.GetLine()->GetUpper() )
2155 pFmt
= rFndLine
.GetLine()->GetUpper()->GetFrmFmt();
2157 pFmt
= pCpyPara
->pTblNd
->GetTable().GetFrmFmt();
2158 aPara
.nOldSize
= pFmt
->GetFrmSize().GetWidth();
2162 for( sal_uInt16 n
= 0; n
< rFndLine
.GetBoxes().size(); ++n
)
2164 aPara
.nOldSize
+= rFndLine
.GetBoxes()[n
]
2165 .GetBox()->GetFrmFmt()->GetFrmSize().GetWidth();
2168 const _FndBoxes
& rBoxes
= rFndLine
.GetBoxes();
2169 for (_FndBoxes::const_iterator it
= rBoxes
.begin(); it
!= rBoxes
.end(); ++it
)
2170 lcl_CopyBoxToDoc(*it
, &aPara
);
2171 if( pCpyPara
->pTblNd
->GetTable().IsNewModel() )
2175 bool SwTable::CopyHeadlineIntoTable( SwTableNode
& rTblNd
)
2177 // Find all Boxes/Lines
2178 SwSelBoxes aSelBoxes
;
2179 SwTableBox
* pBox
= GetTabSortBoxes()[ 0 ];
2180 pBox
= GetTblBox( pBox
->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 );
2181 SelLineFromBox( pBox
, aSelBoxes
, true );
2183 _FndBox
aFndBox( 0, 0 );
2185 _FndPara
aPara( aSelBoxes
, &aFndBox
);
2186 ForEach_FndLineCopyCol( GetTabLines(), &aPara
);
2188 if( aFndBox
.GetLines().empty() )
2192 // Convert Table formulas to their relative representation
2193 SwTableFmlUpdate
aMsgHnt( this );
2194 aMsgHnt
.eFlags
= TBL_RELBOXNAME
;
2195 GetFrmFmt()->GetDoc()->UpdateTblFlds( &aMsgHnt
);
2198 _CpyTabFrms aCpyFmt
;
2199 _CpyPara
aPara( &rTblNd
, 1, aCpyFmt
, true );
2200 aPara
.nNewSize
= aPara
.nOldSize
= rTblNd
.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
2203 lcl_CalcNewWidths( aFndBox
.GetLines(), aPara
);
2204 BOOST_FOREACH( _FndLine
& rFndLine
, aFndBox
.GetLines() )
2205 lcl_CopyLineToDoc( rFndLine
, &aPara
);
2206 if( rTblNd
.GetTable().IsNewModel() )
2207 { // The copied line must not contain any row span attributes > 1
2208 SwTableLine
* pLine
= rTblNd
.GetTable().GetTabLines()[0];
2209 sal_uInt16 nColCount
= pLine
->GetTabBoxes().size();
2210 OSL_ENSURE( nColCount
, "Empty Table Line" );
2211 for( sal_uInt16 nCurrCol
= 0; nCurrCol
< nColCount
; ++nCurrCol
)
2213 SwTableBox
* pTableBox
= pLine
->GetTabBoxes()[nCurrCol
];
2214 OSL_ENSURE( pTableBox
, "Missing Table Box" );
2215 pTableBox
->setRowSpan( 1 );
2222 bool SwTable::MakeCopy( SwDoc
* pInsDoc
, const SwPosition
& rPos
,
2223 const SwSelBoxes
& rSelBoxes
, bool bCpyNds
,
2224 bool bCpyName
) const
2226 // Find all Boxes/Lines
2227 _FndBox
aFndBox( 0, 0 );
2229 _FndPara
aPara( rSelBoxes
, &aFndBox
);
2230 ForEach_FndLineCopyCol( (SwTableLines
&)GetTabLines(), &aPara
);
2232 if( aFndBox
.GetLines().empty() )
2235 // First copy the PoolTemplates for the Table, so that the Tables are
2236 // actually copied and have valid values.
2237 SwDoc
* pSrcDoc
= GetFrmFmt()->GetDoc();
2238 if( pSrcDoc
!= pInsDoc
)
2240 pInsDoc
->CopyTxtColl( *pSrcDoc
->GetTxtCollFromPool( RES_POOLCOLL_TABLE
) );
2241 pInsDoc
->CopyTxtColl( *pSrcDoc
->GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN
) );
2244 SwTable
* pNewTbl
= (SwTable
*)pInsDoc
->InsertTable(
2245 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER
, 1 ),
2246 rPos
, 1, 1, GetFrmFmt()->GetHoriOrient().GetHoriOrient(),
2247 0, 0, sal_False
, IsNewModel() );
2251 SwNodeIndex
aIdx( rPos
.nNode
, -1 );
2252 SwTableNode
* pTblNd
= aIdx
.GetNode().FindTableNode();
2254 OSL_ENSURE( pTblNd
, "Where is the TableNode now?" );
2256 pTblNd
->GetTable().SetRowsToRepeat( GetRowsToRepeat() );
2258 if( IS_TYPE( SwDDETable
, this ))
2260 // A DDE-Table is being copied
2261 // Does the new Document actually have it's FieldType?
2262 SwFieldType
* pFldType
= pInsDoc
->InsertFldType(
2263 *((SwDDETable
*)this)->GetDDEFldType() );
2264 OSL_ENSURE( pFldType
, "unknown FieldType" );
2266 // Change the Table Pointer at the Node
2267 pNewTbl
= new SwDDETable( *pNewTbl
,
2268 (SwDDEFieldType
*)pFldType
);
2269 pTblNd
->SetNewTable( pNewTbl
, sal_False
);
2272 pNewTbl
->GetFrmFmt()->CopyAttrs( *GetFrmFmt() );
2273 pNewTbl
->SetTblChgMode( GetTblChgMode() );
2275 // Destroy the already created Frames
2279 // Conver the Table formulas to their relative representation
2280 SwTableFmlUpdate
aMsgHnt( this );
2281 aMsgHnt
.eFlags
= TBL_RELBOXNAME
;
2282 pSrcDoc
->UpdateTblFlds( &aMsgHnt
);
2285 SwTblNumFmtMerge
aTNFM( *pSrcDoc
, *pInsDoc
);
2287 // Also copy Names or enforce a new unique one
2289 pNewTbl
->GetFrmFmt()->SetName( GetFrmFmt()->GetName() );
2291 _CpyTabFrms aCpyFmt
;
2292 _CpyPara
aPara( pTblNd
, 1, aCpyFmt
, bCpyNds
);
2293 aPara
.nNewSize
= aPara
.nOldSize
= GetFrmFmt()->GetFrmSize().GetWidth();
2296 lcl_CalcNewWidths( aFndBox
.GetLines(), aPara
);
2298 BOOST_FOREACH( _FndLine
& rFndLine
, aFndBox
.GetLines() )
2299 lcl_CopyLineToDoc( rFndLine
, &aPara
);
2301 // Set the "right" margin above/below
2303 _FndLine
* pFndLn
= &aFndBox
.GetLines().front();
2304 SwTableLine
* pLn
= pFndLn
->GetLine();
2305 const SwTableLine
* pTmp
= pLn
;
2306 sal_uInt16 nLnPos
= GetTabLines().GetPos( pTmp
);
2307 if( USHRT_MAX
!= nLnPos
&& nLnPos
)
2309 // There is a Line before it
2310 SwCollectTblLineBoxes
aLnPara( sal_False
, HEADLINE_BORDERCOPY
);
2312 pLn
= GetTabLines()[ nLnPos
- 1 ];
2313 for( SwTableBoxes::iterator it
= pLn
->GetTabBoxes().begin();
2314 it
!= pLn
->GetTabBoxes().end(); ++it
)
2315 sw_Box_CollectBox( *it
, &aLnPara
);
2317 if( aLnPara
.Resize( lcl_GetBoxOffset( aFndBox
),
2318 lcl_GetLineWidth( *pFndLn
)) )
2320 aLnPara
.SetValues( sal_True
);
2321 pLn
= pNewTbl
->GetTabLines()[ 0 ];
2322 for( SwTableBoxes::iterator it
= pLn
->GetTabBoxes().begin();
2323 it
!= pLn
->GetTabBoxes().end(); ++it
)
2324 sw_BoxSetSplitBoxFmts(*it
, &aLnPara
);
2328 pFndLn
= &aFndBox
.GetLines().back();
2329 pLn
= pFndLn
->GetLine();
2331 nLnPos
= GetTabLines().GetPos( pTmp
);
2332 if( nLnPos
< GetTabLines().size() - 1 )
2334 // There is a Line following it
2335 SwCollectTblLineBoxes
aLnPara( sal_True
, HEADLINE_BORDERCOPY
);
2337 pLn
= GetTabLines()[ nLnPos
+ 1 ];
2338 for( SwTableBoxes::iterator it
= pLn
->GetTabBoxes().begin();
2339 it
!= pLn
->GetTabBoxes().end(); ++it
)
2340 sw_Box_CollectBox( *it
, &aLnPara
);
2342 if( aLnPara
.Resize( lcl_GetBoxOffset( aFndBox
),
2343 lcl_GetLineWidth( *pFndLn
)) )
2345 aLnPara
.SetValues( sal_False
);
2346 pLn
= pNewTbl
->GetTabLines().back();
2347 for( SwTableBoxes::iterator it
= pLn
->GetTabBoxes().begin();
2348 it
!= pLn
->GetTabBoxes().end(); ++it
)
2349 sw_BoxSetSplitBoxFmts(*it
, &aLnPara
);
2354 // We need to delete the initial Box
2355 _DeleteBox( *pNewTbl
, pNewTbl
->GetTabLines().back()->GetTabBoxes()[0],
2358 if( pNewTbl
->IsNewModel() )
2359 lcl_CheckRowSpan( *pNewTbl
);
2363 pTblNd
->MakeFrms( &aIdx
); // re-generate the Frames
2370 // Find the next Box with content from this Line
2371 SwTableBox
* SwTableLine::FindNextBox( const SwTable
& rTbl
,
2372 const SwTableBox
* pSrchBox
, bool bOvrTblLns
) const
2374 const SwTableLine
* pLine
= this; // for M800
2377 if( !GetTabBoxes().empty() && pSrchBox
&&
2378 USHRT_MAX
!= ( nFndPos
= GetTabBoxes().GetPos( pSrchBox
)) &&
2379 nFndPos
+ 1 != (sal_uInt16
)GetTabBoxes().size() )
2381 pBox
= GetTabBoxes()[ nFndPos
+ 1 ];
2382 while( !pBox
->GetTabLines().empty() )
2383 pBox
= pBox
->GetTabLines().front()->GetTabBoxes()[0];
2389 nFndPos
= GetUpper()->GetTabLines().GetPos( pLine
);
2390 OSL_ENSURE( USHRT_MAX
!= nFndPos
, "Line is not in the Table" );
2391 // Is there another Line?
2392 if( nFndPos
+1 >= (sal_uInt16
)GetUpper()->GetTabLines().size() )
2393 return GetUpper()->GetUpper()->FindNextBox( rTbl
, GetUpper(), bOvrTblLns
);
2394 pLine
= GetUpper()->GetTabLines()[nFndPos
+1];
2396 else if( bOvrTblLns
) // Over a Table's the "BaseLines"??
2398 // Search for the next Line in the Table
2399 nFndPos
= rTbl
.GetTabLines().GetPos( pLine
);
2400 if( nFndPos
+ 1 >= (sal_uInt16
)rTbl
.GetTabLines().size() )
2401 return 0; // there are no more Boxes
2403 pLine
= rTbl
.GetTabLines()[ nFndPos
+1 ];
2408 if( !pLine
->GetTabBoxes().empty() )
2410 pBox
= pLine
->GetTabBoxes().front();
2411 while( !pBox
->GetTabLines().empty() )
2412 pBox
= pBox
->GetTabLines().front()->GetTabBoxes().front();
2415 return pLine
->FindNextBox( rTbl
, 0, bOvrTblLns
);
2418 // Find the previous Box from this Line
2419 SwTableBox
* SwTableLine::FindPreviousBox( const SwTable
& rTbl
,
2420 const SwTableBox
* pSrchBox
, bool bOvrTblLns
) const
2422 const SwTableLine
* pLine
= this; // for M800
2425 if( !GetTabBoxes().empty() && pSrchBox
&&
2426 USHRT_MAX
!= ( nFndPos
= GetTabBoxes().GetPos( pSrchBox
)) &&
2429 pBox
= GetTabBoxes()[ nFndPos
- 1 ];
2430 while( !pBox
->GetTabLines().empty() )
2432 pLine
= pBox
->GetTabLines().back();
2433 pBox
= pLine
->GetTabBoxes().back();
2440 nFndPos
= GetUpper()->GetTabLines().GetPos( pLine
);
2441 OSL_ENSURE( USHRT_MAX
!= nFndPos
, "Line is not in the Table" );
2442 // Is there another Line?
2444 return GetUpper()->GetUpper()->FindPreviousBox( rTbl
, GetUpper(), bOvrTblLns
);
2445 pLine
= GetUpper()->GetTabLines()[nFndPos
-1];
2447 else if( bOvrTblLns
) // Over a Table's the "BaseLines"??
2449 // Search for the next Line in the Table
2450 nFndPos
= rTbl
.GetTabLines().GetPos( pLine
);
2452 return 0; // there are no more Boxes
2454 pLine
= rTbl
.GetTabLines()[ nFndPos
-1 ];
2459 if( !pLine
->GetTabBoxes().empty() )
2461 pBox
= pLine
->GetTabBoxes().back();
2462 while( !pBox
->GetTabLines().empty() )
2464 pLine
= pBox
->GetTabLines().back();
2465 pBox
= pLine
->GetTabBoxes().back();
2469 return pLine
->FindPreviousBox( rTbl
, 0, bOvrTblLns
);
2472 // Find the next Box with content from this Line
2473 SwTableBox
* SwTableBox::FindNextBox( const SwTable
& rTbl
,
2474 const SwTableBox
* pSrchBox
, bool bOvrTblLns
) const
2476 if( !pSrchBox
&& GetTabLines().empty() )
2477 return (SwTableBox
*)this;
2478 return GetUpper()->FindNextBox( rTbl
, pSrchBox
? pSrchBox
: this,
2483 // Find the next Box with content from this Line
2484 SwTableBox
* SwTableBox::FindPreviousBox( const SwTable
& rTbl
,
2485 const SwTableBox
* pSrchBox
, bool bOvrTblLns
) const
2487 if( !pSrchBox
&& GetTabLines().empty() )
2488 return (SwTableBox
*)this;
2489 return GetUpper()->FindPreviousBox( rTbl
, pSrchBox
? pSrchBox
: this,
2493 static void lcl_BoxSetHeadCondColl( const SwTableBox
* pBox
)
2495 // We need to adapt the paragraphs with conditional templates in the HeadLine
2496 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
2498 pSttNd
->CheckSectionCondColl();
2500 BOOST_FOREACH( const SwTableLine
* pLine
, pBox
->GetTabLines() )
2501 sw_LineSetHeadCondColl( pLine
);
2504 void sw_LineSetHeadCondColl( const SwTableLine
* pLine
)
2506 BOOST_FOREACH( const SwTableBox
* pBox
, pLine
->GetTabBoxes() )
2507 lcl_BoxSetHeadCondColl(pBox
);
2510 static SwTwips
lcl_GetDistance( SwTableBox
* pBox
, bool bLeft
)
2515 while( pBox
&& 0 != ( pLine
= pBox
->GetUpper() ) )
2517 sal_uInt16 nStt
= 0, nPos
= pLine
->GetTabBoxes().GetPos( pBox
);
2519 if( bFirst
&& !bLeft
)
2523 while( nStt
< nPos
)
2524 nRet
+= pLine
->GetTabBoxes()[ nStt
++ ]->GetFrmFmt()
2525 ->GetFrmSize().GetWidth();
2526 pBox
= pLine
->GetUpper();
2531 static bool lcl_SetSelBoxWidth( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
2532 SwTwips nDist
, bool bCheck
)
2534 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2535 for( sal_uInt16 n
= 0; n
< rBoxes
.size(); ++n
)
2537 SwTableBox
* pBox
= rBoxes
[ n
];
2538 SwFrmFmt
* pFmt
= pBox
->GetFrmFmt();
2539 const SwFmtFrmSize
& rSz
= pFmt
->GetFrmSize();
2540 SwTwips nWidth
= rSz
.GetWidth();
2541 bool bGreaterBox
= false;
2545 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2546 if( !::lcl_SetSelBoxWidth( pBox
->GetTabLines()[ i
], rParam
,
2550 // Collect all "ContentBoxes"
2551 if( ( 0 != ( bGreaterBox
= TBLFIX_CHGABS
!= rParam
.nMode
&& ( nDist
+ ( rParam
.bLeft
? 0 : nWidth
) ) >= rParam
.nSide
)) ||
2552 ( !rParam
.bBigger
&& ( Abs( nDist
+ (( rParam
.nMode
&& rParam
.bLeft
) ? 0 : nWidth
) - rParam
.nSide
) < COLFUZZY
) ) )
2554 rParam
.bAnyBoxFnd
= true;
2556 if( bGreaterBox
&& TBLFIX_CHGPROP
== rParam
.nMode
)
2558 // The "other Boxes" have been adapted, so change by this value
2559 nLowerDiff
= (nDist
+ ( rParam
.bLeft
? 0 : nWidth
) ) - rParam
.nSide
;
2560 nLowerDiff
*= rParam
.nDiff
;
2561 nLowerDiff
/= rParam
.nMaxSize
;
2562 nLowerDiff
= rParam
.nDiff
- nLowerDiff
;
2565 nLowerDiff
= rParam
.nDiff
;
2567 if( nWidth
< nLowerDiff
|| nWidth
- nLowerDiff
< MINLAY
)
2573 SwTwips nLowerDiff
= 0, nOldLower
= rParam
.nLowerDiff
;
2574 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2576 rParam
.nLowerDiff
= 0;
2577 lcl_SetSelBoxWidth( pBox
->GetTabLines()[ i
], rParam
, nDist
, false );
2579 if( nLowerDiff
< rParam
.nLowerDiff
)
2580 nLowerDiff
= rParam
.nLowerDiff
;
2582 rParam
.nLowerDiff
= nOldLower
;
2586 ( 0 != ( bGreaterBox
= !nOldLower
&& TBLFIX_CHGABS
!= rParam
.nMode
&&
2587 ( nDist
+ ( rParam
.bLeft
? 0 : nWidth
) ) >= rParam
.nSide
)) ||
2588 ( Abs( nDist
+ ( (rParam
.nMode
&& rParam
.bLeft
) ? 0 : nWidth
)
2589 - rParam
.nSide
) < COLFUZZY
))
2591 // This column contains the Cursor - so decrease/increase
2592 SwFmtFrmSize
aNew( rSz
);
2596 if( bGreaterBox
&& TBLFIX_CHGPROP
== rParam
.nMode
)
2598 // The "other Boxes" have been adapted, so change by this value
2599 nLowerDiff
= (nDist
+ ( rParam
.bLeft
? 0 : nWidth
) ) - rParam
.nSide
;
2600 nLowerDiff
*= rParam
.nDiff
;
2601 nLowerDiff
/= rParam
.nMaxSize
;
2602 nLowerDiff
= rParam
.nDiff
- nLowerDiff
;
2605 nLowerDiff
= rParam
.nDiff
;
2608 rParam
.nLowerDiff
+= nLowerDiff
;
2610 if( rParam
.bBigger
)
2611 aNew
.SetWidth( nWidth
+ nLowerDiff
);
2613 aNew
.SetWidth( nWidth
- nLowerDiff
);
2614 rParam
.aShareFmts
.SetSize( *pBox
, aNew
);
2619 if( rParam
.bLeft
&& rParam
.nMode
&& nDist
>= rParam
.nSide
)
2624 // If it gets bigger, then that's it
2625 if( ( TBLFIX_CHGABS
== rParam
.nMode
|| !rParam
.bLeft
) &&
2626 nDist
>= rParam
.nSide
)
2632 static bool lcl_SetOtherBoxWidth( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
2633 SwTwips nDist
, bool bCheck
)
2635 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2636 for( sal_uInt16 n
= 0; n
< rBoxes
.size(); ++n
)
2638 SwTableBox
* pBox
= rBoxes
[ n
];
2639 SwFrmFmt
* pFmt
= pBox
->GetFrmFmt();
2640 const SwFmtFrmSize
& rSz
= pFmt
->GetFrmSize();
2641 SwTwips nWidth
= rSz
.GetWidth();
2645 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2646 if( !::lcl_SetOtherBoxWidth( pBox
->GetTabLines()[ i
],
2647 rParam
, nDist
, true ))
2650 if( rParam
.bBigger
&& ( TBLFIX_CHGABS
== rParam
.nMode
2651 ? Abs( nDist
- rParam
.nSide
) < COLFUZZY
2652 : ( rParam
.bLeft
? nDist
< rParam
.nSide
- COLFUZZY
2653 : nDist
>= rParam
.nSide
- COLFUZZY
)) )
2655 rParam
.bAnyBoxFnd
= true;
2657 if( TBLFIX_CHGPROP
== rParam
.nMode
) // Table fixed, proportional
2659 // calculate relative
2661 nDiff
*= rParam
.nDiff
;
2662 nDiff
/= rParam
.nMaxSize
;
2665 nDiff
= rParam
.nDiff
;
2667 if( nWidth
< nDiff
|| nWidth
- nDiff
< MINLAY
)
2673 SwTwips nLowerDiff
= 0, nOldLower
= rParam
.nLowerDiff
;
2674 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2676 rParam
.nLowerDiff
= 0;
2677 lcl_SetOtherBoxWidth( pBox
->GetTabLines()[ i
], rParam
,
2680 if( nLowerDiff
< rParam
.nLowerDiff
)
2681 nLowerDiff
= rParam
.nLowerDiff
;
2683 rParam
.nLowerDiff
= nOldLower
;
2686 ( TBLFIX_CHGABS
== rParam
.nMode
2687 ? Abs( nDist
- rParam
.nSide
) < COLFUZZY
2688 : ( rParam
.bLeft
? nDist
< rParam
.nSide
- COLFUZZY
2689 : nDist
>= rParam
.nSide
- COLFUZZY
)
2692 SwFmtFrmSize
aNew( rSz
);
2696 if( TBLFIX_CHGPROP
== rParam
.nMode
) // Table fixed, proportional
2698 // calculate relative
2699 nLowerDiff
= nWidth
;
2700 nLowerDiff
*= rParam
.nDiff
;
2701 nLowerDiff
/= rParam
.nMaxSize
;
2704 nLowerDiff
= rParam
.nDiff
;
2707 rParam
.nLowerDiff
+= nLowerDiff
;
2709 if( rParam
.bBigger
)
2710 aNew
.SetWidth( nWidth
- nLowerDiff
);
2712 aNew
.SetWidth( nWidth
+ nLowerDiff
);
2714 rParam
.aShareFmts
.SetSize( *pBox
, aNew
);
2719 if( ( TBLFIX_CHGABS
== rParam
.nMode
|| rParam
.bLeft
) &&
2720 nDist
> rParam
.nSide
)
2726 static bool lcl_InsSelBox( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
2727 SwTwips nDist
, bool bCheck
)
2729 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2731 for( n
= 0; n
< rBoxes
.size(); ++n
)
2733 SwTableBox
* pBox
= rBoxes
[ n
];
2734 SwTableBoxFmt
* pFmt
= (SwTableBoxFmt
*)pBox
->GetFrmFmt();
2735 const SwFmtFrmSize
& rSz
= pFmt
->GetFrmSize();
2736 SwTwips nWidth
= rSz
.GetWidth();
2740 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2741 if( !::lcl_InsSelBox( pBox
->GetTabLines()[ i
], rParam
,
2745 // Collect all "ContentBoxes"
2746 if( Abs( nDist
+ ( rParam
.bLeft
? 0 : nWidth
)
2747 - rParam
.nSide
) < COLFUZZY
)
2749 else if( nDist
+ ( rParam
.bLeft
? 0 : nWidth
/2 ) > rParam
.nSide
)
2756 rParam
.bAnyBoxFnd
= true;
2757 if( pFmt
->GetProtect().IsCntntProtected() )
2760 if( rParam
.bSplittBox
&&
2761 nWidth
- rParam
.nDiff
<= COLFUZZY
+
2762 ( 567 / 2 /*leave room for at least 0.5 cm*/) )
2765 if( pBox
->GetSttNd() )
2767 rParam
.m_Boxes
.insert(pBox
);
2775 SwTwips nLowerDiff
= 0, nOldLower
= rParam
.nLowerDiff
;
2776 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2778 rParam
.nLowerDiff
= 0;
2779 lcl_InsSelBox( pBox
->GetTabLines()[ i
], rParam
, nDist
, false );
2781 if( nLowerDiff
< rParam
.nLowerDiff
)
2782 nLowerDiff
= rParam
.nLowerDiff
;
2784 rParam
.nLowerDiff
= nOldLower
;
2788 else if( Abs( nDist
+ ( rParam
.bLeft
? 0 : nWidth
)
2789 - rParam
.nSide
) < COLFUZZY
)
2791 else if( nDist
+ nWidth
/ 2 > rParam
.nSide
)
2798 // This column contains the Cursor - so decrease/increase
2801 if( !rParam
.bSplittBox
)
2803 // the current Box on
2804 SwFmtFrmSize
aNew( rSz
);
2805 aNew
.SetWidth( nWidth
+ rParam
.nDiff
);
2806 rParam
.aShareFmts
.SetSize( *pBox
, aNew
);
2811 OSL_ENSURE( pBox
->GetSttNd(), "This must be an EndBox!");
2813 if( !rParam
.bLeft
&& 3 != nCmp
)
2816 ::_InsTblBox( pFmt
->GetDoc(), rParam
.pTblNd
,
2817 pLine
, pFmt
, pBox
, n
);
2819 SwTableBox
* pNewBox
= rBoxes
[ n
];
2820 SwFmtFrmSize
aNew( rSz
);
2821 aNew
.SetWidth( rParam
.nDiff
);
2822 rParam
.aShareFmts
.SetSize( *pNewBox
, aNew
);
2824 // Special case: There is no space in the other Boxes, but in the Cell
2825 if( rParam
.bSplittBox
)
2827 // the current Box on
2828 SwFmtFrmSize
aNewSize( rSz
);
2829 aNewSize
.SetWidth( nWidth
- rParam
.nDiff
);
2830 rParam
.aShareFmts
.SetSize( *pBox
, aNewSize
);
2833 // Special treatment for the Border
2834 // The right one needs to be removed
2836 const SvxBoxItem
& rBoxItem
= pBox
->GetFrmFmt()->GetBox();
2837 if( rBoxItem
.GetRight() )
2839 SvxBoxItem
aTmp( rBoxItem
);
2840 aTmp
.SetLine( 0, BOX_LINE_RIGHT
);
2841 rParam
.aShareFmts
.SetAttr( rParam
.bLeft
2848 rParam
.nLowerDiff
= rParam
.nDiff
;
2853 if( rParam
.bLeft
&& rParam
.nMode
&& nDist
>= rParam
.nSide
)
2861 static bool lcl_InsOtherBox( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
,
2862 SwTwips nDist
, bool bCheck
)
2864 // Special case: There is no space in the other Boxes, but in the cell
2865 if( rParam
.bSplittBox
)
2868 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2871 // Table fixed, proportional
2872 if( !rParam
.nRemainWidth
&& TBLFIX_CHGPROP
== rParam
.nMode
)
2874 // Find the right width to which the relative width adjustment
2876 SwTwips nTmpDist
= nDist
;
2877 for( n
= 0; n
< rBoxes
.size(); ++n
)
2879 SwTwips nWidth
= rBoxes
[ n
]->GetFrmFmt()->GetFrmSize().GetWidth();
2880 if( (nTmpDist
+ nWidth
/ 2 ) > rParam
.nSide
)
2882 rParam
.nRemainWidth
= rParam
.bLeft
2883 ? sal_uInt16(nTmpDist
)
2884 : sal_uInt16(rParam
.nTblWidth
- nTmpDist
);
2891 for( n
= 0; n
< rBoxes
.size(); ++n
)
2893 SwTableBox
* pBox
= rBoxes
[ n
];
2894 SwFrmFmt
* pFmt
= pBox
->GetFrmFmt();
2895 const SwFmtFrmSize
& rSz
= pFmt
->GetFrmSize();
2896 SwTwips nWidth
= rSz
.GetWidth();
2900 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2901 if( !::lcl_InsOtherBox( pBox
->GetTabLines()[ i
],
2902 rParam
, nDist
, true ))
2906 rParam
.bLeft
? ((nDist
+ nWidth
/ 2 ) <= rParam
.nSide
&&
2907 (TBLFIX_CHGABS
!= rParam
.nMode
||
2908 (n
< rBoxes
.size() &&
2909 (nDist
+ nWidth
+ rBoxes
[ n
+1 ]->
2910 GetFrmFmt()->GetFrmSize().GetWidth() / 2)
2912 : (nDist
+ nWidth
/ 2 ) > rParam
.nSide
2915 rParam
.bAnyBoxFnd
= true;
2917 if( TBLFIX_CHGPROP
== rParam
.nMode
) // Table fixed, proportional
2919 // relativ berechnen
2921 nDiff
*= rParam
.nDiff
;
2922 nDiff
/= rParam
.nRemainWidth
;
2924 if( nWidth
< nDiff
|| nWidth
- nDiff
< MINLAY
)
2929 nDiff
= rParam
.nDiff
;
2931 // See if the left or right Box is big enough to give up space.
2932 // We're inserting a Box before or after.
2933 SwTwips nTmpWidth
= nWidth
;
2934 if( rParam
.bLeft
&& pBox
->GetUpper()->GetUpper() )
2936 const SwTableBox
* pTmpBox
= pBox
;
2937 sal_uInt16 nBoxPos
= n
;
2938 while( !nBoxPos
&& pTmpBox
->GetUpper()->GetUpper() )
2940 pTmpBox
= pTmpBox
->GetUpper()->GetUpper();
2941 nBoxPos
= pTmpBox
->GetUpper()->GetTabBoxes().GetPos( pTmpBox
);
2944 nTmpWidth
= pTmpBox
->GetFrmFmt()->GetFrmSize().GetWidth();
2949 if( nTmpWidth
< nDiff
|| nTmpWidth
- nDiff
< MINLAY
)
2957 SwTwips nLowerDiff
= 0, nOldLower
= rParam
.nLowerDiff
;
2958 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
2960 rParam
.nLowerDiff
= 0;
2961 lcl_InsOtherBox( pBox
->GetTabLines()[ i
], rParam
,
2964 if( nLowerDiff
< rParam
.nLowerDiff
)
2965 nLowerDiff
= rParam
.nLowerDiff
;
2967 rParam
.nLowerDiff
= nOldLower
;
2970 (rParam
.bLeft
? ((nDist
+ nWidth
/ 2 ) <= rParam
.nSide
&&
2971 (TBLFIX_CHGABS
!= rParam
.nMode
||
2972 (n
< rBoxes
.size() &&
2973 (nDist
+ nWidth
+ rBoxes
[ n
+1 ]->
2974 GetFrmFmt()->GetFrmSize().GetWidth() / 2)
2976 : (nDist
+ nWidth
/ 2 ) > rParam
.nSide
))
2980 if( TBLFIX_CHGPROP
== rParam
.nMode
) // Table fixed, proportional
2982 // Calculate relatively
2983 nLowerDiff
= nWidth
;
2984 nLowerDiff
*= rParam
.nDiff
;
2985 nLowerDiff
/= rParam
.nRemainWidth
;
2988 nLowerDiff
= rParam
.nDiff
;
2991 SwFmtFrmSize
aNew( rSz
);
2992 rParam
.nLowerDiff
+= nLowerDiff
;
2994 if( rParam
.bBigger
)
2995 aNew
.SetWidth( nWidth
- nLowerDiff
);
2997 aNew
.SetWidth( nWidth
+ nLowerDiff
);
2998 rParam
.aShareFmts
.SetSize( *pBox
, aNew
);
3000 if( TBLFIX_CHGABS
== rParam
.nMode
)
3010 // The position comparison's result
3011 // POS_BEFORE, // Box comes before
3012 // POS_BEHIND, // Box comes after
3013 // POS_INSIDE, // Box is completely wthin start/end
3014 // POS_OUTSIDE, // Box overlaps start/end completely
3015 // POS_EQUAL, // Box and start/end are the same
3016 // POS_OVERLAP_BEFORE, // Box overlapps the start
3017 // POS_OVERLAP_BEHIND // Box overlapps the end
3018 SwComparePosition
_CheckBoxInRange( sal_uInt16 nStt
, sal_uInt16 nEnd
,
3019 sal_uInt16 nBoxStt
, sal_uInt16 nBoxEnd
)
3021 // Still treat COLFUZZY!
3022 SwComparePosition nRet
;
3023 if( nBoxStt
+ COLFUZZY
< nStt
)
3025 if( nBoxEnd
> nStt
+ COLFUZZY
)
3027 if( nBoxEnd
>= nEnd
+ COLFUZZY
)
3030 nRet
= POS_OVERLAP_BEFORE
;
3035 else if( nEnd
> nBoxStt
+ COLFUZZY
)
3037 if( nEnd
+ COLFUZZY
>= nBoxEnd
)
3039 if( COLFUZZY
> Abs( long(nEnd
) - long(nBoxEnd
) ) &&
3040 COLFUZZY
> Abs( long(nStt
) - long(nBoxStt
) ) )
3046 nRet
= POS_OVERLAP_BEHIND
;
3054 static void lcl_DelSelBox_CorrLowers( SwTableLine
& rLine
, CR_SetBoxWidth
& rParam
,
3057 // 1. step: Calculate own width
3058 SwTableBoxes
& rBoxes
= rLine
.GetTabBoxes();
3059 SwTwips nBoxWidth
= 0;
3062 for( n
= rBoxes
.size(); n
; )
3063 nBoxWidth
+= rBoxes
[ --n
]->GetFrmFmt()->GetFrmSize().GetWidth();
3065 if( COLFUZZY
< Abs( nWidth
- nBoxWidth
))
3067 // Thus, they need to be adjusted
3068 for( n
= rBoxes
.size(); n
; )
3070 SwTableBox
* pBox
= rBoxes
[ --n
];
3071 SwFmtFrmSize
aNew( pBox
->GetFrmFmt()->GetFrmSize() );
3072 long nDiff
= aNew
.GetWidth();
3075 aNew
.SetWidth( nDiff
);
3077 rParam
.aShareFmts
.SetSize( *pBox
, aNew
);
3079 if( !pBox
->GetSttNd() )
3081 // Has Lower itself, so also adjust that
3082 for( sal_uInt16 i
= pBox
->GetTabLines().size(); i
; )
3083 ::lcl_DelSelBox_CorrLowers( *pBox
->GetTabLines()[ --i
],
3090 static void lcl_ChgBoxSize( SwTableBox
& rBox
, CR_SetBoxWidth
& rParam
,
3091 const SwFmtFrmSize
& rOldSz
,
3092 sal_uInt16
& rDelWidth
, SwTwips nDist
)
3095 bool bSetSize
= false;
3097 switch( rParam
.nMode
)
3099 case TBLFIX_CHGABS
: // Fixed width table, change neighbor
3100 nDiff
= rDelWidth
+ rParam
.nLowerDiff
;
3104 case TBLFIX_CHGPROP
: // Fixed width table, change all neighbors
3105 if( !rParam
.nRemainWidth
)
3109 rParam
.nRemainWidth
= sal_uInt16(nDist
);
3111 rParam
.nRemainWidth
= sal_uInt16(rParam
.nTblWidth
- nDist
);
3114 // Calculate relatively
3115 nDiff
= rOldSz
.GetWidth();
3116 nDiff
*= rDelWidth
+ rParam
.nLowerDiff
;
3117 nDiff
/= rParam
.nRemainWidth
;
3122 case TBLVAR_CHGABS
: // Variable table, change all neighbors
3123 if( COLFUZZY
< Abs( rParam
.nBoxWidth
-
3124 ( rDelWidth
+ rParam
.nLowerDiff
)))
3126 nDiff
= rDelWidth
+ rParam
.nLowerDiff
- rParam
.nBoxWidth
;
3128 rDelWidth
= rDelWidth
- sal_uInt16(nDiff
);
3130 rDelWidth
= rDelWidth
+ sal_uInt16(-nDiff
);
3138 SwFmtFrmSize
aNew( rOldSz
);
3139 aNew
.SetWidth( aNew
.GetWidth() + nDiff
);
3140 rParam
.aShareFmts
.SetSize( rBox
, aNew
);
3142 // Change the Lower once again
3143 for( sal_uInt16 i
= rBox
.GetTabLines().size(); i
; )
3144 ::lcl_DelSelBox_CorrLowers( *rBox
.GetTabLines()[ --i
], rParam
,
3149 static bool lcl_DeleteBox_Rekursiv( CR_SetBoxWidth
& rParam
, SwTableBox
& rBox
,
3153 if( rBox
.GetSttNd() )
3157 rParam
.bAnyBoxFnd
= true;
3158 if( rBox
.GetFrmFmt()->GetProtect().IsCntntProtected() )
3162 SwTableBox
* pBox
= &rBox
;
3163 rParam
.m_Boxes
.insert(pBox
);
3167 ::_DeleteBox( rParam
.pTblNd
->GetTable(), &rBox
,
3168 rParam
.pUndo
, false, true, &rParam
.aShareFmts
);
3172 // We need to delete these sequentially via the ContentBoxes
3173 for( sal_uInt16 i
= rBox
.GetTabLines().size(); i
; )
3175 SwTableLine
& rLine
= *rBox
.GetTabLines()[ --i
];
3176 for( sal_uInt16 n
= rLine
.GetTabBoxes().size(); n
; )
3177 if( !::lcl_DeleteBox_Rekursiv( rParam
,
3178 *rLine
.GetTabBoxes()[ --n
], bCheck
))
3185 static bool lcl_DelSelBox( SwTableLine
* pTabLine
, CR_SetBoxWidth
& rParam
,
3186 SwTwips nDist
, bool bCheck
)
3188 SwTableBoxes
& rBoxes
= pTabLine
->GetTabBoxes();
3189 sal_uInt16 n
, nCntEnd
, nBoxChkStt
, nBoxChkEnd
, nDelWidth
= 0;
3194 nBoxChkStt
= (sal_uInt16
)rParam
.nSide
;
3195 nBoxChkEnd
= static_cast<sal_uInt16
>(rParam
.nSide
+ rParam
.nBoxWidth
);
3200 nCntEnd
= rBoxes
.size();
3201 nBoxChkStt
= static_cast<sal_uInt16
>(rParam
.nSide
- rParam
.nBoxWidth
);
3202 nBoxChkEnd
= (sal_uInt16
)rParam
.nSide
;
3206 while( n
!= nCntEnd
)
3210 pBox
= rBoxes
[ --n
];
3212 pBox
= rBoxes
[ n
++ ];
3214 SwFrmFmt
* pFmt
= pBox
->GetFrmFmt();
3215 const SwFmtFrmSize
& rSz
= pFmt
->GetFrmSize();
3216 long nWidth
= rSz
.GetWidth();
3217 bool bDelBox
= false, bChgLowers
= false;
3219 // Test the Box width and react accordingly
3220 SwComparePosition ePosType
= ::_CheckBoxInRange(
3221 nBoxChkStt
, nBoxChkEnd
,
3222 sal_uInt16(rParam
.bLeft
? nDist
- nWidth
: nDist
),
3223 sal_uInt16(rParam
.bLeft
? nDist
: nDist
+ nWidth
));
3233 else if( rParam
.bLeft
)
3235 ::lcl_ChgBoxSize( *pBox
, rParam
, rSz
, nDelWidth
, nDist
);
3236 if( TBLFIX_CHGABS
== rParam
.nMode
)
3247 else if( !rParam
.bLeft
)
3249 ::lcl_ChgBoxSize( *pBox
, rParam
, rSz
, nDelWidth
, nDist
);
3250 if( TBLFIX_CHGABS
== rParam
.nMode
)
3255 case POS_OUTSIDE
: // Box fully overlaps start/end
3256 case POS_INSIDE
: // Box is completely within start/end
3257 case POS_EQUAL
: // Box and start/end are the same
3261 case POS_OVERLAP_BEFORE
: // Box overlaps the start
3262 if( nBoxChkStt
<= ( nDist
+ (rParam
.bLeft
? - nWidth
/ 2
3265 if( !pBox
->GetSttNd() )
3270 else if( !bCheck
&& rParam
.bLeft
)
3272 if( !pBox
->GetSttNd() )
3276 ::lcl_ChgBoxSize( *pBox
, rParam
, rSz
, nDelWidth
, nDist
);
3277 if( TBLFIX_CHGABS
== rParam
.nMode
)
3283 case POS_OVERLAP_BEHIND
: // Box overlaps the end
3285 // Delete generally or (like in OVERLAP_BEFORE) only delete the one who reaches up to the half into the delete Box?
3286 if( !pBox
->GetSttNd() )
3296 nDelWidth
= nDelWidth
+ sal_uInt16(nWidth
);
3299 // The last/first Box can only be deleted for the variable Table,
3300 // if it's as large as the change in the Table.
3301 if( (( TBLVAR_CHGABS
!= rParam
.nMode
||
3302 nDelWidth
!= rParam
.nBoxWidth
) &&
3303 COLFUZZY
> Abs( rParam
.bLeft
3305 : (nDist
+ nWidth
- rParam
.nTblWidth
)))
3306 || !::lcl_DeleteBox_Rekursiv( rParam
, *pBox
, bCheck
) )
3309 if( pFmt
->GetProtect().IsCntntProtected() )
3314 ::lcl_DeleteBox_Rekursiv( rParam
, *pBox
, bCheck
);
3320 else if( bChgLowers
)
3322 bool bFirst
= true, bCorrLowers
= false;
3323 long nLowerDiff
= 0;
3324 long nOldLower
= rParam
.nLowerDiff
;
3325 sal_uInt16 nOldRemain
= rParam
.nRemainWidth
;
3328 for( i
= pBox
->GetTabLines().size(); i
; )
3330 rParam
.nLowerDiff
= nDelWidth
+ nOldLower
;
3331 rParam
.nRemainWidth
= nOldRemain
;
3332 SwTableLine
* pLine
= pBox
->GetTabLines()[ --i
];
3333 if( !::lcl_DelSelBox( pLine
, rParam
, nDist
, bCheck
))
3336 // Do the Box and its Lines still exist?
3337 if( n
< rBoxes
.size() &&
3338 pBox
== rBoxes
[ rParam
.bLeft
? n
: n
-1 ] &&
3339 i
< pBox
->GetTabLines().size() &&
3340 pLine
== pBox
->GetTabLines()[ i
] )
3342 if( !bFirst
&& !bCorrLowers
&&
3343 COLFUZZY
< Abs( nLowerDiff
- rParam
.nLowerDiff
) )
3346 // The largest deletion width counts, but only if we don't
3347 // delete the whole Line
3348 if( nLowerDiff
< rParam
.nLowerDiff
)
3349 nLowerDiff
= rParam
.nLowerDiff
;
3354 rParam
.nLowerDiff
= nOldLower
;
3355 rParam
.nRemainWidth
= nOldRemain
;
3357 // Did we delete all Boxes? Then the deletion width = the Box width, of course
3359 nLowerDiff
= nWidth
;
3361 // Adjust deletion width!
3362 nDelWidth
= nDelWidth
+ sal_uInt16(nLowerDiff
);
3366 // Has the Box already been removed?
3367 if( n
> rBoxes
.size() ||
3368 pBox
!= rBoxes
[ ( rParam
.bLeft
? n
: n
-1 ) ] )
3370 // Then change the loop variable when deleting to the right
3376 // Or else we need to adapt the Box's size
3377 SwFmtFrmSize
aNew( rSz
);
3378 bool bCorrRel
= false;
3380 if( TBLVAR_CHGABS
!= rParam
.nMode
)
3384 case POS_OVERLAP_BEFORE
: // Box overlaps the start
3385 if( TBLFIX_CHGPROP
== rParam
.nMode
)
3386 bCorrRel
= rParam
.bLeft
;
3387 else if( rParam
.bLeft
) // TBLFIX_CHGABS
3389 nLowerDiff
= nLowerDiff
- nDelWidth
;
3395 case POS_OVERLAP_BEHIND
: // Box overlaps the end
3396 if( TBLFIX_CHGPROP
== rParam
.nMode
)
3397 bCorrRel
= !rParam
.bLeft
;
3398 else if( !rParam
.bLeft
) // TBLFIX_CHGABS
3400 nLowerDiff
= nLowerDiff
- nDelWidth
;
3407 OSL_ENSURE( !pBox
, "we should never reach this!" );
3414 if( !rParam
.nRemainWidth
)
3418 rParam
.nRemainWidth
= sal_uInt16(nDist
- nLowerDiff
);
3420 rParam
.nRemainWidth
= sal_uInt16(rParam
.nTblWidth
- nDist
3424 long nDiff
= aNew
.GetWidth() - nLowerDiff
;
3425 nDiff
*= nDelWidth
+ rParam
.nLowerDiff
;
3426 nDiff
/= rParam
.nRemainWidth
;
3428 aNew
.SetWidth( aNew
.GetWidth() - nLowerDiff
+ nDiff
);
3431 aNew
.SetWidth( aNew
.GetWidth() - nLowerDiff
);
3432 rParam
.aShareFmts
.SetSize( *pBox
, aNew
);
3436 // Adapt the Lower once again
3437 for( i
= pBox
->GetTabLines().size(); i
; )
3438 ::lcl_DelSelBox_CorrLowers( *pBox
->
3439 GetTabLines()[ --i
], rParam
, aNew
.GetWidth() );
3450 rParam
.nLowerDiff
= nDelWidth
;
3454 // Dummy function for the method SetColWidth
3455 static bool lcl_DelOtherBox( SwTableLine
* , CR_SetBoxWidth
& , SwTwips
, bool )
3460 static void lcl_AjustLines( SwTableLine
* pLine
, CR_SetBoxWidth
& rParam
)
3462 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
3463 for( sal_uInt16 n
= 0; n
< rBoxes
.size(); ++n
)
3465 SwTableBox
* pBox
= rBoxes
[ n
];
3467 SwFmtFrmSize
aSz( pBox
->GetFrmFmt()->GetFrmSize() );
3468 SwTwips nWidth
= aSz
.GetWidth();
3469 nWidth
*= rParam
.nDiff
;
3470 nWidth
/= rParam
.nMaxSize
;
3471 aSz
.SetWidth( nWidth
);
3472 rParam
.aShareFmts
.SetSize( *pBox
, aSz
);
3474 for( sal_uInt16 i
= 0; i
< pBox
->GetTabLines().size(); ++i
)
3475 ::lcl_AjustLines( pBox
->GetTabLines()[ i
], rParam
);
3480 void _CheckBoxWidth( const SwTableLine
& rLine
, SwTwips nSize
)
3482 const SwTableBoxes
& rBoxes
= rLine
.GetTabBoxes();
3484 SwTwips nAktSize
= 0;
3485 // See if the tables have a correct width
3486 for (SwTableBoxes::const_iterator
i(rBoxes
.begin()); i
!= rBoxes
.end(); ++i
)
3488 const SwTableBox
* pBox
= *i
;
3489 const SwTwips nBoxW
= pBox
->GetFrmFmt()->GetFrmSize().GetWidth();
3492 for( sal_uInt16 j
= 0; j
< pBox
->GetTabLines().size(); ++j
)
3493 _CheckBoxWidth( *pBox
->GetTabLines()[ j
], nBoxW
);
3496 if (sal::static_int_cast
< unsigned long >(Abs(nAktSize
- nSize
)) >
3497 (COLFUZZY
* rBoxes
.size()))
3499 OSL_FAIL( "Line's Boxes are too small or too large" );
3504 static _FndBox
* lcl_SaveInsDelData( CR_SetBoxWidth
& rParam
, SwUndo
** ppUndo
,
3505 SwTableSortBoxes
& rTmpLst
, SwTwips nDistStt
)
3507 // Find all Boxes/Lines
3508 SwTable
& rTbl
= rParam
.pTblNd
->GetTable();
3510 if (rParam
.m_Boxes
.empty())
3513 if( rParam
.bBigger
)
3514 for( sal_uInt16 n
= 0; n
< rTbl
.GetTabLines().size(); ++n
)
3515 ::lcl_DelSelBox( rTbl
.GetTabLines()[ n
], rParam
, nDistStt
, true );
3517 for( sal_uInt16 n
= 0; n
< rTbl
.GetTabLines().size(); ++n
)
3518 ::lcl_InsSelBox( rTbl
.GetTabLines()[ n
], rParam
, nDistStt
, true );
3521 // Prevent deleting the whole Table
3523 && rParam
.m_Boxes
.size() == rTbl
.GetTabSortBoxes().size())
3528 _FndBox
* pFndBox
= new _FndBox( 0, 0 );
3529 if( rParam
.bBigger
)
3530 pFndBox
->SetTableLines( rParam
.m_Boxes
, rTbl
);
3533 _FndPara
aPara(rParam
.m_Boxes
, pFndBox
);
3534 ForEach_FndLineCopyCol( rTbl
.GetTabLines(), &aPara
);
3535 OSL_ENSURE( pFndBox
->GetLines().size(), "Where are the Boxes" );
3536 pFndBox
->SetTableLines( rTbl
);
3539 rTmpLst
.insert( rTbl
.GetTabSortBoxes() );
3542 // Find Lines for the Layout update
3543 pFndBox
->DelFrms( rTbl
);
3545 // TL_CHART2: this function gest called from SetColWidth exclusively,
3546 // thus it is currently speculated that nothing needs to be done here.
3547 // Note: that SetColWidth is currently not completely understood though :-(
3552 bool SwTable::SetColWidth( SwTableBox
& rAktBox
, sal_uInt16 eType
,
3553 SwTwips nAbsDiff
, SwTwips nRelDiff
, SwUndo
** ppUndo
)
3555 SetHTMLTableLayout( 0 ); // Delete HTML Layout
3557 const SwFmtFrmSize
& rSz
= GetFrmFmt()->GetFrmSize();
3558 const SvxLRSpaceItem
& rLR
= GetFrmFmt()->GetLRSpace();
3560 _FndBox
* pFndBox
= 0; // for insertion/deletion
3561 SwTableSortBoxes aTmpLst
; // for Undo
3564 bLeft
= nsTblChgWidthHeightType::WH_COL_LEFT
== ( eType
& 0xff ) ||
3565 nsTblChgWidthHeightType::WH_CELL_LEFT
== ( eType
& 0xff ),
3566 bInsDel
= 0 != (eType
& nsTblChgWidthHeightType::WH_FLAG_INSDEL
);
3568 sal_uLong nBoxIdx
= rAktBox
.GetSttIdx();
3570 // Get the current Box's edge
3571 // Only needed for manipulating the width
3572 const SwTwips nDist
= ::lcl_GetDistance( &rAktBox
, bLeft
);
3573 SwTwips nDistStt
= 0;
3574 CR_SetBoxWidth
aParam( eType
, nRelDiff
, nDist
, rSz
.GetWidth(),
3575 bLeft
? nDist
: rSz
.GetWidth() - nDist
,
3576 (SwTableNode
*)rAktBox
.GetSttNd()->FindTableNode() );
3577 bBigger
= aParam
.bBigger
;
3579 FN_lcl_SetBoxWidth fnSelBox
, fnOtherBox
;
3584 fnSelBox
= lcl_DelSelBox
;
3585 fnOtherBox
= lcl_DelOtherBox
;
3586 aParam
.nBoxWidth
= (sal_uInt16
)rAktBox
.GetFrmFmt()->GetFrmSize().GetWidth();
3588 nDistStt
= rSz
.GetWidth();
3592 fnSelBox
= lcl_InsSelBox
;
3593 fnOtherBox
= lcl_InsOtherBox
;
3598 fnSelBox
= lcl_SetSelBoxWidth
;
3599 fnOtherBox
= lcl_SetOtherBoxWidth
;
3603 switch( eType
& 0xff )
3605 case nsTblChgWidthHeightType::WH_COL_RIGHT
:
3606 case nsTblChgWidthHeightType::WH_COL_LEFT
:
3607 if( TBLVAR_CHGABS
== eTblChgMode
)
3612 // First test if we have room at all
3613 bool bChgLRSpace
= true;
3616 if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) &&
3617 !rSz
.GetWidthPercent() )
3619 bRet
= rSz
.GetWidth() < USHRT_MAX
- nRelDiff
;
3620 bChgLRSpace
= bLeft
? rLR
.GetLeft() >= nAbsDiff
3621 : rLR
.GetRight() >= nAbsDiff
;
3624 bRet
= bLeft
? rLR
.GetLeft() >= nAbsDiff
3625 : rLR
.GetRight() >= nAbsDiff
;
3627 if( !bRet
&& bInsDel
&&
3628 // Is the room on the other side?
3629 ( bLeft
? rLR
.GetRight() >= nAbsDiff
3630 : rLR
.GetLeft() >= nAbsDiff
))
3632 bRet
= true; bLeft
= !bLeft
;
3637 // Then call itself recursively; only with another mode (proportional)
3638 TblChgMode eOld
= eTblChgMode
;
3639 eTblChgMode
= TBLFIX_CHGPROP
;
3641 bRet
= SetColWidth( rAktBox
, eType
, nAbsDiff
, nRelDiff
,
3650 for( n
= 0; n
< aLines
.size(); ++n
)
3653 if( !(*fnSelBox
)( aLines
[ n
], aParam
, nDistStt
, true ))
3665 pFndBox
= ::lcl_SaveInsDelData( aParam
, ppUndo
,
3666 aTmpLst
, nDistStt
);
3667 if (aParam
.bBigger
&&
3668 aParam
.m_Boxes
.size() == m_TabSortContentBoxes
.size())
3670 // This whole Table is to be deleted!
3671 GetFrmFmt()->GetDoc()->DeleteRowCol(aParam
.m_Boxes
);
3676 *ppUndo
= aParam
.CreateUndo(
3677 aParam
.bBigger
? UNDO_COL_DELETE
3678 : UNDO_TABLE_INSCOL
);
3681 *ppUndo
= new SwUndoAttrTbl( *aParam
.pTblNd
, sal_True
);
3683 long nFrmWidth
= LONG_MAX
;
3685 SwFmtFrmSize
aSz( rSz
);
3686 SvxLRSpaceItem
aLR( rLR
);
3689 // If the Table does not have any room to grow, we need to create some!
3690 if( aSz
.GetWidth() + nRelDiff
> USHRT_MAX
)
3692 // Break down to USHRT_MAX / 2
3693 CR_SetBoxWidth
aTmpPara( 0, aSz
.GetWidth() / 2,
3694 0, aSz
.GetWidth(), aSz
.GetWidth(), aParam
.pTblNd
);
3695 for( sal_uInt16 nLn
= 0; nLn
< aLines
.size(); ++nLn
)
3696 ::lcl_AjustLines( aLines
[ nLn
], aTmpPara
);
3697 aSz
.SetWidth( aSz
.GetWidth() / 2 );
3698 aParam
.nDiff
= nRelDiff
/= 2;
3700 aParam
.nMaxSize
/= 2;
3704 aLR
.SetLeft( sal_uInt16( aLR
.GetLeft() - nAbsDiff
) );
3706 aLR
.SetRight( sal_uInt16( aLR
.GetRight() - nAbsDiff
) );
3709 aLR
.SetLeft( sal_uInt16( aLR
.GetLeft() + nAbsDiff
) );
3711 aLR
.SetRight( sal_uInt16( aLR
.GetRight() + nAbsDiff
) );
3714 GetFrmFmt()->SetFmtAttr( aLR
);
3715 const SwFmtHoriOrient
& rHOri
= GetFrmFmt()->GetHoriOrient();
3716 if( text::HoriOrientation::FULL
== rHOri
.GetHoriOrient() ||
3717 (text::HoriOrientation::LEFT
== rHOri
.GetHoriOrient() && aLR
.GetLeft()) ||
3718 (text::HoriOrientation::RIGHT
== rHOri
.GetHoriOrient() && aLR
.GetRight()))
3720 SwFmtHoriOrient
aHOri( rHOri
);
3721 aHOri
.SetHoriOrient( text::HoriOrientation::NONE
);
3722 GetFrmFmt()->SetFmtAttr( aHOri
);
3724 // If the Table happens to contain relative values (USHORT_MAX),
3725 // we need to convert them to absolute ones now.
3727 if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) &&
3728 !rSz
.GetWidthPercent() )
3730 SwTabFrm
* pTabFrm
= SwIterator
<SwTabFrm
,SwFmt
>::FirstElement( *GetFrmFmt() );
3732 pTabFrm
->Prt().Width() != rSz
.GetWidth() )
3734 nFrmWidth
= pTabFrm
->Prt().Width();
3736 nFrmWidth
+= nAbsDiff
;
3738 nFrmWidth
-= nAbsDiff
;
3744 aSz
.SetWidth( aSz
.GetWidth() + nRelDiff
);
3746 aSz
.SetWidth( aSz
.GetWidth() - nRelDiff
);
3748 if( rSz
.GetWidthPercent() )
3749 aSz
.SetWidthPercent( static_cast<sal_uInt8
>(( aSz
.GetWidth() * 100 ) /
3750 ( aSz
.GetWidth() + aLR
.GetRight() + aLR
.GetLeft())));
3752 GetFrmFmt()->SetFmtAttr( aSz
);
3753 aParam
.nTblWidth
= sal_uInt16( aSz
.GetWidth() );
3757 for( n
= aLines
.size(); n
; )
3761 (*fnSelBox
)( aLines
[ n
], aParam
, nDistStt
, false );
3764 // If the Table happens to contain relative values (USHORT_MAX),
3765 // we need to convert them to absolute ones now.
3767 if( LONG_MAX
!= nFrmWidth
)
3769 SwFmtFrmSize
aAbsSz( aSz
);
3770 aAbsSz
.SetWidth( nFrmWidth
);
3771 GetFrmFmt()->SetFmtAttr( aAbsSz
);
3776 ( bLeft
? nDist
: Abs( rSz
.GetWidth() - nDist
) > COLFUZZY
) )
3779 if( bLeft
&& TBLFIX_CHGABS
== eTblChgMode
&& !bInsDel
)
3780 aParam
.bBigger
= !bBigger
;
3782 // First test if we have room at all
3785 if( aParam
.bBigger
)
3787 for( n
= 0; n
< aLines
.size(); ++n
)
3790 if( !(*fnSelBox
)( aLines
[ n
], aParam
, nDistStt
, true ))
3799 if( ( bRet
= bLeft
? nDist
!= 0
3800 : ( rSz
.GetWidth() - nDist
) > COLFUZZY
) )
3802 for( n
= 0; n
< aLines
.size(); ++n
)
3805 if( !(*fnOtherBox
)( aLines
[ n
], aParam
, 0, true ))
3811 if( bRet
&& !aParam
.bAnyBoxFnd
)
3815 if( !bRet
&& rAktBox
.GetFrmFmt()->GetFrmSize().GetWidth()
3816 - nRelDiff
> COLFUZZY
+
3817 ( 567 / 2 /*leave room for at least 0.5 cm*/) )
3819 // Consume the space from the current Cell
3820 aParam
.bSplittBox
= true;
3821 // We also need to test this!
3824 for( n
= 0; n
< aLines
.size(); ++n
)
3827 if( !(*fnSelBox
)( aLines
[ n
], aParam
, nDistStt
, true ))
3836 else if( aParam
.bBigger
)
3838 for( n
= 0; n
< aLines
.size(); ++n
)
3841 if( !(*fnOtherBox
)( aLines
[ n
], aParam
, 0, true ))
3850 for( n
= 0; n
< aLines
.size(); ++n
)
3853 if( !(*fnSelBox
)( aLines
[ n
], aParam
, nDistStt
, true ))
3864 CR_SetBoxWidth
aParam1( aParam
);
3867 aParam1
.bBigger
= !aParam
.bBigger
;
3868 pFndBox
= ::lcl_SaveInsDelData( aParam
, ppUndo
,
3869 aTmpLst
, nDistStt
);
3871 *ppUndo
= aParam
.CreateUndo(
3872 aParam
.bBigger
? UNDO_TABLE_DELBOX
3873 : UNDO_TABLE_INSCOL
);
3876 *ppUndo
= new SwUndoAttrTbl( *aParam
.pTblNd
, sal_True
);
3879 ? ( TBLFIX_CHGABS
== eTblChgMode
? bLeft
: bLeft
)
3880 : ( TBLFIX_CHGABS
!= eTblChgMode
&& bLeft
) )
3882 for( n
= aLines
.size(); n
; )
3886 aParam1
.LoopClear();
3887 (*fnSelBox
)( aLines
[ n
], aParam
, nDistStt
, false );
3888 (*fnOtherBox
)( aLines
[ n
], aParam1
, nDistStt
, false );
3892 for( n
= aLines
.size(); n
; )
3896 aParam1
.LoopClear();
3897 (*fnOtherBox
)( aLines
[ n
], aParam1
, nDistStt
, false );
3898 (*fnSelBox
)( aLines
[ n
], aParam
, nDistStt
, false );
3904 case nsTblChgWidthHeightType::WH_CELL_RIGHT
:
3905 case nsTblChgWidthHeightType::WH_CELL_LEFT
:
3906 if( TBLVAR_CHGABS
== eTblChgMode
)
3908 // Then call itself recursively; only with another mode (proportional)
3909 TblChgMode eOld
= eTblChgMode
;
3910 eTblChgMode
= TBLFIX_CHGABS
;
3912 bRet
= SetColWidth( rAktBox
, eType
, nAbsDiff
, nRelDiff
,
3917 else if( bInsDel
|| ( bLeft
? nDist
3918 : (rSz
.GetWidth() - nDist
) > COLFUZZY
))
3920 if( bLeft
&& TBLFIX_CHGABS
== eTblChgMode
&& !bInsDel
)
3921 aParam
.bBigger
= !bBigger
;
3923 // First, see if there is enough room at all
3924 SwTableBox
* pBox
= &rAktBox
;
3925 SwTableLine
* pLine
= rAktBox
.GetUpper();
3926 while( pLine
->GetUpper() )
3928 sal_uInt16 nPos
= pLine
->GetTabBoxes().GetPos( pBox
);
3929 if( bLeft
? nPos
: nPos
+ 1 != (sal_uInt16
)pLine
->GetTabBoxes().size() )
3932 pBox
= pLine
->GetUpper();
3933 pLine
= pBox
->GetUpper();
3936 if( pLine
->GetUpper() )
3938 // We need to correct the distance once again!
3939 aParam
.nSide
-= ::lcl_GetDistance( pLine
->GetUpper(), true );
3942 aParam
.nMaxSize
= aParam
.nSide
;
3944 aParam
.nMaxSize
= pLine
->GetUpper()->GetFrmFmt()->
3945 GetFrmSize().GetWidth() - aParam
.nSide
;
3948 // First, see if there is enough room at all
3951 if( 0 != ( bRet
= bLeft
? nDist
!= 0
3952 : ( rSz
.GetWidth() - nDist
) > COLFUZZY
) &&
3955 bRet
= (*fnOtherBox
)( pLine
, aParam
, 0, true );
3956 if( bRet
&& !aParam
.bAnyBoxFnd
)
3960 if( !bRet
&& !aParam
.bBigger
&& rAktBox
.GetFrmFmt()->
3961 GetFrmSize().GetWidth() - nRelDiff
> COLFUZZY
+
3962 ( 567 / 2 /*leave room for at least 0.5 cm*/) )
3964 // Consume the room from the current Cell
3965 aParam
.bSplittBox
= true;
3971 FN_lcl_SetBoxWidth fnTmp
= aParam
.bBigger
? fnOtherBox
: fnSelBox
;
3972 bRet
= (*fnTmp
)( pLine
, aParam
, nDistStt
, true );
3978 CR_SetBoxWidth
aParam1( aParam
);
3981 aParam1
.bBigger
= !aParam
.bBigger
;
3982 pFndBox
= ::lcl_SaveInsDelData( aParam
, ppUndo
, aTmpLst
, nDistStt
);
3984 *ppUndo
= aParam
.CreateUndo(
3985 aParam
.bBigger
? UNDO_TABLE_DELBOX
3986 : UNDO_TABLE_INSCOL
);
3989 *ppUndo
= new SwUndoAttrTbl( *aParam
.pTblNd
, sal_True
);
3992 ? ( TBLFIX_CHGABS
== eTblChgMode
? (bBigger
&& bLeft
) : bLeft
)
3993 : ( TBLFIX_CHGABS
!= eTblChgMode
&& bLeft
) )
3995 (*fnSelBox
)( pLine
, aParam
, nDistStt
, false );
3996 (*fnOtherBox
)( pLine
, aParam1
, nDistStt
, false );
4000 (*fnOtherBox
)( pLine
, aParam1
, nDistStt
, false );
4001 (*fnSelBox
)( pLine
, aParam
, nDistStt
, false );
4011 // Clean up the structure of all Lines
4015 if( !bBigger
|| pFndBox
->AreLinesToRestore( *this ) )
4016 pFndBox
->MakeFrms( *this );
4018 // TL_CHART2: it is currently unclear if sth has to be done here.
4019 // The function name hints that nothing needs to be done, on the other
4020 // hand there is a case where sth gets deleted. :-(
4024 if( ppUndo
&& *ppUndo
)
4026 aParam
.pUndo
->SetColWidthParam( nBoxIdx
, static_cast<sal_uInt16
>(eTblChgMode
), eType
,
4027 nAbsDiff
, nRelDiff
);
4028 if( !aParam
.bBigger
)
4029 aParam
.pUndo
->SaveNewBoxes( *aParam
.pTblNd
, aTmpLst
);
4042 static _FndBox
* lcl_SaveInsDelData( CR_SetLineHeight
& rParam
, SwUndo
** ppUndo
,
4043 SwTableSortBoxes
& rTmpLst
)
4045 // Find all Boxes/Lines
4046 SwTable
& rTbl
= rParam
.pTblNd
->GetTable();
4048 OSL_ENSURE( !rParam
.m_Boxes
.empty(), "We can't go on without Boxes!" );
4050 // Prevent deleting the whole Table
4052 && rParam
.m_Boxes
.size() == rTbl
.GetTabSortBoxes().size())
4057 _FndBox
* pFndBox
= new _FndBox( 0, 0 );
4058 if( !rParam
.bBigger
)
4059 pFndBox
->SetTableLines( rParam
.m_Boxes
, rTbl
);
4062 _FndPara
aPara(rParam
.m_Boxes
, pFndBox
);
4063 ForEach_FndLineCopyCol( rTbl
.GetTabLines(), &aPara
);
4064 OSL_ENSURE( pFndBox
->GetLines().size(), "Where are the Boxes?" );
4065 pFndBox
->SetTableLines( rTbl
);
4068 rTmpLst
.insert( rTbl
.GetTabSortBoxes() );
4071 // Find Lines for the Layout update
4072 pFndBox
->DelFrms( rTbl
);
4074 // TL_CHART2: it is currently unclear if sth has to be done here.
4079 void SetLineHeight( SwTableLine
& rLine
, SwTwips nOldHeight
, SwTwips nNewHeight
,
4082 SwLayoutFrm
* pLineFrm
= GetRowFrm( rLine
);
4083 OSL_ENSURE( pLineFrm
, "Where is the Frame from the SwTableLine?" );
4085 SwFrmFmt
* pFmt
= rLine
.ClaimFrmFmt();
4087 SwTwips nMyNewH
, nMyOldH
= pLineFrm
->Frm().Height();
4088 if( !nOldHeight
) // the BaseLine and absolute
4089 nMyNewH
= nMyOldH
+ nNewHeight
;
4092 // Calculate as exactly as possible
4093 Fraction
aTmp( nMyOldH
);
4094 aTmp
*= Fraction( nNewHeight
, nOldHeight
);
4095 aTmp
+= Fraction( 1, 2 ); // round up if needed
4099 SwFrmSize eSize
= ATT_MIN_SIZE
;
4101 ( nMyOldH
- nMyNewH
) > ( CalcRowRstHeight( pLineFrm
) + ROWFUZZY
))
4102 eSize
= ATT_FIX_SIZE
;
4104 pFmt
->SetFmtAttr( SwFmtFrmSize( eSize
, 0, nMyNewH
) );
4106 // First adapt all internal ones
4107 SwTableBoxes
& rBoxes
= rLine
.GetTabBoxes();
4108 for( sal_uInt16 n
= 0; n
< rBoxes
.size(); ++n
)
4110 SwTableBox
& rBox
= *rBoxes
[ n
];
4111 for( sal_uInt16 i
= 0; i
< rBox
.GetTabLines().size(); ++i
)
4112 SetLineHeight( *rBox
.GetTabLines()[ i
], nMyOldH
, nMyNewH
, bMinSize
);
4116 static bool lcl_SetSelLineHeight( SwTableLine
* pLine
, CR_SetLineHeight
& rParam
,
4117 SwTwips nDist
, bool bCheck
)
4123 SetLineHeight( *pLine
, 0, rParam
.bBigger
? nDist
: -nDist
,
4126 else if( !rParam
.bBigger
)
4128 // Calculate the new relative size by means of the old one
4129 SwLayoutFrm
* pLineFrm
= GetRowFrm( *pLine
);
4130 OSL_ENSURE( pLineFrm
, "Where is the Frame from the SwTableLine?" );
4131 SwTwips nRstHeight
= CalcRowRstHeight( pLineFrm
);
4132 if( (nRstHeight
+ ROWFUZZY
) < nDist
)
4138 static bool lcl_SetOtherLineHeight( SwTableLine
* pLine
, CR_SetLineHeight
& rParam
,
4139 SwTwips nDist
, bool bCheck
)
4144 if( rParam
.bBigger
)
4146 // Calculate the new relative size by means of the old one
4147 SwLayoutFrm
* pLineFrm
= GetRowFrm( *pLine
);
4148 OSL_ENSURE( pLineFrm
, "Where is the Frame from the SwTableLine?" );
4150 if( TBLFIX_CHGPROP
== rParam
.nMode
)
4152 nDist
*= pLineFrm
->Frm().Height();
4153 nDist
/= rParam
.nMaxHeight
;
4155 bRet
= nDist
<= CalcRowRstHeight( pLineFrm
);
4161 // pLine is the following/preceeding, thus adjust it
4162 if( TBLFIX_CHGPROP
== rParam
.nMode
)
4164 SwLayoutFrm
* pLineFrm
= GetRowFrm( *pLine
);
4165 OSL_ENSURE( pLineFrm
, "Where is the Frame from the SwTableLine??" );
4167 // Calculate the new relative size by means of the old one
4168 // If the selected Box get bigger, adjust via the max space else
4169 // via the max height.
4170 if( 1 /*!rParam.bBigger*/ )
4172 nDist
*= pLineFrm
->Frm().Height();
4173 nDist
/= rParam
.nMaxHeight
;
4177 // Calculate the new relative size by means of the old one
4178 nDist
*= CalcRowRstHeight( pLineFrm
);
4179 nDist
/= rParam
.nMaxSpace
;
4182 SetLineHeight( *pLine
, 0, rParam
.bBigger
? -nDist
: nDist
,
4188 static bool lcl_InsDelSelLine( SwTableLine
* pLine
, CR_SetLineHeight
& rParam
,
4189 SwTwips nDist
, bool bCheck
)
4194 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
4195 SwDoc
* pDoc
= pLine
->GetFrmFmt()->GetDoc();
4196 if( !rParam
.bBigger
)
4198 for (size_t n
= rBoxes
.size(); n
; )
4200 ::lcl_SaveUpperLowerBorder( rParam
.pTblNd
->GetTable(),
4202 rParam
.aShareFmts
);
4204 for (size_t n
= rBoxes
.size(); n
; )
4206 ::_DeleteBox( rParam
.pTblNd
->GetTable(),
4207 rBoxes
[ --n
], rParam
.pUndo
, false,
4208 false, &rParam
.aShareFmts
);
4214 SwTableLine
* pNewLine
= new SwTableLine( (SwTableLineFmt
*)pLine
->GetFrmFmt(),
4215 rBoxes
.size(), pLine
->GetUpper() );
4216 SwTableLines
* pLines
;
4217 if( pLine
->GetUpper() )
4218 pLines
= &pLine
->GetUpper()->GetTabLines();
4220 pLines
= &rParam
.pTblNd
->GetTable().GetTabLines();
4221 sal_uInt16 nPos
= pLines
->GetPos( pLine
);
4224 pLines
->insert( pLines
->begin() + nPos
, pNewLine
);
4226 SwFrmFmt
* pNewFmt
= pNewLine
->ClaimFrmFmt();
4227 pNewFmt
->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE
, 0, nDist
) );
4229 // And once again calculate the Box count
4230 SwTableBoxes
& rNewBoxes
= pNewLine
->GetTabBoxes();
4231 for( sal_uInt16 n
= 0; n
< rBoxes
.size(); ++n
)
4234 SwTableBox
* pOld
= rBoxes
[ n
];
4235 if( !pOld
->GetSttNd() )
4237 // Not a normal content Box, so fall back to the 1st next Box
4238 nWidth
= pOld
->GetFrmFmt()->GetFrmSize().GetWidth();
4239 while( !pOld
->GetSttNd() )
4240 pOld
= pOld
->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ];
4242 ::_InsTblBox( pDoc
, rParam
.pTblNd
, pNewLine
,
4243 (SwTableBoxFmt
*)pOld
->GetFrmFmt(), pOld
, n
);
4245 // Special treatment for the border:
4246 // The top one needs to be removed
4247 const SvxBoxItem
& rBoxItem
= pOld
->GetFrmFmt()->GetBox();
4248 if( rBoxItem
.GetTop() )
4250 SvxBoxItem
aTmp( rBoxItem
);
4251 aTmp
.SetLine( 0, BOX_LINE_TOP
);
4252 rParam
.aShareFmts
.SetAttr( rParam
.bTop
4254 : *rNewBoxes
[ n
], aTmp
);
4258 rParam
.aShareFmts
.SetAttr( *rNewBoxes
[ n
],
4259 SwFmtFrmSize( ATT_FIX_SIZE
, nWidth
, 0 ) );
4266 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
4267 for( sal_uInt16 n
= rBoxes
.size(); n
; )
4269 SwTableBox
* pBox
= rBoxes
[ --n
];
4270 if( pBox
->GetFrmFmt()->GetProtect().IsCntntProtected() )
4273 if( pBox
->GetSttNd() )
4275 rParam
.m_Boxes
.insert(pBox
);
4279 for( sal_uInt16 i
= pBox
->GetTabLines().size(); i
; )
4280 lcl_InsDelSelLine( pBox
->GetTabLines()[ --i
],
4288 bool SwTable::SetRowHeight( SwTableBox
& rAktBox
, sal_uInt16 eType
,
4289 SwTwips nAbsDiff
, SwTwips nRelDiff
,SwUndo
** ppUndo
)
4291 SwTableLine
* pLine
= rAktBox
.GetUpper();
4293 SwTableLine
* pBaseLine
= pLine
;
4294 while( pBaseLine
->GetUpper() )
4295 pBaseLine
= pBaseLine
->GetUpper()->GetUpper();
4297 _FndBox
* pFndBox
= 0; // for insertion/deletion
4298 SwTableSortBoxes aTmpLst
; // for Undo
4301 bTop
= nsTblChgWidthHeightType::WH_ROW_TOP
== ( eType
& 0xff ) ||
4302 nsTblChgWidthHeightType::WH_CELL_TOP
== ( eType
& 0xff ),
4303 bInsDel
= 0 != (eType
& nsTblChgWidthHeightType::WH_FLAG_INSDEL
);
4304 sal_uInt16 n
, nBaseLinePos
= GetTabLines().GetPos( pBaseLine
);
4305 sal_uLong nBoxIdx
= rAktBox
.GetSttIdx();
4307 CR_SetLineHeight
aParam( eType
,
4308 (SwTableNode
*)rAktBox
.GetSttNd()->FindTableNode() );
4309 bBigger
= aParam
.bBigger
;
4311 FN_lcl_SetLineHeight fnSelLine
, fnOtherLine
= lcl_SetOtherLineHeight
;
4313 fnSelLine
= lcl_InsDelSelLine
;
4315 fnSelLine
= lcl_SetSelLineHeight
;
4317 SwTableLines
* pLines
= &aLines
;
4319 // How do we get to the height?
4320 switch( eType
& 0xff )
4322 case nsTblChgWidthHeightType::WH_CELL_TOP
:
4323 case nsTblChgWidthHeightType::WH_CELL_BOTTOM
:
4324 if( pLine
== pBaseLine
)
4325 break; // it doesn't work then!
4327 // Is a nested Line (Box!)
4328 pLines
= &pLine
->GetUpper()->GetTabLines();
4329 nBaseLinePos
= pLines
->GetPos( pLine
);
4333 case nsTblChgWidthHeightType::WH_ROW_TOP
:
4334 case nsTblChgWidthHeightType::WH_ROW_BOTTOM
:
4336 if( bInsDel
&& !bBigger
) // By how much does it get higher?
4338 nAbsDiff
= GetRowFrm( *pBaseLine
)->Frm().Height();
4341 if( TBLVAR_CHGABS
== eTblChgMode
)
4343 // First test if we have room at all
4347 // What's up with Top, Table in a Frame or Header/Footer with fixed width??
4350 // Then call itself recursively; only with another mode (proportional)
4351 TblChgMode eOld
= eTblChgMode
;
4352 eTblChgMode
= TBLFIX_CHGPROP
;
4354 bRet
= SetRowHeight( rAktBox
, eType
, nAbsDiff
,
4362 bRet
= (*fnSelLine
)( (*pLines
)[ nBaseLinePos
], aParam
,
4369 if (aParam
.m_Boxes
.empty())
4371 ::lcl_InsDelSelLine( (*pLines
)[ nBaseLinePos
],
4375 pFndBox
= ::lcl_SaveInsDelData( aParam
, ppUndo
, aTmpLst
);
4377 // delete complete table when last row is deleted
4379 aParam
.m_Boxes
.size() == m_TabSortContentBoxes
.size())
4381 GetFrmFmt()->GetDoc()->DeleteRowCol(aParam
.m_Boxes
);
4387 *ppUndo
= aParam
.CreateUndo(
4388 bBigger
? UNDO_TABLE_INSROW
4389 : UNDO_ROW_DELETE
);
4392 *ppUndo
= new SwUndoAttrTbl( *aParam
.pTblNd
, sal_True
);
4394 (*fnSelLine
)( (*pLines
)[ nBaseLinePos
], aParam
,
4401 sal_uInt16 nStt
, nEnd
;
4403 nStt
= 0, nEnd
= nBaseLinePos
;
4405 nStt
= nBaseLinePos
+ 1, nEnd
= pLines
->size();
4407 // Get the current Lines' height
4408 if( TBLFIX_CHGPROP
== eTblChgMode
)
4410 for( n
= nStt
; n
< nEnd
; ++n
)
4412 SwLayoutFrm
* pLineFrm
= GetRowFrm( *(*pLines
)[ n
] );
4413 OSL_ENSURE( pLineFrm
, "Where is the Frame from the SwTableLine??" );
4414 aParam
.nMaxSpace
+= CalcRowRstHeight( pLineFrm
);
4415 aParam
.nMaxHeight
+= pLineFrm
->Frm().Height();
4417 if( bBigger
&& aParam
.nMaxSpace
< nAbsDiff
)
4422 if( bTop
? nEnd
: nStt
< nEnd
)
4437 for( n
= nStt
; n
< nEnd
; ++n
)
4439 if( !(*fnOtherLine
)( (*pLines
)[ n
], aParam
,
4448 bRet
= (*fnSelLine
)( (*pLines
)[ nBaseLinePos
], aParam
,
4457 if (aParam
.m_Boxes
.empty())
4459 ::lcl_InsDelSelLine( (*pLines
)[ nBaseLinePos
],
4462 pFndBox
= ::lcl_SaveInsDelData( aParam
, ppUndo
, aTmpLst
);
4464 *ppUndo
= aParam
.CreateUndo(
4465 bBigger
? UNDO_TABLE_INSROW
4466 : UNDO_ROW_DELETE
);
4469 *ppUndo
= new SwUndoAttrTbl( *aParam
.pTblNd
, sal_True
);
4471 CR_SetLineHeight
aParam1( aParam
);
4472 if( TBLFIX_CHGPROP
== eTblChgMode
&& !bBigger
&&
4475 // We need to distribute the space evenly among all the Lines.
4476 // That's why we need their count.
4477 aParam1
.nLines
= nEnd
- nStt
;
4482 (*fnSelLine
)( (*pLines
)[ nBaseLinePos
], aParam
,
4484 for( n
= nStt
; n
< nEnd
; ++n
)
4485 (*fnOtherLine
)( (*pLines
)[ n
], aParam1
,
4490 for( n
= nStt
; n
< nEnd
; ++n
)
4491 (*fnOtherLine
)( (*pLines
)[ n
], aParam1
,
4493 (*fnSelLine
)( (*pLines
)[ nBaseLinePos
], aParam
,
4499 // Then call itself recursively; only with another mode (proportional)
4500 TblChgMode eOld
= eTblChgMode
;
4501 eTblChgMode
= TBLVAR_CHGABS
;
4503 bRet
= SetRowHeight( rAktBox
, eType
, nAbsDiff
,
4516 // then clean up the structure of all Lines
4520 if( bBigger
|| pFndBox
->AreLinesToRestore( *this ) )
4521 pFndBox
->MakeFrms( *this );
4523 // TL_CHART2: it is currently unclear if sth has to be done here.
4527 if( ppUndo
&& *ppUndo
)
4529 aParam
.pUndo
->SetColWidthParam( nBoxIdx
, static_cast<sal_uInt16
>(eTblChgMode
), eType
,
4530 nAbsDiff
, nRelDiff
);
4532 aParam
.pUndo
->SaveNewBoxes( *aParam
.pTblNd
, aTmpLst
);
4541 SwFrmFmt
* SwShareBoxFmt::GetFormat( long nWidth
) const
4543 SwFrmFmt
*pRet
= 0, *pTmp
;
4544 for( sal_uInt16 n
= aNewFmts
.size(); n
; )
4545 if( ( pTmp
= aNewFmts
[ --n
])->GetFrmSize().GetWidth()
4554 SwFrmFmt
* SwShareBoxFmt::GetFormat( const SfxPoolItem
& rItem
) const
4556 const SfxPoolItem
* pItem
;
4557 sal_uInt16 nWhich
= rItem
.Which();
4558 SwFrmFmt
*pRet
= 0, *pTmp
;
4559 const SfxPoolItem
& rFrmSz
= pOldFmt
->GetFmtAttr( RES_FRM_SIZE
, sal_False
);
4560 for( sal_uInt16 n
= aNewFmts
.size(); n
; )
4561 if( SFX_ITEM_SET
== ( pTmp
= aNewFmts
[ --n
])->
4562 GetItemState( nWhich
, sal_False
, &pItem
) && *pItem
== rItem
&&
4563 pTmp
->GetFmtAttr( RES_FRM_SIZE
, sal_False
) == rFrmSz
)
4571 void SwShareBoxFmt::AddFormat( SwFrmFmt
& rNew
)
4573 aNewFmts
.push_back( &rNew
);
4576 bool SwShareBoxFmt::RemoveFormat( const SwFrmFmt
& rFmt
)
4578 // returns true, if we can delete
4579 if( pOldFmt
== &rFmt
)
4582 std::vector
<SwFrmFmt
*>::iterator it
= std::find( aNewFmts
.begin(), aNewFmts
.end(), &rFmt
);
4583 if( aNewFmts
.end() != it
)
4584 aNewFmts
.erase( it
);
4585 return aNewFmts
.empty();
4588 SwShareBoxFmts::~SwShareBoxFmts()
4592 SwFrmFmt
* SwShareBoxFmts::GetFormat( const SwFrmFmt
& rFmt
, long nWidth
) const
4595 return Seek_Entry( rFmt
, &nPos
)
4596 ? aShareArr
[ nPos
].GetFormat( nWidth
)
4599 SwFrmFmt
* SwShareBoxFmts::GetFormat( const SwFrmFmt
& rFmt
,
4600 const SfxPoolItem
& rItem
) const
4603 return Seek_Entry( rFmt
, &nPos
)
4604 ? aShareArr
[ nPos
].GetFormat( rItem
)
4608 void SwShareBoxFmts::AddFormat( const SwFrmFmt
& rOld
, SwFrmFmt
& rNew
)
4612 SwShareBoxFmt
* pEntry
;
4613 if( !Seek_Entry( rOld
, &nPos
))
4615 pEntry
= new SwShareBoxFmt( rOld
);
4616 aShareArr
.insert( aShareArr
.begin() + nPos
, pEntry
);
4619 pEntry
= &aShareArr
[ nPos
];
4621 pEntry
->AddFormat( rNew
);
4625 void SwShareBoxFmts::ChangeFrmFmt( SwTableBox
* pBox
, SwTableLine
* pLn
,
4632 pOld
= pBox
->GetFrmFmt();
4634 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)&rFmt
);
4638 pOld
= pLn
->GetFrmFmt();
4640 pLn
->ChgFrmFmt( (SwTableLineFmt
*)&rFmt
);
4642 if( pOld
&& pOld
->IsLastDepend() )
4644 RemoveFormat( *pOld
);
4649 void SwShareBoxFmts::SetSize( SwTableBox
& rBox
, const SwFmtFrmSize
& rSz
)
4651 SwFrmFmt
*pBoxFmt
= rBox
.GetFrmFmt(),
4652 *pRet
= GetFormat( *pBoxFmt
, rSz
.GetWidth() );
4654 ChangeFrmFmt( &rBox
, 0, *pRet
);
4657 pRet
= rBox
.ClaimFrmFmt();
4658 pRet
->SetFmtAttr( rSz
);
4659 AddFormat( *pBoxFmt
, *pRet
);
4663 void SwShareBoxFmts::SetAttr( SwTableBox
& rBox
, const SfxPoolItem
& rItem
)
4665 SwFrmFmt
*pBoxFmt
= rBox
.GetFrmFmt(),
4666 *pRet
= GetFormat( *pBoxFmt
, rItem
);
4668 ChangeFrmFmt( &rBox
, 0, *pRet
);
4671 pRet
= rBox
.ClaimFrmFmt();
4672 pRet
->SetFmtAttr( rItem
);
4673 AddFormat( *pBoxFmt
, *pRet
);
4677 void SwShareBoxFmts::SetAttr( SwTableLine
& rLine
, const SfxPoolItem
& rItem
)
4679 SwFrmFmt
*pLineFmt
= rLine
.GetFrmFmt(),
4680 *pRet
= GetFormat( *pLineFmt
, rItem
);
4682 ChangeFrmFmt( 0, &rLine
, *pRet
);
4685 pRet
= rLine
.ClaimFrmFmt();
4686 pRet
->SetFmtAttr( rItem
);
4687 AddFormat( *pLineFmt
, *pRet
);
4691 void SwShareBoxFmts::RemoveFormat( const SwFrmFmt
& rFmt
)
4693 for( sal_uInt16 i
= aShareArr
.size(); i
; )
4694 if( aShareArr
[ --i
].RemoveFormat( rFmt
))
4695 aShareArr
.erase( aShareArr
.begin() + i
);
4698 bool SwShareBoxFmts::Seek_Entry( const SwFrmFmt
& rFmt
, sal_uInt16
* pPos
) const
4700 sal_uLong nIdx
= (sal_uLong
)&rFmt
;
4701 sal_uInt16 nO
= aShareArr
.size(), nM
, nU
= 0;
4707 nM
= nU
+ ( nO
- nU
) / 2;
4708 sal_uLong nFmt
= (sal_uLong
)&aShareArr
[ nM
].GetOldFormat();
4715 else if( nFmt
< nIdx
)
4732 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */