| /************************************************************** |
| * |
| * 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 "hintids.hxx" |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/boxitem.hxx> |
| #include <editeng/brshitem.hxx> |
| #include <editeng/frmdiritem.hxx> |
| #include <fmtornt.hxx> |
| #include <fmtfsize.hxx> |
| #include <fmtlsplt.hxx> |
| #include <fmtrowsplt.hxx> |
| #include <tabcol.hxx> |
| #include <frmatr.hxx> |
| #include <cellfrm.hxx> |
| #include <tabfrm.hxx> |
| #include <cntfrm.hxx> |
| #include <txtfrm.hxx> |
| #include <svx/svxids.hrc> |
| #include <doc.hxx> |
| #include <IDocumentUndoRedo.hxx> |
| #include "pam.hxx" |
| #include "swcrsr.hxx" |
| #include "viscrs.hxx" |
| #include "swtable.hxx" |
| #include "htmltbl.hxx" |
| #include "tblsel.hxx" |
| #include "swtblfmt.hxx" |
| #include "docary.hxx" |
| #include "ndindex.hxx" |
| #include "undobj.hxx" |
| #include "switerator.hxx" |
| #include <UndoTable.hxx> |
| |
| using namespace ::com::sun::star; |
| |
| |
| extern void ClearFEShellTabCols(); |
| |
| //siehe auch swtable.cxx |
| #define COLFUZZY 20L |
| |
| inline sal_Bool IsSame( long nA, long nB ) { return Abs(nA-nB) <= COLFUZZY; } |
| |
| class SwTblFmtCmp |
| { |
| public: |
| SwFrmFmt *pOld, |
| *pNew; |
| sal_Int16 nType; |
| |
| SwTblFmtCmp( SwFrmFmt *pOld, SwFrmFmt *pNew, sal_Int16 nType ); |
| |
| static SwFrmFmt *FindNewFmt( SvPtrarr &rArr, SwFrmFmt*pOld, sal_Int16 nType ); |
| static void Delete( SvPtrarr &rArr ); |
| }; |
| |
| |
| SwTblFmtCmp::SwTblFmtCmp( SwFrmFmt *pO, SwFrmFmt *pN, sal_Int16 nT ) |
| : pOld ( pO ), pNew ( pN ), nType( nT ) |
| { |
| } |
| |
| SwFrmFmt *SwTblFmtCmp::FindNewFmt( SvPtrarr &rArr, SwFrmFmt *pOld, sal_Int16 nType ) |
| { |
| for ( sal_uInt16 i = 0; i < rArr.Count(); ++i ) |
| { |
| SwTblFmtCmp *pCmp = (SwTblFmtCmp*)rArr[i]; |
| if ( pCmp->pOld == pOld && pCmp->nType == nType ) |
| return pCmp->pNew; |
| } |
| return 0; |
| } |
| |
| void SwTblFmtCmp::Delete( SvPtrarr &rArr ) |
| { |
| for ( sal_uInt16 i = 0; i < rArr.Count(); ++i ) |
| delete (SwTblFmtCmp*)rArr[i]; |
| } |
| |
| void lcl_GetStartEndCell( const SwCursor& rCrsr, |
| SwLayoutFrm *&prStart, SwLayoutFrm *&prEnd ) |
| { |
| ASSERT( rCrsr.GetCntntNode() && rCrsr.GetCntntNode( sal_False ), |
| "Tabselection nicht auf Cnt." ); |
| |
| Point aPtPos, aMkPos; |
| const SwShellCrsr* pShCrsr = dynamic_cast<const SwShellCrsr*>(&rCrsr); |
| if( pShCrsr ) |
| { |
| aPtPos = pShCrsr->GetPtPos(); |
| aMkPos = pShCrsr->GetMkPos(); |
| } |
| |
| // robust: |
| SwCntntNode* pPointNd = rCrsr.GetCntntNode(); |
| SwCntntNode* pMarkNd = rCrsr.GetCntntNode(sal_False); |
| |
| SwFrm* pPointFrm = pPointNd ? pPointNd->getLayoutFrm( pPointNd->GetDoc()->GetCurrentLayout(), &aPtPos ) : 0; |
| SwFrm* pMarkFrm = pMarkNd ? pMarkNd->getLayoutFrm( pMarkNd->GetDoc()->GetCurrentLayout(), &aMkPos ) : 0; |
| |
| prStart = pPointFrm ? pPointFrm->GetUpper() : 0; |
| prEnd = pMarkFrm ? pMarkFrm->GetUpper() : 0; |
| } |
| |
| sal_Bool lcl_GetBoxSel( const SwCursor& rCursor, SwSelBoxes& rBoxes, |
| sal_Bool bAllCrsr = sal_False ) |
| { |
| const SwTableCursor* pTblCrsr = |
| dynamic_cast<const SwTableCursor*>(&rCursor); |
| if( pTblCrsr ) |
| ::GetTblSelCrs( *pTblCrsr, rBoxes ); |
| else |
| { |
| const SwPaM *pCurPam = &rCursor, *pSttPam = pCurPam; |
| do { |
| const SwNode* pNd = pCurPam->GetNode()->FindTableBoxStartNode(); |
| if( pNd ) |
| { |
| SwTableBox* pBox = (SwTableBox*)pNd->FindTableNode()->GetTable(). |
| GetTblBox( pNd->GetIndex() ); |
| rBoxes.Insert( pBox ); |
| } |
| } while( bAllCrsr && |
| pSttPam != ( pCurPam = (SwPaM*)pCurPam->GetNext()) ); |
| } |
| return 0 != rBoxes.Count(); |
| } |
| |
| /*********************************************************************** |
| #* Class : SwDoc |
| #* Methoden : SetRowHeight(), GetRowHeight() |
| #* Datum : MA 17. May. 93 |
| #* Update : JP 28.04.98 |
| #***********************************************************************/ |
| //Die Zeilenhoehe wird ausgehend von der Selektion ermittelt/gesetzt. |
| //Ausgehend von jeder Zelle innerhalb der Selektion werden nach oben alle |
| //Zeilen abgeklappert, die oberste Zeile erhaelt den gewuenschten Wert alle |
| //tieferliegenden Zeilen einen entsprechenden Wert der sich aus der |
| //Relation der alten und neuen Groesse der obersten Zeile und ihrer |
| //eigenen Groesse ergiebt. |
| //Alle veraenderten Zeilen erhalten ggf. ein eigenes FrmFmt. |
| //Natuerlich darf jede Zeile nur einmal angefasst werden. |
| |
| inline void InsertLine( SvPtrarr& rLineArr, SwTableLine* pLine ) |
| { |
| if( USHRT_MAX == rLineArr.GetPos( pLine ) ) |
| rLineArr.Insert( pLine, rLineArr.Count() ); |
| } |
| |
| //----------------------------------------------------------------------------- |
| |
| sal_Bool lcl_IsAnLower( const SwTableLine *pLine, const SwTableLine *pAssumed ) |
| { |
| const SwTableLine *pTmp = pAssumed->GetUpper() ? |
| pAssumed->GetUpper()->GetUpper() : 0; |
| while ( pTmp ) |
| { |
| if ( pTmp == pLine ) |
| return sal_True; |
| pTmp = pTmp->GetUpper() ? pTmp->GetUpper()->GetUpper() : 0; |
| } |
| return sal_False; |
| } |
| //----------------------------------------------------------------------------- |
| |
| struct LinesAndTable |
| { |
| SvPtrarr &rLines; |
| const SwTable &rTable; |
| sal_Bool bInsertLines; |
| |
| LinesAndTable( SvPtrarr &rL, const SwTable &rTbl ) : |
| rLines( rL ), rTable( rTbl ), bInsertLines( sal_True ) {} |
| }; |
| |
| |
| sal_Bool _FindLine( const _FndLine*& rpLine, void* pPara ); |
| |
| sal_Bool _FindBox( const _FndBox*& rpBox, void* pPara ) |
| { |
| if ( rpBox->GetLines().Count() ) |
| { |
| ((LinesAndTable*)pPara)->bInsertLines = sal_True; |
| ((_FndBox*)rpBox)->GetLines().ForEach( _FindLine, pPara ); |
| if ( ((LinesAndTable*)pPara)->bInsertLines ) |
| { |
| const SwTableLines &rLines = rpBox->GetBox() |
| ? rpBox->GetBox()->GetTabLines() |
| : ((LinesAndTable*)pPara)->rTable.GetTabLines(); |
| if ( rpBox->GetLines().Count() == rLines.Count() ) |
| { |
| for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) |
| ::InsertLine( ((LinesAndTable*)pPara)->rLines, |
| (SwTableLine*)rLines[i] ); |
| } |
| else |
| ((LinesAndTable*)pPara)->bInsertLines = sal_False; |
| } |
| } |
| else if ( rpBox->GetBox() ) |
| ::InsertLine( ((LinesAndTable*)pPara)->rLines, |
| (SwTableLine*)rpBox->GetBox()->GetUpper() ); |
| return sal_True; |
| } |
| |
| sal_Bool _FindLine( const _FndLine*& rpLine, void* pPara ) |
| { |
| ((_FndLine*)rpLine)->GetBoxes().ForEach( _FindBox, pPara ); |
| return sal_True; |
| } |
| |
| void lcl_CollectLines( SvPtrarr &rArr, const SwCursor& rCursor, bool bRemoveLines ) |
| { |
| //Zuerst die selektierten Boxen einsammeln. |
| SwSelBoxes aBoxes; |
| if( !::lcl_GetBoxSel( rCursor, aBoxes )) |
| return ; |
| |
| //Die selektierte Struktur kopieren. |
| const SwTable &rTable = aBoxes[0]->GetSttNd()->FindTableNode()->GetTable(); |
| LinesAndTable aPara( rArr, rTable ); |
| _FndBox aFndBox( 0, 0 ); |
| { |
| _FndPara aTmpPara( aBoxes, &aFndBox ); |
| ((SwTableLines&)rTable.GetTabLines()).ForEach( &_FndLineCopyCol, &aTmpPara ); |
| } |
| |
| //Diejenigen Lines einsammeln, die nur selektierte Boxen enthalten. |
| const _FndBox *pTmp = &aFndBox; |
| ::_FindBox( pTmp, &aPara ); |
| |
| // Remove lines, that have a common superordinate row. |
| // (Not for row split) |
| if ( bRemoveLines ) |
| { |
| for ( sal_uInt16 i = 0; i < rArr.Count(); ++i ) |
| { |
| SwTableLine *pUpLine = (SwTableLine*)rArr[i]; |
| for ( sal_uInt16 k = 0; k < rArr.Count(); ++k ) |
| { |
| if ( k != i && ::lcl_IsAnLower( pUpLine, (SwTableLine*)rArr[k] ) ) |
| { |
| rArr.Remove( k ); |
| if ( k <= i ) |
| --i; |
| --k; |
| } |
| } |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------- |
| |
| void lcl_ProcessRowAttr( SvPtrarr& rFmtCmp, SwTableLine* pLine, const SfxPoolItem& rNew ) |
| { |
| SwFrmFmt *pNewFmt; |
| if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( rFmtCmp, pLine->GetFrmFmt(), 0 ))) |
| pLine->ChgFrmFmt( (SwTableLineFmt*)pNewFmt ); |
| else |
| { |
| SwFrmFmt *pOld = pLine->GetFrmFmt(); |
| SwFrmFmt *pNew = pLine->ClaimFrmFmt(); |
| pNew->SetFmtAttr( rNew ); |
| rFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, 0 ), rFmtCmp.Count()); |
| } |
| } |
| |
| //----------------------------------------------------------------------------- |
| |
| void lcl_ProcessBoxSize( SvPtrarr &rFmtCmp, SwTableBox *pBox, const SwFmtFrmSize &rNew ); |
| |
| void lcl_ProcessRowSize( SvPtrarr &rFmtCmp, SwTableLine *pLine, const SwFmtFrmSize &rNew ) |
| { |
| lcl_ProcessRowAttr( rFmtCmp, pLine, rNew ); |
| SwTableBoxes &rBoxes = pLine->GetTabBoxes(); |
| for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i ) |
| ::lcl_ProcessBoxSize( rFmtCmp, rBoxes[i], rNew ); |
| } |
| |
| //----------------------------------------------------------------------------- |
| |
| void lcl_ProcessBoxSize( SvPtrarr &rFmtCmp, SwTableBox *pBox, const SwFmtFrmSize &rNew ) |
| { |
| SwTableLines &rLines = pBox->GetTabLines(); |
| if ( rLines.Count() ) |
| { |
| SwFmtFrmSize aSz( rNew ); |
| aSz.SetHeight( rNew.GetHeight() ? rNew.GetHeight() / rLines.Count() : 0 ); |
| for ( sal_uInt16 i = 0; i < rLines.Count(); ++i ) |
| ::lcl_ProcessRowSize( rFmtCmp, rLines[i], aSz ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------- |
| |
| /****************************************************************************** |
| * void SwDoc::SetRowSplit() |
| ******************************************************************************/ |
| void SwDoc::SetRowSplit( const SwCursor& rCursor, const SwFmtRowSplit &rNew ) |
| { |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| { |
| SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines. |
| ::lcl_CollectLines( aRowArr, rCursor, false ); |
| |
| if( aRowArr.Count() ) |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd)); |
| } |
| |
| SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 ); |
| |
| for( sal_uInt16 i = 0; i < aRowArr.Count(); ++i ) |
| ::lcl_ProcessRowAttr( aFmtCmp, (SwTableLine*)aRowArr[i], rNew ); |
| |
| SwTblFmtCmp::Delete( aFmtCmp ); |
| SetModified(); |
| } |
| } |
| } |
| |
| |
| /****************************************************************************** |
| * SwTwips SwDoc::GetRowSplit() const |
| ******************************************************************************/ |
| void SwDoc::GetRowSplit( const SwCursor& rCursor, SwFmtRowSplit *& rpSz ) const |
| { |
| rpSz = 0; |
| |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| { |
| SvPtrarr aRowArr( 25, 50 ); //Zum sammeln der Lines. |
| ::lcl_CollectLines( aRowArr, rCursor, false ); |
| |
| if( aRowArr.Count() ) |
| { |
| rpSz = &(SwFmtRowSplit&)((SwTableLine*)aRowArr[0])-> |
| GetFrmFmt()->GetRowSplit(); |
| |
| for ( sal_uInt16 i = 1; i < aRowArr.Count() && rpSz; ++i ) |
| { |
| if ( (*rpSz).GetValue() != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetRowSplit().GetValue() ) |
| rpSz = 0; |
| } |
| if ( rpSz ) |
| rpSz = new SwFmtRowSplit( *rpSz ); |
| } |
| } |
| } |
| |
| |
| /****************************************************************************** |
| * void SwDoc::SetRowHeight( SwTwips nNew ) |
| ******************************************************************************/ |
| void SwDoc::SetRowHeight( const SwCursor& rCursor, const SwFmtFrmSize &rNew ) |
| { |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| { |
| SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines. |
| ::lcl_CollectLines( aRowArr, rCursor, true ); |
| |
| if( aRowArr.Count() ) |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd)); |
| } |
| |
| SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 ); |
| for ( sal_uInt16 i = 0; i < aRowArr.Count(); ++i ) |
| ::lcl_ProcessRowSize( aFmtCmp, (SwTableLine*)aRowArr[i], rNew ); |
| SwTblFmtCmp::Delete( aFmtCmp ); |
| |
| SetModified(); |
| } |
| } |
| } |
| |
| |
| /****************************************************************************** |
| * SwTwips SwDoc::GetRowHeight() const |
| ******************************************************************************/ |
| void SwDoc::GetRowHeight( const SwCursor& rCursor, SwFmtFrmSize *& rpSz ) const |
| { |
| rpSz = 0; |
| |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| { |
| SvPtrarr aRowArr( 25, 50 ); //Zum sammeln der Lines. |
| ::lcl_CollectLines( aRowArr, rCursor, true ); |
| |
| if( aRowArr.Count() ) |
| { |
| rpSz = &(SwFmtFrmSize&)((SwTableLine*)aRowArr[0])-> |
| GetFrmFmt()->GetFrmSize(); |
| |
| for ( sal_uInt16 i = 1; i < aRowArr.Count() && rpSz; ++i ) |
| { |
| if ( *rpSz != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetFrmSize() ) |
| rpSz = 0; |
| } |
| if ( rpSz ) |
| rpSz = new SwFmtFrmSize( *rpSz ); |
| } |
| } |
| } |
| |
| sal_Bool SwDoc::BalanceRowHeight( const SwCursor& rCursor, sal_Bool bTstOnly ) |
| { |
| sal_Bool bRet = sal_False; |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| { |
| SvPtrarr aRowArr( 25, 50 ); //Zum sammeln der Lines. |
| ::lcl_CollectLines( aRowArr, rCursor, true ); |
| |
| if( 1 < aRowArr.Count() ) |
| { |
| if( !bTstOnly ) |
| { |
| long nHeight = 0; |
| sal_uInt16 i; |
| |
| for ( i = 0; i < aRowArr.Count(); ++i ) |
| { |
| SwIterator<SwFrm,SwFmt> aIter( *((SwTableLine*)aRowArr[i])->GetFrmFmt() ); |
| SwFrm* pFrm = aIter.First(); |
| while ( pFrm ) |
| { |
| nHeight = Max( nHeight, pFrm->Frm().Height() ); |
| pFrm = aIter.Next(); |
| } |
| } |
| SwFmtFrmSize aNew( ATT_MIN_SIZE, 0, nHeight ); |
| |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo( |
| new SwUndoAttrTbl(*pTblNd)); |
| } |
| |
| SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 ); |
| for( i = 0; i < aRowArr.Count(); ++i ) |
| ::lcl_ProcessRowSize( aFmtCmp, (SwTableLine*)aRowArr[i], aNew ); |
| SwTblFmtCmp::Delete( aFmtCmp ); |
| |
| SetModified(); |
| } |
| bRet = sal_True; |
| } |
| } |
| return bRet; |
| } |
| |
| /****************************************************************************** |
| * void SwDoc::SetRowBackground() |
| ******************************************************************************/ |
| void SwDoc::SetRowBackground( const SwCursor& rCursor, const SvxBrushItem &rNew ) |
| { |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| { |
| SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines. |
| ::lcl_CollectLines( aRowArr, rCursor, true ); |
| |
| if( aRowArr.Count() ) |
| { |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd)); |
| } |
| |
| SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aRowArr.Count()) ), 255 ); |
| |
| for( sal_uInt16 i = 0; i < aRowArr.Count(); ++i ) |
| ::lcl_ProcessRowAttr( aFmtCmp, (SwTableLine*)aRowArr[i], rNew ); |
| |
| SwTblFmtCmp::Delete( aFmtCmp ); |
| SetModified(); |
| } |
| } |
| } |
| |
| /****************************************************************************** |
| * SwTwips SwDoc::GetRowBackground() const |
| ******************************************************************************/ |
| sal_Bool SwDoc::GetRowBackground( const SwCursor& rCursor, SvxBrushItem &rToFill ) const |
| { |
| sal_Bool bRet = sal_False; |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| if( pTblNd ) |
| { |
| SvPtrarr aRowArr( 25, 50 ); //Zum sammeln Lines. |
| ::lcl_CollectLines( aRowArr, rCursor, true ); |
| |
| if( aRowArr.Count() ) |
| { |
| rToFill = ((SwTableLine*)aRowArr[0])->GetFrmFmt()->GetBackground(); |
| |
| bRet = sal_True; |
| for ( sal_uInt16 i = 1; i < aRowArr.Count(); ++i ) |
| if ( rToFill != ((SwTableLine*)aRowArr[i])->GetFrmFmt()->GetBackground() ) |
| { |
| bRet = sal_False; |
| break; |
| } |
| } |
| } |
| return bRet; |
| } |
| |
| /*********************************************************************** |
| #* Class : SwDoc |
| #* Methoden : SetTabBorders(), GetTabBorders() |
| #* Datum : MA 18. May. 93 |
| #* Update : JP 29.04.98 |
| #***********************************************************************/ |
| inline void InsertCell( SvPtrarr& rCellArr, SwCellFrm* pCellFrm ) |
| { |
| if( USHRT_MAX == rCellArr.GetPos( pCellFrm ) ) |
| rCellArr.Insert( pCellFrm, rCellArr.Count() ); |
| } |
| |
| //----------------------------------------------------------------------------- |
| void lcl_CollectCells( SvPtrarr &rArr, const SwRect &rUnion, |
| SwTabFrm *pTab ) |
| { |
| SwLayoutFrm *pCell = pTab->FirstCell(); |
| do |
| { |
| // Wenn in der Zelle ein spaltiger Bereich sitzt, muessen wir |
| // uns erst wieder zur Zelle hochhangeln |
| while ( !pCell->IsCellFrm() ) |
| pCell = pCell->GetUpper(); |
| ASSERT( pCell, "Frame ist keine Zelle." ); |
| if ( rUnion.IsOver( pCell->Frm() ) ) |
| ::InsertCell( rArr, (SwCellFrm*)pCell ); |
| //Dafuer sorgen, dass die Zelle auch verlassen wird (Bereiche) |
| SwLayoutFrm *pTmp = pCell; |
| do |
| { pTmp = pTmp->GetNextLayoutLeaf(); |
| } while ( pCell->IsAnLower( pTmp ) ); |
| pCell = pTmp; |
| } while( pCell && pTab->IsAnLower( pCell ) ); |
| } |
| |
| void SwDoc::SetTabBorders( const SwCursor& rCursor, const SfxItemSet& rSet ) |
| { |
| SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode(); |
| SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0; |
| if( !pTblNd ) |
| return ; |
| |
| SwLayoutFrm *pStart, *pEnd; |
| ::lcl_GetStartEndCell( rCursor, pStart, pEnd ); |
| |
| SwSelUnions aUnions; |
| ::MakeSelUnions( aUnions, pStart, pEnd ); |
| |
| if( aUnions.Count() ) |
| { |
| SwTable& rTable = pTblNd->GetTable(); |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTbl(*pTblNd) ); |
| } |
| |
| SvPtrarr aFmtCmp( 255, 255 ); |
| const SvxBoxItem* pSetBox; |
| const SvxBoxInfoItem *pSetBoxInfo; |
| |
| const SvxBorderLine* pLeft = 0; |
| const SvxBorderLine* pRight = 0; |
| const SvxBorderLine* pTop = 0; |
| const SvxBorderLine* pBottom = 0; |
| const SvxBorderLine* pHori = 0; |
| const SvxBorderLine* pVert = 0; |
| sal_Bool bHoriValid = sal_True, bVertValid = sal_True, |
| bTopValid = sal_True, bBottomValid = sal_True, |
| bLeftValid = sal_True, bRightValid = sal_True; |
| |
| // JP 21.07.95: die Flags im BoxInfo-Item entscheiden, wann eine |
| // BorderLine gueltig ist!! |
| if( SFX_ITEM_SET == rSet.GetItemState( SID_ATTR_BORDER_INNER, sal_False, |
| (const SfxPoolItem**)&pSetBoxInfo) ) |
| { |
| pHori = pSetBoxInfo->GetHori(); |
| pVert = pSetBoxInfo->GetVert(); |
| |
| bHoriValid = pSetBoxInfo->IsValid(VALID_HORI); |
| bVertValid = pSetBoxInfo->IsValid(VALID_VERT); |
| |
| // wollen wir die auswerten ?? |
| bTopValid = pSetBoxInfo->IsValid(VALID_TOP); |
| bBottomValid = pSetBoxInfo->IsValid(VALID_BOTTOM); |
| bLeftValid = pSetBoxInfo->IsValid(VALID_LEFT); |
| bRightValid = pSetBoxInfo->IsValid(VALID_RIGHT); |
| } |
| |
| if( SFX_ITEM_SET == rSet.GetItemState( RES_BOX, sal_False, |
| (const SfxPoolItem**)&pSetBox) ) |
| { |
| pLeft = pSetBox->GetLeft(); |
| pRight = pSetBox->GetRight(); |
| pTop = pSetBox->GetTop(); |
| pBottom = pSetBox->GetBottom(); |
| } |
| else |
| { |
| // nicht gesetzt, also keine gueltigen Werte |
| bTopValid = bBottomValid = bLeftValid = bRightValid = sal_False; |
| pSetBox = 0; |
| } |
| |
| sal_Bool bFirst = sal_True; |
| for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i ) |
| { |
| SwSelUnion *pUnion = aUnions[i]; |
| SwTabFrm *pTab = pUnion->GetTable(); |
| const SwRect &rUnion = pUnion->GetUnion(); |
| const sal_Bool bLast = i == aUnions.Count() - 1 ? sal_True : sal_False; |
| |
| SvPtrarr aCellArr( 255, 255 ); |
| ::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab ); |
| |
| //Alle Zellenkanten, die mit dem UnionRect uebereinstimmen oder |
| //darueber hinausragen sind Aussenkanten. Alle anderen sind |
| //Innenkanten. |
| //neu: Die Aussenkanten koennen abhaengig davon, ob es sich um eine |
| //Start/Mittlere/Folge -Tabelle (bei Selektionen ueber FollowTabs) |
| //handelt doch keine Aussenkanten sein. |
| //Aussenkanten werden links, rechts, oben und unten gesetzt. |
| //Innenkanten werden nur oben und links gesetzt. |
| for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j ) |
| { |
| SwCellFrm *pCell = (SwCellFrm*)aCellArr[j]; |
| const sal_Bool bVert = pTab->IsVertical(); |
| const sal_Bool bRTL = pTab->IsRightToLeft(); |
| sal_Bool bTopOver, bLeftOver, bRightOver, bBottomOver; |
| if ( bVert ) |
| { |
| bTopOver = pCell->Frm().Right() >= rUnion.Right(); |
| bLeftOver = pCell->Frm().Top() <= rUnion.Top(); |
| bRightOver = pCell->Frm().Bottom() >= rUnion.Bottom(); |
| bBottomOver = pCell->Frm().Left() <= rUnion.Left(); |
| } |
| else |
| { |
| bTopOver = pCell->Frm().Top() <= rUnion.Top(); |
| bLeftOver = pCell->Frm().Left() <= rUnion.Left(); |
| bRightOver = pCell->Frm().Right() >= rUnion.Right(); |
| bBottomOver = pCell->Frm().Bottom() >= rUnion.Bottom(); |
| } |
| |
| if ( bRTL ) |
| { |
| sal_Bool bTmp = bRightOver; |
| bRightOver = bLeftOver; |
| bLeftOver = bTmp; |
| } |
| |
| //Grundsaetzlich nichts setzen in HeadlineRepeats. |
| if ( pTab->IsFollow() && |
| ( pTab->IsInHeadline( *pCell ) || |
| // --> FME 2006-02-07 #126092# Same holds for follow flow rows. |
| pCell->IsInFollowFlowRow() ) ) |
| // <-- |
| continue; |
| |
| SvxBoxItem aBox( pCell->GetFmt()->GetBox() ); |
| |
| sal_Int16 nType = 0; |
| |
| //Obere Kante |
| if( bTopValid ) |
| { |
| if ( bFirst && bTopOver ) |
| { |
| aBox.SetLine( pTop, BOX_LINE_TOP ); |
| nType |= 0x0001; |
| } |
| else if ( bHoriValid ) |
| { |
| aBox.SetLine( 0, BOX_LINE_TOP ); |
| nType |= 0x0002; |
| } |
| } |
| |
| //Linke Kante |
| if ( bLeftOver ) |
| { |
| if( bLeftValid ) |
| { |
| aBox.SetLine( pLeft, BOX_LINE_LEFT ); |
| nType |= 0x0004; |
| } |
| } |
| else if( bVertValid ) |
| { |
| aBox.SetLine( pVert, BOX_LINE_LEFT ); |
| nType |= 0x0008; |
| } |
| |
| //Rechte Kante |
| if( bRightValid ) |
| { |
| if ( bRightOver ) |
| { |
| aBox.SetLine( pRight, BOX_LINE_RIGHT ); |
| nType |= 0x0010; |
| } |
| else if ( bVertValid ) |
| { |
| aBox.SetLine( 0, BOX_LINE_RIGHT ); |
| nType |= 0x0020; |
| } |
| } |
| |
| //Untere Kante |
| if ( bLast && bBottomOver ) |
| { |
| if( bBottomValid ) |
| { |
| aBox.SetLine( pBottom, BOX_LINE_BOTTOM ); |
| nType |= 0x0040; |
| } |
| } |
| else if( bHoriValid ) |
| { |
| aBox.SetLine( pHori, BOX_LINE_BOTTOM ); |
| nType |= 0x0080; |
| } |
| |
| if( pSetBox ) |
| { |
| static sal_uInt16 __READONLY_DATA aBorders[] = { |
| BOX_LINE_BOTTOM, BOX_LINE_TOP, |
| BOX_LINE_RIGHT, BOX_LINE_LEFT }; |
| const sal_uInt16* pBrd = aBorders; |
| for( int k = 0; k < 4; ++k, ++pBrd ) |
| aBox.SetDistance( pSetBox->GetDistance( *pBrd ), *pBrd ); |
| } |
| |
| SwTableBox *pBox = (SwTableBox*)pCell->GetTabBox(); |
| SwFrmFmt *pNewFmt; |
| if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( aFmtCmp, pBox->GetFrmFmt(), nType ))) |
| pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt ); |
| else |
| { |
| SwFrmFmt *pOld = pBox->GetFrmFmt(); |
| SwFrmFmt *pNew = pBox->ClaimFrmFmt(); |
| pNew->SetFmtAttr( aBox ); |
| aFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, nType ), aFmtCmp.Count()); |
| } |
| } |
| |
| bFirst = sal_False; |
| } |
| |
| SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout(); |
| if( pTableLayout ) |
| { |
| SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() ); |
| SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm(); |
| |
| pTableLayout->BordersChanged( |
| pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True ); |
| } |
| SwTblFmtCmp::Delete( aFmtCmp ); |
| ::ClearFEShellTabCols(); |
| SetModified(); |
| } |
| } |
| |
| void lcl_SetLineStyle( SvxBorderLine *pToSet, |
| const Color *pColor, const SvxBorderLine *pBorderLine) |
| { |
| if ( pBorderLine ) |
| { |
| if ( !pColor ) |
| { |
| Color aTmp( pToSet->GetColor() ); |
| *pToSet = *pBorderLine; |
| pToSet->SetColor( aTmp ); |
| } |
| else |
| *pToSet = *pBorderLine; |
| } |
| if ( pColor ) |
| pToSet->SetColor( *pColor ); |
| } |
| |
| void SwDoc::SetTabLineStyle( const SwCursor& rCursor, |
| const Color* pColor, sal_Bool bSetLine, |
| const SvxBorderLine* pBorderLine ) |
| { |
| SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode(); |
| SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0; |
| if( !pTblNd ) |
| return ; |
| |
| SwLayoutFrm *pStart, *pEnd; |
| ::lcl_GetStartEndCell( rCursor, pStart, pEnd ); |
| |
| SwSelUnions aUnions; |
| ::MakeSelUnions( aUnions, pStart, pEnd ); |
| |
| if( aUnions.Count() ) |
| { |
| SwTable& rTable = pTblNd->GetTable(); |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo(new SwUndoAttrTbl(*pTblNd)); |
| } |
| |
| for( sal_uInt16 i = 0; i < aUnions.Count(); ++i ) |
| { |
| SwSelUnion *pUnion = aUnions[i]; |
| SwTabFrm *pTab = pUnion->GetTable(); |
| SvPtrarr aCellArr( 255, 255 ); |
| ::lcl_CollectCells( aCellArr, pUnion->GetUnion(), pTab ); |
| |
| for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j ) |
| { |
| SwCellFrm *pCell = ( SwCellFrm* )aCellArr[j]; |
| |
| //Grundsaetzlich nichts setzen in HeadlineRepeats. |
| if ( pTab->IsFollow() && pTab->IsInHeadline( *pCell ) ) |
| continue; |
| |
| ((SwTableBox*)pCell->GetTabBox())->ClaimFrmFmt(); |
| SwFrmFmt *pFmt = pCell->GetFmt(); |
| SvxBoxItem aBox( pFmt->GetBox() ); |
| |
| if ( !pBorderLine && bSetLine ) |
| aBox = *(SvxBoxItem*)::GetDfltAttr( RES_BOX ); |
| else |
| { |
| if ( aBox.GetTop() ) |
| ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetTop(), |
| pColor, pBorderLine ); |
| if ( aBox.GetBottom() ) |
| ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetBottom(), |
| pColor, pBorderLine ); |
| if ( aBox.GetLeft() ) |
| ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetLeft(), |
| pColor, pBorderLine ); |
| if ( aBox.GetRight() ) |
| ::lcl_SetLineStyle( (SvxBorderLine*)aBox.GetRight(), |
| pColor, pBorderLine ); |
| } |
| pFmt->SetFmtAttr( aBox ); |
| } |
| } |
| |
| SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout(); |
| if( pTableLayout ) |
| { |
| SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() ); |
| SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm(); |
| |
| pTableLayout->BordersChanged( |
| pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True ); |
| } |
| ::ClearFEShellTabCols(); |
| SetModified(); |
| } |
| } |
| |
| void SwDoc::GetTabBorders( const SwCursor& rCursor, SfxItemSet& rSet ) const |
| { |
| SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode(); |
| SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0; |
| if( !pTblNd ) |
| return ; |
| |
| SwLayoutFrm *pStart, *pEnd; |
| ::lcl_GetStartEndCell( rCursor, pStart, pEnd ); |
| |
| SwSelUnions aUnions; |
| ::MakeSelUnions( aUnions, pStart, pEnd ); |
| |
| if( aUnions.Count() ) |
| { |
| SvxBoxItem aSetBox ((const SvxBoxItem &) rSet.Get(RES_BOX )); |
| SvxBoxInfoItem aSetBoxInfo((const SvxBoxInfoItem&) rSet.Get(SID_ATTR_BORDER_INNER)); |
| |
| sal_Bool bTopSet = sal_False, |
| bBottomSet = sal_False, |
| bLeftSet = sal_False, |
| bRightSet = sal_False, |
| bHoriSet = sal_False, |
| bVertSet = sal_False, |
| bDistanceSet = sal_False; |
| |
| aSetBoxInfo.ResetFlags(); |
| |
| for ( sal_uInt16 i = 0; i < aUnions.Count(); ++i ) |
| { |
| SwSelUnion *pUnion = aUnions[i]; |
| const SwTabFrm *pTab = pUnion->GetTable(); |
| const SwRect &rUnion = pUnion->GetUnion(); |
| const sal_Bool bFirst = i == 0 ? sal_True : sal_False; |
| const sal_Bool bLast = i == aUnions.Count() - 1 ? sal_True : sal_False; |
| |
| SvPtrarr aCellArr( 255, 255 ); |
| ::lcl_CollectCells( aCellArr, rUnion, (SwTabFrm*)pTab ); |
| |
| for ( sal_uInt16 j = 0; j < aCellArr.Count(); ++j ) |
| { |
| const SwCellFrm *pCell = (const SwCellFrm*)aCellArr[j]; |
| const sal_Bool bVert = pTab->IsVertical(); |
| const sal_Bool bRTL = pTab->IsRightToLeft(); |
| sal_Bool bTopOver, bLeftOver, bRightOver, bBottomOver; |
| if ( bVert ) |
| { |
| bTopOver = pCell->Frm().Right() >= rUnion.Right(); |
| bLeftOver = pCell->Frm().Top() <= rUnion.Top(); |
| bRightOver = pCell->Frm().Bottom() >= rUnion.Bottom(); |
| bBottomOver = pCell->Frm().Left() <= rUnion.Left(); |
| } |
| else |
| { |
| bTopOver = pCell->Frm().Top() <= rUnion.Top(); |
| bLeftOver = pCell->Frm().Left() <= rUnion.Left(); |
| bRightOver = pCell->Frm().Right() >= rUnion.Right(); |
| bBottomOver = pCell->Frm().Bottom() >= rUnion.Bottom(); |
| } |
| |
| if ( bRTL ) |
| { |
| sal_Bool bTmp = bRightOver; |
| bRightOver = bLeftOver; |
| bLeftOver = bTmp; |
| } |
| |
| const SwFrmFmt *pFmt = pCell->GetFmt(); |
| const SvxBoxItem &rBox = pFmt->GetBox(); |
| |
| //Obere Kante |
| if ( bFirst && bTopOver ) |
| { |
| if (aSetBoxInfo.IsValid(VALID_TOP)) |
| { |
| if ( !bTopSet ) |
| { bTopSet = sal_True; |
| aSetBox.SetLine( rBox.GetTop(), BOX_LINE_TOP ); |
| } |
| else if ((aSetBox.GetTop() && rBox.GetTop() && |
| !(*aSetBox.GetTop() == *rBox.GetTop())) || |
| ((!aSetBox.GetTop()) ^ (!rBox.GetTop()))) // XOR-Ausdruck ist sal_True, wenn genau einer der beiden Pointer 0 ist |
| { |
| aSetBoxInfo.SetValid(VALID_TOP, sal_False ); |
| aSetBox.SetLine( 0, BOX_LINE_TOP ); |
| } |
| } |
| } |
| |
| //Linke Kante |
| if ( bLeftOver ) |
| { |
| if (aSetBoxInfo.IsValid(VALID_LEFT)) |
| { |
| if ( !bLeftSet ) |
| { bLeftSet = sal_True; |
| aSetBox.SetLine( rBox.GetLeft(), BOX_LINE_LEFT ); |
| } |
| else if ((aSetBox.GetLeft() && rBox.GetLeft() && |
| !(*aSetBox.GetLeft() == *rBox.GetLeft())) || |
| ((!aSetBox.GetLeft()) ^ (!rBox.GetLeft()))) |
| { |
| aSetBoxInfo.SetValid(VALID_LEFT, sal_False ); |
| aSetBox.SetLine( 0, BOX_LINE_LEFT ); |
| } |
| } |
| } |
| else |
| { |
| if (aSetBoxInfo.IsValid(VALID_VERT)) |
| { |
| if ( !bVertSet ) |
| { bVertSet = sal_True; |
| aSetBoxInfo.SetLine( rBox.GetLeft(), BOXINFO_LINE_VERT ); |
| } |
| else if ((aSetBoxInfo.GetVert() && rBox.GetLeft() && |
| !(*aSetBoxInfo.GetVert() == *rBox.GetLeft())) || |
| ((!aSetBoxInfo.GetVert()) ^ (!rBox.GetLeft()))) |
| { aSetBoxInfo.SetValid( VALID_VERT, sal_False ); |
| aSetBoxInfo.SetLine( 0, BOXINFO_LINE_VERT ); |
| } |
| } |
| } |
| |
| //Rechte Kante |
| if ( aSetBoxInfo.IsValid(VALID_RIGHT) && bRightOver ) |
| { |
| if ( !bRightSet ) |
| { bRightSet = sal_True; |
| aSetBox.SetLine( rBox.GetRight(), BOX_LINE_RIGHT ); |
| } |
| else if ((aSetBox.GetRight() && rBox.GetRight() && |
| !(*aSetBox.GetRight() == *rBox.GetRight())) || |
| (!aSetBox.GetRight() ^ !rBox.GetRight())) |
| { aSetBoxInfo.SetValid( VALID_RIGHT, sal_False ); |
| aSetBox.SetLine( 0, BOX_LINE_RIGHT ); |
| } |
| } |
| |
| //Untere Kante |
| if ( bLast && bBottomOver ) |
| { |
| if ( aSetBoxInfo.IsValid(VALID_BOTTOM) ) |
| { |
| if ( !bBottomSet ) |
| { bBottomSet = sal_True; |
| aSetBox.SetLine( rBox.GetBottom(), BOX_LINE_BOTTOM ); |
| } |
| else if ((aSetBox.GetBottom() && rBox.GetBottom() && |
| !(*aSetBox.GetBottom() == *rBox.GetBottom())) || |
| (!aSetBox.GetBottom() ^ !rBox.GetBottom())) |
| { aSetBoxInfo.SetValid( VALID_BOTTOM, sal_False ); |
| aSetBox.SetLine( 0, BOX_LINE_BOTTOM ); |
| } |
| } |
| } |
| //in allen Zeilen ausser der letzten werden die |
| // horiz. Linien aus der Bottom-Linie entnommen |
| else |
| { |
| if (aSetBoxInfo.IsValid(VALID_HORI)) |
| { |
| if ( !bHoriSet ) |
| { bHoriSet = sal_True; |
| aSetBoxInfo.SetLine( rBox.GetBottom(), BOXINFO_LINE_HORI ); |
| } |
| else if ((aSetBoxInfo.GetHori() && rBox.GetBottom() && |
| !(*aSetBoxInfo.GetHori() == *rBox.GetBottom())) || |
| ((!aSetBoxInfo.GetHori()) ^ (!rBox.GetBottom()))) |
| { |
| aSetBoxInfo.SetValid( VALID_HORI, sal_False ); |
| aSetBoxInfo.SetLine( 0, BOXINFO_LINE_HORI ); |
| } |
| } |
| } |
| |
| // Abstand zum Text |
| if (aSetBoxInfo.IsValid(VALID_DISTANCE)) |
| { |
| static sal_uInt16 __READONLY_DATA aBorders[] = { |
| BOX_LINE_BOTTOM, BOX_LINE_TOP, |
| BOX_LINE_RIGHT, BOX_LINE_LEFT }; |
| const sal_uInt16* pBrd = aBorders; |
| |
| if( !bDistanceSet ) // bei 1. Durchlauf erstmal setzen |
| { |
| bDistanceSet = sal_True; |
| for( int k = 0; k < 4; ++k, ++pBrd ) |
| aSetBox.SetDistance( rBox.GetDistance( *pBrd ), |
| *pBrd ); |
| } |
| else |
| { |
| for( int k = 0; k < 4; ++k, ++pBrd ) |
| if( aSetBox.GetDistance( *pBrd ) != |
| rBox.GetDistance( *pBrd ) ) |
| { |
| aSetBoxInfo.SetValid( VALID_DISTANCE, sal_False ); |
| aSetBox.SetDistance( (sal_uInt16) 0 ); |
| break; |
| } |
| } |
| } |
| } |
| } |
| rSet.Put( aSetBox ); |
| rSet.Put( aSetBoxInfo ); |
| } |
| } |
| |
| /*********************************************************************** |
| #* Class : SwDoc |
| #* Methoden : SetBoxAttr |
| #* Datum : MA 18. Dec. 96 |
| #* Update : JP 29.04.98 |
| #***********************************************************************/ |
| void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew ) |
| { |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| SwSelBoxes aBoxes; |
| if( pTblNd && ::lcl_GetBoxSel( rCursor, aBoxes, sal_True ) ) |
| { |
| SwTable& rTable = pTblNd->GetTable(); |
| if (GetIDocumentUndoRedo().DoesUndo()) |
| { |
| GetIDocumentUndoRedo().AppendUndo( new SwUndoAttrTbl(*pTblNd) ); |
| } |
| |
| SvPtrarr aFmtCmp( Max( sal_uInt8(255), sal_uInt8(aBoxes.Count()) ), 255 ); |
| for ( sal_uInt16 i = 0; i < aBoxes.Count(); ++i ) |
| { |
| SwTableBox *pBox = aBoxes[i]; |
| |
| SwFrmFmt *pNewFmt; |
| if ( 0 != (pNewFmt = SwTblFmtCmp::FindNewFmt( aFmtCmp, pBox->GetFrmFmt(), 0 ))) |
| pBox->ChgFrmFmt( (SwTableBoxFmt*)pNewFmt ); |
| else |
| { |
| SwFrmFmt *pOld = pBox->GetFrmFmt(); |
| SwFrmFmt *pNew = pBox->ClaimFrmFmt(); |
| pNew->SetFmtAttr( rNew ); |
| aFmtCmp.Insert( new SwTblFmtCmp( pOld, pNew, 0 ), aFmtCmp.Count()); |
| } |
| } |
| |
| SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout(); |
| if( pTableLayout ) |
| { |
| SwCntntFrm* pFrm = rCursor.GetCntntNode()->getLayoutFrm( rCursor.GetCntntNode()->GetDoc()->GetCurrentLayout() ); |
| SwTabFrm* pTabFrm = pFrm->ImplFindTabFrm(); |
| |
| pTableLayout->Resize( |
| pTableLayout->GetBrowseWidthByTabFrm( *pTabFrm ), sal_True ); |
| } |
| SwTblFmtCmp::Delete( aFmtCmp ); |
| SetModified(); |
| } |
| } |
| |
| /*********************************************************************** |
| #* Class : SwDoc |
| #* Methoden : GetBoxAttr() |
| #* Datum : MA 01. Jun. 93 |
| #* Update : JP 29.04.98 |
| #***********************************************************************/ |
| |
| sal_Bool SwDoc::GetBoxAttr( const SwCursor& rCursor, SfxPoolItem& rToFill ) const |
| { |
| sal_Bool bRet = sal_False; |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| SwSelBoxes aBoxes; |
| if( pTblNd && lcl_GetBoxSel( rCursor, aBoxes )) |
| { |
| bRet = sal_True; |
| sal_Bool bOneFound = sal_False; |
| const sal_uInt16 nWhich = rToFill.Which(); |
| for( sal_uInt16 i = 0; i < aBoxes.Count(); ++i ) |
| { |
| switch ( nWhich ) |
| { |
| case RES_BACKGROUND: |
| { |
| const SvxBrushItem &rBack = |
| aBoxes[i]->GetFrmFmt()->GetBackground(); |
| if( !bOneFound ) |
| { |
| (SvxBrushItem&)rToFill = rBack; |
| bOneFound = sal_True; |
| } |
| else if( rToFill != rBack ) |
| bRet = sal_False; |
| } |
| break; |
| |
| case RES_FRAMEDIR: |
| { |
| const SvxFrameDirectionItem& rDir = |
| aBoxes[i]->GetFrmFmt()->GetFrmDir(); |
| if( !bOneFound ) |
| { |
| (SvxFrameDirectionItem&)rToFill = rDir; |
| bOneFound = sal_True; |
| } |
| else if( rToFill != rDir ) |
| bRet = sal_False; |
| } |
| } |
| |
| if ( sal_False == bRet ) |
| break; |
| } |
| } |
| return bRet; |
| } |
| |
| /*********************************************************************** |
| #* Class : SwDoc |
| #* Methoden : SetBoxAlign, SetBoxAlign |
| #* Datum : MA 18. Dec. 96 |
| #* Update : JP 29.04.98 |
| #***********************************************************************/ |
| void SwDoc::SetBoxAlign( const SwCursor& rCursor, sal_uInt16 nAlign ) |
| { |
| ASSERT( nAlign == text::VertOrientation::NONE || |
| nAlign == text::VertOrientation::CENTER || |
| nAlign == text::VertOrientation::BOTTOM, "wrong alignment" ); |
| SwFmtVertOrient aVertOri( 0, nAlign ); |
| SetBoxAttr( rCursor, aVertOri ); |
| } |
| |
| sal_uInt16 SwDoc::GetBoxAlign( const SwCursor& rCursor ) const |
| { |
| sal_uInt16 nAlign = USHRT_MAX; |
| SwTableNode* pTblNd = rCursor.GetPoint()->nNode.GetNode().FindTableNode(); |
| SwSelBoxes aBoxes; |
| if( pTblNd && ::lcl_GetBoxSel( rCursor, aBoxes )) |
| for( sal_uInt16 i = 0; i < aBoxes.Count(); ++i ) |
| { |
| const SwFmtVertOrient &rOri = |
| aBoxes[i]->GetFrmFmt()->GetVertOrient(); |
| if( USHRT_MAX == nAlign ) |
| nAlign = static_cast<sal_uInt16>(rOri.GetVertOrient()); |
| else if( rOri.GetVertOrient() != nAlign ) |
| { |
| nAlign = USHRT_MAX; |
| break; |
| } |
| } |
| return nAlign; |
| } |
| |
| |
| /*********************************************************************** |
| #* Class : SwDoc |
| #* Methoden : AdjustCellWidth() |
| #* Datum : MA 20. Feb. 95 |
| #* Update : JP 29.04.98 |
| #***********************************************************************/ |
| sal_uInt16 lcl_CalcCellFit( const SwLayoutFrm *pCell ) |
| { |
| SwTwips nRet = 0; |
| const SwFrm *pFrm = pCell->Lower(); //Die ganze Zelle. |
| SWRECTFN( pCell ) |
| while ( pFrm ) |
| { |
| const SwTwips nAdd = (pFrm->Frm().*fnRect->fnGetWidth)() - |
| (pFrm->Prt().*fnRect->fnGetWidth)(); |
| |
| // --> FME 2005-12-02 #127801# pFrm does not necessarily have to be a SwTxtFrm! |
| const SwTwips nCalcFitToContent = pFrm->IsTxtFrm() ? |
| ((SwTxtFrm*)pFrm)->CalcFitToContent() : |
| (pFrm->Prt().*fnRect->fnGetWidth)(); |
| // <-- |
| |
| nRet = Max( nRet, nCalcFitToContent + nAdd ); |
| pFrm = pFrm->GetNext(); |
| } |
| //Umrandung und linker/rechter Rand wollen mit kalkuliert werden. |
| nRet += (pCell->Frm().*fnRect->fnGetWidth)() - |
| (pCell->Prt().*fnRect->fnGetWidth)(); |
| |
| //Um Rechenungenauikeiten, die spaeter bei SwTable::SetTabCols enstehen, |
| //auszugleichen, addieren wir noch ein bischen. |
| nRet += COLFUZZY; |
| return (sal_uInt16)Max( long(MINLAY), nRet ); |
| } |
| |
| /*Die Zelle ist in der Selektion, wird aber nicht von den TabCols beschrieben. |
| *Das bedeutet, dass die Zelle aufgrund der zweidimensionalen Darstellung von |
| *anderen Zellen "geteilt" wurde. Wir muessen also den Wunsch- bzw. Minimalwert |
| *der Zelle auf die Spalten, durch die sie geteilt wurde verteilen. |
| * |
| *Dazu sammeln wir zuerst die Spalten - nicht die Spaltentrenner! - ein, die |
| *sich mit der Zelle ueberschneiden. Den Wunschwert der Zelle verteilen wir |
| *dann anhand des Betrages der Ueberschneidung auf die Zellen. |
| *Wenn eine Zelle bereits einen groesseren Wunschwert angemeldet hat, so bleibt |
| *dieser erhalten, kleinere Wuensche werden ueberschrieben. |
| */ |
| |
| void lcl_CalcSubColValues( SvUShorts &rToFill, const SwTabCols &rCols, |
| const SwLayoutFrm *pCell, const SwLayoutFrm *pTab, |
| sal_Bool bWishValues ) |
| { |
| const sal_uInt16 nWish = bWishValues ? |
| ::lcl_CalcCellFit( pCell ) : |
| MINLAY + sal_uInt16(pCell->Frm().Width() - pCell->Prt().Width()); |
| |
| SWRECTFN( pTab ) |
| |
| for ( sal_uInt16 i = 0 ; i <= rCols.Count(); ++i ) |
| { |
| long nColLeft = i == 0 ? rCols.GetLeft() : rCols[i-1]; |
| long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i]; |
| nColLeft += rCols.GetLeftMin(); |
| nColRight += rCols.GetLeftMin(); |
| |
| //Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen. |
| if ( rCols.GetLeftMin() != sal_uInt16((pTab->Frm().*fnRect->fnGetLeft)()) ) |
| { |
| const long nDiff = (pTab->Frm().*fnRect->fnGetLeft)() - rCols.GetLeftMin(); |
| nColLeft += nDiff; |
| nColRight += nDiff; |
| } |
| const long nCellLeft = (pCell->Frm().*fnRect->fnGetLeft)(); |
| const long nCellRight = (pCell->Frm().*fnRect->fnGetRight)(); |
| |
| //Ueberschneidungsbetrag ermitteln. |
| long nWidth = 0; |
| if ( nColLeft <= nCellLeft && nColRight >= (nCellLeft+COLFUZZY) ) |
| nWidth = nColRight - nCellLeft; |
| else if ( nColLeft <= (nCellRight-COLFUZZY) && nColRight >= nCellRight ) |
| nWidth = nCellRight - nColLeft; |
| else if ( nColLeft >= nCellLeft && nColRight <= nCellRight ) |
| nWidth = nColRight - nColLeft; |
| if ( nWidth && pCell->Frm().Width() ) |
| { |
| long nTmp = nWidth * nWish / pCell->Frm().Width(); |
| if ( sal_uInt16(nTmp) > rToFill[i] ) |
| rToFill[i] = sal_uInt16(nTmp); |
| } |
| } |
| } |
| |
| /*Besorgt neue Werte zu Einstellung der TabCols. |
| *Es wird nicht ueber die Eintrage in den TabCols itereriert, sondern |
| *quasi ueber die Zwischenraeume, die ja die Zellen beschreiben. |
| * |
| *bWishValues == sal_True: Es werden zur aktuellen Selektion bzw. zur aktuellen |
| * Zelle die Wunschwerte aller betroffen Zellen ermittelt. |
| * Sind mehrere Zellen in einer Spalte, so wird der |
| * groesste Wunschwert als Ergebnis geliefert. |
| * Fuer die TabCol-Eintraege, zu denen keine Zellen |
| * ermittelt wurden, werden 0-en eingetragen. |
| * |
| *bWishValues == sal_False: Die Selektion wird senkrecht ausgedehnt. Zu jeder |
| * Spalte in den TabCols, die sich mit der Selektion |
| * schneidet wird der Minimalwert ermittelt. |
| */ |
| |
| void lcl_CalcColValues( SvUShorts &rToFill, const SwTabCols &rCols, |
| const SwLayoutFrm *pStart, const SwLayoutFrm *pEnd, |
| sal_Bool bWishValues ) |
| { |
| SwSelUnions aUnions; |
| ::MakeSelUnions( aUnions, pStart, pEnd, |
| bWishValues ? nsSwTblSearchType::TBLSEARCH_NONE : nsSwTblSearchType::TBLSEARCH_COL ); |
| |
| for ( sal_uInt16 i2 = 0; i2 < aUnions.Count(); ++i2 ) |
| { |
| SwSelUnion *pSelUnion = aUnions[i2]; |
| const SwTabFrm *pTab = pSelUnion->GetTable(); |
| const SwRect &rUnion = pSelUnion->GetUnion(); |
| |
| SWRECTFN( pTab ) |
| sal_Bool bRTL = pTab->IsRightToLeft(); |
| |
| const SwLayoutFrm *pCell = pTab->FirstCell(); |
| do |
| { |
| if ( pCell->IsCellFrm() && pCell->FindTabFrm() == pTab && ::IsFrmInTblSel( rUnion, pCell ) ) |
| { |
| const long nCLeft = (pCell->Frm().*fnRect->fnGetLeft)(); |
| const long nCRight = (pCell->Frm().*fnRect->fnGetRight)(); |
| |
| sal_Bool bNotInCols = sal_True; |
| |
| for ( sal_uInt16 i = 0; i <= rCols.Count(); ++i ) |
| { |
| sal_uInt16 nFit = rToFill[i]; |
| long nColLeft = i == 0 ? rCols.GetLeft() : rCols[i-1]; |
| long nColRight = i == rCols.Count() ? rCols.GetRight() : rCols[i]; |
| |
| if ( bRTL ) |
| { |
| long nTmpRight = nColRight; |
| nColRight = rCols.GetRight() - nColLeft; |
| nColLeft = rCols.GetRight() - nTmpRight; |
| } |
| |
| nColLeft += rCols.GetLeftMin(); |
| nColRight += rCols.GetLeftMin(); |
| |
| //Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen. |
| long nLeftA = nColLeft; |
| long nRightA = nColRight; |
| if ( rCols.GetLeftMin() != sal_uInt16((pTab->Frm().*fnRect->fnGetLeft)()) ) |
| { |
| const long nDiff = (pTab->Frm().*fnRect->fnGetLeft)() - rCols.GetLeftMin(); |
| nLeftA += nDiff; |
| nRightA += nDiff; |
| } |
| |
| //Wir wollen nicht allzu genau hinsehen. |
| if ( ::IsSame(nCLeft, nLeftA) && ::IsSame(nCRight, nRightA)) |
| { |
| bNotInCols = sal_False; |
| if ( bWishValues ) |
| { |
| const sal_uInt16 nWish = ::lcl_CalcCellFit( pCell ); |
| if ( nWish > nFit ) |
| nFit = nWish; |
| } |
| else |
| { const sal_uInt16 nMin = MINLAY + sal_uInt16(pCell->Frm().Width() - |
| pCell->Prt().Width()); |
| if ( !nFit || nMin < nFit ) |
| nFit = nMin; |
| } |
| if ( rToFill[i] < nFit ) |
| rToFill[i] = nFit; |
| } |
| } |
| if ( bNotInCols ) |
| ::lcl_CalcSubColValues( rToFill, rCols, pCell, pTab, bWishValues ); |
| } |
| do { |
| pCell = pCell->GetNextLayoutLeaf(); |
| }while( pCell && pCell->Frm().Width() == 0 ); |
| } while ( pCell && pTab->IsAnLower( pCell ) ); |
| } |
| } |
| |
| |
| void SwDoc::AdjustCellWidth( const SwCursor& rCursor, sal_Bool bBalance ) |
| { |
| // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen |
| SwCntntNode* pCntNd = rCursor.GetPoint()->nNode.GetNode().GetCntntNode(); |
| SwTableNode* pTblNd = pCntNd ? pCntNd->FindTableNode() : 0; |
| if( !pTblNd ) |
| return ; |
| |
| SwLayoutFrm *pStart, *pEnd; |
| ::lcl_GetStartEndCell( rCursor, pStart, pEnd ); |
| |
| //TabCols besorgen, den ueber diese stellen wir die Tabelle neu ein. |
| SwFrm* pBoxFrm = pStart; |
| while( pBoxFrm && !pBoxFrm->IsCellFrm() ) |
| pBoxFrm = pBoxFrm->GetUpper(); |
| |
| if ( !pBoxFrm ) |
| return; // robust |
| |
| SwTabCols aTabCols; |
| GetTabCols( aTabCols, 0, (SwCellFrm*)pBoxFrm ); |
| |
| if ( ! aTabCols.Count() ) |
| return; |
| |
| const sal_uInt8 nTmp = (sal_uInt8)Max( sal_uInt16(255), sal_uInt16(aTabCols.Count() + 1) ); |
| SvUShorts aWish( nTmp, nTmp ), |
| aMins( nTmp, nTmp ); |
| sal_uInt16 i; |
| |
| for ( i = 0; i <= aTabCols.Count(); ++i ) |
| { |
| aWish.Insert( sal_uInt16(0), aWish.Count() ); |
| aMins.Insert( sal_uInt16(0), aMins.Count() ); |
| } |
| ::lcl_CalcColValues( aWish, aTabCols, pStart, pEnd, sal_True ); |
| |
| //Es ist Robuster wenn wir die Min-Werte fuer die ganze Tabelle berechnen. |
| const SwTabFrm *pTab = pStart->ImplFindTabFrm(); |
| pStart = (SwLayoutFrm*)pTab->FirstCell(); |
| pEnd = (SwLayoutFrm*)pTab->FindLastCntnt()->GetUpper(); |
| while( !pEnd->IsCellFrm() ) |
| pEnd = pEnd->GetUpper(); |
| ::lcl_CalcColValues( aMins, aTabCols, pStart, pEnd, sal_False ); |
| |
| if( bBalance ) |
| { |
| //Alle Spalten, die makiert sind haben jetzt einen Wunschwert |
| //eingtragen. Wir addieren die aktuellen Werte, teilen das Ergebnis |
| //durch die Anzahl und haben eine Wunschwert fuer den ausgleich. |
| sal_uInt16 nWish = 0, nCnt = 0; |
| for ( i = 0; i <= aTabCols.Count(); ++i ) |
| { |
| int nDiff = aWish[i]; |
| if ( nDiff ) |
| { |
| if ( i == 0 ) |
| nWish = static_cast<sal_uInt16>( nWish + aTabCols[i] - aTabCols.GetLeft() ); |
| else if ( i == aTabCols.Count() ) |
| nWish = static_cast<sal_uInt16>(nWish + aTabCols.GetRight() - aTabCols[i-1] ); |
| else |
| nWish = static_cast<sal_uInt16>(nWish + aTabCols[i] - aTabCols[i-1] ); |
| ++nCnt; |
| } |
| } |
| nWish = nWish / nCnt; |
| for ( i = 0; i < aWish.Count(); ++i ) |
| if ( aWish[i] ) |
| aWish[i] = nWish; |
| } |
| |
| const sal_uInt16 nOldRight = static_cast<sal_uInt16>(aTabCols.GetRight()); |
| |
| //Um die Impl. einfach zu gestalten, aber trotzdem in den meissten Faellen |
| //den Platz richtig auszunutzen laufen wir zweimal. |
| //Problem: Erste Spalte wird breiter, die anderen aber erst danach |
| //schmaler. Die Wunschbreite der ersten Spalte wuerde abgelehnt, weil |
| //mit ihr die max. Breite der Tabelle ueberschritten wuerde. |
| for ( sal_uInt16 k= 0; k < 2; ++k ) |
| { |
| for ( i = 0; i <= aTabCols.Count(); ++i ) |
| { |
| int nDiff = aWish[i]; |
| if ( nDiff ) |
| { |
| int nMin = aMins[i]; |
| if ( nMin > nDiff ) |
| nDiff = nMin; |
| |
| if ( i == 0 ) |
| { |
| if( aTabCols.Count() ) |
| nDiff -= aTabCols[0] - aTabCols.GetLeft(); |
| else |
| nDiff -= aTabCols.GetRight() - aTabCols.GetLeft(); |
| } |
| else if ( i == aTabCols.Count() ) |
| nDiff -= aTabCols.GetRight() - aTabCols[i-1]; |
| else |
| nDiff -= aTabCols[i] - aTabCols[i-1]; |
| |
| long nTabRight = aTabCols.GetRight() + nDiff; |
| |
| //Wenn die Tabelle zu breit wuerde begrenzen wir die Anpassung |
| //auf das erlaubte Maximum. |
| if ( !bBalance && nTabRight > aTabCols.GetRightMax() ) |
| { |
| const long nTmpD = nTabRight - aTabCols.GetRightMax(); |
| nDiff -= nTmpD; |
| nTabRight -= nTmpD; |
| } |
| for ( sal_uInt16 i2 = i; i2 < aTabCols.Count(); ++i2 ) |
| aTabCols[i2] += nDiff; |
| aTabCols.SetRight( nTabRight ); |
| } |
| } |
| } |
| |
| const sal_uInt16 nNewRight = static_cast<sal_uInt16>(aTabCols.GetRight()); |
| |
| SwFrmFmt *pFmt = pTblNd->GetTable().GetFrmFmt(); |
| const sal_Int16 nOriHori = pFmt->GetHoriOrient().GetHoriOrient(); |
| |
| //So, die richtige Arbeit koennen wir jetzt der SwTable ueberlassen. |
| SetTabCols( aTabCols, sal_False, 0, (SwCellFrm*)pBoxFrm ); |
| |
| // i54248: lijian/fme |
| // alignment might have been changed in SetTabCols, restore old value: |
| const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient(); |
| SwFmtHoriOrient aHori( rHori ); |
| if ( aHori.GetHoriOrient() != nOriHori ) |
| { |
| aHori.SetHoriOrient( nOriHori ); |
| pFmt->SetFmtAttr( aHori ); |
| } |
| |
| //Bei Automatischer Breite wird auf Linksbuendig umgeschaltet. |
| //Bei Randattributen wird der Rechte Rand angepasst. |
| if( !bBalance && nNewRight < nOldRight ) |
| { |
| if( aHori.GetHoriOrient() == text::HoriOrientation::FULL ) |
| { |
| aHori.SetHoriOrient( text::HoriOrientation::LEFT ); |
| pFmt->SetFmtAttr( aHori ); |
| } |
| } |
| |
| SetModified(); |
| } |
| |