| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| #include <com/sun/star/text/HoriOrientation.hpp> |
| #include <com/sun/star/chart2/XChartDocument.hpp> |
| #include <hintids.hxx> |
| |
| #define _ZFORLIST_DECLARE_TABLE |
| #include <editeng/brshitem.hxx> |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/protitem.hxx> |
| #include <editeng/boxitem.hxx> |
| #include <tools/fract.hxx> |
| #include <fmtfsize.hxx> |
| #include <fmtornt.hxx> |
| #include <doc.hxx> |
| #include <cntfrm.hxx> |
| #include <tabfrm.hxx> |
| #include <frmtool.hxx> |
| #include <pam.hxx> |
| #include <swtable.hxx> |
| #include <ndtxt.hxx> |
| #include <tblsel.hxx> |
| #include <fldbas.hxx> |
| #include <swundo.hxx> |
| #include <rowfrm.hxx> |
| #include <ddefld.hxx> |
| #include <hints.hxx> |
| #include <UndoTable.hxx> |
| #include <cellatr.hxx> |
| #include <mvsave.hxx> |
| #include <swtblfmt.hxx> |
| #include <swddetbl.hxx> |
| #include <poolfmt.hxx> |
| #include <tblrwcl.hxx> |
| #include <unochart.hxx> |
| #include <boost/shared_ptr.hpp> |
| #include <switerator.hxx> |
| |
| using namespace com::sun::star; |
| using namespace com::sun::star::uno; |
| |
| |
| #define COLFUZZY 20 |
| #define ROWFUZZY 10 |
| |
| using namespace ::com::sun::star; |
| |
| #ifndef DBG_UTIL |
| #define CHECK_TABLE(t) |
| #else |
| #ifdef DEBUG |
| #define CHECK_TABLE(t) (t).CheckConsistency(); |
| #else |
| #define CHECK_TABLE(t) |
| #endif |
| #endif |
| |
| typedef SwTableLine* SwTableLinePtr; |
| SV_DECL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr, 16, 16 ) |
| SV_IMPL_PTRARR_SORT( SwSortTableLines, SwTableLinePtr ); |
| |
| SV_IMPL_PTRARR( _SwShareBoxFmts, SwShareBoxFmt* ) |
| |
| // fuers setzen der Frame-Formate an den Boxen reicht es, das aktuelle |
| // im Array zu suchen. Ist es vorhanden, so gebe das neue zurueck |
| struct _CpyTabFrm |
| { |
| union { |
| SwTableBoxFmt *pFrmFmt; // fuer CopyCol |
| SwTwips nSize; // fuer DelCol |
| } Value; |
| SwTableBoxFmt *pNewFrmFmt; |
| |
| _CpyTabFrm( SwTableBoxFmt* pAktFrmFmt ) : pNewFrmFmt( 0 ) |
| { Value.pFrmFmt = pAktFrmFmt; } |
| |
| _CpyTabFrm& operator=( const _CpyTabFrm& ); |
| |
| sal_Bool operator==( const _CpyTabFrm& rCpyTabFrm ) |
| { return (sal_uLong)Value.nSize == (sal_uLong)rCpyTabFrm.Value.nSize; } |
| sal_Bool operator<( const _CpyTabFrm& rCpyTabFrm ) |
| { return (sal_uLong)Value.nSize < (sal_uLong)rCpyTabFrm.Value.nSize; } |
| }; |
| |
| struct CR_SetBoxWidth |
| { |
| SwSelBoxes aBoxes; |
| SwSortTableLines aLines; |
| SvUShorts aLinesWidth; |
| SwShareBoxFmts aShareFmts; |
| SwTableNode* pTblNd; |
| SwUndoTblNdsChg* pUndo; |
| SwTwips nDiff, nSide, nMaxSize, nLowerDiff; |
| TblChgMode nMode; |
| sal_uInt16 nTblWidth, nRemainWidth, nBoxWidth; |
| sal_Bool bBigger, bLeft, bSplittBox, bAnyBoxFnd; |
| |
| CR_SetBoxWidth( sal_uInt16 eType, SwTwips nDif, SwTwips nSid, SwTwips nTblW, |
| SwTwips nMax, SwTableNode* pTNd ) |
| : pTblNd( pTNd ), |
| nDiff( nDif ), nSide( nSid ), nMaxSize( nMax ), nLowerDiff( 0 ), |
| nTblWidth( (sal_uInt16)nTblW ), nRemainWidth( 0 ), nBoxWidth( 0 ), |
| bSplittBox( sal_False ), bAnyBoxFnd( sal_False ) |
| { |
| bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) || |
| nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ); |
| bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER ); |
| nMode = pTblNd->GetTable().GetTblChgMode(); |
| } |
| CR_SetBoxWidth( const CR_SetBoxWidth& rCpy ) |
| : pTblNd( rCpy.pTblNd ), |
| pUndo( rCpy.pUndo ), |
| nDiff( rCpy.nDiff ), nSide( rCpy.nSide ), |
| nMaxSize( rCpy.nMaxSize ), nLowerDiff( 0 ), |
| nMode( rCpy.nMode ), nTblWidth( rCpy.nTblWidth ), |
| nRemainWidth( rCpy.nRemainWidth ), nBoxWidth( rCpy.nBoxWidth ), |
| bBigger( rCpy.bBigger ), bLeft( rCpy.bLeft ), |
| bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd ) |
| { |
| aLines.Insert( &rCpy.aLines ); |
| aLinesWidth.Insert( &rCpy.aLinesWidth, 0 ); |
| } |
| |
| SwUndoTblNdsChg* CreateUndo( SwUndoId eUndoType ) |
| { |
| return pUndo = new SwUndoTblNdsChg( eUndoType, aBoxes, *pTblNd ); |
| } |
| |
| void LoopClear() |
| { |
| nLowerDiff = 0; nRemainWidth = 0; |
| } |
| |
| void AddBoxWidth( const SwTableBox& rBox, sal_uInt16 nWidth ) |
| { |
| SwTableLinePtr p = (SwTableLine*)rBox.GetUpper(); |
| sal_uInt16 nFndPos; |
| if( aLines.Insert( p, nFndPos )) |
| aLinesWidth.Insert( nWidth, nFndPos ); |
| else |
| aLinesWidth[ nFndPos ] = aLinesWidth[ nFndPos ] + nWidth; |
| } |
| |
| sal_uInt16 GetBoxWidth( const SwTableLine& rLn ) const |
| { |
| SwTableLinePtr p = (SwTableLine*)&rLn; |
| sal_uInt16 nFndPos; |
| if( aLines.Seek_Entry( p, &nFndPos ) ) |
| nFndPos = aLinesWidth[ nFndPos ]; |
| else |
| nFndPos = 0; |
| return nFndPos; |
| } |
| }; |
| |
| sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| sal_Bool lcl_DelSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| sal_Bool lcl_DelOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| |
| typedef sal_Bool (*FN_lcl_SetBoxWidth)(SwTableLine*, CR_SetBoxWidth&, SwTwips, sal_Bool ); |
| |
| #if defined(DBG_UTIL) || defined( JP_DEBUG ) |
| |
| void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize ); |
| |
| #define CHECKBOXWIDTH \ |
| { \ |
| SwTwips nSize = GetFrmFmt()->GetFrmSize().GetWidth(); \ |
| for( sal_uInt16 nTmp = 0; nTmp < aLines.Count(); ++nTmp ) \ |
| ::_CheckBoxWidth( *aLines[ nTmp ], nSize ); \ |
| } |
| |
| #define CHECKTABLELAYOUT \ |
| { \ |
| for ( sal_uInt16 i = 0; i < GetTabLines().Count(); ++i ) \ |
| { \ |
| SwFrmFmt* pFmt = GetTabLines()[i]->GetFrmFmt(); \ |
| SwIterator<SwRowFrm,SwFmt> aIter( *pFmt ); \ |
| for (SwRowFrm* pFrm=aIter.First(); pFrm; pFrm=aIter.Next())\ |
| { \ |
| if ( pFrm->GetTabLine() == GetTabLines()[i] ) \ |
| { \ |
| ASSERT( pFrm->GetUpper()->IsTabFrm(), \ |
| "Table layout does not match table structure" ) \ |
| } \ |
| } \ |
| } \ |
| } |
| |
| #else |
| |
| #define CHECKBOXWIDTH |
| #define CHECKTABLELAYOUT |
| |
| #endif |
| |
| |
| struct CR_SetLineHeight |
| { |
| SwSelBoxes aBoxes; |
| SwShareBoxFmts aShareFmts; |
| SwTableNode* pTblNd; |
| SwUndoTblNdsChg* pUndo; |
| SwTwips nMaxSpace, nMaxHeight; |
| TblChgMode nMode; |
| sal_uInt16 nLines; |
| sal_Bool bBigger, bTop, bSplittBox, bAnyBoxFnd; |
| |
| CR_SetLineHeight( sal_uInt16 eType, SwTableNode* pTNd ) |
| : pTblNd( pTNd ), pUndo( 0 ), |
| nMaxSpace( 0 ), nMaxHeight( 0 ), nLines( 0 ), |
| bSplittBox( sal_False ), bAnyBoxFnd( sal_False ) |
| { |
| bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ); |
| bBigger = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_BIGGER ); |
| if( eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL ) |
| bBigger = !bBigger; |
| nMode = pTblNd->GetTable().GetTblChgMode(); |
| } |
| CR_SetLineHeight( const CR_SetLineHeight& rCpy ) |
| : pTblNd( rCpy.pTblNd ), pUndo( rCpy.pUndo ), |
| nMaxSpace( rCpy.nMaxSpace ), nMaxHeight( rCpy.nMaxHeight ), |
| nMode( rCpy.nMode ), nLines( rCpy.nLines ), |
| bBigger( rCpy.bBigger ), bTop( rCpy.bTop ), |
| bSplittBox( rCpy.bSplittBox ), bAnyBoxFnd( rCpy.bAnyBoxFnd ) |
| {} |
| |
| SwUndoTblNdsChg* CreateUndo( SwUndoId nUndoType ) |
| { |
| return pUndo = new SwUndoTblNdsChg( nUndoType, aBoxes, *pTblNd ); |
| } |
| }; |
| |
| sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam, |
| SwTwips nDist, sal_Bool bCheck ); |
| |
| typedef sal_Bool (*FN_lcl_SetLineHeight)(SwTableLine*, CR_SetLineHeight&, SwTwips, sal_Bool ); |
| |
| _CpyTabFrm& _CpyTabFrm::operator=( const _CpyTabFrm& rCpyTabFrm ) |
| { |
| pNewFrmFmt = rCpyTabFrm.pNewFrmFmt; |
| Value = rCpyTabFrm.Value; |
| return *this; |
| } |
| |
| SV_DECL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm, 0, 50 ) |
| SV_IMPL_VARARR_SORT( _CpyTabFrms, _CpyTabFrm ) |
| |
| void lcl_DelCpyTabFrmFmts( _CpyTabFrm& rArr ); |
| |
| // --------------------------------------------------------------- |
| |
| struct _CpyPara |
| { |
| boost::shared_ptr< std::vector< std::vector< sal_uLong > > > pWidths; |
| SwDoc* pDoc; |
| SwTableNode* pTblNd; |
| _CpyTabFrms& rTabFrmArr; |
| SwTableLine* pInsLine; |
| SwTableBox* pInsBox; |
| sal_uLong nOldSize, nNewSize; // zum Korrigieren der Size-Attribute |
| sal_uLong nMinLeft, nMaxRight; |
| sal_uInt16 nCpyCnt, nInsPos; |
| sal_uInt16 nLnIdx, nBoxIdx; |
| sal_uInt8 nDelBorderFlag; |
| sal_Bool bCpyCntnt; |
| |
| _CpyPara( SwTableNode* pNd, sal_uInt16 nCopies, _CpyTabFrms& rFrmArr, |
| sal_Bool bCopyContent = sal_True ) |
| : pDoc( pNd->GetDoc() ), pTblNd( pNd ), rTabFrmArr(rFrmArr), |
| pInsLine(0), pInsBox(0), nOldSize(0), nNewSize(0), |
| nMinLeft(ULONG_MAX), nMaxRight(0), |
| nCpyCnt(nCopies), nInsPos(0), |
| nLnIdx(0), nBoxIdx(0), |
| nDelBorderFlag(0), bCpyCntnt( bCopyContent ) |
| {} |
| _CpyPara( const _CpyPara& rPara, SwTableLine* pLine ) |
| : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd), |
| rTabFrmArr(rPara.rTabFrmArr), pInsLine(pLine), pInsBox(rPara.pInsBox), |
| nOldSize(0), nNewSize(rPara.nNewSize), nMinLeft( rPara.nMinLeft ), |
| nMaxRight( rPara.nMaxRight ), nCpyCnt(rPara.nCpyCnt), nInsPos(0), |
| nLnIdx( rPara.nLnIdx), nBoxIdx( rPara.nBoxIdx ), |
| nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt ) |
| {} |
| _CpyPara( const _CpyPara& rPara, SwTableBox* pBox ) |
| : pWidths( rPara.pWidths ), pDoc(rPara.pDoc), pTblNd(rPara.pTblNd), |
| rTabFrmArr(rPara.rTabFrmArr), pInsLine(rPara.pInsLine), pInsBox(pBox), |
| nOldSize(rPara.nOldSize), nNewSize(rPara.nNewSize), |
| nMinLeft( rPara.nMinLeft ), nMaxRight( rPara.nMaxRight ), |
| nCpyCnt(rPara.nCpyCnt), nInsPos(0), nLnIdx(rPara.nLnIdx), nBoxIdx(rPara.nBoxIdx), |
| nDelBorderFlag( rPara.nDelBorderFlag ), bCpyCntnt( rPara.bCpyCntnt ) |
| {} |
| void SetBoxWidth( SwTableBox* pBox ); |
| }; |
| |
| |
| sal_Bool lcl_CopyCol( const _FndBox*& rpFndBox, void* pPara ) |
| { |
| _CpyPara* pCpyPara = (_CpyPara*)pPara; |
| |
| // suche das FrmFmt im Array aller Frame-Formate |
| SwTableBox* pBox = (SwTableBox*)rpFndBox->GetBox(); |
| _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pBox->GetFrmFmt() ); |
| |
| sal_uInt16 nFndPos; |
| if( pCpyPara->nCpyCnt ) |
| { |
| if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos )) |
| { |
| // fuer das verschachtelte Kopieren sicher auch das neue Format |
| // als alt. |
| SwTableBoxFmt* pNewFmt = (SwTableBoxFmt*)pBox->ClaimFrmFmt(); |
| |
| // suche die selektierten Boxen in der Line: |
| _FndLine* pCmpLine = NULL; |
| SwFmtFrmSize aFrmSz( pNewFmt->GetFrmSize() ); |
| |
| bool bDiffCount = false; |
| if( pBox->GetTabLines().Count() ) |
| { |
| pCmpLine = rpFndBox->GetLines()[ 0 ]; |
| if ( pCmpLine->GetBoxes().Count() != pCmpLine->GetLine()->GetTabBoxes().Count() ) |
| bDiffCount = true; |
| } |
| |
| if( bDiffCount ) |
| { |
| // die erste Line sollte reichen |
| _FndBoxes& rFndBoxes = pCmpLine->GetBoxes(); |
| long nSz = 0; |
| for( sal_uInt16 n = rFndBoxes.Count(); n; ) |
| nSz += rFndBoxes[ --n ]->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); |
| aFrmSz.SetWidth( aFrmSz.GetWidth() - |
| nSz / ( pCpyPara->nCpyCnt + 1 ) ); |
| pNewFmt->SetFmtAttr( aFrmSz ); |
| aFrmSz.SetWidth( nSz / ( pCpyPara->nCpyCnt + 1 ) ); |
| |
| // fuer die neue Box ein neues Format mit der Groesse anlegen! |
| aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pNewFmt->GetDoc()-> |
| MakeTableLineFmt(); |
| *aFindFrm.pNewFrmFmt = *pNewFmt; |
| aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz ); |
| } |
| else |
| { |
| aFrmSz.SetWidth( aFrmSz.GetWidth() / ( pCpyPara->nCpyCnt + 1 ) ); |
| pNewFmt->SetFmtAttr( aFrmSz ); |
| |
| aFindFrm.pNewFrmFmt = pNewFmt; |
| pCpyPara->rTabFrmArr.Insert( aFindFrm ); |
| aFindFrm.Value.pFrmFmt = pNewFmt; |
| pCpyPara->rTabFrmArr.Insert( aFindFrm ); |
| } |
| } |
| else |
| { |
| aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]; |
| // aFindFrm.pNewFrmFmt->Add( pBox ); |
| pBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt ); |
| } |
| } |
| else |
| { |
| if( pCpyPara->nDelBorderFlag && |
| pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos )) |
| aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]; |
| else |
| aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); |
| } |
| |
| if( rpFndBox->GetLines().Count() ) |
| { |
| pBox = new SwTableBox( aFindFrm.pNewFrmFmt, |
| rpFndBox->GetLines().Count(), pCpyPara->pInsLine ); |
| pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++); |
| _CpyPara aPara( *pCpyPara, pBox ); |
| aPara.nDelBorderFlag &= 7; |
| |
| ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyRow, &aPara ); |
| } |
| else |
| { |
| ::_InsTblBox( pCpyPara->pDoc, pCpyPara->pTblNd, pCpyPara->pInsLine, |
| aFindFrm.pNewFrmFmt, pBox, pCpyPara->nInsPos++ ); |
| |
| const _FndBoxes& rFndBxs = rpFndBox->GetUpper()->GetBoxes(); |
| if( 8 > pCpyPara->nDelBorderFlag |
| ? pCpyPara->nDelBorderFlag |
| : rpFndBox == rFndBxs[ rFndBxs.Count() - 1 ] ) |
| { |
| const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox(); |
| if( 8 > pCpyPara->nDelBorderFlag |
| ? rBoxItem.GetTop() |
| : rBoxItem.GetRight() ) |
| { |
| aFindFrm.Value.pFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); |
| |
| SvxBoxItem aNew( rBoxItem ); |
| if( 8 > pCpyPara->nDelBorderFlag ) |
| aNew.SetLine( 0, BOX_LINE_TOP ); |
| else |
| aNew.SetLine( 0, BOX_LINE_RIGHT ); |
| |
| if( 1 == pCpyPara->nDelBorderFlag || |
| 8 == pCpyPara->nDelBorderFlag ) |
| { |
| // es wird dahinter kopiert, bei allen Boxen die |
| // TopBorderLine loeschen |
| pBox = pCpyPara->pInsLine->GetTabBoxes()[ |
| pCpyPara->nInsPos - 1 ]; |
| } |
| |
| aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); |
| |
| // ansonsten wird davor kopiert und die erste Line behaelt |
| // die TopLine und an der originalen wird sie entfernt |
| pBox->ClaimFrmFmt()->SetFmtAttr( aNew ); |
| |
| if( !pCpyPara->nCpyCnt ) |
| pCpyPara->rTabFrmArr.Insert( aFindFrm ); |
| } |
| } |
| } |
| return sal_True; |
| } |
| |
| sal_Bool lcl_CopyRow( const _FndLine*& rpFndLine, void* pPara ) |
| { |
| _CpyPara* pCpyPara = (_CpyPara*)pPara; |
| SwTableLine* pNewLine = new SwTableLine( |
| (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(), |
| rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox ); |
| if( pCpyPara->pInsBox ) |
| { |
| pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ ); |
| } |
| else |
| { |
| pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine, |
| pCpyPara->nInsPos++ ); |
| } |
| |
| _CpyPara aPara( *pCpyPara, pNewLine ); |
| ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyCol, &aPara ); |
| |
| pCpyPara->nDelBorderFlag &= 0xf8; |
| return sal_True; |
| } |
| |
| //----------------------------------------------------------- |
| |
| void lcl_InsCol( _FndLine* pFndLn, _CpyPara& rCpyPara, sal_uInt16 nCpyCnt, |
| sal_Bool bBehind ) |
| { |
| // Bug 29124: nicht nur in den Grundlines kopieren. Wenns geht, so weit |
| // runter wie moeglich. |
| _FndBox* pFBox; |
| if( 1 == pFndLn->GetBoxes().Count() && |
| !( pFBox = pFndLn->GetBoxes()[ 0 ] )->GetBox()->GetSttNd() ) |
| { |
| // eine Box mit mehreren Lines, also in diese Lines einfuegen |
| for( sal_uInt16 n = 0; n < pFBox->GetLines().Count(); ++n ) |
| lcl_InsCol( pFBox->GetLines()[ n ], rCpyPara, nCpyCnt, bBehind ); |
| } |
| else |
| { |
| rCpyPara.pInsLine = pFndLn->GetLine(); |
| SwTableBox* pBox = pFndLn->GetBoxes()[ bBehind ? |
| pFndLn->GetBoxes().Count()-1 : 0 ]->GetBox(); |
| rCpyPara.nInsPos = pFndLn->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pBox ); |
| if( bBehind ) |
| ++rCpyPara.nInsPos; |
| |
| for( sal_uInt16 n = 0; n < nCpyCnt; ++n ) |
| { |
| if( n + 1 == nCpyCnt && bBehind ) |
| rCpyPara.nDelBorderFlag = 9; |
| else |
| rCpyPara.nDelBorderFlag = 8; |
| pFndLn->GetBoxes().ForEach( &lcl_CopyCol, &rCpyPara ); |
| } |
| } |
| } |
| |
| SwRowFrm* GetRowFrm( SwTableLine& rLine ) |
| { |
| SwIterator<SwRowFrm,SwFmt> aIter( *rLine.GetFrmFmt() ); |
| for( SwRowFrm* pFrm = aIter.First(); pFrm; pFrm = aIter.Next() ) |
| if( pFrm->GetTabLine() == &rLine ) |
| return pFrm; |
| return 0; |
| } |
| |
| |
| sal_Bool SwTable::InsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, sal_Bool bBehind ) |
| { |
| ASSERT( rBoxes.Count() && nCnt, "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| sal_Bool bRes = sal_True; |
| if( IsNewModel() ) |
| bRes = NewInsertCol( pDoc, rBoxes, nCnt, bBehind ); |
| else |
| { |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( rBoxes, &aFndBox ); |
| GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| //Lines fuer das Layout-Update herausuchen. |
| aFndBox.SetTableLines( *this ); |
| aFndBox.DelFrms( *this ); |
| |
| // TL_CHART2: nothing to be done since chart2 currently does not want to |
| // get notified about new rows/cols. |
| |
| _CpyTabFrms aTabFrmArr; |
| _CpyPara aCpyPara( pTblNd, nCnt, aTabFrmArr ); |
| |
| for( sal_uInt16 n = 0; n < aFndBox.GetLines().Count(); ++n ) |
| lcl_InsCol( aFndBox.GetLines()[ n ], aCpyPara, nCnt, bBehind ); |
| |
| // dann raeume die Struktur dieser Line noch mal auf, generell alle |
| GCLines(); |
| |
| //Layout updaten |
| aFndBox.MakeFrms( *this ); |
| |
| CHECKBOXWIDTH |
| CHECKTABLELAYOUT |
| bRes = sal_True; |
| } |
| |
| SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); |
| if (pPCD && nCnt) |
| pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind ); |
| pDoc->UpdateCharts( GetFrmFmt()->GetName() ); |
| |
| return bRes; |
| } |
| |
| sal_Bool SwTable::_InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, |
| sal_uInt16 nCnt, sal_Bool bBehind ) |
| { |
| ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltige Box-Liste" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( rBoxes, &aFndBox ); |
| GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| _FndBox* pFndBox = &aFndBox; |
| { |
| _FndLine* pFndLine; |
| while( 1 == pFndBox->GetLines().Count() && |
| 1 == ( pFndLine = pFndBox->GetLines()[ 0 ])->GetBoxes().Count() ) |
| { |
| // nicht zu weit runter, eine Line mit Boxen muss nachbleiben!! |
| _FndBox* pTmpBox = pFndLine->GetBoxes()[ 0 ]; |
| if( pTmpBox->GetLines().Count() ) |
| pFndBox = pTmpBox; |
| else |
| break; |
| } |
| } |
| |
| //Lines fuer das Layout-Update herausuchen. |
| const sal_Bool bLayout = !IsNewModel() && |
| 0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() ); |
| |
| if ( bLayout ) |
| { |
| aFndBox.SetTableLines( *this ); |
| if( pFndBox != &aFndBox ) |
| aFndBox.DelFrms( *this ); |
| // TL_CHART2: nothing to be done since chart2 currently does not want to |
| // get notified about new rows/cols. |
| } |
| |
| _CpyTabFrms aTabFrmArr; |
| _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr ); |
| |
| SwTableLine* pLine = pFndBox->GetLines()[ bBehind ? |
| pFndBox->GetLines().Count()-1 : 0 ]->GetLine(); |
| if( &aFndBox == pFndBox ) |
| aCpyPara.nInsPos = GetTabLines().C40_GETPOS( SwTableLine, pLine ); |
| else |
| { |
| aCpyPara.pInsBox = pFndBox->GetBox(); |
| aCpyPara.nInsPos = pFndBox->GetBox()->GetTabLines().C40_GETPOS( SwTableLine, pLine ); |
| } |
| |
| if( bBehind ) |
| { |
| ++aCpyPara.nInsPos; |
| aCpyPara.nDelBorderFlag = 1; |
| } |
| else |
| aCpyPara.nDelBorderFlag = 2; |
| |
| for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt ) |
| { |
| if( bBehind ) |
| aCpyPara.nDelBorderFlag = 1; |
| pFndBox->GetLines().ForEach( &lcl_CopyRow, &aCpyPara ); |
| } |
| |
| // dann raeume die Struktur dieser Line noch mal auf, generell alle |
| if( !pDoc->IsInReading() ) |
| GCLines(); |
| |
| //Layout updaten |
| if ( bLayout ) |
| { |
| if( pFndBox != &aFndBox ) |
| aFndBox.MakeFrms( *this ); |
| else |
| aFndBox.MakeNewFrms( *this, nCnt, bBehind ); |
| } |
| |
| CHECKBOXWIDTH |
| CHECKTABLELAYOUT |
| |
| SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); |
| if (pPCD && nCnt) |
| pPCD->AddRowCols( *this, rBoxes, nCnt, bBehind ); |
| pDoc->UpdateCharts( GetFrmFmt()->GetName() ); |
| |
| return sal_True; |
| } |
| |
| sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara ); |
| |
| sal_Bool _FndBoxAppendRowBox( const SwTableBox*& rpBox, void* pPara ) |
| { |
| _FndPara* pFndPara = (_FndPara*)pPara; |
| _FndBox* pFndBox = new _FndBox( (SwTableBox*)rpBox, pFndPara->pFndLine ); |
| if( rpBox->GetTabLines().Count() ) |
| { |
| _FndPara aPara( *pFndPara, pFndBox ); |
| pFndBox->GetBox()->GetTabLines().ForEach( &_FndBoxAppendRowLine, &aPara ); |
| if( !pFndBox->GetLines().Count() ) |
| delete pFndBox; |
| } |
| else |
| pFndPara->pFndLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, |
| pFndPara->pFndLine->GetBoxes().Count() ); |
| return sal_True; |
| } |
| |
| sal_Bool _FndBoxAppendRowLine( const SwTableLine*& rpLine, void* pPara ) |
| { |
| _FndPara* pFndPara = (_FndPara*)pPara; |
| _FndLine* pFndLine = new _FndLine( (SwTableLine*)rpLine, pFndPara->pFndBox ); |
| _FndPara aPara( *pFndPara, pFndLine ); |
| pFndLine->GetLine()->GetTabBoxes().ForEach( &_FndBoxAppendRowBox, &aPara ); |
| if( pFndLine->GetBoxes().Count() ) |
| { |
| pFndPara->pFndBox->GetLines().C40_INSERT( _FndLine, pFndLine, |
| pFndPara->pFndBox->GetLines().Count() ); |
| } |
| else |
| delete pFndLine; |
| return sal_True; |
| } |
| |
| |
| sal_Bool SwTable::AppendRow( SwDoc* pDoc, sal_uInt16 nCnt ) |
| { |
| SwTableNode* pTblNd = (SwTableNode*)aSortCntBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| const SwTableLine* pLLine = GetTabLines()[ GetTabLines().Count()-1 ]; |
| |
| const SwSelBoxes* pBxs = 0; // Dummy !!! |
| _FndPara aPara( *pBxs, &aFndBox ); |
| |
| _FndBoxAppendRowLine( pLLine, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| //Lines fuer das Layout-Update herausuchen. |
| bool bLayout = 0 != SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() ); |
| if( bLayout ) |
| { |
| aFndBox.SetTableLines( *this ); |
| // TL_CHART2: nothing to be done since chart2 currently does not want to |
| // get notified about new rows/cols. |
| } |
| |
| _CpyTabFrms aTabFrmArr; |
| _CpyPara aCpyPara( pTblNd, 0, aTabFrmArr ); |
| aCpyPara.nInsPos = GetTabLines().Count(); |
| aCpyPara.nDelBorderFlag = 1; |
| |
| for( sal_uInt16 nCpyCnt = 0; nCpyCnt < nCnt; ++nCpyCnt ) |
| { |
| aCpyPara.nDelBorderFlag = 1; |
| aFndBox.GetLines().ForEach( &lcl_CopyRow, &aCpyPara ); |
| } |
| |
| // dann raeume die Struktur dieser Line noch mal auf, generell alle |
| if( !pDoc->IsInReading() ) |
| GCLines(); |
| |
| //Layout updaten |
| if ( bLayout ) |
| { |
| aFndBox.MakeNewFrms( *this, nCnt, sal_True ); |
| } |
| // TL_CHART2: need to inform chart of probably changed cell names |
| pDoc->UpdateCharts( GetFrmFmt()->GetName() ); |
| |
| CHECKBOXWIDTH |
| CHECKTABLELAYOUT |
| |
| return sal_True; |
| } |
| |
| |
| void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset, |
| sal_Bool bFirst, SwShareBoxFmts& rShareFmts ); |
| |
| void lcl_LastBoxSetWidthLine( SwTableLines &rLines, const long nOffset, |
| sal_Bool bFirst, SwShareBoxFmts& rShareFmts ) |
| { |
| for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) |
| ::lcl_LastBoxSetWidth( rLines[i]->GetTabBoxes(), nOffset, bFirst, |
| rShareFmts ); |
| } |
| |
| void lcl_LastBoxSetWidth( SwTableBoxes &rBoxes, const long nOffset, |
| sal_Bool bFirst, SwShareBoxFmts& rShareFmts ) |
| { |
| SwTableBox& rBox = *rBoxes[ bFirst ? 0 : rBoxes.Count() - 1 ]; |
| if( !rBox.GetSttNd() ) |
| ::lcl_LastBoxSetWidthLine( rBox.GetTabLines(), nOffset, |
| bFirst, rShareFmts ); |
| |
| //Die Box anpassen |
| SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(); |
| SwFmtFrmSize aNew( pBoxFmt->GetFrmSize() ); |
| aNew.SetWidth( aNew.GetWidth() + nOffset ); |
| SwFrmFmt *pFmt = rShareFmts.GetFormat( *pBoxFmt, aNew ); |
| if( pFmt ) |
| rBox.ChgFrmFmt( (SwTableBoxFmt*)pFmt ); |
| else |
| { |
| pFmt = rBox.ClaimFrmFmt(); |
| |
| pFmt->LockModify(); |
| pFmt->SetFmtAttr( aNew ); |
| pFmt->UnlockModify(); |
| |
| rShareFmts.AddFormat( *pBoxFmt, *pFmt ); |
| } |
| } |
| |
| void _DeleteBox( SwTable& rTbl, SwTableBox* pBox, SwUndo* pUndo, |
| sal_Bool bCalcNewSize, const sal_Bool bCorrBorder, |
| SwShareBoxFmts* pShareFmts ) |
| { |
| do { |
| SwTwips nBoxSz = bCalcNewSize ? |
| pBox->GetFrmFmt()->GetFrmSize().GetWidth() : 0; |
| SwTableLine* pLine = pBox->GetUpper(); |
| SwTableBoxes& rTblBoxes = pLine->GetTabBoxes(); |
| sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pBox ); |
| SwTableBox* pUpperBox = pBox->GetUpper()->GetUpper(); |
| |
| // Sonderbehandlung fuer Umrandung: |
| if( bCorrBorder && 1 < rTblBoxes.Count() ) |
| { |
| sal_Bool bChgd = sal_False; |
| const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox(); |
| |
| if( rBoxItem.GetLeft() || rBoxItem.GetRight() ) |
| { |
| //JP 02.04.97: 1.Teil fuer Bug 36271 |
| // zuerst die linken/rechten Kanten |
| if( nDelPos + 1 < rTblBoxes.Count() ) |
| { |
| SwTableBox* pNxtBox = rTblBoxes[ nDelPos + 1 ]; |
| const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox(); |
| |
| SwTableBox* pPrvBox = nDelPos ? rTblBoxes[ nDelPos - 1 ] : 0; |
| |
| if( pNxtBox->GetSttNd() && !rNxtBoxItem.GetLeft() && |
| ( !pPrvBox || !pPrvBox->GetFrmFmt()->GetBox().GetRight()) ) |
| { |
| SvxBoxItem aTmp( rNxtBoxItem ); |
| aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft() |
| : rBoxItem.GetRight(), |
| BOX_LINE_LEFT ); |
| if( pShareFmts ) |
| pShareFmts->SetAttr( *pNxtBox, aTmp ); |
| else |
| pNxtBox->ClaimFrmFmt()->SetFmtAttr( aTmp ); |
| bChgd = sal_True; |
| } |
| } |
| if( !bChgd && nDelPos ) |
| { |
| SwTableBox* pPrvBox = rTblBoxes[ nDelPos - 1 ]; |
| const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox(); |
| |
| SwTableBox* pNxtBox = nDelPos + 1 < rTblBoxes.Count() |
| ? rTblBoxes[ nDelPos + 1 ] : 0; |
| |
| if( pPrvBox->GetSttNd() && !rPrvBoxItem.GetRight() && |
| ( !pNxtBox || !pNxtBox->GetFrmFmt()->GetBox().GetLeft()) ) |
| { |
| SvxBoxItem aTmp( rPrvBoxItem ); |
| aTmp.SetLine( rBoxItem.GetLeft() ? rBoxItem.GetLeft() |
| : rBoxItem.GetRight(), |
| BOX_LINE_RIGHT ); |
| if( pShareFmts ) |
| pShareFmts->SetAttr( *pPrvBox, aTmp ); |
| else |
| pPrvBox->ClaimFrmFmt()->SetFmtAttr( aTmp ); |
| } |
| } |
| } |
| |
| } |
| |
| // erst die Box, dann die Nodes loeschen!! |
| SwStartNode* pSttNd = (SwStartNode*)pBox->GetSttNd(); |
| if( pShareFmts ) |
| pShareFmts->RemoveFormat( *rTblBoxes[ nDelPos ]->GetFrmFmt() ); |
| rTblBoxes.DeleteAndDestroy( nDelPos ); |
| |
| if( pSttNd ) |
| { |
| // ist das UndoObject zum speichern der Section vorbereitet? |
| if( pUndo && pUndo->IsDelBox() ) |
| ((SwUndoTblNdsChg*)pUndo)->SaveSection( pSttNd ); |
| else |
| pSttNd->GetDoc()->DeleteSection( pSttNd ); |
| } |
| |
| // auch die Zeile noch loeschen ?? |
| if( rTblBoxes.Count() ) |
| { |
| // dann passe noch die Frame-SSize an |
| sal_Bool bLastBox = nDelPos == rTblBoxes.Count(); |
| if( bLastBox ) |
| --nDelPos; |
| pBox = rTblBoxes[nDelPos]; |
| if( bCalcNewSize ) |
| { |
| SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() ); |
| aNew.SetWidth( aNew.GetWidth() + nBoxSz ); |
| if( pShareFmts ) |
| pShareFmts->SetSize( *pBox, aNew ); |
| else |
| pBox->ClaimFrmFmt()->SetFmtAttr( aNew ); |
| |
| if( !pBox->GetSttNd() ) |
| { |
| // dann muss es auch rekursiv in allen Zeilen, in allen |
| // Zellen erfolgen! |
| SwShareBoxFmts aShareFmts; |
| ::lcl_LastBoxSetWidthLine( pBox->GetTabLines(), nBoxSz, |
| !bLastBox, |
| pShareFmts ? *pShareFmts |
| : aShareFmts ); |
| } |
| } |
| break; // nichts mehr loeschen |
| } |
| // loesche die Line aus Tabelle/Box |
| if( !pUpperBox ) |
| { |
| // dann loesche auch noch die Line aus der Tabelle |
| nDelPos = rTbl.GetTabLines().C40_GETPOS( SwTableLine, pLine ); |
| if( pShareFmts ) |
| pShareFmts->RemoveFormat( *rTbl.GetTabLines()[ nDelPos ]->GetFrmFmt() ); |
| rTbl.GetTabLines().DeleteAndDestroy( nDelPos ); |
| break; // mehr kann nicht geloescht werden |
| } |
| |
| // dann loesche auch noch die Line |
| pBox = pUpperBox; |
| nDelPos = pBox->GetTabLines().C40_GETPOS( SwTableLine, pLine ); |
| if( pShareFmts ) |
| pShareFmts->RemoveFormat( *pBox->GetTabLines()[ nDelPos ]->GetFrmFmt() ); |
| pBox->GetTabLines().DeleteAndDestroy( nDelPos ); |
| } while( !pBox->GetTabLines().Count() ); |
| } |
| |
| SwTableBox* lcl_FndNxtPrvDelBox( const SwTableLines& rTblLns, |
| SwTwips nBoxStt, SwTwips nBoxWidth, |
| sal_uInt16 nLinePos, sal_Bool bNxt, |
| SwSelBoxes* pAllDelBoxes, sal_uInt16* pCurPos ) |
| { |
| SwTableBox* pFndBox = 0; |
| do { |
| if( bNxt ) |
| ++nLinePos; |
| else |
| --nLinePos; |
| SwTableLine* pLine = rTblLns[ nLinePos ]; |
| SwTwips nFndBoxWidth = 0; |
| SwTwips nFndWidth = nBoxStt + nBoxWidth; |
| sal_uInt16 nBoxCnt = pLine->GetTabBoxes().Count(); |
| |
| pFndBox = pLine->GetTabBoxes()[ 0 ]; |
| for( sal_uInt16 n = 0; 0 < nFndWidth && n < nBoxCnt; ++n ) |
| { |
| pFndBox = pLine->GetTabBoxes()[ n ]; |
| nFndWidth -= (nFndBoxWidth = pFndBox->GetFrmFmt()-> |
| GetFrmSize().GetWidth()); |
| } |
| |
| // suche die erste ContentBox |
| while( !pFndBox->GetSttNd() ) |
| { |
| const SwTableLines& rLowLns = pFndBox->GetTabLines(); |
| if( bNxt ) |
| pFndBox = rLowLns[ 0 ]->GetTabBoxes()[ 0 ]; |
| else |
| pFndBox = rLowLns[ rLowLns.Count() - 1 ]->GetTabBoxes()[ 0 ]; |
| } |
| |
| if( Abs( nFndWidth ) > COLFUZZY || |
| Abs( nBoxWidth - nFndBoxWidth ) > COLFUZZY ) |
| pFndBox = 0; |
| else if( pAllDelBoxes ) |
| { |
| // falls der Vorganger auch geloscht wird, ist nicht zu tun |
| sal_uInt16 nFndPos; |
| if( !pAllDelBoxes->Seek_Entry( pFndBox, &nFndPos ) ) |
| break; |
| |
| // sonst noch mal weitersuchen |
| // Die Box muessen wir aber nicht nochmal abpruefen |
| pFndBox = 0; |
| if( nFndPos <= *pCurPos ) |
| --*pCurPos; |
| pAllDelBoxes->Remove( nFndPos ); |
| } |
| } while( bNxt ? ( nLinePos + 1 < rTblLns.Count() ) : nLinePos ); |
| return pFndBox; |
| } |
| |
| void lcl_SaveUpperLowerBorder( SwTable& rTbl, const SwTableBox& rBox, |
| SwShareBoxFmts& rShareFmts, |
| SwSelBoxes* pAllDelBoxes = 0, |
| sal_uInt16* pCurPos = 0 ) |
| { |
| //JP 16.04.97: 2.Teil fuer Bug 36271 |
| sal_Bool bChgd = sal_False; |
| const SwTableLine* pLine = rBox.GetUpper(); |
| const SwTableBoxes& rTblBoxes = pLine->GetTabBoxes(); |
| const SwTableBox* pUpperBox = &rBox; |
| sal_uInt16 nDelPos = rTblBoxes.C40_GETPOS( SwTableBox, pUpperBox ); |
| pUpperBox = rBox.GetUpper()->GetUpper(); |
| const SvxBoxItem& rBoxItem = rBox.GetFrmFmt()->GetBox(); |
| |
| // dann die unteren/oberen Kanten |
| if( rBoxItem.GetTop() || rBoxItem.GetBottom() ) |
| { |
| bChgd = sal_False; |
| const SwTableLines* pTblLns; |
| if( pUpperBox ) |
| pTblLns = &pUpperBox->GetTabLines(); |
| else |
| pTblLns = &rTbl.GetTabLines(); |
| |
| sal_uInt16 nLnPos = pTblLns->GetPos( pLine ); |
| |
| // bestimme die Attr.Position der akt. zu loeschenden Box |
| // und suche dann in der unteren / oberen Line die entspr. |
| // Gegenstuecke |
| SwTwips nBoxStt = 0; |
| for( sal_uInt16 n = 0; n < nDelPos; ++n ) |
| nBoxStt += rTblBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth(); |
| SwTwips nBoxWidth = rBox.GetFrmFmt()->GetFrmSize().GetWidth(); |
| |
| SwTableBox *pPrvBox = 0, *pNxtBox = 0; |
| if( nLnPos ) // Vorgaenger? |
| pPrvBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth, |
| nLnPos, sal_False, pAllDelBoxes, pCurPos ); |
| |
| if( nLnPos + 1 < pTblLns->Count() ) // Nachfolger? |
| pNxtBox = ::lcl_FndNxtPrvDelBox( *pTblLns, nBoxStt, nBoxWidth, |
| nLnPos, sal_True, pAllDelBoxes, pCurPos ); |
| |
| if( pNxtBox && pNxtBox->GetSttNd() ) |
| { |
| const SvxBoxItem& rNxtBoxItem = pNxtBox->GetFrmFmt()->GetBox(); |
| if( !rNxtBoxItem.GetTop() && ( !pPrvBox || |
| !pPrvBox->GetFrmFmt()->GetBox().GetBottom()) ) |
| { |
| SvxBoxItem aTmp( rNxtBoxItem ); |
| aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop() |
| : rBoxItem.GetBottom(), |
| BOX_LINE_TOP ); |
| rShareFmts.SetAttr( *pNxtBox, aTmp ); |
| bChgd = sal_True; |
| } |
| } |
| if( !bChgd && pPrvBox && pPrvBox->GetSttNd() ) |
| { |
| const SvxBoxItem& rPrvBoxItem = pPrvBox->GetFrmFmt()->GetBox(); |
| if( !rPrvBoxItem.GetTop() && ( !pNxtBox || |
| !pNxtBox->GetFrmFmt()->GetBox().GetTop()) ) |
| { |
| SvxBoxItem aTmp( rPrvBoxItem ); |
| aTmp.SetLine( rBoxItem.GetTop() ? rBoxItem.GetTop() |
| : rBoxItem.GetBottom(), |
| BOX_LINE_BOTTOM ); |
| rShareFmts.SetAttr( *pPrvBox, aTmp ); |
| } |
| } |
| |
| } |
| } |
| |
| |
| sal_Bool SwTable::DeleteSel( |
| SwDoc* pDoc |
| , |
| const SwSelBoxes& rBoxes, |
| const SwSelBoxes* pMerged, SwUndo* pUndo, |
| const sal_Bool bDelMakeFrms, const sal_Bool bCorrBorder ) |
| { |
| ASSERT( pDoc, "No doc?" ); |
| SwTableNode* pTblNd = 0; |
| if( rBoxes.Count() ) |
| { |
| pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| } |
| |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| //Lines fuer das Layout-Update herausuchen. |
| _FndBox aFndBox( 0, 0 ); |
| if ( bDelMakeFrms ) |
| { |
| if( pMerged && pMerged->Count() ) |
| aFndBox.SetTableLines( *pMerged, *this ); |
| else if( rBoxes.Count() ) |
| aFndBox.SetTableLines( rBoxes, *this ); |
| aFndBox.DelFrms( *this ); |
| } |
| |
| SwShareBoxFmts aShareFmts; |
| |
| // erst die Umrandung umsetzen, dann loeschen |
| if( bCorrBorder ) |
| { |
| SwSelBoxes aBoxes; |
| aBoxes.Insert( &rBoxes ); |
| for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n ) |
| ::lcl_SaveUpperLowerBorder( *this, *rBoxes[ n ], aShareFmts, |
| &aBoxes, &n ); |
| } |
| |
| PrepareDelBoxes( rBoxes ); |
| |
| SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); |
| // |
| // delete boxes from last to first |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| sal_uInt16 nIdx = rBoxes.Count() - 1 - n; |
| |
| // first adapt the data-sequence for chart if necessary |
| // (needed to move the implementation cursor properly to it's new |
| // position which can't be done properly if the cell is already gone) |
| if (pPCD && pTblNd) |
| pPCD->DeleteBox( &pTblNd->GetTable(), *rBoxes[nIdx] ); |
| |
| // ... then delete the boxes |
| _DeleteBox( *this, rBoxes[nIdx], pUndo, sal_True, bCorrBorder, &aShareFmts ); |
| } |
| |
| // dann raeume die Struktur aller Lines auf |
| GCLines(); |
| |
| if( bDelMakeFrms && aFndBox.AreLinesToRestore( *this ) ) |
| aFndBox.MakeFrms( *this ); |
| |
| // TL_CHART2: now inform chart that sth has changed |
| pDoc->UpdateCharts( GetFrmFmt()->GetName() ); |
| |
| CHECKTABLELAYOUT |
| CHECK_TABLE( *this ) |
| |
| return sal_True; |
| } |
| |
| |
| // --------------------------------------------------------------- |
| |
| sal_Bool SwTable::OldSplitRow( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt, |
| sal_Bool bSameHeight ) |
| { |
| ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| // TL_CHART2: splitting/merging of a number of cells or rows will usually make |
| // the table to complex to be handled with chart. |
| // Thus we tell the charts to use their own data provider and forget about this table |
| pDoc->CreateChartInternalDataProviders( this ); |
| |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| // If the rows should get the same (min) height, we first have |
| // to store the old row heights before deleting the frames |
| long* pRowHeights = 0; |
| if ( bSameHeight ) |
| { |
| pRowHeights = new long[ rBoxes.Count() ]; |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox* pSelBox = *( rBoxes.GetData() + n ); |
| const SwRowFrm* pRow = GetRowFrm( *pSelBox->GetUpper() ); |
| ASSERT( pRow, "wo ist der Frm von der SwTableLine?" ) |
| SWRECTFN( pRow ) |
| pRowHeights[ n ] = (pRow->Frm().*fnRect->fnGetHeight)(); |
| } |
| } |
| |
| //Lines fuer das Layout-Update herausuchen. |
| _FndBox aFndBox( 0, 0 ); |
| aFndBox.SetTableLines( rBoxes, *this ); |
| aFndBox.DelFrms( *this ); |
| |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox* pSelBox = *( rBoxes.GetData() + n ); |
| ASSERT( pSelBox, "Box steht nicht in der Tabelle" ); |
| |
| // dann fuege in die Box nCnt neue Zeilen ein |
| SwTableLine* pInsLine = pSelBox->GetUpper(); |
| SwTableBoxFmt* pFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt(); |
| |
| // Hoehe der Line beachten, gegebenenfalls neu setzen |
| SwFmtFrmSize aFSz( pInsLine->GetFrmFmt()->GetFrmSize() ); |
| if ( bSameHeight && ATT_VAR_SIZE == aFSz.GetHeightSizeType() ) |
| aFSz.SetHeightSizeType( ATT_MIN_SIZE ); |
| |
| sal_Bool bChgLineSz = 0 != aFSz.GetHeight() || bSameHeight; |
| if ( bChgLineSz ) |
| aFSz.SetHeight( ( bSameHeight ? pRowHeights[ n ] : aFSz.GetHeight() ) / |
| (nCnt + 1) ); |
| |
| SwTableBox* pNewBox = new SwTableBox( pFrmFmt, nCnt, pInsLine ); |
| sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox ); |
| pInsLine->GetTabBoxes().Remove( nBoxPos ); // alte loeschen |
| pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox, nBoxPos ); |
| |
| // Hintergrund- / Rand Attribut loeschen |
| SwTableBox* pLastBox = pSelBox; // zum verteilen der TextNodes !! |
| // sollte Bereiche in der Box stehen, dann bleibt sie so bestehen |
| // !! FALLS DAS GEAENDERT WIRD MUSS DAS UNDO ANGEPASST WERDEN !!! |
| sal_Bool bMoveNodes = sal_True; |
| { |
| sal_uLong nSttNd = pLastBox->GetSttIdx() + 1, |
| nEndNd = pLastBox->GetSttNd()->EndOfSectionIndex(); |
| while( nSttNd < nEndNd ) |
| if( !pDoc->GetNodes()[ nSttNd++ ]->IsTxtNode() ) |
| { |
| bMoveNodes = sal_False; |
| break; |
| } |
| } |
| |
| SwTableBoxFmt* pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->GetFrmFmt(); |
| sal_Bool bChkBorder = 0 != pCpyBoxFrmFmt->GetBox().GetTop(); |
| if( bChkBorder ) |
| pCpyBoxFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt(); |
| |
| for( sal_uInt16 i = 0; i <= nCnt; ++i ) |
| { |
| // also erstmal eine neue Linie in der neuen Box |
| SwTableLine* pNewLine = new SwTableLine( |
| (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pNewBox ); |
| if( bChgLineSz ) |
| { |
| pNewLine->ClaimFrmFmt()->SetFmtAttr( aFSz ); |
| } |
| |
| pNewBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, i ); |
| // dann eine neue Box in der Line |
| if( !i ) // haenge die originale Box ein |
| { |
| pSelBox->SetUpper( pNewLine ); |
| pNewLine->GetTabBoxes().C40_INSERT( SwTableBox, pSelBox, 0 ); |
| } |
| else |
| { |
| ::_InsTblBox( pDoc, pTblNd, pNewLine, pCpyBoxFrmFmt, |
| pLastBox, 0 ); |
| |
| if( bChkBorder ) |
| { |
| pCpyBoxFrmFmt = (SwTableBoxFmt*)pNewLine->GetTabBoxes()[ 0 ]->ClaimFrmFmt(); |
| SvxBoxItem aTmp( pCpyBoxFrmFmt->GetBox() ); |
| aTmp.SetLine( 0, BOX_LINE_TOP ); |
| pCpyBoxFrmFmt->SetFmtAttr( aTmp ); |
| bChkBorder = sal_False; |
| } |
| |
| if( bMoveNodes ) |
| { |
| const SwNode* pEndNd = pLastBox->GetSttNd()->EndOfSectionNode(); |
| if( pLastBox->GetSttIdx()+2 != pEndNd->GetIndex() ) |
| { |
| // TextNodes verschieben |
| SwNodeRange aRg( *pLastBox->GetSttNd(), +2, *pEndNd ); |
| pLastBox = pNewLine->GetTabBoxes()[0]; // neu setzen |
| SwNodeIndex aInsPos( *pLastBox->GetSttNd(), 1 ); |
| pDoc->GetNodes()._MoveNodes(aRg, pDoc->GetNodes(), aInsPos, sal_False); |
| pDoc->GetNodes().Delete( aInsPos, 1 ); // den leeren noch loeschen |
| } |
| } |
| } |
| } |
| // in Boxen mit Lines darf es nur noch Size/Fillorder geben |
| pFrmFmt = (SwTableBoxFmt*)pNewBox->ClaimFrmFmt(); |
| pFrmFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 ); |
| pFrmFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 ); |
| } |
| |
| delete[] pRowHeights; |
| |
| GCLines(); |
| |
| aFndBox.MakeFrms( *this ); |
| |
| CHECKBOXWIDTH |
| CHECKTABLELAYOUT |
| return sal_True; |
| } |
| |
| sal_Bool SwTable::SplitCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCnt ) |
| { |
| ASSERT( pDoc && rBoxes.Count() && nCnt, "keine gueltigen Werte" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| // TL_CHART2: splitting/merging of a number of cells or rows will usually make |
| // the table to complex to be handled with chart. |
| // Thus we tell the charts to use their own data provider and forget about this table |
| pDoc->CreateChartInternalDataProviders( this ); |
| |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| SwSelBoxes aSelBoxes; |
| aSelBoxes.Insert(rBoxes.GetData(), rBoxes.Count()); |
| ExpandSelection( aSelBoxes ); |
| |
| //Lines fuer das Layout-Update herausuchen. |
| _FndBox aFndBox( 0, 0 ); |
| aFndBox.SetTableLines( aSelBoxes, *this ); |
| aFndBox.DelFrms( *this ); |
| |
| _CpyTabFrms aFrmArr; |
| SvPtrarr aLastBoxArr; |
| sal_uInt16 nFndPos; |
| for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n ) |
| { |
| SwTableBox* pSelBox = *( aSelBoxes.GetData() + n ); |
| ASSERT( pSelBox, "Box steht nicht in der Tabelle" ); |
| |
| // We don't want to split small table cells into very very small cells |
| if( pSelBox->GetFrmFmt()->GetFrmSize().GetWidth()/( nCnt + 1 ) < 10 ) |
| continue; |
| |
| // dann teile die Box nCnt in nCnt Boxen |
| SwTableLine* pInsLine = pSelBox->GetUpper(); |
| sal_uInt16 nBoxPos = pInsLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSelBox ); |
| |
| // suche das FrmFmt im Array aller Frame-Formate |
| SwTableBoxFmt* pLastBoxFmt; |
| _CpyTabFrm aFindFrm( (SwTableBoxFmt*)pSelBox->GetFrmFmt() ); |
| if( !aFrmArr.Seek_Entry( aFindFrm, &nFndPos )) |
| { |
| // aender das FrmFmt |
| aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pSelBox->ClaimFrmFmt(); |
| SwTwips nBoxSz = aFindFrm.pNewFrmFmt->GetFrmSize().GetWidth(); |
| SwTwips nNewBoxSz = nBoxSz / ( nCnt + 1 ); |
| aFindFrm.pNewFrmFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, |
| nNewBoxSz, 0 ) ); |
| aFrmArr.Insert( aFindFrm ); |
| |
| pLastBoxFmt = aFindFrm.pNewFrmFmt; |
| if( nBoxSz != ( nNewBoxSz * (nCnt + 1))) |
| { |
| // es bleibt ein Rest, also muss fuer die letzte Box ein |
| // eigenes Format definiert werden |
| pLastBoxFmt = new SwTableBoxFmt( *aFindFrm.pNewFrmFmt ); |
| pLastBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, |
| nBoxSz - ( nNewBoxSz * nCnt ), 0 ) ); |
| } |
| void* p = pLastBoxFmt; |
| aLastBoxArr.Insert( p, nFndPos ); |
| } |
| else |
| { |
| aFindFrm = aFrmArr[ nFndPos ]; |
| pSelBox->ChgFrmFmt( (SwTableBoxFmt*)aFindFrm.pNewFrmFmt ); |
| pLastBoxFmt = (SwTableBoxFmt*)aLastBoxArr[ nFndPos ]; |
| } |
| |
| // dann fuege mal an der Position die neuen Boxen ein |
| for( sal_uInt16 i = 1; i < nCnt; ++i ) |
| ::_InsTblBox( pDoc, pTblNd, pInsLine, aFindFrm.pNewFrmFmt, |
| pSelBox, nBoxPos + i ); // dahinter einfuegen |
| |
| ::_InsTblBox( pDoc, pTblNd, pInsLine, pLastBoxFmt, |
| pSelBox, nBoxPos + nCnt ); // dahinter einfuegen |
| |
| // Sonderbehandlung fuer die Umrandung: |
| const SvxBoxItem& aSelBoxItem = aFindFrm.pNewFrmFmt->GetBox(); |
| if( aSelBoxItem.GetRight() ) |
| { |
| pInsLine->GetTabBoxes()[ nBoxPos + nCnt ]->ClaimFrmFmt(); |
| |
| SvxBoxItem aTmp( aSelBoxItem ); |
| aTmp.SetLine( 0, BOX_LINE_RIGHT ); |
| aFindFrm.pNewFrmFmt->SetFmtAttr( aTmp ); |
| |
| // und dann das Format aus dem "cache" entfernen |
| for( sal_uInt16 i = aFrmArr.Count(); i; ) |
| { |
| const _CpyTabFrm& rCTF = aFrmArr[ --i ]; |
| if( rCTF.pNewFrmFmt == aFindFrm.pNewFrmFmt || |
| rCTF.Value.pFrmFmt == aFindFrm.pNewFrmFmt ) |
| { |
| aFrmArr.Remove( i ); |
| aLastBoxArr.Remove( i ); |
| } |
| } |
| } |
| } |
| |
| //Layout updaten |
| aFndBox.MakeFrms( *this ); |
| |
| CHECKBOXWIDTH |
| CHECKTABLELAYOUT |
| return sal_True; |
| } |
| |
| // --------------------------------------------------------------- |
| |
| /* |
| ----------------------- >> MERGE << ------------------------ |
| Algorithmus: |
| ist in der _FndBox nur eine Line angegeben, nehme die Line |
| und teste die Anzahl der Boxen |
| - ist mehr als 1 Box angegeben, so wird auf Boxenebene zusammen- |
| gefasst, d.H. die neue Box wird so Breit wie die alten. |
| - Alle Lines die ueber/unter dem Bereich liegen werden in die |
| Box als Line + Box mit Lines eingefuegt |
| - Alle Lines die vor/hinter dem Bereich liegen werden in |
| die Boxen Left/Right eingetragen |
| |
| ----------------------- >> MERGE << ------------------------ |
| */ |
| |
| void lcl_CpyLines( sal_uInt16 nStt, sal_uInt16 nEnd, |
| SwTableLines& rLines, |
| SwTableBox* pInsBox, |
| sal_uInt16 nPos = USHRT_MAX ) |
| { |
| for( sal_uInt16 n = nStt; n < nEnd; ++n ) |
| rLines[n]->SetUpper( pInsBox ); |
| if( USHRT_MAX == nPos ) |
| nPos = pInsBox->GetTabLines().Count(); |
| pInsBox->GetTabLines().Insert( &rLines, nPos, nStt, nEnd ); |
| rLines.Remove( nStt, nEnd - nStt ); |
| } |
| |
| void lcl_CpyBoxes( sal_uInt16 nStt, sal_uInt16 nEnd, |
| SwTableBoxes& rBoxes, |
| SwTableLine* pInsLine, |
| sal_uInt16 nPos = USHRT_MAX ) |
| { |
| for( sal_uInt16 n = nStt; n < nEnd; ++n ) |
| rBoxes[n]->SetUpper( pInsLine ); |
| if( USHRT_MAX == nPos ) |
| nPos = pInsLine->GetTabBoxes().Count(); |
| pInsLine->GetTabBoxes().Insert( &rBoxes, nPos, nStt, nEnd ); |
| rBoxes.Remove( nStt, nEnd - nStt ); |
| } |
| |
| void lcl_CalcWidth( SwTableBox* pBox ) |
| { |
| // Annahme: jede Line in der Box ist gleich gross |
| SwFrmFmt* pFmt = pBox->ClaimFrmFmt(); |
| ASSERT( pBox->GetTabLines().Count(), "Box hat keine Lines" ); |
| |
| SwTableLine* pLine = pBox->GetTabLines()[0]; |
| ASSERT( pLine, "Box steht in keiner Line" ); |
| |
| long nWidth = 0; |
| for( sal_uInt16 n = 0; n < pLine->GetTabBoxes().Count(); ++n ) |
| nWidth += pLine->GetTabBoxes()[n]->GetFrmFmt()->GetFrmSize().GetWidth(); |
| |
| pFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nWidth, 0 )); |
| |
| // in Boxen mit Lines darf es nur noch Size/Fillorder geben |
| pFmt->ResetFmtAttr( RES_LR_SPACE, RES_FRMATR_END - 1 ); |
| pFmt->ResetFmtAttr( RES_BOXATR_BEGIN, RES_BOXATR_END - 1 ); |
| } |
| |
| |
| |
| struct _InsULPara |
| { |
| SwTableNode* pTblNd; |
| SwTableLine* pInsLine; |
| SwTableBox* pInsBox; |
| sal_Bool bUL_LR : 1; // Upper-Lower(sal_True) oder Left-Right(sal_False) ? |
| sal_Bool bUL : 1; // Upper-Left(sal_True) oder Lower-Right(sal_False) ? |
| |
| SwTableBox* pLeftBox; |
| SwTableBox* pRightBox; |
| SwTableBox* pMergeBox; |
| |
| _InsULPara( SwTableNode* pTNd, sal_Bool bUpperLower, sal_Bool bUpper, |
| SwTableBox* pLeft, SwTableBox* pMerge, SwTableBox* pRight, |
| SwTableLine* pLine=0, SwTableBox* pBox=0 ) |
| : pTblNd( pTNd ), pInsLine( pLine ), pInsBox( pBox ), |
| pLeftBox( pLeft ), pRightBox( pRight ), pMergeBox( pMerge ) |
| { bUL_LR = bUpperLower; bUL = bUpper; } |
| |
| void SetLeft( SwTableBox* pBox=0 ) |
| { bUL_LR = sal_False; bUL = sal_True; if( pBox ) pInsBox = pBox; } |
| void SetRight( SwTableBox* pBox=0 ) |
| { bUL_LR = sal_False; bUL = sal_False; if( pBox ) pInsBox = pBox; } |
| void SetUpper( SwTableLine* pLine=0 ) |
| { bUL_LR = sal_True; bUL = sal_True; if( pLine ) pInsLine = pLine; } |
| void SetLower( SwTableLine* pLine=0 ) |
| { bUL_LR = sal_True; bUL = sal_False; if( pLine ) pInsLine = pLine; } |
| }; |
| |
| |
| sal_Bool lcl_Merge_MoveBox( const _FndBox*& rpFndBox, void* pPara ) |
| { |
| _InsULPara* pULPara = (_InsULPara*)pPara; |
| SwTableBoxes* pBoxes; |
| |
| sal_uInt16 nStt = 0, nEnd = rpFndBox->GetLines().Count(); |
| sal_uInt16 nInsPos = USHRT_MAX; |
| if( !pULPara->bUL_LR ) // Left/Right |
| { |
| sal_uInt16 nPos; |
| SwTableBox* pFndBox = (SwTableBox*)rpFndBox->GetBox(); |
| pBoxes = &pFndBox->GetUpper()->GetTabBoxes(); |
| if( pULPara->bUL ) // Left ? |
| { |
| // gibt es noch davor Boxen, dann move sie |
| if( 0 != ( nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) ) |
| lcl_CpyBoxes( 0, nPos, *pBoxes, pULPara->pInsLine ); |
| } |
| else // Right |
| // gibt es noch dahinter Boxen, dann move sie |
| if( (nPos = pBoxes->C40_GETPOS( SwTableBox, pFndBox )) +1 < pBoxes->Count() ) |
| { |
| nInsPos = pULPara->pInsLine->GetTabBoxes().Count(); |
| lcl_CpyBoxes( nPos+1, pBoxes->Count(), |
| *pBoxes, pULPara->pInsLine ); |
| } |
| } |
| // Upper/Lower und gehts noch tiefer ?? |
| else if( rpFndBox->GetLines().Count() ) |
| { |
| // suche nur die Line, ab der Verschoben werden muss |
| nStt = pULPara->bUL ? 0 : rpFndBox->GetLines().Count()-1; |
| nEnd = nStt+1; |
| } |
| |
| pBoxes = &pULPara->pInsLine->GetTabBoxes(); |
| |
| // geht es noch eine weitere Stufe runter? |
| if( rpFndBox->GetBox()->GetTabLines().Count() ) |
| { |
| SwTableBox* pBox = new SwTableBox( |
| (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt(), 0, pULPara->pInsLine ); |
| _InsULPara aPara( *pULPara ); |
| aPara.pInsBox = pBox; |
| ((_FndBox*)rpFndBox)->GetLines().ForEach( nStt, nEnd, |
| &lcl_Merge_MoveLine, &aPara ); |
| if( pBox->GetTabLines().Count() ) |
| { |
| if( USHRT_MAX == nInsPos ) |
| nInsPos = pBoxes->Count(); |
| pBoxes->C40_INSERT( SwTableBox, pBox, nInsPos ); |
| lcl_CalcWidth( pBox ); // bereche die Breite der Box |
| } |
| else |
| delete pBox; |
| } |
| return sal_True; |
| } |
| |
| sal_Bool lcl_Merge_MoveLine( const _FndLine*& rpFndLine, void* pPara ) |
| { |
| _InsULPara* pULPara = (_InsULPara*)pPara; |
| SwTableLines* pLines; |
| |
| sal_uInt16 nStt = 0, nEnd = rpFndLine->GetBoxes().Count(); |
| sal_uInt16 nInsPos = USHRT_MAX; |
| if( pULPara->bUL_LR ) // UpperLower ? |
| { |
| sal_uInt16 nPos; |
| SwTableLine* pFndLn = (SwTableLine*)rpFndLine->GetLine(); |
| pLines = pFndLn->GetUpper() ? |
| &pFndLn->GetUpper()->GetTabLines() : |
| &pULPara->pTblNd->GetTable().GetTabLines(); |
| |
| SwTableBox* pLBx = rpFndLine->GetBoxes()[0]->GetBox(); |
| SwTableBox* pRBx = rpFndLine->GetBoxes()[ |
| rpFndLine->GetBoxes().Count()-1]->GetBox(); |
| sal_uInt16 nLeft = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pLBx ); |
| sal_uInt16 nRight = pFndLn->GetTabBoxes().C40_GETPOS( SwTableBox, pRBx ); |
| |
| // if( ( nLeft && nRight+1 < pFndLn->GetTabBoxes().Count() ) || |
| // ( !nLeft && nRight+1 >= pFndLn->GetTabBoxes().Count() ) ) |
| if( !nLeft || nRight == pFndLn->GetTabBoxes().Count() ) |
| { |
| if( pULPara->bUL ) // Upper ? |
| { |
| // gibt es noch davor Zeilen, dann move sie |
| if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) ) |
| lcl_CpyLines( 0, nPos, *pLines, pULPara->pInsBox ); |
| } |
| else |
| // gibt es noch dahinter Zeilen, dann move sie |
| if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() ) |
| { |
| nInsPos = pULPara->pInsBox->GetTabLines().Count(); |
| lcl_CpyLines( nPos+1, pLines->Count(), *pLines, |
| pULPara->pInsBox ); |
| } |
| } |
| else if( nLeft ) |
| { |
| // es gibt links noch weitere Boxen, also setze Left- |
| // und Merge-Box in eine Box und Line, fuege davor/dahinter |
| // eine Line mit Box ein, in die die oberen/unteren Lines |
| // eingefuegt werden |
| SwTableLine* pInsLine = pULPara->pLeftBox->GetUpper(); |
| SwTableBox* pLMBox = new SwTableBox( |
| (SwTableBoxFmt*)pULPara->pLeftBox->GetFrmFmt(), 0, pInsLine ); |
| SwTableLine* pLMLn = new SwTableLine( |
| (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pLMBox ); |
| pLMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); |
| |
| pLMBox->GetTabLines().C40_INSERT( SwTableLine, pLMLn, 0 ); |
| |
| lcl_CpyBoxes( 0, 2, pInsLine->GetTabBoxes(), pLMLn ); |
| |
| pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLMBox, 0 ); |
| |
| if( pULPara->bUL ) // Upper ? |
| { |
| // gibt es noch davor Zeilen, dann move sie |
| if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) ) |
| lcl_CpyLines( 0, nPos, *pLines, pLMBox, 0 ); |
| } |
| else |
| // gibt es noch dahinter Zeilen, dann move sie |
| if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() ) |
| lcl_CpyLines( nPos+1, pLines->Count(), *pLines, |
| pLMBox ); |
| lcl_CalcWidth( pLMBox ); // bereche die Breite der Box |
| } |
| else if( nRight+1 < pFndLn->GetTabBoxes().Count() ) |
| { |
| // es gibt rechts noch weitere Boxen, also setze Right- |
| // und Merge-Box in eine Box und Line, fuege davor/dahinter |
| // eine Line mit Box ein, in die die oberen/unteren Lines |
| // eingefuegt werden |
| SwTableLine* pInsLine = pULPara->pRightBox->GetUpper(); |
| SwTableBox* pRMBox; |
| if( pULPara->pLeftBox->GetUpper() == pInsLine ) |
| { |
| pRMBox = new SwTableBox( |
| (SwTableBoxFmt*)pULPara->pRightBox->GetFrmFmt(), 0, pInsLine ); |
| SwTableLine* pRMLn = new SwTableLine( |
| (SwTableLineFmt*)pInsLine->GetFrmFmt(), 2, pRMBox ); |
| pRMLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); |
| pRMBox->GetTabLines().C40_INSERT( SwTableLine, pRMLn, 0 ); |
| |
| lcl_CpyBoxes( 1, 3, pInsLine->GetTabBoxes(), pRMLn ); |
| |
| pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 ); |
| } |
| else |
| { |
| // Left und Merge wurden schon zusammengefuegt, also move |
| // Right auch mit in die Line |
| |
| pInsLine = pULPara->pLeftBox->GetUpper(); |
| sal_uInt16 nMvPos = pULPara->pRightBox->GetUpper()->GetTabBoxes(). |
| C40_GETPOS( SwTableBox, pULPara->pRightBox ); |
| lcl_CpyBoxes( nMvPos, nMvPos+1, |
| pULPara->pRightBox->GetUpper()->GetTabBoxes(), |
| pInsLine ); |
| pRMBox = pInsLine->GetUpper(); |
| |
| // sind schon Lines vorhanden, dann muessen diese in eine |
| // neue Line und Box |
| nMvPos = pRMBox->GetTabLines().C40_GETPOS( SwTableLine, pInsLine ); |
| if( pULPara->bUL ? nMvPos |
| : nMvPos+1 < pRMBox->GetTabLines().Count() ) |
| { |
| // alle Lines zu einer neuen Line und Box zusammenfassen |
| SwTableLine* pNewLn = new SwTableLine( |
| (SwTableLineFmt*)pInsLine->GetFrmFmt(), 1, pRMBox ); |
| pNewLn->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); |
| pRMBox->GetTabLines().C40_INSERT( SwTableLine, pNewLn, |
| pULPara->bUL ? nMvPos : nMvPos+1 ); |
| pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn ); |
| pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, 0 ); |
| |
| sal_uInt16 nPos1, nPos2; |
| if( pULPara->bUL ) |
| nPos1 = 0, |
| nPos2 = nMvPos; |
| else |
| nPos1 = nMvPos+2, |
| nPos2 = pNewLn->GetUpper()->GetTabLines().Count(); |
| |
| lcl_CpyLines( nPos1, nPos2, |
| pNewLn->GetUpper()->GetTabLines(), pRMBox ); |
| lcl_CalcWidth( pRMBox ); // bereche die Breite der Box |
| |
| pRMBox = new SwTableBox( (SwTableBoxFmt*)pRMBox->GetFrmFmt(), 0, pNewLn ); |
| pNewLn->GetTabBoxes().C40_INSERT( SwTableBox, pRMBox, |
| pNewLn->GetTabBoxes().Count() ); |
| } |
| } |
| if( pULPara->bUL ) // Upper ? |
| { |
| // gibt es noch davor Zeilen, dann move sie |
| if( 0 != ( nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) ) |
| lcl_CpyLines( 0, nPos, *pLines, pRMBox, 0 ); |
| } |
| else |
| // gibt es noch dahinter Zeilen, dann move sie |
| if( (nPos = pLines->C40_GETPOS( SwTableLine, pFndLn )) +1 < pLines->Count() ) |
| lcl_CpyLines( nPos+1, pLines->Count(), *pLines, |
| pRMBox ); |
| lcl_CalcWidth( pRMBox ); // bereche die Breite der Box |
| } |
| else { |
| ASSERT( sal_False , "Was denn nun" ); |
| } |
| } |
| // Left/Right |
| else |
| { |
| // suche nur die Line, ab der Verschoben werden muss |
| nStt = pULPara->bUL ? 0 : rpFndLine->GetBoxes().Count()-1; |
| nEnd = nStt+1; |
| } |
| pLines = &pULPara->pInsBox->GetTabLines(); |
| |
| SwTableLine* pNewLine = new SwTableLine( |
| (SwTableLineFmt*)rpFndLine->GetLine()->GetFrmFmt(), 0, pULPara->pInsBox ); |
| _InsULPara aPara( *pULPara ); // kopieren |
| aPara.pInsLine = pNewLine; |
| ((_FndLine*)rpFndLine)->GetBoxes().ForEach( nStt, nEnd, |
| &lcl_Merge_MoveBox, &aPara ); |
| if( pNewLine->GetTabBoxes().Count() ) |
| { |
| if( USHRT_MAX == nInsPos ) |
| nInsPos = pLines->Count(); |
| pLines->C40_INSERT( SwTableLine, pNewLine, nInsPos ); |
| } |
| else |
| delete pNewLine; |
| |
| return sal_True; |
| } |
| |
| |
| sal_Bool SwTable::OldMerge( SwDoc* pDoc, const SwSelBoxes& rBoxes, |
| SwTableBox* pMergeBox, SwUndoTblMerge* pUndo ) |
| { |
| ASSERT( rBoxes.Count() && pMergeBox, "keine gueltigen Werte" ); |
| SwTableNode* pTblNd = (SwTableNode*)rBoxes[0]->GetSttNd()->FindTableNode(); |
| if( !pTblNd ) |
| return sal_False; |
| |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( rBoxes, &aFndBox ); |
| GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| // TL_CHART2: splitting/merging of a number of cells or rows will usually make |
| // the table to complex to be handled with chart. |
| // Thus we tell the charts to use their own data provider and forget about this table |
| pDoc->CreateChartInternalDataProviders( this ); |
| |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| if( pUndo ) |
| pUndo->SetSelBoxes( rBoxes ); |
| |
| //Lines fuer das Layout-Update herausuchen. |
| aFndBox.SetTableLines( *this ); |
| aFndBox.DelFrms( *this ); |
| |
| _FndBox* pFndBox = &aFndBox; |
| while( 1 == pFndBox->GetLines().Count() && |
| 1 == pFndBox->GetLines()[0]->GetBoxes().Count() ) |
| pFndBox = pFndBox->GetLines()[0]->GetBoxes()[0]; |
| |
| SwTableLine* pInsLine = new SwTableLine( |
| (SwTableLineFmt*)pFndBox->GetLines()[0]->GetLine()->GetFrmFmt(), 0, |
| !pFndBox->GetUpper() ? 0 : pFndBox->GetBox() ); |
| pInsLine->ClaimFrmFmt()->ResetFmtAttr( RES_FRM_SIZE ); |
| |
| // trage die neue Line ein |
| SwTableLines* pLines = pFndBox->GetUpper() ? |
| &pFndBox->GetBox()->GetTabLines() : &GetTabLines(); |
| |
| SwTableLine* pNewLine = pFndBox->GetLines()[0]->GetLine(); |
| sal_uInt16 nInsPos = pLines->C40_GETPOS( SwTableLine, pNewLine ); |
| pLines->C40_INSERT( SwTableLine, pInsLine, nInsPos ); |
| |
| SwTableBox* pLeftBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine ); |
| SwTableBox* pRightBox = new SwTableBox( (SwTableBoxFmt*)pMergeBox->GetFrmFmt(), 0, pInsLine ); |
| pMergeBox->SetUpper( pInsLine ); |
| pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pLeftBox, 0 ); |
| pLeftBox->ClaimFrmFmt(); |
| pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pMergeBox, 1 ); |
| pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pRightBox, 2 ); |
| pRightBox->ClaimFrmFmt(); |
| |
| // in diese kommen alle Lines, die ueber dem selektierten Bereich stehen |
| // Sie bilden also eine Upper/Lower Line |
| _InsULPara aPara( pTblNd, sal_True, sal_True, pLeftBox, pMergeBox, pRightBox, pInsLine ); |
| |
| // move die oben/unten ueberhaengenden Lines vom selektierten Bereich |
| pFndBox->GetLines()[0]->GetBoxes().ForEach( &lcl_Merge_MoveBox, |
| &aPara ); |
| aPara.SetLower( pInsLine ); |
| sal_uInt16 nEnd = pFndBox->GetLines().Count()-1; |
| pFndBox->GetLines()[nEnd]->GetBoxes().ForEach( &lcl_Merge_MoveBox, |
| &aPara ); |
| |
| // move die links/rechts hereinreichenden Boxen vom selektierten Bereich |
| aPara.SetLeft( pLeftBox ); |
| pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara ); |
| |
| aPara.SetRight( pRightBox ); |
| pFndBox->GetLines().ForEach( &lcl_Merge_MoveLine, &aPara ); |
| |
| if( !pLeftBox->GetTabLines().Count() ) |
| _DeleteBox( *this, pLeftBox, 0, sal_False, sal_False ); |
| else |
| { |
| lcl_CalcWidth( pLeftBox ); // bereche die Breite der Box |
| if( pUndo && pLeftBox->GetSttNd() ) |
| pUndo->AddNewBox( pLeftBox->GetSttIdx() ); |
| } |
| if( !pRightBox->GetTabLines().Count() ) |
| _DeleteBox( *this, pRightBox, 0, sal_False, sal_False ); |
| else |
| { |
| lcl_CalcWidth( pRightBox ); // bereche die Breite der Box |
| if( pUndo && pRightBox->GetSttNd() ) |
| pUndo->AddNewBox( pRightBox->GetSttIdx() ); |
| } |
| |
| DeleteSel( pDoc, rBoxes, 0, 0, sal_False, sal_False ); |
| |
| // dann raeume die Struktur dieser Line noch mal auf: |
| // generell alle Aufraeumen |
| GCLines(); |
| |
| GetTabLines()[0]->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 ); |
| |
| aFndBox.MakeFrms( *this ); |
| |
| CHECKBOXWIDTH |
| CHECKTABLELAYOUT |
| |
| return sal_True; |
| } |
| |
| // --------------------------------------------------------------- |
| |
| void lcl_CheckRowSpan( SwTable &rTbl ) |
| { |
| sal_uInt16 nLineCount = rTbl.GetTabLines().Count(); |
| sal_uInt16 nMaxSpan = nLineCount; |
| long nMinSpan = 1; |
| while( nMaxSpan ) |
| { |
| SwTableLine* pLine = rTbl.GetTabLines()[ nLineCount - nMaxSpan ]; |
| for( sal_uInt16 nBox = 0; nBox < pLine->GetTabBoxes().Count(); ++nBox ) |
| { |
| SwTableBox* pBox = pLine->GetTabBoxes()[nBox]; |
| long nRowSpan = pBox->getRowSpan(); |
| if( nRowSpan > nMaxSpan ) |
| pBox->setRowSpan( nMaxSpan ); |
| else if( nRowSpan < nMinSpan ) |
| pBox->setRowSpan( nMinSpan > 0 ? nMaxSpan : nMinSpan ); |
| } |
| --nMaxSpan; |
| nMinSpan = -nMaxSpan; |
| } |
| } |
| |
| sal_uInt16 lcl_GetBoxOffset( const _FndBox& rBox ) |
| { |
| // suche die erste Box |
| const _FndBox* pFirstBox = &rBox; |
| while( pFirstBox->GetLines().Count() ) |
| pFirstBox = pFirstBox->GetLines()[ 0 ]->GetBoxes()[ 0 ]; |
| |
| sal_uInt16 nRet = 0; |
| // dann ueber die Lines nach oben die Position bestimmen |
| const SwTableBox* pBox = pFirstBox->GetBox(); |
| do { |
| const SwTableBoxes& rBoxes = pBox->GetUpper()->GetTabBoxes(); |
| const SwTableBox* pCmp; |
| for( sal_uInt16 n = 0; pBox != ( pCmp = rBoxes[ n ] ); ++n ) |
| nRet = nRet + (sal_uInt16) pCmp->GetFrmFmt()->GetFrmSize().GetWidth(); |
| pBox = pBox->GetUpper()->GetUpper(); |
| } while( pBox ); |
| return nRet; |
| } |
| |
| sal_uInt16 lcl_GetLineWidth( const _FndLine& rLine ) |
| { |
| sal_uInt16 nRet = 0; |
| for( sal_uInt16 n = rLine.GetBoxes().Count(); n; ) |
| nRet = nRet + (sal_uInt16)rLine.GetBoxes()[ --n ]->GetBox()->GetFrmFmt() |
| ->GetFrmSize().GetWidth(); |
| return nRet; |
| } |
| |
| void lcl_CalcNewWidths( const _FndLines& rFndLines, _CpyPara& rPara ) |
| { |
| rPara.pWidths.reset(); |
| sal_uInt16 nLineCount = rFndLines.Count(); |
| if( nLineCount ) |
| { |
| rPara.pWidths = boost::shared_ptr< std::vector< std::vector< sal_uLong > > > |
| ( new std::vector< std::vector< sal_uLong > >( nLineCount )); |
| // First we collect information about the left/right borders of all |
| // selected cells |
| for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine ) |
| { |
| std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ]; |
| const _FndLine *pFndLine = rFndLines[ nLine ]; |
| if( pFndLine && pFndLine->GetBoxes().Count() ) |
| { |
| const SwTableLine *pLine = pFndLine->GetLine(); |
| if( pLine && pLine->GetTabBoxes().Count() ) |
| { |
| sal_uInt16 nBoxCount = pLine->GetTabBoxes().Count(); |
| sal_uLong nPos = 0; |
| // The first selected box... |
| const SwTableBox *pSel = pFndLine->GetBoxes()[0]->GetBox(); |
| sal_uInt16 nBox = 0; |
| // Sum up the width of all boxes before the first selected box |
| while( nBox < nBoxCount ) |
| { |
| SwTableBox* pBox = pLine->GetTabBoxes()[nBox++]; |
| if( pBox != pSel ) |
| nPos += pBox->GetFrmFmt()->GetFrmSize().GetWidth(); |
| else |
| break; |
| } |
| // nPos is now the left border of the first selceted box |
| if( rPara.nMinLeft > nPos ) |
| rPara.nMinLeft = nPos; |
| nBoxCount = pFndLine->GetBoxes().Count(); |
| rWidth = std::vector< sal_uLong >( nBoxCount+2 ); |
| rWidth[ 0 ] = nPos; |
| // Add now the widths of all selected boxes and store |
| // the positions in the vector |
| for( nBox = 0; nBox < nBoxCount; ) |
| { |
| nPos += pFndLine->GetBoxes()[nBox] |
| ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); |
| rWidth[ ++nBox ] = nPos; |
| } |
| // nPos: The right border of the last selected box |
| if( rPara.nMaxRight < nPos ) |
| rPara.nMaxRight = nPos; |
| if( nPos <= rWidth[ 0 ] ) |
| rWidth.clear(); |
| } |
| } |
| } |
| } |
| // Second step: calculate the new widths for the copied cells |
| sal_uLong nSelSize = rPara.nMaxRight - rPara.nMinLeft; |
| if( nSelSize ) |
| { |
| for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine ) |
| { |
| std::vector< sal_uLong > &rWidth = (*rPara.pWidths.get())[ nLine ]; |
| sal_uInt16 nCount = (sal_uInt16)rWidth.size(); |
| if( nCount > 2 ) |
| { |
| rWidth[ nCount - 1 ] = rPara.nMaxRight; |
| sal_uLong nLastPos = 0; |
| for( sal_uInt16 nBox = 0; nBox < nCount; ++nBox ) |
| { |
| sal_uInt64 nNextPos = rWidth[ nBox ]; |
| nNextPos -= rPara.nMinLeft; |
| nNextPos *= rPara.nNewSize; |
| nNextPos /= nSelSize; |
| rWidth[ nBox ] = (sal_uLong)(nNextPos - nLastPos); |
| nLastPos = (sal_uLong)nNextPos; |
| } |
| } |
| } |
| } |
| } |
| |
| sal_Bool lcl_CopyBoxToDoc( const _FndBox*& rpFndBox, void* pPara ) |
| { |
| _CpyPara* pCpyPara = (_CpyPara*)pPara; |
| |
| // Calculation of new size |
| sal_uLong nRealSize; |
| sal_uLong nDummy1 = 0; |
| sal_uLong nDummy2 = 0; |
| if( pCpyPara->pTblNd->GetTable().IsNewModel() ) |
| { |
| if( pCpyPara->nBoxIdx == 1 ) |
| nDummy1 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][0]; |
| nRealSize = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx++]; |
| if( pCpyPara->nBoxIdx == (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx].size()-1 ) |
| nDummy2 = (*pCpyPara->pWidths.get())[pCpyPara->nLnIdx][pCpyPara->nBoxIdx]; |
| } |
| else |
| { |
| nRealSize = pCpyPara->nNewSize; |
| nRealSize *= rpFndBox->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); |
| nRealSize /= pCpyPara->nOldSize; |
| } |
| |
| sal_uLong nSize; |
| bool bDummy = nDummy1 > 0; |
| if( bDummy ) |
| nSize = nDummy1; |
| else |
| { |
| nSize = nRealSize; |
| nRealSize = 0; |
| } |
| do |
| { |
| // suche das Frame-Format in der Liste aller Frame-Formate |
| _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndBox->GetBox()->GetFrmFmt() ); |
| |
| SwFmtFrmSize aFrmSz; |
| sal_uInt16 nFndPos; |
| if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos ) || |
| ( aFrmSz = ( aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]).pNewFrmFmt-> |
| GetFrmSize()).GetWidth() != (SwTwips)nSize ) |
| { |
| // es ist noch nicht vorhanden, also kopiere es |
| aFindFrm.pNewFrmFmt = pCpyPara->pDoc->MakeTableBoxFmt(); |
| aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndBox->GetBox()->GetFrmFmt() ); |
| if( !pCpyPara->bCpyCntnt ) |
| aFindFrm.pNewFrmFmt->ResetFmtAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE ); |
| aFrmSz.SetWidth( nSize ); |
| aFindFrm.pNewFrmFmt->SetFmtAttr( aFrmSz ); |
| pCpyPara->rTabFrmArr.Insert( aFindFrm ); |
| } |
| |
| SwTableBox* pBox; |
| if( rpFndBox->GetLines().Count() ) |
| { |
| pBox = new SwTableBox( aFindFrm.pNewFrmFmt, |
| rpFndBox->GetLines().Count(), pCpyPara->pInsLine ); |
| pCpyPara->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, pCpyPara->nInsPos++ ); |
| _CpyPara aPara( *pCpyPara, pBox ); |
| aPara.nNewSize = nSize; // hole die Groesse |
| ((_FndBox*)rpFndBox)->GetLines().ForEach( &lcl_CopyLineToDoc, &aPara ); |
| } |
| else |
| { |
| // erzeuge eine leere Box |
| pCpyPara->pDoc->GetNodes().InsBoxen( pCpyPara->pTblNd, pCpyPara->pInsLine, |
| aFindFrm.pNewFrmFmt, |
| (SwTxtFmtColl*)pCpyPara->pDoc->GetDfltTxtFmtColl(), |
| 0, pCpyPara->nInsPos ); |
| pBox = pCpyPara->pInsLine->GetTabBoxes()[ pCpyPara->nInsPos ]; |
| if( bDummy ) |
| pBox->setDummyFlag( true ); |
| else if( pCpyPara->bCpyCntnt ) |
| { |
| // dann kopiere mal den Inhalt in diese leere Box |
| pBox->setRowSpan( rpFndBox->GetBox()->getRowSpan() ); |
| |
| // der Inhalt kopiert wird, dann koennen auch Formeln&Values |
| // kopiert werden. |
| { |
| SfxItemSet aBoxAttrSet( pCpyPara->pDoc->GetAttrPool(), |
| RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); |
| aBoxAttrSet.Put( rpFndBox->GetBox()->GetFrmFmt()->GetAttrSet() ); |
| if( aBoxAttrSet.Count() ) |
| { |
| const SfxPoolItem* pItem; |
| SvNumberFormatter* pN = pCpyPara->pDoc->GetNumberFormatter( sal_False ); |
| if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet. |
| GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) ) |
| { |
| sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue(); |
| sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx ); |
| if( nNewIdx != nOldIdx ) |
| aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx )); |
| } |
| pBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet ); |
| } |
| } |
| SwDoc* pFromDoc = rpFndBox->GetBox()->GetFrmFmt()->GetDoc(); |
| SwNodeRange aCpyRg( *rpFndBox->GetBox()->GetSttNd(), 1, |
| *rpFndBox->GetBox()->GetSttNd()->EndOfSectionNode() ); |
| SwNodeIndex aInsIdx( *pBox->GetSttNd(), 1 ); |
| |
| pFromDoc->CopyWithFlyInFly( aCpyRg, 0, aInsIdx, NULL, sal_False ); |
| // den initialen TextNode loeschen |
| pCpyPara->pDoc->GetNodes().Delete( aInsIdx, 1 ); |
| } |
| ++pCpyPara->nInsPos; |
| } |
| if( nRealSize ) |
| { |
| bDummy = false; |
| nSize = nRealSize; |
| nRealSize = 0; |
| } |
| else |
| { |
| bDummy = true; |
| nSize = nDummy2; |
| nDummy2 = 0; |
| } |
| } |
| while( nSize ); |
| return sal_True; |
| } |
| |
| sal_Bool lcl_CopyLineToDoc( const _FndLine*& rpFndLine, void* pPara ) |
| { |
| _CpyPara* pCpyPara = (_CpyPara*)pPara; |
| |
| // suche das Format in der Liste aller Formate |
| _CpyTabFrm aFindFrm( (SwTableBoxFmt*)rpFndLine->GetLine()->GetFrmFmt() ); |
| sal_uInt16 nFndPos; |
| if( !pCpyPara->rTabFrmArr.Seek_Entry( aFindFrm, &nFndPos )) |
| { |
| // es ist noch nicht vorhanden, also kopiere es |
| aFindFrm.pNewFrmFmt = (SwTableBoxFmt*)pCpyPara->pDoc->MakeTableLineFmt(); |
| aFindFrm.pNewFrmFmt->CopyAttrs( *rpFndLine->GetLine()->GetFrmFmt() ); |
| pCpyPara->rTabFrmArr.Insert( aFindFrm ); |
| } |
| else |
| aFindFrm = pCpyPara->rTabFrmArr[ nFndPos ]; |
| |
| SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)aFindFrm.pNewFrmFmt, |
| rpFndLine->GetBoxes().Count(), pCpyPara->pInsBox ); |
| if( pCpyPara->pInsBox ) |
| { |
| pCpyPara->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine, pCpyPara->nInsPos++ ); |
| } |
| else |
| { |
| pCpyPara->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine, |
| pCpyPara->nInsPos++ ); |
| } |
| |
| _CpyPara aPara( *pCpyPara, pNewLine ); |
| |
| if( pCpyPara->pTblNd->GetTable().IsNewModel() ) |
| { |
| aPara.nOldSize = 0; // will not be used |
| aPara.nBoxIdx = 1; |
| } |
| else if( rpFndLine->GetBoxes().Count() == |
| rpFndLine->GetLine()->GetTabBoxes().Count() ) |
| { |
| // hole die Size vom Parent |
| const SwFrmFmt* pFmt; |
| |
| if( rpFndLine->GetLine()->GetUpper() ) |
| pFmt = rpFndLine->GetLine()->GetUpper()->GetFrmFmt(); |
| else |
| pFmt = pCpyPara->pTblNd->GetTable().GetFrmFmt(); |
| aPara.nOldSize = pFmt->GetFrmSize().GetWidth(); |
| } |
| else |
| // errechne sie |
| for( sal_uInt16 n = 0; n < rpFndLine->GetBoxes().Count(); ++n ) |
| aPara.nOldSize += rpFndLine->GetBoxes()[n] |
| ->GetBox()->GetFrmFmt()->GetFrmSize().GetWidth(); |
| |
| ((_FndLine*)rpFndLine)->GetBoxes().ForEach( &lcl_CopyBoxToDoc, &aPara ); |
| if( pCpyPara->pTblNd->GetTable().IsNewModel() ) |
| ++pCpyPara->nLnIdx; |
| return sal_True; |
| } |
| |
| sal_Bool SwTable::CopyHeadlineIntoTable( SwTableNode& rTblNd ) |
| { |
| // suche alle Boxen / Lines |
| SwSelBoxes aSelBoxes; |
| SwTableBox* pBox = GetTabSortBoxes()[ 0 ]; |
| pBox = GetTblBox( pBox->GetSttNd()->StartOfSectionNode()->GetIndex() + 1 ); |
| SelLineFromBox( pBox, aSelBoxes, sal_True ); |
| |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( aSelBoxes, &aFndBox ); |
| ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| { |
| // Tabellen-Formeln in die relative Darstellung umwandeln |
| SwTableFmlUpdate aMsgHnt( this ); |
| aMsgHnt.eFlags = TBL_RELBOXNAME; |
| GetFrmFmt()->GetDoc()->UpdateTblFlds( &aMsgHnt ); |
| } |
| |
| _CpyTabFrms aCpyFmt; |
| _CpyPara aPara( &rTblNd, 1, aCpyFmt, sal_True ); |
| aPara.nNewSize = aPara.nOldSize = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth(); |
| // dann kopiere mal |
| if( IsNewModel() ) |
| lcl_CalcNewWidths( aFndBox.GetLines(), aPara ); |
| aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara ); |
| if( rTblNd.GetTable().IsNewModel() ) |
| { // The copied line must not contain any row span attributes > 1 |
| SwTableLine* pLine = rTblNd.GetTable().GetTabLines()[0]; |
| sal_uInt16 nColCount = pLine->GetTabBoxes().Count(); |
| ASSERT( nColCount, "Empty Table Line" ) |
| for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol ) |
| { |
| SwTableBox* pTableBox = pLine->GetTabBoxes()[nCurrCol]; |
| ASSERT( pTableBox, "Missing Table Box" ); |
| pTableBox->setRowSpan( 1 ); |
| } |
| } |
| |
| return sal_True; |
| } |
| |
| sal_Bool SwTable::MakeCopy( SwDoc* pInsDoc, const SwPosition& rPos, |
| const SwSelBoxes& rSelBoxes, sal_Bool bCpyNds, |
| sal_Bool bCpyName ) const |
| { |
| // suche alle Boxen / Lines |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aPara( rSelBoxes, &aFndBox ); |
| ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara ); |
| } |
| if( !aFndBox.GetLines().Count() ) |
| return sal_False; |
| |
| // erst die Poolvorlagen fuer die Tabelle kopieren, damit die dann |
| // wirklich kopiert und damit die gueltigen Werte haben. |
| SwDoc* pSrcDoc = GetFrmFmt()->GetDoc(); |
| if( pSrcDoc != pInsDoc ) |
| { |
| pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE ) ); |
| pInsDoc->CopyTxtColl( *pSrcDoc->GetTxtCollFromPool( RES_POOLCOLL_TABLE_HDLN ) ); |
| } |
| |
| SwTable* pNewTbl = (SwTable*)pInsDoc->InsertTable( |
| SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ), |
| rPos, 1, 1, GetFrmFmt()->GetHoriOrient().GetHoriOrient(), |
| 0, 0, sal_False, IsNewModel() ); |
| if( !pNewTbl ) |
| return sal_False; |
| |
| SwNodeIndex aIdx( rPos.nNode, -1 ); |
| SwTableNode* pTblNd = aIdx.GetNode().FindTableNode(); |
| aIdx++; |
| ASSERT( pTblNd, "wo ist denn nun der TableNode?" ); |
| |
| pTblNd->GetTable().SetRowsToRepeat( GetRowsToRepeat() ); |
| |
| if( IS_TYPE( SwDDETable, this )) |
| { |
| // es wird eine DDE-Tabelle kopiert |
| // ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ? |
| SwFieldType* pFldType = pInsDoc->InsertFldType( |
| *((SwDDETable*)this)->GetDDEFldType() ); |
| ASSERT( pFldType, "unbekannter FieldType" ); |
| |
| // tauschen am Node den Tabellen-Pointer aus |
| pNewTbl = new SwDDETable( *pNewTbl, |
| (SwDDEFieldType*)pFldType ); |
| pTblNd->SetNewTable( pNewTbl, sal_False ); |
| } |
| |
| pNewTbl->GetFrmFmt()->CopyAttrs( *GetFrmFmt() ); |
| pNewTbl->SetTblChgMode( GetTblChgMode() ); |
| |
| //Vernichten der Frms die bereits angelegt wurden. |
| pTblNd->DelFrms(); |
| |
| { |
| // Tabellen-Formeln in die relative Darstellung umwandeln |
| SwTableFmlUpdate aMsgHnt( this ); |
| aMsgHnt.eFlags = TBL_RELBOXNAME; |
| pSrcDoc->UpdateTblFlds( &aMsgHnt ); |
| } |
| |
| SwTblNumFmtMerge aTNFM( *pSrcDoc, *pInsDoc ); |
| |
| // Namen auch kopieren oder neuen eindeutigen erzeugen |
| if( bCpyName ) |
| pNewTbl->GetFrmFmt()->SetName( GetFrmFmt()->GetName() ); |
| |
| _CpyTabFrms aCpyFmt; |
| _CpyPara aPara( pTblNd, 1, aCpyFmt, bCpyNds ); |
| aPara.nNewSize = aPara.nOldSize = GetFrmFmt()->GetFrmSize().GetWidth(); |
| |
| if( IsNewModel() ) |
| lcl_CalcNewWidths( aFndBox.GetLines(), aPara ); |
| // dann kopiere mal |
| aFndBox.GetLines().ForEach( &lcl_CopyLineToDoc, &aPara ); |
| |
| // dann setze oben und unten noch die "richtigen" Raender: |
| { |
| _FndLine* pFndLn = aFndBox.GetLines()[ 0 ]; |
| SwTableLine* pLn = pFndLn->GetLine(); |
| const SwTableLine* pTmp = pLn; |
| sal_uInt16 nLnPos = GetTabLines().GetPos( pTmp ); |
| if( USHRT_MAX != nLnPos && nLnPos ) |
| { |
| // es gibt eine Line davor |
| SwCollectTblLineBoxes aLnPara( sal_False, HEADLINE_BORDERCOPY ); |
| |
| pLn = GetTabLines()[ nLnPos - 1 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara ); |
| |
| if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ), |
| lcl_GetLineWidth( *pFndLn )) ) |
| { |
| aLnPara.SetValues( sal_True ); |
| pLn = pNewTbl->GetTabLines()[ 0 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara ); |
| } |
| } |
| |
| pFndLn = aFndBox.GetLines()[ aFndBox.GetLines().Count() -1 ]; |
| pLn = pFndLn->GetLine(); |
| pTmp = pLn; |
| nLnPos = GetTabLines().GetPos( pTmp ); |
| if( nLnPos < GetTabLines().Count() - 1 ) |
| { |
| // es gibt eine Line dahinter |
| SwCollectTblLineBoxes aLnPara( sal_True, HEADLINE_BORDERCOPY ); |
| |
| pLn = GetTabLines()[ nLnPos + 1 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_Box_CollectBox, &aLnPara ); |
| |
| if( aLnPara.Resize( lcl_GetBoxOffset( aFndBox ), |
| lcl_GetLineWidth( *pFndLn )) ) |
| { |
| aLnPara.SetValues( sal_False ); |
| pLn = pNewTbl->GetTabLines()[ pNewTbl->GetTabLines().Count()-1 ]; |
| pLn->GetTabBoxes().ForEach( &lcl_BoxSetSplitBoxFmts, &aLnPara ); |
| } |
| } |
| } |
| |
| // die initiale Box muss noch geloescht werden |
| _DeleteBox( *pNewTbl, pNewTbl->GetTabLines()[ |
| pNewTbl->GetTabLines().Count() - 1 ]->GetTabBoxes()[0], |
| 0, sal_False, sal_False ); |
| |
| if( pNewTbl->IsNewModel() ) |
| lcl_CheckRowSpan( *pNewTbl ); |
| // Mal kurz aufraeumen: |
| pNewTbl->GCLines(); |
| |
| pTblNd->MakeFrms( &aIdx ); // erzeuge die Frames neu |
| |
| CHECKTABLELAYOUT |
| |
| return sal_True; |
| } |
| |
| |
| |
| // --------------------------------------------------------------- |
| |
| // suche ab dieser Line nach der naechsten Box mit Inhalt |
| SwTableBox* SwTableLine::FindNextBox( const SwTable& rTbl, |
| const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const |
| { |
| const SwTableLine* pLine = this; // fuer M800 |
| SwTableBox* pBox; |
| sal_uInt16 nFndPos; |
| if( GetTabBoxes().Count() && pSrchBox && |
| USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) && |
| nFndPos + 1 != GetTabBoxes().Count() ) |
| { |
| pBox = GetTabBoxes()[ nFndPos + 1 ]; |
| while( pBox->GetTabLines().Count() ) |
| pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0]; |
| return pBox; |
| } |
| |
| if( GetUpper() ) |
| { |
| nFndPos = GetUpper()->GetTabLines().GetPos( pLine ); |
| ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" ); |
| // gibts eine weitere Line |
| if( nFndPos+1 >= GetUpper()->GetTabLines().Count() ) |
| return GetUpper()->GetUpper()->FindNextBox( rTbl, GetUpper(), bOvrTblLns ); |
| pLine = GetUpper()->GetTabLines()[nFndPos+1]; |
| } |
| else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ? |
| { |
| // suche in der Tabelle nach der naechsten Line |
| nFndPos = rTbl.GetTabLines().GetPos( pLine ); |
| if( nFndPos + 1 >= rTbl.GetTabLines().Count() ) |
| return 0; // es gibt keine weitere Box mehr |
| |
| pLine = rTbl.GetTabLines()[ nFndPos+1 ]; |
| } |
| else |
| return 0; |
| |
| if( pLine->GetTabBoxes().Count() ) |
| { |
| pBox = pLine->GetTabBoxes()[0]; |
| while( pBox->GetTabLines().Count() ) |
| pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0]; |
| return pBox; |
| } |
| return pLine->FindNextBox( rTbl, 0, bOvrTblLns ); |
| } |
| |
| // suche ab dieser Line nach der vorherigen Box |
| SwTableBox* SwTableLine::FindPreviousBox( const SwTable& rTbl, |
| const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const |
| { |
| const SwTableLine* pLine = this; // fuer M800 |
| SwTableBox* pBox; |
| sal_uInt16 nFndPos; |
| if( GetTabBoxes().Count() && pSrchBox && |
| USHRT_MAX != ( nFndPos = GetTabBoxes().GetPos( pSrchBox )) && |
| nFndPos ) |
| { |
| pBox = GetTabBoxes()[ nFndPos - 1 ]; |
| while( pBox->GetTabLines().Count() ) |
| { |
| pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1]; |
| pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1]; |
| } |
| return pBox; |
| } |
| |
| if( GetUpper() ) |
| { |
| nFndPos = GetUpper()->GetTabLines().GetPos( pLine ); |
| ASSERT( USHRT_MAX != nFndPos, "Line nicht in der Tabelle" ); |
| // gibts eine weitere Line |
| if( !nFndPos ) |
| return GetUpper()->GetUpper()->FindPreviousBox( rTbl, GetUpper(), bOvrTblLns ); |
| pLine = GetUpper()->GetTabLines()[nFndPos-1]; |
| } |
| else if( bOvrTblLns ) // ueber die "GrundLines" einer Tabelle ? |
| { |
| // suche in der Tabelle nach der naechsten Line |
| nFndPos = rTbl.GetTabLines().GetPos( pLine ); |
| if( !nFndPos ) |
| return 0; // es gibt keine weitere Box mehr |
| |
| pLine = rTbl.GetTabLines()[ nFndPos-1 ]; |
| } |
| else |
| return 0; |
| |
| if( pLine->GetTabBoxes().Count() ) |
| { |
| pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1]; |
| while( pBox->GetTabLines().Count() ) |
| { |
| pLine = pBox->GetTabLines()[pBox->GetTabLines().Count()-1]; |
| pBox = pLine->GetTabBoxes()[pLine->GetTabBoxes().Count()-1]; |
| } |
| return pBox; |
| } |
| return pLine->FindPreviousBox( rTbl, 0, bOvrTblLns ); |
| } |
| |
| // suche ab dieser Line nach der naechsten Box mit Inhalt |
| SwTableBox* SwTableBox::FindNextBox( const SwTable& rTbl, |
| const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const |
| { |
| if( !pSrchBox && !GetTabLines().Count() ) |
| return (SwTableBox*)this; |
| return GetUpper()->FindNextBox( rTbl, pSrchBox ? pSrchBox : this, |
| bOvrTblLns ); |
| |
| } |
| |
| // suche ab dieser Line nach der naechsten Box mit Inhalt |
| SwTableBox* SwTableBox::FindPreviousBox( const SwTable& rTbl, |
| const SwTableBox* pSrchBox, sal_Bool bOvrTblLns ) const |
| { |
| if( !pSrchBox && !GetTabLines().Count() ) |
| return (SwTableBox*)this; |
| return GetUpper()->FindPreviousBox( rTbl, pSrchBox ? pSrchBox : this, |
| bOvrTblLns ); |
| } |
| |
| |
| sal_Bool lcl_BoxSetHeadCondColl( const SwTableBox*& rpBox, void* ) |
| { |
| // in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen |
| const SwStartNode* pSttNd = rpBox->GetSttNd(); |
| if( pSttNd ) |
| pSttNd->CheckSectionCondColl(); |
| else |
| ((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_LineSetHeadCondColl, 0 ); |
| return sal_True; |
| } |
| |
| sal_Bool lcl_LineSetHeadCondColl( const SwTableLine*& rpLine, void* ) |
| { |
| ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_BoxSetHeadCondColl, 0 ); |
| return sal_True; |
| } |
| |
| /* */ |
| |
| SwTwips lcl_GetDistance( SwTableBox* pBox, sal_Bool bLeft ) |
| { |
| sal_Bool bFirst = sal_True; |
| SwTwips nRet = 0; |
| SwTableLine* pLine; |
| while( pBox && 0 != ( pLine = pBox->GetUpper() ) ) |
| { |
| sal_uInt16 nStt = 0, nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox ); |
| |
| if( bFirst && !bLeft ) |
| ++nPos; |
| bFirst = sal_False; |
| |
| while( nStt < nPos ) |
| nRet += pLine->GetTabBoxes()[ nStt++ ]->GetFrmFmt() |
| ->GetFrmSize().GetWidth(); |
| pBox = pLine->GetUpper(); |
| } |
| return nRet; |
| } |
| |
| sal_Bool lcl_SetSelBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox* pBox = rBoxes[ n ]; |
| SwFrmFmt* pFmt = pBox->GetFrmFmt(); |
| const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); |
| SwTwips nWidth = rSz.GetWidth(); |
| sal_Bool bGreaterBox = sal_False; |
| |
| if( bCheck ) |
| { |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| if( !::lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, |
| nDist, sal_True )) |
| return sal_False; |
| |
| // dann noch mal alle "ContentBoxen" sammeln |
| if( ( 0 != ( bGreaterBox = TBLFIX_CHGABS != rParam.nMode && ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) || |
| ( !rParam.bBigger && ( Abs( nDist + (( rParam.nMode && rParam.bLeft ) ? 0 : nWidth ) - rParam.nSide ) < COLFUZZY ) ) ) |
| { |
| rParam.bAnyBoxFnd = sal_True; |
| SwTwips nLowerDiff; |
| if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode ) |
| { |
| // die "anderen Boxen" wurden angepasst, |
| // also sich um diesen Betrag aendern |
| nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide; |
| nLowerDiff *= rParam.nDiff; |
| nLowerDiff /= rParam.nMaxSize; |
| nLowerDiff = rParam.nDiff - nLowerDiff; |
| } |
| else |
| nLowerDiff = rParam.nDiff; |
| |
| if( nWidth < nLowerDiff || nWidth - nLowerDiff < MINLAY ) |
| return sal_False; |
| } |
| } |
| else |
| { |
| SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| { |
| rParam.nLowerDiff = 0; |
| lcl_SetSelBoxWidth( pBox->GetTabLines()[ i ], rParam, nDist, sal_False ); |
| |
| if( nLowerDiff < rParam.nLowerDiff ) |
| nLowerDiff = rParam.nLowerDiff; |
| } |
| rParam.nLowerDiff = nOldLower; |
| |
| |
| if( nLowerDiff || |
| ( 0 != ( bGreaterBox = !nOldLower && TBLFIX_CHGABS != rParam.nMode && |
| ( nDist + ( rParam.bLeft ? 0 : nWidth ) ) >= rParam.nSide)) || |
| ( Abs( nDist + ( (rParam.nMode && rParam.bLeft) ? 0 : nWidth ) |
| - rParam.nSide ) < COLFUZZY )) |
| { |
| // in dieser Spalte ist der Cursor - also verkleinern / vergroessern |
| SwFmtFrmSize aNew( rSz ); |
| |
| if( !nLowerDiff ) |
| { |
| if( bGreaterBox && TBLFIX_CHGPROP == rParam.nMode ) |
| { |
| // die "anderen Boxen" wurden angepasst, |
| // also sich um diesen Betrag aendern |
| nLowerDiff = (nDist + ( rParam.bLeft ? 0 : nWidth ) ) - rParam.nSide; |
| nLowerDiff *= rParam.nDiff; |
| nLowerDiff /= rParam.nMaxSize; |
| nLowerDiff = rParam.nDiff - nLowerDiff; |
| } |
| else |
| nLowerDiff = rParam.nDiff; |
| } |
| |
| rParam.nLowerDiff += nLowerDiff; |
| |
| if( rParam.bBigger ) |
| aNew.SetWidth( nWidth + nLowerDiff ); |
| else |
| aNew.SetWidth( nWidth - nLowerDiff ); |
| rParam.aShareFmts.SetSize( *pBox, aNew ); |
| break; |
| } |
| } |
| |
| if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide ) |
| break; |
| |
| nDist += nWidth; |
| |
| // wenns groesser wird, dann wars das |
| if( ( TBLFIX_CHGABS == rParam.nMode || !rParam.bLeft ) && |
| nDist >= rParam.nSide ) |
| break; |
| } |
| return sal_True; |
| } |
| |
| sal_Bool lcl_SetOtherBoxWidth( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox* pBox = rBoxes[ n ]; |
| SwFrmFmt* pFmt = pBox->GetFrmFmt(); |
| const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); |
| SwTwips nWidth = rSz.GetWidth(); |
| |
| if( bCheck ) |
| { |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| if( !::lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], |
| rParam, nDist, sal_True )) |
| return sal_False; |
| |
| if( rParam.bBigger && ( TBLFIX_CHGABS == rParam.nMode |
| ? Abs( nDist - rParam.nSide ) < COLFUZZY |
| : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY |
| : nDist >= rParam.nSide - COLFUZZY )) ) |
| { |
| rParam.bAnyBoxFnd = sal_True; |
| SwTwips nDiff; |
| if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. |
| { |
| // relativ berechnen |
| nDiff = nWidth; |
| nDiff *= rParam.nDiff; |
| nDiff /= rParam.nMaxSize; |
| } |
| else |
| nDiff = rParam.nDiff; |
| |
| if( nWidth < nDiff || nWidth - nDiff < MINLAY ) |
| return sal_False; |
| } |
| } |
| else |
| { |
| SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| { |
| rParam.nLowerDiff = 0; |
| lcl_SetOtherBoxWidth( pBox->GetTabLines()[ i ], rParam, |
| nDist, sal_False ); |
| |
| if( nLowerDiff < rParam.nLowerDiff ) |
| nLowerDiff = rParam.nLowerDiff; |
| } |
| rParam.nLowerDiff = nOldLower; |
| |
| if( nLowerDiff || |
| ( TBLFIX_CHGABS == rParam.nMode |
| ? Abs( nDist - rParam.nSide ) < COLFUZZY |
| : ( rParam.bLeft ? nDist < rParam.nSide - COLFUZZY |
| : nDist >= rParam.nSide - COLFUZZY) |
| ) ) |
| { |
| SwFmtFrmSize aNew( rSz ); |
| |
| if( !nLowerDiff ) |
| { |
| if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. |
| { |
| // relativ berechnen |
| nLowerDiff = nWidth; |
| nLowerDiff *= rParam.nDiff; |
| nLowerDiff /= rParam.nMaxSize; |
| } |
| else |
| nLowerDiff = rParam.nDiff; |
| } |
| |
| rParam.nLowerDiff += nLowerDiff; |
| |
| if( rParam.bBigger ) |
| aNew.SetWidth( nWidth - nLowerDiff ); |
| else |
| aNew.SetWidth( nWidth + nLowerDiff ); |
| |
| rParam.aShareFmts.SetSize( *pBox, aNew ); |
| } |
| } |
| |
| nDist += nWidth; |
| if( ( TBLFIX_CHGABS == rParam.nMode || rParam.bLeft ) && |
| nDist > rParam.nSide ) |
| break; |
| } |
| return sal_True; |
| } |
| |
| /**/ |
| |
| sal_Bool lcl_InsSelBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| sal_uInt16 n, nCmp; |
| for( n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox* pBox = rBoxes[ n ]; |
| SwTableBoxFmt* pFmt = (SwTableBoxFmt*)pBox->GetFrmFmt(); |
| const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); |
| SwTwips nWidth = rSz.GetWidth(); |
| |
| if( bCheck ) |
| { |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| if( !::lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, |
| nDist, sal_True )) |
| return sal_False; |
| |
| // dann noch mal alle "ContentBoxen" sammeln |
| if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth ) |
| - rParam.nSide ) < COLFUZZY ) |
| nCmp = 1; |
| else if( nDist + ( rParam.bLeft ? 0 : nWidth/2 ) > rParam.nSide ) |
| nCmp = 2; |
| else |
| nCmp = 0; |
| |
| if( nCmp ) |
| { |
| rParam.bAnyBoxFnd = sal_True; |
| if( pFmt->GetProtect().IsCntntProtected() ) |
| return sal_False; |
| |
| if( rParam.bSplittBox && |
| nWidth - rParam.nDiff <= COLFUZZY + |
| ( 567 / 2 /* min. 0,5 cm Platz lassen*/) ) |
| return sal_False; |
| |
| if( pBox->GetSttNd() ) |
| rParam.aBoxes.Insert( pBox ); |
| |
| break; |
| } |
| } |
| else |
| { |
| SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| { |
| rParam.nLowerDiff = 0; |
| lcl_InsSelBox( pBox->GetTabLines()[ i ], rParam, nDist, sal_False ); |
| |
| if( nLowerDiff < rParam.nLowerDiff ) |
| nLowerDiff = rParam.nLowerDiff; |
| } |
| rParam.nLowerDiff = nOldLower; |
| |
| if( nLowerDiff ) |
| nCmp = 1; |
| else if( Abs( nDist + ( rParam.bLeft ? 0 : nWidth ) |
| - rParam.nSide ) < COLFUZZY ) |
| nCmp = 2; |
| else if( nDist + nWidth / 2 > rParam.nSide ) |
| nCmp = 3; |
| else |
| nCmp = 0; |
| |
| if( nCmp ) |
| { |
| // in dieser Spalte ist der Cursor - also verkleinern / vergroessern |
| if( 1 == nCmp ) |
| { |
| if( !rParam.bSplittBox ) |
| { |
| // die akt. Box auf |
| SwFmtFrmSize aNew( rSz ); |
| aNew.SetWidth( nWidth + rParam.nDiff ); |
| rParam.aShareFmts.SetSize( *pBox, aNew ); |
| } |
| } |
| else |
| { |
| ASSERT( pBox->GetSttNd(), "Das muss eine EndBox sein!"); |
| |
| if( !rParam.bLeft && 3 != nCmp ) |
| ++n; |
| |
| ::_InsTblBox( pFmt->GetDoc(), rParam.pTblNd, |
| pLine, pFmt, pBox, n ); |
| |
| SwTableBox* pNewBox = rBoxes[ n ]; |
| SwFmtFrmSize aNew( rSz ); |
| aNew.SetWidth( rParam.nDiff ); |
| rParam.aShareFmts.SetSize( *pNewBox, aNew ); |
| |
| // Sonderfall: kein Platz in den anderen Boxen |
| // aber in der Zelle |
| if( rParam.bSplittBox ) |
| { |
| // die akt. Box auf |
| SwFmtFrmSize aNewSize( rSz ); |
| aNewSize.SetWidth( nWidth - rParam.nDiff ); |
| rParam.aShareFmts.SetSize( *pBox, aNewSize ); |
| } |
| |
| // Sonderbehandlung fuer Umrandung die Rechte muss |
| // entfernt werden |
| { |
| const SvxBoxItem& rBoxItem = pBox->GetFrmFmt()->GetBox(); |
| if( rBoxItem.GetRight() ) |
| { |
| SvxBoxItem aTmp( rBoxItem ); |
| aTmp.SetLine( 0, BOX_LINE_RIGHT ); |
| rParam.aShareFmts.SetAttr( rParam.bLeft |
| ? *pNewBox |
| : *pBox, aTmp ); |
| } |
| } |
| } |
| |
| rParam.nLowerDiff = rParam.nDiff; |
| break; |
| } |
| } |
| |
| if( rParam.bLeft && rParam.nMode && nDist >= rParam.nSide ) |
| break; |
| |
| nDist += nWidth; |
| } |
| return sal_True; |
| } |
| |
| sal_Bool lcl_InsOtherBox( SwTableLine* pLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| // Sonderfall: kein Platz in den anderen Boxen aber in der Zelle |
| if( rParam.bSplittBox ) |
| return sal_True; |
| |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| sal_uInt16 n; |
| |
| // Tabelle fix, proport. |
| if( !rParam.nRemainWidth && TBLFIX_CHGPROP == rParam.nMode ) |
| { |
| // dann die richtige Breite suchen, auf die sich die relative |
| // Breitenanpassung bezieht. |
| SwTwips nTmpDist = nDist; |
| for( n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTwips nWidth = rBoxes[ n ]->GetFrmFmt()->GetFrmSize().GetWidth(); |
| if( (nTmpDist + nWidth / 2 ) > rParam.nSide ) |
| { |
| rParam.nRemainWidth = rParam.bLeft |
| ? sal_uInt16(nTmpDist) |
| : sal_uInt16(rParam.nTblWidth - nTmpDist); |
| break; |
| } |
| nTmpDist += nWidth; |
| } |
| } |
| |
| for( n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox* pBox = rBoxes[ n ]; |
| SwFrmFmt* pFmt = pBox->GetFrmFmt(); |
| const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); |
| SwTwips nWidth = rSz.GetWidth(); |
| |
| if( bCheck ) |
| { |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| if( !::lcl_InsOtherBox( pBox->GetTabLines()[ i ], |
| rParam, nDist, sal_True )) |
| return sal_False; |
| |
| if( |
| rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide && |
| (TBLFIX_CHGABS != rParam.nMode || |
| (n < rBoxes.Count() && |
| (nDist + nWidth + rBoxes[ n+1 ]-> |
| GetFrmFmt()->GetFrmSize().GetWidth() / 2) |
| > rParam.nSide) )) |
| : (nDist + nWidth / 2 ) > rParam.nSide |
| ) |
| { |
| rParam.bAnyBoxFnd = sal_True; |
| SwTwips nDiff; |
| if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. |
| { |
| // relativ berechnen |
| nDiff = nWidth; |
| nDiff *= rParam.nDiff; |
| nDiff /= rParam.nRemainWidth; |
| |
| if( nWidth < nDiff || nWidth - nDiff < MINLAY ) |
| return sal_False; |
| } |
| else |
| { |
| nDiff = rParam.nDiff; |
| |
| // teste ob die linke oder rechte Box gross genug |
| // ist, um den Platz abzugeben! |
| // es wird davor oder dahinter eine Box eingefuegt! |
| SwTwips nTmpWidth = nWidth; |
| if( rParam.bLeft && pBox->GetUpper()->GetUpper() ) |
| { |
| const SwTableBox* pTmpBox = pBox; |
| sal_uInt16 nBoxPos = n; |
| while( !nBoxPos && pTmpBox->GetUpper()->GetUpper() ) |
| { |
| pTmpBox = pTmpBox->GetUpper()->GetUpper(); |
| nBoxPos = pTmpBox->GetUpper()->GetTabBoxes().GetPos( pTmpBox ); |
| } |
| // if( nBoxPos ) |
| nTmpWidth = pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth(); |
| // else |
| // nTmpWidth = 0; |
| } |
| |
| if( nTmpWidth < nDiff || nTmpWidth - nDiff < MINLAY ) |
| return sal_False; |
| break; |
| } |
| } |
| } |
| else |
| { |
| SwTwips nLowerDiff = 0, nOldLower = rParam.nLowerDiff; |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| { |
| rParam.nLowerDiff = 0; |
| lcl_InsOtherBox( pBox->GetTabLines()[ i ], rParam, |
| nDist, sal_False ); |
| |
| if( nLowerDiff < rParam.nLowerDiff ) |
| nLowerDiff = rParam.nLowerDiff; |
| } |
| rParam.nLowerDiff = nOldLower; |
| |
| if( nLowerDiff || |
| (rParam.bLeft ? ((nDist + nWidth / 2 ) <= rParam.nSide && |
| (TBLFIX_CHGABS != rParam.nMode || |
| (n < rBoxes.Count() && |
| (nDist + nWidth + rBoxes[ n+1 ]-> |
| GetFrmFmt()->GetFrmSize().GetWidth() / 2) |
| > rParam.nSide) )) |
| : (nDist + nWidth / 2 ) > rParam.nSide )) |
| { |
| if( !nLowerDiff ) |
| { |
| if( TBLFIX_CHGPROP == rParam.nMode ) // Tabelle fix, proport. |
| { |
| // relativ berechnen |
| nLowerDiff = nWidth; |
| nLowerDiff *= rParam.nDiff; |
| nLowerDiff /= rParam.nRemainWidth; |
| } |
| else |
| nLowerDiff = rParam.nDiff; |
| } |
| |
| SwFmtFrmSize aNew( rSz ); |
| rParam.nLowerDiff += nLowerDiff; |
| |
| if( rParam.bBigger ) |
| aNew.SetWidth( nWidth - nLowerDiff ); |
| else |
| aNew.SetWidth( nWidth + nLowerDiff ); |
| rParam.aShareFmts.SetSize( *pBox, aNew ); |
| |
| if( TBLFIX_CHGABS == rParam.nMode ) |
| break; |
| } |
| } |
| |
| nDist += nWidth; |
| } |
| return sal_True; |
| } |
| |
| |
| // das Ergebnis des Positions Vergleiches |
| // POS_BEFORE, // Box liegt davor |
| // POS_BEHIND, // Box liegt dahinter |
| // POS_INSIDE, // Box liegt vollstaendig in Start/End |
| // POS_OUTSIDE, // Box ueberlappt Start/End vollstaendig |
| // POS_EQUAL, // Box und Start/End sind gleich |
| // POS_OVERLAP_BEFORE, // Box ueberlappt den Start |
| // POS_OVERLAP_BEHIND // Box ueberlappt das Ende |
| |
| SwComparePosition _CheckBoxInRange( sal_uInt16 nStt, sal_uInt16 nEnd, |
| sal_uInt16 nBoxStt, sal_uInt16 nBoxEnd ) |
| { |
| // COLFUZZY noch beachten!! |
| SwComparePosition nRet; |
| if( nBoxStt + COLFUZZY < nStt ) |
| { |
| if( nBoxEnd > nStt + COLFUZZY ) |
| { |
| if( nBoxEnd >= nEnd + COLFUZZY ) |
| nRet = POS_OUTSIDE; |
| else |
| nRet = POS_OVERLAP_BEFORE; |
| } |
| else |
| nRet = POS_BEFORE; |
| } |
| else if( nEnd > nBoxStt + COLFUZZY ) |
| { |
| if( nEnd + COLFUZZY >= nBoxEnd ) |
| { |
| if( COLFUZZY > Abs( long(nEnd) - long(nBoxEnd) ) && |
| COLFUZZY > Abs( long(nStt) - long(nBoxStt) ) ) |
| nRet = POS_EQUAL; |
| else |
| nRet = POS_INSIDE; |
| } |
| else |
| nRet = POS_OVERLAP_BEHIND; |
| } |
| else |
| nRet = POS_BEHIND; |
| |
| return nRet; |
| } |
| |
| void lcl_DelSelBox_CorrLowers( SwTableLine& rLine, CR_SetBoxWidth& rParam, |
| SwTwips nWidth ) |
| { |
| // 1. Schritt die eigene Breite feststellen |
| SwTableBoxes& rBoxes = rLine.GetTabBoxes(); |
| SwTwips nBoxWidth = 0; |
| sal_uInt16 n; |
| |
| for( n = rBoxes.Count(); n; ) |
| nBoxWidth += rBoxes[ --n ]->GetFrmFmt()->GetFrmSize().GetWidth(); |
| |
| if( COLFUZZY < Abs( nWidth - nBoxWidth )) |
| { |
| // sie muessen also angepasst werden |
| for( n = rBoxes.Count(); n; ) |
| { |
| SwTableBox* pBox = rBoxes[ --n ]; |
| SwFmtFrmSize aNew( pBox->GetFrmFmt()->GetFrmSize() ); |
| long nDiff = aNew.GetWidth(); |
| nDiff *= nWidth; |
| nDiff /= nBoxWidth; |
| aNew.SetWidth( nDiff ); |
| |
| rParam.aShareFmts.SetSize( *pBox, aNew ); |
| |
| if( !pBox->GetSttNd() ) |
| { |
| // hat selbst auch Lower, also auch die anpassen |
| for( sal_uInt16 i = pBox->GetTabLines().Count(); i; ) |
| ::lcl_DelSelBox_CorrLowers( *pBox->GetTabLines()[ --i ], |
| rParam, nDiff ); |
| } |
| } |
| } |
| } |
| |
| void lcl_ChgBoxSize( SwTableBox& rBox, CR_SetBoxWidth& rParam, |
| const SwFmtFrmSize& rOldSz, |
| sal_uInt16& rDelWidth, SwTwips nDist ) |
| { |
| long nDiff = 0; |
| sal_Bool bSetSize = sal_False; |
| |
| switch( rParam.nMode ) |
| { |
| case TBLFIX_CHGABS: // Tabelle feste Breite, den Nachbar andern |
| nDiff = rDelWidth + rParam.nLowerDiff; |
| bSetSize = sal_True; |
| break; |
| |
| case TBLFIX_CHGPROP: // Tabelle feste Breite, alle Nachbarn aendern |
| if( !rParam.nRemainWidth ) |
| { |
| // dann kurz berechnen: |
| if( rParam.bLeft ) |
| rParam.nRemainWidth = sal_uInt16(nDist); |
| else |
| rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist); |
| } |
| |
| // relativ berechnen |
| nDiff = rOldSz.GetWidth(); |
| nDiff *= rDelWidth + rParam.nLowerDiff; |
| nDiff /= rParam.nRemainWidth; |
| |
| bSetSize = sal_True; |
| break; |
| |
| case TBLVAR_CHGABS: // Tabelle variable, alle Nachbarn aendern |
| if( COLFUZZY < Abs( rParam.nBoxWidth - |
| ( rDelWidth + rParam.nLowerDiff ))) |
| { |
| nDiff = rDelWidth + rParam.nLowerDiff - rParam.nBoxWidth; |
| if( 0 < nDiff ) |
| rDelWidth = rDelWidth - sal_uInt16(nDiff); |
| else |
| rDelWidth = rDelWidth + sal_uInt16(-nDiff); |
| bSetSize = sal_True; |
| } |
| break; |
| } |
| |
| if( bSetSize ) |
| { |
| SwFmtFrmSize aNew( rOldSz ); |
| aNew.SetWidth( aNew.GetWidth() + nDiff ); |
| rParam.aShareFmts.SetSize( rBox, aNew ); |
| |
| // dann leider nochmals die Lower anpassen |
| for( sal_uInt16 i = rBox.GetTabLines().Count(); i; ) |
| ::lcl_DelSelBox_CorrLowers( *rBox.GetTabLines()[ --i ], rParam, |
| aNew.GetWidth() ); |
| } |
| } |
| |
| sal_Bool lcl_DeleteBox_Rekursiv( CR_SetBoxWidth& rParam, SwTableBox& rBox, |
| sal_Bool bCheck ) |
| { |
| sal_Bool bRet = sal_True; |
| if( rBox.GetSttNd() ) |
| { |
| if( bCheck ) |
| { |
| rParam.bAnyBoxFnd = sal_True; |
| if( rBox.GetFrmFmt()->GetProtect().IsCntntProtected() ) |
| bRet = sal_False; |
| else |
| { |
| SwTableBox* pBox = &rBox; |
| rParam.aBoxes.Insert( pBox ); |
| } |
| } |
| else |
| ::_DeleteBox( rParam.pTblNd->GetTable(), &rBox, |
| rParam.pUndo, sal_False, sal_True, &rParam.aShareFmts ); |
| } |
| else |
| { |
| // die muessen leider alle sequentiel ueber die |
| // Contentboxen geloescht werden |
| for( sal_uInt16 i = rBox.GetTabLines().Count(); i; ) |
| { |
| SwTableLine& rLine = *rBox.GetTabLines()[ --i ]; |
| for( sal_uInt16 n = rLine.GetTabBoxes().Count(); n; ) |
| if( !::lcl_DeleteBox_Rekursiv( rParam, |
| *rLine.GetTabBoxes()[ --n ], bCheck )) |
| return sal_False; |
| } |
| } |
| return bRet; |
| } |
| |
| sal_Bool lcl_DelSelBox( SwTableLine* pTabLine, CR_SetBoxWidth& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| SwTableBoxes& rBoxes = pTabLine->GetTabBoxes(); |
| sal_uInt16 n, nCntEnd, nBoxChkStt, nBoxChkEnd, nDelWidth = 0; |
| if( rParam.bLeft ) |
| { |
| n = rBoxes.Count(); |
| nCntEnd = 0; |
| nBoxChkStt = (sal_uInt16)rParam.nSide; |
| nBoxChkEnd = static_cast<sal_uInt16>(rParam.nSide + rParam.nBoxWidth); |
| } |
| else |
| { |
| n = 0; |
| nCntEnd = rBoxes.Count(); |
| nBoxChkStt = static_cast<sal_uInt16>(rParam.nSide - rParam.nBoxWidth); |
| nBoxChkEnd = (sal_uInt16)rParam.nSide; |
| } |
| |
| |
| while( n != nCntEnd ) |
| { |
| SwTableBox* pBox; |
| if( rParam.bLeft ) |
| pBox = rBoxes[ --n ]; |
| else |
| pBox = rBoxes[ n++ ]; |
| |
| SwFrmFmt* pFmt = pBox->GetFrmFmt(); |
| const SwFmtFrmSize& rSz = pFmt->GetFrmSize(); |
| long nWidth = rSz.GetWidth(); |
| sal_Bool bDelBox = sal_False, bChgLowers = sal_False; |
| |
| // die Boxenbreite testen und entpsrechend reagieren |
| SwComparePosition ePosType = ::_CheckBoxInRange( |
| nBoxChkStt, nBoxChkEnd, |
| sal_uInt16(rParam.bLeft ? nDist - nWidth : nDist), |
| sal_uInt16(rParam.bLeft ? nDist : nDist + nWidth)); |
| |
| switch( ePosType ) |
| { |
| case POS_BEFORE: |
| if( bCheck ) |
| { |
| if( rParam.bLeft ) |
| return sal_True; |
| } |
| else if( rParam.bLeft ) |
| { |
| ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist ); |
| if( TBLFIX_CHGABS == rParam.nMode ) |
| n = nCntEnd; |
| } |
| break; |
| |
| case POS_BEHIND: |
| if( bCheck ) |
| { |
| if( !rParam.bLeft ) |
| return sal_True; |
| } |
| else if( !rParam.bLeft ) |
| { |
| ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist ); |
| if( TBLFIX_CHGABS == rParam.nMode ) |
| n = nCntEnd; |
| } |
| break; |
| |
| case POS_OUTSIDE: // Box ueberlappt Start/End vollstaendig |
| case POS_INSIDE: // Box liegt vollstaendig in Start/End |
| case POS_EQUAL: // Box und Start/End sind gleich |
| bDelBox = sal_True; |
| break; |
| |
| case POS_OVERLAP_BEFORE: // Box ueberlappt den Start |
| if( nBoxChkStt <= ( nDist + (rParam.bLeft ? - nWidth / 2 |
| : nWidth / 2 ))) |
| { |
| if( !pBox->GetSttNd() ) |
| bChgLowers = sal_True; |
| else |
| bDelBox = sal_True; |
| } |
| else if( !bCheck && rParam.bLeft ) |
| { |
| if( !pBox->GetSttNd() ) |
| bChgLowers = sal_True; |
| else |
| { |
| ::lcl_ChgBoxSize( *pBox, rParam, rSz, nDelWidth, nDist ); |
| if( TBLFIX_CHGABS == rParam.nMode ) |
| n = nCntEnd; |
| } |
| } |
| break; |
| |
| case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende |
| // JP 10.02.99: |
| // generell loeschen oder wie beim OVERLAP_Before nur die, die |
| // bis zur Haelfte in die "Loesch-"Box reicht ??? |
| if( !pBox->GetSttNd() ) |
| bChgLowers = sal_True; |
| else |
| bDelBox = sal_True; |
| break; |
| default: break; |
| } |
| |
| if( bDelBox ) |
| { |
| nDelWidth = nDelWidth + sal_uInt16(nWidth); |
| if( bCheck ) |
| { |
| // die letzte/erste Box kann nur bei Tbl-Var geloescht werden, |
| // wenn diese so gross ist, wie die Aenderung an der Tabelle |
| if( (( TBLVAR_CHGABS != rParam.nMode || |
| nDelWidth != rParam.nBoxWidth ) && |
| COLFUZZY > Abs( rParam.bLeft |
| ? nWidth - nDist |
| : (nDist + nWidth - rParam.nTblWidth ))) |
| || !::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ) ) |
| return sal_False; |
| |
| if( pFmt->GetProtect().IsCntntProtected() ) |
| return sal_False; |
| } |
| else |
| { |
| ::lcl_DeleteBox_Rekursiv( rParam, *pBox, bCheck ); |
| |
| if( !rParam.bLeft ) |
| --n, --nCntEnd; |
| } |
| } |
| else if( bChgLowers ) |
| { |
| sal_Bool bFirst = sal_True, bCorrLowers = sal_False; |
| long nLowerDiff = 0; |
| long nOldLower = rParam.nLowerDiff; |
| sal_uInt16 nOldRemain = rParam.nRemainWidth; |
| sal_uInt16 i; |
| |
| for( i = pBox->GetTabLines().Count(); i; ) |
| { |
| rParam.nLowerDiff = nDelWidth + nOldLower; |
| rParam.nRemainWidth = nOldRemain; |
| SwTableLine* pLine = pBox->GetTabLines()[ --i ]; |
| if( !::lcl_DelSelBox( pLine, rParam, nDist, bCheck )) |
| return sal_False; |
| |
| // gibt es die Box und die darin enthaltenen Lines noch?? |
| if( n < rBoxes.Count() && |
| pBox == rBoxes[ rParam.bLeft ? n : n-1 ] && |
| i < pBox->GetTabLines().Count() && |
| pLine == pBox->GetTabLines()[ i ] ) |
| { |
| if( !bFirst && !bCorrLowers && |
| COLFUZZY < Abs( nLowerDiff - rParam.nLowerDiff ) ) |
| bCorrLowers = sal_True; |
| |
| // die groesste "loesch" Breite entscheidet, aber nur wenn |
| // nicht die gesamte Line geloescht wurde |
| if( nLowerDiff < rParam.nLowerDiff ) |
| nLowerDiff = rParam.nLowerDiff; |
| |
| bFirst = sal_False; |
| } |
| } |
| rParam.nLowerDiff = nOldLower; |
| rParam.nRemainWidth = nOldRemain; |
| |
| // wurden alle Boxen geloescht? Dann ist die DelBreite natuerlich |
| // die Boxenbreite |
| if( !nLowerDiff ) |
| nLowerDiff = nWidth; |
| |
| // DelBreite anpassen!! |
| nDelWidth = nDelWidth + sal_uInt16(nLowerDiff); |
| |
| if( !bCheck ) |
| { |
| // wurde die Box schon entfernt? |
| if( n > rBoxes.Count() || |
| pBox != rBoxes[ ( rParam.bLeft ? n : n-1 ) ] ) |
| { |
| // dann beim Loeschen nach rechts die Laufvar. anpassen |
| if( !rParam.bLeft ) |
| --n, --nCntEnd; |
| } |
| else |
| { |
| // sonst muss die Groesse der Box angepasst werden |
| SwFmtFrmSize aNew( rSz ); |
| sal_Bool bCorrRel = sal_False; |
| |
| if( TBLVAR_CHGABS != rParam.nMode ) |
| { |
| switch( ePosType ) |
| { |
| case POS_OVERLAP_BEFORE: // Box ueberlappt den Start |
| if( TBLFIX_CHGPROP == rParam.nMode ) |
| bCorrRel = rParam.bLeft; |
| else if( rParam.bLeft ) // TBLFIX_CHGABS |
| { |
| nLowerDiff = nLowerDiff - nDelWidth; |
| bCorrLowers = sal_True; |
| n = nCntEnd; |
| } |
| break; |
| |
| case POS_OVERLAP_BEHIND: // Box ueberlappt das Ende |
| if( TBLFIX_CHGPROP == rParam.nMode ) |
| bCorrRel = !rParam.bLeft; |
| else if( !rParam.bLeft ) // TBLFIX_CHGABS |
| { |
| nLowerDiff = nLowerDiff - nDelWidth; |
| bCorrLowers = sal_True; |
| n = nCntEnd; |
| } |
| break; |
| |
| default: |
| ASSERT( !pBox, "hier sollte man nie hinkommen" ); |
| break; |
| } |
| } |
| |
| if( bCorrRel ) |
| { |
| if( !rParam.nRemainWidth ) |
| { |
| // dann kurz berechnen: |
| if( rParam.bLeft ) |
| rParam.nRemainWidth = sal_uInt16(nDist - nLowerDiff); |
| else |
| rParam.nRemainWidth = sal_uInt16(rParam.nTblWidth - nDist |
| - nLowerDiff ); |
| } |
| |
| long nDiff = aNew.GetWidth() - nLowerDiff; |
| nDiff *= nDelWidth + rParam.nLowerDiff; |
| nDiff /= rParam.nRemainWidth; |
| |
| aNew.SetWidth( aNew.GetWidth() - nLowerDiff + nDiff ); |
| } |
| else |
| aNew.SetWidth( aNew.GetWidth() - nLowerDiff ); |
| rParam.aShareFmts.SetSize( *pBox, aNew ); |
| |
| if( bCorrLowers ) |
| { |
| // dann leider nochmals die Lower anpassen |
| for( i = pBox->GetTabLines().Count(); i; ) |
| ::lcl_DelSelBox_CorrLowers( *pBox-> |
| GetTabLines()[ --i ], rParam, aNew.GetWidth() ); |
| } |
| } |
| } |
| } |
| |
| if( rParam.bLeft ) |
| nDist -= nWidth; |
| else |
| nDist += nWidth; |
| } |
| rParam.nLowerDiff = nDelWidth; |
| return sal_True; |
| } |
| |
| // Dummy Funktion fuer die Methode SetColWidth |
| sal_Bool lcl_DelOtherBox( SwTableLine* , CR_SetBoxWidth& , SwTwips , sal_Bool ) |
| { |
| return sal_True; |
| } |
| |
| /**/ |
| |
| void lcl_AjustLines( SwTableLine* pLine, CR_SetBoxWidth& rParam ) |
| { |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox* pBox = rBoxes[ n ]; |
| |
| SwFmtFrmSize aSz( pBox->GetFrmFmt()->GetFrmSize() ); |
| SwTwips nWidth = aSz.GetWidth(); |
| nWidth *= rParam.nDiff; |
| nWidth /= rParam.nMaxSize; |
| aSz.SetWidth( nWidth ); |
| rParam.aShareFmts.SetSize( *pBox, aSz ); |
| |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| ::lcl_AjustLines( pBox->GetTabLines()[ i ], rParam ); |
| } |
| } |
| |
| #if defined(DBG_UTIL) || defined( JP_DEBUG ) |
| |
| void _CheckBoxWidth( const SwTableLine& rLine, SwTwips nSize ) |
| { |
| const SwTableBoxes& rBoxes = rLine.GetTabBoxes(); |
| |
| SwTwips nAktSize = 0; |
| // checke doch mal ob die Tabellen korrekte Breiten haben |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| const SwTableBox* pBox = rBoxes[ n ]; |
| const SwTwips nBoxW = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); |
| nAktSize += nBoxW; |
| |
| for( sal_uInt16 i = 0; i < pBox->GetTabLines().Count(); ++i ) |
| _CheckBoxWidth( *pBox->GetTabLines()[ i ], nBoxW ); |
| } |
| |
| if( Abs( nAktSize - nSize ) > ( COLFUZZY * rBoxes.Count() ) ) |
| { |
| DBG_ERROR( "Boxen der Line zu klein/gross" ); |
| #if defined( WNT ) && defined( JP_DEBUG ) |
| __asm int 3; |
| #endif |
| } |
| } |
| |
| #endif |
| |
| _FndBox* lcl_SaveInsDelData( CR_SetBoxWidth& rParam, SwUndo** ppUndo, |
| SwTableSortBoxes& rTmpLst, SwTwips nDistStt ) |
| { |
| // suche alle Boxen / Lines |
| SwTable& rTbl = rParam.pTblNd->GetTable(); |
| |
| if( !rParam.aBoxes.Count() ) |
| { |
| // erstmal die Boxen besorgen ! |
| if( rParam.bBigger ) |
| for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n ) |
| ::lcl_DelSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True ); |
| else |
| for( sal_uInt16 n = 0; n < rTbl.GetTabLines().Count(); ++n ) |
| ::lcl_InsSelBox( rTbl.GetTabLines()[ n ], rParam, nDistStt, sal_True ); |
| } |
| |
| // loeschen der gesamten Tabelle verhindern |
| if( rParam.bBigger && rParam.aBoxes.Count() == |
| rTbl.GetTabSortBoxes().Count() ) |
| return 0; |
| |
| _FndBox* pFndBox = new _FndBox( 0, 0 ); |
| if( rParam.bBigger ) |
| pFndBox->SetTableLines( rParam.aBoxes, rTbl ); |
| else |
| { |
| _FndPara aPara( rParam.aBoxes, pFndBox ); |
| rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" ); |
| pFndBox->SetTableLines( rTbl ); |
| |
| if( ppUndo ) |
| rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); |
| } |
| |
| //Lines fuer das Layout-Update herausuchen. |
| pFndBox->DelFrms( rTbl ); |
| |
| // TL_CHART2: this function gest called from SetColWidth exclusively, |
| // thus it is currently speculated that nothing needs to be done here. |
| // Note: that SetColWidth is currently not completely understood though :-( |
| |
| return pFndBox; |
| } |
| |
| sal_Bool SwTable::SetColWidth( SwTableBox& rAktBox, sal_uInt16 eType, |
| SwTwips nAbsDiff, SwTwips nRelDiff, SwUndo** ppUndo ) |
| { |
| SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen |
| |
| const SwFmtFrmSize& rSz = GetFrmFmt()->GetFrmSize(); |
| const SvxLRSpaceItem& rLR = GetFrmFmt()->GetLRSpace(); |
| |
| _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen |
| SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo |
| sal_Bool bBigger, |
| bRet = sal_False, |
| bLeft = nsTblChgWidthHeightType::WH_COL_LEFT == ( eType & 0xff ) || |
| nsTblChgWidthHeightType::WH_CELL_LEFT == ( eType & 0xff ), |
| bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL ); |
| sal_uInt16 n; |
| sal_uLong nBoxIdx = rAktBox.GetSttIdx(); |
| |
| // bestimme die akt. Kante der Box |
| // wird nur fuer die Breitenmanipulation benoetigt! |
| const SwTwips nDist = ::lcl_GetDistance( &rAktBox, bLeft ); |
| SwTwips nDistStt = 0; |
| CR_SetBoxWidth aParam( eType, nRelDiff, nDist, rSz.GetWidth(), |
| bLeft ? nDist : rSz.GetWidth() - nDist, |
| (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() ); |
| bBigger = aParam.bBigger; |
| |
| FN_lcl_SetBoxWidth fnSelBox, fnOtherBox; |
| if( bInsDel ) |
| { |
| if( bBigger ) |
| { |
| fnSelBox = lcl_DelSelBox; |
| fnOtherBox = lcl_DelOtherBox; |
| aParam.nBoxWidth = (sal_uInt16)rAktBox.GetFrmFmt()->GetFrmSize().GetWidth(); |
| if( bLeft ) |
| nDistStt = rSz.GetWidth(); |
| } |
| else |
| { |
| fnSelBox = lcl_InsSelBox; |
| fnOtherBox = lcl_InsOtherBox; |
| } |
| } |
| else |
| { |
| fnSelBox = lcl_SetSelBoxWidth; |
| fnOtherBox = lcl_SetOtherBoxWidth; |
| } |
| |
| |
| switch( eType & 0xff ) |
| { |
| case nsTblChgWidthHeightType::WH_COL_RIGHT: |
| case nsTblChgWidthHeightType::WH_COL_LEFT: |
| if( TBLVAR_CHGABS == eTblChgMode ) |
| { |
| if( bInsDel ) |
| bBigger = !bBigger; |
| |
| // erstmal testen, ob ueberhaupt Platz ist |
| sal_Bool bChgLRSpace = sal_True; |
| if( bBigger ) |
| { |
| if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) && |
| !rSz.GetWidthPercent() ) |
| { |
| bRet = rSz.GetWidth() < USHRT_MAX - nRelDiff; |
| bChgLRSpace = bLeft ? rLR.GetLeft() >= nAbsDiff |
| : rLR.GetRight() >= nAbsDiff; |
| } |
| else |
| bRet = bLeft ? rLR.GetLeft() >= nAbsDiff |
| : rLR.GetRight() >= nAbsDiff; |
| |
| if( !bRet && bInsDel && |
| // auf der anderen Seite Platz? |
| ( bLeft ? rLR.GetRight() >= nAbsDiff |
| : rLR.GetLeft() >= nAbsDiff )) |
| { |
| bRet = sal_True; bLeft = !bLeft; |
| } |
| |
| if( !bRet ) |
| { |
| // dann sich selbst rekursiv aufrufen; nur mit |
| // einem anderen Mode -> proprotional |
| TblChgMode eOld = eTblChgMode; |
| eTblChgMode = TBLFIX_CHGPROP; |
| |
| bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff, |
| ppUndo ); |
| eTblChgMode = eOld; |
| return bRet; |
| } |
| } |
| else |
| { |
| bRet = sal_True; |
| for( n = 0; n < aLines.Count(); ++n ) |
| { |
| aParam.LoopClear(); |
| if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| } |
| |
| if( bRet ) |
| { |
| if( bInsDel ) |
| { |
| pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, |
| aTmpLst, nDistStt ); |
| if( aParam.bBigger && aParam.aBoxes.Count() == |
| aSortCntBoxes.Count() ) |
| { |
| // dies gesamte Tabelle soll geloescht werden!! |
| GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes ); |
| return sal_False; |
| } |
| |
| if( ppUndo ) |
| *ppUndo = aParam.CreateUndo( |
| aParam.bBigger ? UNDO_COL_DELETE |
| : UNDO_TABLE_INSCOL ); |
| } |
| else if( ppUndo ) |
| *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); |
| |
| long nFrmWidth = LONG_MAX; |
| LockModify(); |
| SwFmtFrmSize aSz( rSz ); |
| SvxLRSpaceItem aLR( rLR ); |
| if( bBigger ) |
| { |
| // falls die Tabelle keinen Platz zum Wachsen hat, dann |
| // muessen wir welchen schaffen! |
| if( aSz.GetWidth() + nRelDiff > USHRT_MAX ) |
| { |
| // dann mal herunterbrechen auf USHRT_MAX / 2 |
| CR_SetBoxWidth aTmpPara( 0, aSz.GetWidth() / 2, |
| 0, aSz.GetWidth(), aSz.GetWidth(), aParam.pTblNd ); |
| for( sal_uInt16 nLn = 0; nLn < aLines.Count(); ++nLn ) |
| ::lcl_AjustLines( aLines[ nLn ], aTmpPara ); |
| aSz.SetWidth( aSz.GetWidth() / 2 ); |
| aParam.nDiff = nRelDiff /= 2; |
| aParam.nSide /= 2; |
| aParam.nMaxSize /= 2; |
| } |
| |
| if( bLeft ) |
| aLR.SetLeft( sal_uInt16( aLR.GetLeft() - nAbsDiff ) ); |
| else |
| aLR.SetRight( sal_uInt16( aLR.GetRight() - nAbsDiff ) ); |
| } |
| else if( bLeft ) |
| aLR.SetLeft( sal_uInt16( aLR.GetLeft() + nAbsDiff ) ); |
| else |
| aLR.SetRight( sal_uInt16( aLR.GetRight() + nAbsDiff ) ); |
| |
| if( bChgLRSpace ) |
| GetFrmFmt()->SetFmtAttr( aLR ); |
| const SwFmtHoriOrient& rHOri = GetFrmFmt()->GetHoriOrient(); |
| if( text::HoriOrientation::FULL == rHOri.GetHoriOrient() || |
| (text::HoriOrientation::LEFT == rHOri.GetHoriOrient() && aLR.GetLeft()) || |
| (text::HoriOrientation::RIGHT == rHOri.GetHoriOrient() && aLR.GetRight())) |
| { |
| SwFmtHoriOrient aHOri( rHOri ); |
| aHOri.SetHoriOrient( text::HoriOrientation::NONE ); |
| GetFrmFmt()->SetFmtAttr( aHOri ); |
| |
| // sollte die Tabelle noch auf relativen Werten |
| // (USHRT_MAX) stehen dann muss es jetzt auf absolute |
| // umgerechnet werden. Bug 61494 |
| if( GetFrmFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) && |
| !rSz.GetWidthPercent() ) |
| { |
| SwTabFrm* pTabFrm = SwIterator<SwTabFrm,SwFmt>::FirstElement( *GetFrmFmt() ); |
| if( pTabFrm && |
| pTabFrm->Prt().Width() != rSz.GetWidth() ) |
| { |
| nFrmWidth = pTabFrm->Prt().Width(); |
| if( bBigger ) |
| nFrmWidth += nAbsDiff; |
| else |
| nFrmWidth -= nAbsDiff; |
| } |
| } |
| } |
| |
| if( bBigger ) |
| aSz.SetWidth( aSz.GetWidth() + nRelDiff ); |
| else |
| aSz.SetWidth( aSz.GetWidth() - nRelDiff ); |
| |
| if( rSz.GetWidthPercent() ) |
| aSz.SetWidthPercent( static_cast<sal_uInt8>(( aSz.GetWidth() * 100 ) / |
| ( aSz.GetWidth() + aLR.GetRight() + aLR.GetLeft()))); |
| |
| GetFrmFmt()->SetFmtAttr( aSz ); |
| aParam.nTblWidth = sal_uInt16( aSz.GetWidth() ); |
| |
| UnlockModify(); |
| |
| for( n = aLines.Count(); n; ) |
| { |
| --n; |
| aParam.LoopClear(); |
| (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False ); |
| } |
| |
| // sollte die Tabelle noch auf relativen Werten |
| // (USHRT_MAX) stehen dann muss es jetzt auf absolute |
| // umgerechnet werden. Bug 61494 |
| if( LONG_MAX != nFrmWidth ) |
| { |
| SwFmtFrmSize aAbsSz( aSz ); |
| aAbsSz.SetWidth( nFrmWidth ); |
| GetFrmFmt()->SetFmtAttr( aAbsSz ); |
| } |
| } |
| } |
| else if( bInsDel || |
| ( bLeft ? nDist : Abs( rSz.GetWidth() - nDist ) > COLFUZZY ) ) |
| { |
| bRet = sal_True; |
| if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel ) |
| aParam.bBigger = !bBigger; |
| |
| // erstmal testen, ob ueberhaupt Platz ist |
| if( bInsDel ) |
| { |
| if( aParam.bBigger ) |
| { |
| for( n = 0; n < aLines.Count(); ++n ) |
| { |
| aParam.LoopClear(); |
| if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| } |
| else |
| { |
| if( 0 != ( bRet = bLeft ? nDist != 0 |
| : ( rSz.GetWidth() - nDist ) > COLFUZZY ) ) |
| { |
| for( n = 0; n < aLines.Count(); ++n ) |
| { |
| aParam.LoopClear(); |
| if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True )) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| if( bRet && !aParam.bAnyBoxFnd ) |
| bRet = sal_False; |
| } |
| |
| if( !bRet && rAktBox.GetFrmFmt()->GetFrmSize().GetWidth() |
| - nRelDiff > COLFUZZY + |
| ( 567 / 2 /* min. 0,5 cm Platz lassen*/) ) |
| { |
| // dann den Platz von der akt. Zelle nehmen |
| aParam.bSplittBox = sal_True; |
| // aber das muss auch mal getestet werden! |
| bRet = sal_True; |
| |
| for( n = 0; n < aLines.Count(); ++n ) |
| { |
| aParam.LoopClear(); |
| if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| } |
| } |
| } |
| else if( aParam.bBigger ) |
| { |
| for( n = 0; n < aLines.Count(); ++n ) |
| { |
| aParam.LoopClear(); |
| if( !(*fnOtherBox)( aLines[ n ], aParam, 0, sal_True )) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| } |
| else |
| { |
| for( n = 0; n < aLines.Count(); ++n ) |
| { |
| aParam.LoopClear(); |
| if( !(*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_True )) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| } |
| |
| // wenn ja, dann setzen |
| if( bRet ) |
| { |
| CR_SetBoxWidth aParam1( aParam ); |
| if( bInsDel ) |
| { |
| aParam1.bBigger = !aParam.bBigger; |
| pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, |
| aTmpLst, nDistStt ); |
| if( ppUndo ) |
| *ppUndo = aParam.CreateUndo( |
| aParam.bBigger ? UNDO_TABLE_DELBOX |
| : UNDO_TABLE_INSCOL ); |
| } |
| else if( ppUndo ) |
| *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); |
| |
| if( bInsDel |
| ? ( TBLFIX_CHGABS == eTblChgMode ? bLeft : bLeft ) |
| : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) ) |
| { |
| for( n = aLines.Count(); n; ) |
| { |
| --n; |
| aParam.LoopClear(); |
| aParam1.LoopClear(); |
| (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False ); |
| (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False ); |
| } |
| } |
| else |
| for( n = aLines.Count(); n; ) |
| { |
| --n; |
| aParam.LoopClear(); |
| aParam1.LoopClear(); |
| (*fnOtherBox)( aLines[ n ], aParam1, nDistStt, sal_False ); |
| (*fnSelBox)( aLines[ n ], aParam, nDistStt, sal_False ); |
| } |
| } |
| } |
| break; |
| |
| case nsTblChgWidthHeightType::WH_CELL_RIGHT: |
| case nsTblChgWidthHeightType::WH_CELL_LEFT: |
| if( TBLVAR_CHGABS == eTblChgMode ) |
| { |
| // dann sich selbst rekursiv aufrufen; nur mit |
| // einem anderen Mode -> Nachbarn |
| TblChgMode eOld = eTblChgMode; |
| eTblChgMode = TBLFIX_CHGABS; |
| |
| bRet = SetColWidth( rAktBox, eType, nAbsDiff, nRelDiff, |
| ppUndo ); |
| eTblChgMode = eOld; |
| return bRet; |
| } |
| else if( bInsDel || ( bLeft ? nDist |
| : (rSz.GetWidth() - nDist) > COLFUZZY )) |
| { |
| if( bLeft && TBLFIX_CHGABS == eTblChgMode && !bInsDel ) |
| aParam.bBigger = !bBigger; |
| |
| // erstmal testen, ob ueberhaupt Platz ist |
| SwTableBox* pBox = &rAktBox; |
| SwTableLine* pLine = rAktBox.GetUpper(); |
| while( pLine->GetUpper() ) |
| { |
| sal_uInt16 nPos = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pBox ); |
| if( bLeft ? nPos : nPos + 1 != pLine->GetTabBoxes().Count() ) |
| break; |
| |
| pBox = pLine->GetUpper(); |
| pLine = pBox->GetUpper(); |
| } |
| |
| if( pLine->GetUpper() ) |
| { |
| // dann muss die Distanz wieder korriegiert werden! |
| aParam.nSide -= ::lcl_GetDistance( pLine->GetUpper(), sal_True ); |
| |
| if( bLeft ) |
| aParam.nMaxSize = aParam.nSide; |
| else |
| aParam.nMaxSize = pLine->GetUpper()->GetFrmFmt()-> |
| GetFrmSize().GetWidth() - aParam.nSide; |
| } |
| |
| // erstmal testen, ob ueberhaupt Platz ist |
| if( bInsDel ) |
| { |
| if( 0 != ( bRet = bLeft ? nDist != 0 |
| : ( rSz.GetWidth() - nDist ) > COLFUZZY ) && |
| !aParam.bBigger ) |
| { |
| bRet = (*fnOtherBox)( pLine, aParam, 0, sal_True ); |
| if( bRet && !aParam.bAnyBoxFnd ) |
| bRet = sal_False; |
| } |
| |
| if( !bRet && !aParam.bBigger && rAktBox.GetFrmFmt()-> |
| GetFrmSize().GetWidth() - nRelDiff > COLFUZZY + |
| ( 567 / 2 /* min. 0,5 cm Platz lassen*/) ) |
| { |
| // dann den Platz von der akt. Zelle nehmen |
| aParam.bSplittBox = sal_True; |
| bRet = sal_True; |
| } |
| } |
| else |
| { |
| FN_lcl_SetBoxWidth fnTmp = aParam.bBigger ? fnOtherBox : fnSelBox; |
| bRet = (*fnTmp)( pLine, aParam, nDistStt, sal_True ); |
| } |
| |
| // wenn ja, dann setzen |
| if( bRet ) |
| { |
| CR_SetBoxWidth aParam1( aParam ); |
| if( bInsDel ) |
| { |
| aParam1.bBigger = !aParam.bBigger; |
| pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst, nDistStt ); |
| if( ppUndo ) |
| *ppUndo = aParam.CreateUndo( |
| aParam.bBigger ? UNDO_TABLE_DELBOX |
| : UNDO_TABLE_INSCOL ); |
| } |
| else if( ppUndo ) |
| *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); |
| |
| if( bInsDel |
| ? ( TBLFIX_CHGABS == eTblChgMode ? (bBigger && bLeft) : bLeft ) |
| : ( TBLFIX_CHGABS != eTblChgMode && bLeft ) ) |
| { |
| (*fnSelBox)( pLine, aParam, nDistStt, sal_False ); |
| (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False ); |
| } |
| else |
| { |
| (*fnOtherBox)( pLine, aParam1, nDistStt, sal_False ); |
| (*fnSelBox)( pLine, aParam, nDistStt, sal_False ); |
| } |
| } |
| } |
| break; |
| |
| } |
| |
| if( pFndBox ) |
| { |
| // dann raeume die Struktur aller Lines auf |
| GCLines(); |
| |
| //Layout updaten |
| if( !bBigger || pFndBox->AreLinesToRestore( *this ) ) |
| pFndBox->MakeFrms( *this ); |
| |
| // TL_CHART2: it is currently unclear if sth has to be done here. |
| // The function name hints that nothing needs to be done, on the other |
| // hand there is a case where sth gets deleted. :-( |
| |
| delete pFndBox; |
| |
| if( ppUndo && *ppUndo ) |
| { |
| aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType, |
| nAbsDiff, nRelDiff ); |
| if( !aParam.bBigger ) |
| aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst ); |
| } |
| } |
| |
| if( bRet ) |
| { |
| CHECKBOXWIDTH |
| CHECKTABLELAYOUT |
| } |
| |
| return bRet; |
| } |
| /* */ |
| |
| _FndBox* lcl_SaveInsDelData( CR_SetLineHeight& rParam, SwUndo** ppUndo, |
| SwTableSortBoxes& rTmpLst ) |
| { |
| // suche alle Boxen / Lines |
| SwTable& rTbl = rParam.pTblNd->GetTable(); |
| |
| ASSERT( rParam.aBoxes.Count(), "ohne Boxen ist nichts zu machen!" ); |
| |
| // loeschen der gesamten Tabelle verhindern |
| if( !rParam.bBigger && rParam.aBoxes.Count() == |
| rTbl.GetTabSortBoxes().Count() ) |
| return 0; |
| |
| _FndBox* pFndBox = new _FndBox( 0, 0 ); |
| if( !rParam.bBigger ) |
| pFndBox->SetTableLines( rParam.aBoxes, rTbl ); |
| else |
| { |
| _FndPara aPara( rParam.aBoxes, pFndBox ); |
| rTbl.GetTabLines().ForEach( &_FndLineCopyCol, &aPara ); |
| ASSERT( pFndBox->GetLines().Count(), "Wo sind die Boxen" ); |
| pFndBox->SetTableLines( rTbl ); |
| |
| if( ppUndo ) |
| rTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); |
| } |
| |
| //Lines fuer das Layout-Update heraussuchen. |
| pFndBox->DelFrms( rTbl ); |
| |
| // TL_CHART2: it is currently unclear if sth has to be done here. |
| |
| return pFndBox; |
| } |
| |
| void SetLineHeight( SwTableLine& rLine, SwTwips nOldHeight, SwTwips nNewHeight, |
| sal_Bool bMinSize ) |
| { |
| SwLayoutFrm* pLineFrm = GetRowFrm( rLine ); |
| ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); |
| |
| SwFrmFmt* pFmt = rLine.ClaimFrmFmt(); |
| |
| SwTwips nMyNewH, nMyOldH = pLineFrm->Frm().Height(); |
| if( !nOldHeight ) // die BaseLine und absolut |
| nMyNewH = nMyOldH + nNewHeight; |
| else |
| { |
| // moeglichst genau rechnen |
| Fraction aTmp( nMyOldH ); |
| aTmp *= Fraction( nNewHeight, nOldHeight ); |
| aTmp += Fraction( 1, 2 ); // ggfs. aufrunden |
| nMyNewH = aTmp; |
| } |
| |
| SwFrmSize eSize = ATT_MIN_SIZE; |
| if( !bMinSize && |
| ( nMyOldH - nMyNewH ) > ( CalcRowRstHeight( pLineFrm ) + ROWFUZZY )) |
| eSize = ATT_FIX_SIZE; |
| |
| pFmt->SetFmtAttr( SwFmtFrmSize( eSize, 0, nMyNewH ) ); |
| |
| // erst alle inneren anpassen |
| SwTableBoxes& rBoxes = rLine.GetTabBoxes(); |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTableBox& rBox = *rBoxes[ n ]; |
| for( sal_uInt16 i = 0; i < rBox.GetTabLines().Count(); ++i ) |
| SetLineHeight( *rBox.GetTabLines()[ i ], nMyOldH, nMyNewH, bMinSize ); |
| } |
| } |
| |
| sal_Bool lcl_SetSelLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| sal_Bool bRet = sal_True; |
| if( !bCheck ) |
| { |
| // Zeilenhoehe einstellen |
| SetLineHeight( *pLine, 0, rParam.bBigger ? nDist : -nDist, |
| rParam.bBigger ); |
| } |
| else if( !rParam.bBigger ) |
| { |
| // anhand der alten Size die neue relative errechnen |
| SwLayoutFrm* pLineFrm = GetRowFrm( *pLine ); |
| ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); |
| SwTwips nRstHeight = CalcRowRstHeight( pLineFrm ); |
| if( (nRstHeight + ROWFUZZY) < nDist ) |
| bRet = sal_False; |
| } |
| return bRet; |
| } |
| |
| sal_Bool lcl_SetOtherLineHeight( SwTableLine* pLine, CR_SetLineHeight& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| sal_Bool bRet = sal_True; |
| if( bCheck ) |
| { |
| if( rParam.bBigger ) |
| { |
| // anhand der alten Size die neue relative errechnen |
| SwLayoutFrm* pLineFrm = GetRowFrm( *pLine ); |
| ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); |
| |
| if( TBLFIX_CHGPROP == rParam.nMode ) |
| { |
| nDist *= pLineFrm->Frm().Height(); |
| nDist /= rParam.nMaxHeight; |
| } |
| bRet = nDist <= CalcRowRstHeight( pLineFrm ); |
| } |
| } |
| else |
| { |
| // Zeilenhoehe einstellen |
| // pLine ist die nachfolgende / vorhergehende -> also anpassen |
| if( TBLFIX_CHGPROP == rParam.nMode ) |
| { |
| SwLayoutFrm* pLineFrm = GetRowFrm( *pLine ); |
| ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); |
| |
| // aus der alten Size die neue relative errechnen |
| // Wird die selektierte Box groesser ueber den MaxSpace anpassen, |
| // sonst ueber die MaxHeight |
| if( 1 /*!rParam.bBigger*/ ) |
| { |
| nDist *= pLineFrm->Frm().Height(); |
| nDist /= rParam.nMaxHeight; |
| } |
| else |
| { |
| // aus der alten Size die neue relative errechnen |
| nDist *= CalcRowRstHeight( pLineFrm ); |
| nDist /= rParam.nMaxSpace; |
| } |
| } |
| SetLineHeight( *pLine, 0, rParam.bBigger ? -nDist : nDist, |
| !rParam.bBigger ); |
| } |
| return bRet; |
| } |
| |
| sal_Bool lcl_InsDelSelLine( SwTableLine* pLine, CR_SetLineHeight& rParam, |
| SwTwips nDist, sal_Bool bCheck ) |
| { |
| sal_Bool bRet = sal_True; |
| if( !bCheck ) |
| { |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| SwDoc* pDoc = pLine->GetFrmFmt()->GetDoc(); |
| if( !rParam.bBigger ) |
| { |
| sal_uInt16 n; |
| |
| for( n = rBoxes.Count(); n; ) |
| ::lcl_SaveUpperLowerBorder( rParam.pTblNd->GetTable(), |
| *rBoxes[ --n ], |
| rParam.aShareFmts ); |
| for( n = rBoxes.Count(); n; ) |
| ::_DeleteBox( rParam.pTblNd->GetTable(), |
| rBoxes[ --n ], rParam.pUndo, sal_False, |
| sal_False, &rParam.aShareFmts ); |
| } |
| else |
| { |
| // Zeile einfuegen |
| SwTableLine* pNewLine = new SwTableLine( (SwTableLineFmt*)pLine->GetFrmFmt(), |
| rBoxes.Count(), pLine->GetUpper() ); |
| SwTableLines* pLines; |
| if( pLine->GetUpper() ) |
| pLines = &pLine->GetUpper()->GetTabLines(); |
| else |
| pLines = &rParam.pTblNd->GetTable().GetTabLines(); |
| sal_uInt16 nPos = pLines->C40_GETPOS( SwTableLine, pLine ); |
| if( !rParam.bTop ) |
| ++nPos; |
| pLines->C40_INSERT( SwTableLine, pNewLine, nPos ); |
| |
| SwFrmFmt* pNewFmt = pNewLine->ClaimFrmFmt(); |
| pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE, 0, nDist ) ); |
| |
| // und noch mal die Anzahl Boxen erzeugen |
| SwTableBoxes& rNewBoxes = pNewLine->GetTabBoxes(); |
| for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) |
| { |
| SwTwips nWidth = 0; |
| SwTableBox* pOld = rBoxes[ n ]; |
| if( !pOld->GetSttNd() ) |
| { |
| // keine normale "Content"-Box also auf die 1. naechste |
| // Box zurueckfallen |
| nWidth = pOld->GetFrmFmt()->GetFrmSize().GetWidth(); |
| while( !pOld->GetSttNd() ) |
| pOld = pOld->GetTabLines()[ 0 ]->GetTabBoxes()[ 0 ]; |
| } |
| ::_InsTblBox( pDoc, rParam.pTblNd, pNewLine, |
| (SwTableBoxFmt*)pOld->GetFrmFmt(), pOld, n ); |
| |
| // Sonderbehandlung fuer Umrandung die Obere muss |
| // entfernt werden |
| const SvxBoxItem& rBoxItem = pOld->GetFrmFmt()->GetBox(); |
| if( rBoxItem.GetTop() ) |
| { |
| SvxBoxItem aTmp( rBoxItem ); |
| aTmp.SetLine( 0, BOX_LINE_TOP ); |
| rParam.aShareFmts.SetAttr( rParam.bTop |
| ? *pOld |
| : *rNewBoxes[ n ], aTmp ); |
| } |
| |
| if( nWidth ) |
| rParam.aShareFmts.SetAttr( *rNewBoxes[ n ], |
| SwFmtFrmSize( ATT_FIX_SIZE, nWidth, 0 ) ); |
| } |
| } |
| } |
| else |
| { |
| // Boxen einsammeln! |
| SwTableBoxes& rBoxes = pLine->GetTabBoxes(); |
| for( sal_uInt16 n = rBoxes.Count(); n; ) |
| { |
| SwTableBox* pBox = rBoxes[ --n ]; |
| if( pBox->GetFrmFmt()->GetProtect().IsCntntProtected() ) |
| return sal_False; |
| |
| if( pBox->GetSttNd() ) |
| rParam.aBoxes.Insert( pBox ); |
| else |
| { |
| for( sal_uInt16 i = pBox->GetTabLines().Count(); i; ) |
| lcl_InsDelSelLine( pBox->GetTabLines()[ --i ], |
| rParam, 0, sal_True ); |
| } |
| } |
| } |
| return bRet; |
| } |
| |
| sal_Bool SwTable::SetRowHeight( SwTableBox& rAktBox, sal_uInt16 eType, |
| SwTwips nAbsDiff, SwTwips nRelDiff,SwUndo** ppUndo ) |
| { |
| SwTableLine* pLine = rAktBox.GetUpper(); |
| |
| SwTableLine* pBaseLine = pLine; |
| while( pBaseLine->GetUpper() ) |
| pBaseLine = pBaseLine->GetUpper()->GetUpper(); |
| |
| _FndBox* pFndBox = 0; // fuers Einfuegen/Loeschen |
| SwTableSortBoxes aTmpLst( 0, 5 ); // fuers Undo |
| sal_Bool bBigger, |
| bRet = sal_False, |
| bTop = nsTblChgWidthHeightType::WH_ROW_TOP == ( eType & 0xff ) || |
| nsTblChgWidthHeightType::WH_CELL_TOP == ( eType & 0xff ), |
| bInsDel = 0 != (eType & nsTblChgWidthHeightType::WH_FLAG_INSDEL ); |
| sal_uInt16 n, nBaseLinePos = GetTabLines().C40_GETPOS( SwTableLine, pBaseLine ); |
| sal_uLong nBoxIdx = rAktBox.GetSttIdx(); |
| |
| CR_SetLineHeight aParam( eType, |
| (SwTableNode*)rAktBox.GetSttNd()->FindTableNode() ); |
| bBigger = aParam.bBigger; |
| |
| FN_lcl_SetLineHeight fnSelLine, fnOtherLine = lcl_SetOtherLineHeight; |
| if( bInsDel ) |
| fnSelLine = lcl_InsDelSelLine; |
| else |
| fnSelLine = lcl_SetSelLineHeight; |
| |
| SwTableLines* pLines = &aLines; |
| |
| // wie kommt man an die Hoehen heran? |
| switch( eType & 0xff ) |
| { |
| case nsTblChgWidthHeightType::WH_CELL_TOP: |
| case nsTblChgWidthHeightType::WH_CELL_BOTTOM: |
| if( pLine == pBaseLine ) |
| break; // dann geht es nicht! |
| |
| // ist eine verschachtelte Line (Box!) |
| pLines = &pLine->GetUpper()->GetTabLines(); |
| nBaseLinePos = pLines->C40_GETPOS( SwTableLine, pLine ); |
| pBaseLine = pLine; |
| // kein break! |
| |
| case nsTblChgWidthHeightType::WH_ROW_TOP: |
| case nsTblChgWidthHeightType::WH_ROW_BOTTOM: |
| { |
| if( bInsDel && !bBigger ) // um wieviel wird es Hoeher? |
| { |
| nAbsDiff = GetRowFrm( *pBaseLine )->Frm().Height(); |
| } |
| |
| if( TBLVAR_CHGABS == eTblChgMode ) |
| { |
| // erstmal testen, ob ueberhaupt Platz ist |
| if( bBigger ) |
| { |
| bRet = sal_True; |
| // was ist mit Top, was ist mit Tabelle im Rahmen oder in Kopf-/Fusszeile |
| // mit fester Hoehe ?? |
| if( !bRet ) |
| { |
| // dann sich selbst rekursiv aufrufen; nur mit |
| // einem anderen Mode -> proprotional |
| TblChgMode eOld = eTblChgMode; |
| eTblChgMode = TBLFIX_CHGPROP; |
| |
| bRet = SetRowHeight( rAktBox, eType, nAbsDiff, |
| nRelDiff, ppUndo ); |
| |
| eTblChgMode = eOld; |
| return bRet; |
| } |
| } |
| else |
| bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, |
| nAbsDiff, sal_True ); |
| |
| if( bRet ) |
| { |
| if( bInsDel ) |
| { |
| if( !aParam.aBoxes.Count() ) |
| ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ], |
| aParam, 0, sal_True ); |
| |
| pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst ); |
| |
| // #110525# delete complete table when last row is |
| // deleted |
| if( !bBigger && |
| aParam.aBoxes.Count() == aSortCntBoxes.Count() ) |
| { |
| GetFrmFmt()->GetDoc()->DeleteRowCol( aParam.aBoxes ); |
| return sal_False; |
| } |
| |
| |
| if( ppUndo ) |
| *ppUndo = aParam.CreateUndo( |
| bBigger ? UNDO_TABLE_INSROW |
| : UNDO_ROW_DELETE ); |
| } |
| else if( ppUndo ) |
| *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); |
| |
| (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, |
| nAbsDiff, sal_False ); |
| } |
| } |
| else |
| { |
| bRet = sal_True; |
| sal_uInt16 nStt, nEnd; |
| if( bTop ) |
| nStt = 0, nEnd = nBaseLinePos; |
| else |
| nStt = nBaseLinePos + 1, nEnd = pLines->Count(); |
| |
| // die akt. Hoehe der Lines besorgen |
| if( TBLFIX_CHGPROP == eTblChgMode ) |
| { |
| for( n = nStt; n < nEnd; ++n ) |
| { |
| SwLayoutFrm* pLineFrm = GetRowFrm( *(*pLines)[ n ] ); |
| ASSERT( pLineFrm, "wo ist der Frm von der SwTableLine?" ); |
| aParam.nMaxSpace += CalcRowRstHeight( pLineFrm ); |
| aParam.nMaxHeight += pLineFrm->Frm().Height(); |
| } |
| if( bBigger && aParam.nMaxSpace < nAbsDiff ) |
| bRet = sal_False; |
| } |
| else |
| { |
| if( bTop ? nEnd : nStt < nEnd ) |
| { |
| if( bTop ) |
| nStt = nEnd - 1; |
| else |
| nEnd = nStt + 1; |
| } |
| else |
| bRet = sal_False; |
| } |
| |
| if( bRet ) |
| { |
| if( bBigger ) |
| { |
| for( n = nStt; n < nEnd; ++n ) |
| { |
| if( !(*fnOtherLine)( (*pLines)[ n ], aParam, |
| nAbsDiff, sal_True )) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| } |
| else |
| bRet = (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, |
| nAbsDiff, sal_True ); |
| } |
| |
| if( bRet ) |
| { |
| // dann mal anpassen |
| if( bInsDel ) |
| { |
| if( !aParam.aBoxes.Count() ) |
| ::lcl_InsDelSelLine( (*pLines)[ nBaseLinePos ], |
| aParam, 0, sal_True ); |
| pFndBox = ::lcl_SaveInsDelData( aParam, ppUndo, aTmpLst ); |
| if( ppUndo ) |
| *ppUndo = aParam.CreateUndo( |
| bBigger ? UNDO_TABLE_INSROW |
| : UNDO_ROW_DELETE ); |
| } |
| else if( ppUndo ) |
| *ppUndo = new SwUndoAttrTbl( *aParam.pTblNd, sal_True ); |
| |
| CR_SetLineHeight aParam1( aParam ); |
| if( TBLFIX_CHGPROP == eTblChgMode && !bBigger && |
| !aParam.nMaxSpace ) |
| { |
| // dann muss der gesamte Platz auf alle Lines |
| // gleichmaessig verteilt werden. Dafuer wird die |
| // Anzahl benoetigt |
| aParam1.nLines = nEnd - nStt; |
| } |
| |
| if( bTop ) |
| { |
| (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, |
| nAbsDiff, sal_False ); |
| for( n = nStt; n < nEnd; ++n ) |
| (*fnOtherLine)( (*pLines)[ n ], aParam1, |
| nAbsDiff, sal_False ); |
| } |
| else |
| { |
| for( n = nStt; n < nEnd; ++n ) |
| (*fnOtherLine)( (*pLines)[ n ], aParam1, |
| nAbsDiff, sal_False ); |
| (*fnSelLine)( (*pLines)[ nBaseLinePos ], aParam, |
| nAbsDiff, sal_False ); |
| } |
| } |
| else |
| { |
| // dann sich selbst rekursiv aufrufen; nur mit |
| // einem anderen Mode -> proprotional |
| TblChgMode eOld = eTblChgMode; |
| eTblChgMode = TBLVAR_CHGABS; |
| |
| bRet = SetRowHeight( rAktBox, eType, nAbsDiff, |
| nRelDiff, ppUndo ); |
| |
| eTblChgMode = eOld; |
| pFndBox = 0; |
| } |
| } |
| } |
| break; |
| } |
| |
| if( pFndBox ) |
| { |
| // dann raeume die Struktur aller Lines auf |
| GCLines(); |
| |
| //Layout updaten |
| if( bBigger || pFndBox->AreLinesToRestore( *this ) ) |
| pFndBox->MakeFrms( *this ); |
| |
| // TL_CHART2: it is currently unclear if sth has to be done here. |
| |
| delete pFndBox; |
| |
| if( ppUndo && *ppUndo ) |
| { |
| aParam.pUndo->SetColWidthParam( nBoxIdx, static_cast<sal_uInt16>(eTblChgMode), eType, |
| nAbsDiff, nRelDiff ); |
| if( bBigger ) |
| aParam.pUndo->SaveNewBoxes( *aParam.pTblNd, aTmpLst ); |
| } |
| } |
| |
| CHECKTABLELAYOUT |
| |
| return bRet; |
| } |
| |
| /* */ |
| |
| SwFrmFmt* SwShareBoxFmt::GetFormat( long nWidth ) const |
| { |
| SwFrmFmt *pRet = 0, *pTmp; |
| for( sal_uInt16 n = aNewFmts.Count(); n; ) |
| if( ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])->GetFrmSize().GetWidth() |
| == nWidth ) |
| { |
| pRet = pTmp; |
| break; |
| } |
| return pRet; |
| } |
| |
| SwFrmFmt* SwShareBoxFmt::GetFormat( const SfxPoolItem& rItem ) const |
| { |
| const SfxPoolItem* pItem; |
| sal_uInt16 nWhich = rItem.Which(); |
| SwFrmFmt *pRet = 0, *pTmp; |
| const SfxPoolItem& rFrmSz = pOldFmt->GetFmtAttr( RES_FRM_SIZE, sal_False ); |
| for( sal_uInt16 n = aNewFmts.Count(); n; ) |
| if( SFX_ITEM_SET == ( pTmp = (SwFrmFmt*)aNewFmts[ --n ])-> |
| GetItemState( nWhich, sal_False, &pItem ) && *pItem == rItem && |
| pTmp->GetFmtAttr( RES_FRM_SIZE, sal_False ) == rFrmSz ) |
| { |
| pRet = pTmp; |
| break; |
| } |
| return pRet; |
| } |
| |
| void SwShareBoxFmt::AddFormat( const SwFrmFmt& rNew ) |
| { |
| void* pFmt = (void*)&rNew; |
| aNewFmts.Insert( pFmt, aNewFmts.Count() ); |
| } |
| |
| sal_Bool SwShareBoxFmt::RemoveFormat( const SwFrmFmt& rFmt ) |
| { |
| // returnt sal_True, wenn geloescht werden kann |
| if( pOldFmt == &rFmt ) |
| return sal_True; |
| |
| void* p = (void*)&rFmt; |
| sal_uInt16 nFnd = aNewFmts.GetPos( p ); |
| if( USHRT_MAX != nFnd ) |
| aNewFmts.Remove( nFnd ); |
| return 0 == aNewFmts.Count(); |
| } |
| |
| SwShareBoxFmts::~SwShareBoxFmts() |
| { |
| } |
| |
| SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, long nWidth ) const |
| { |
| sal_uInt16 nPos; |
| return Seek_Entry( rFmt, &nPos ) |
| ? aShareArr[ nPos ]->GetFormat( nWidth ) |
| : 0; |
| } |
| SwFrmFmt* SwShareBoxFmts::GetFormat( const SwFrmFmt& rFmt, |
| const SfxPoolItem& rItem ) const |
| { |
| sal_uInt16 nPos; |
| return Seek_Entry( rFmt, &nPos ) |
| ? aShareArr[ nPos ]->GetFormat( rItem ) |
| : 0; |
| } |
| |
| void SwShareBoxFmts::AddFormat( const SwFrmFmt& rOld, const SwFrmFmt& rNew ) |
| { |
| // wenn das Format nicht geshared ist, braucht es auch nicht in die |
| // Liste aufgenommen werden. Denn es gibt keinen 2. der es sucht. |
| //leider werden auch die CellFrms gefunden |
| // if( !rOld.IsLastDepend() ) |
| { |
| sal_uInt16 nPos; |
| SwShareBoxFmt* pEntry; |
| if( !Seek_Entry( rOld, &nPos )) |
| { |
| pEntry = new SwShareBoxFmt( rOld ); |
| aShareArr.C40_INSERT( SwShareBoxFmt, pEntry, nPos ); |
| } |
| else |
| pEntry = aShareArr[ nPos ]; |
| |
| pEntry->AddFormat( rNew ); |
| } |
| } |
| void SwShareBoxFmts::ChangeFrmFmt( SwTableBox* pBox, SwTableLine* pLn, |
| SwFrmFmt& rFmt ) |
| { |
| SwClient aCl; |
| SwFrmFmt* pOld = 0; |
| if( pBox ) |
| { |
| pOld = pBox->GetFrmFmt(); |
| pOld->Add( &aCl ); |
| pBox->ChgFrmFmt( (SwTableBoxFmt*)&rFmt ); |
| } |
| else if( pLn ) |
| { |
| pOld = pLn->GetFrmFmt(); |
| pOld->Add( &aCl ); |
| pLn->ChgFrmFmt( (SwTableLineFmt*)&rFmt ); |
| } |
| if( pOld && pOld->IsLastDepend() ) |
| { |
| RemoveFormat( *pOld ); |
| delete pOld; |
| } |
| } |
| |
| void SwShareBoxFmts::SetSize( SwTableBox& rBox, const SwFmtFrmSize& rSz ) |
| { |
| SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(), |
| *pRet = GetFormat( *pBoxFmt, rSz.GetWidth() ); |
| if( pRet ) |
| ChangeFrmFmt( &rBox, 0, *pRet ); |
| else |
| { |
| pRet = rBox.ClaimFrmFmt(); |
| pRet->SetFmtAttr( rSz ); |
| AddFormat( *pBoxFmt, *pRet ); |
| } |
| } |
| |
| void SwShareBoxFmts::SetAttr( SwTableBox& rBox, const SfxPoolItem& rItem ) |
| { |
| SwFrmFmt *pBoxFmt = rBox.GetFrmFmt(), |
| *pRet = GetFormat( *pBoxFmt, rItem ); |
| if( pRet ) |
| ChangeFrmFmt( &rBox, 0, *pRet ); |
| else |
| { |
| pRet = rBox.ClaimFrmFmt(); |
| pRet->SetFmtAttr( rItem ); |
| AddFormat( *pBoxFmt, *pRet ); |
| } |
| } |
| |
| void SwShareBoxFmts::SetAttr( SwTableLine& rLine, const SfxPoolItem& rItem ) |
| { |
| SwFrmFmt *pLineFmt = rLine.GetFrmFmt(), |
| *pRet = GetFormat( *pLineFmt, rItem ); |
| if( pRet ) |
| ChangeFrmFmt( 0, &rLine, *pRet ); |
| else |
| { |
| pRet = rLine.ClaimFrmFmt(); |
| pRet->SetFmtAttr( rItem ); |
| AddFormat( *pLineFmt, *pRet ); |
| } |
| } |
| |
| void SwShareBoxFmts::RemoveFormat( const SwFrmFmt& rFmt ) |
| { |
| for( sal_uInt16 i = aShareArr.Count(); i; ) |
| if( aShareArr[ --i ]->RemoveFormat( rFmt )) |
| aShareArr.DeleteAndDestroy( i ); |
| } |
| |
| sal_Bool SwShareBoxFmts::Seek_Entry( const SwFrmFmt& rFmt, sal_uInt16* pPos ) const |
| { |
| sal_uLong nIdx = (sal_uLong)&rFmt; |
| sal_uInt16 nO = aShareArr.Count(), nM, nU = 0; |
| if( nO > 0 ) |
| { |
| nO--; |
| while( nU <= nO ) |
| { |
| nM = nU + ( nO - nU ) / 2; |
| sal_uLong nFmt = (sal_uLong)&aShareArr[ nM ]->GetOldFormat(); |
| if( nFmt == nIdx ) |
| { |
| if( pPos ) |
| *pPos = nM; |
| return sal_True; |
| } |
| else if( nFmt < nIdx ) |
| nU = nM + 1; |
| else if( nM == 0 ) |
| { |
| if( pPos ) |
| *pPos = nU; |
| return sal_False; |
| } |
| else |
| nO = nM - 1; |
| } |
| } |
| if( pPos ) |
| *pPos = nU; |
| return sal_False; |
| } |
| |
| |