1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ndtbl1.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
36 #define private public
39 #include "hintids.hxx"
40 #include <svx/lrspitem.hxx>
41 #include <svx/boxitem.hxx>
42 #include <svx/brshitem.hxx>
43 #include <svx/frmdiritem.hxx>
44 #include <fmtornt.hxx>
45 #include <fmtfsize.hxx>
46 #include <fmtlsplt.hxx>
47 #include <fmtrowsplt.hxx>
50 #include <cellfrm.hxx>
59 #include "swtable.hxx"
60 #include "htmltbl.hxx"
62 #include "swtblfmt.hxx"
64 #include "ndindex.hxx"
67 using namespace ::com::sun::star
;
70 extern void ClearFEShellTabCols();
72 //siehe auch swtable.cxx
75 inline BOOL
IsSame( long nA
, long nB
) { return Abs(nA
-nB
) <= COLFUZZY
; }
84 SwTblFmtCmp( SwFrmFmt
*pOld
, SwFrmFmt
*pNew
, INT16 nType
);
86 static SwFrmFmt
*FindNewFmt( SvPtrarr
&rArr
, SwFrmFmt
*pOld
, INT16 nType
);
87 static void Delete( SvPtrarr
&rArr
);
91 SwTblFmtCmp::SwTblFmtCmp( SwFrmFmt
*pO
, SwFrmFmt
*pN
, INT16 nT
)
92 : pOld ( pO
), pNew ( pN
), nType( nT
)
96 SwFrmFmt
*SwTblFmtCmp::FindNewFmt( SvPtrarr
&rArr
, SwFrmFmt
*pOld
, INT16 nType
)
98 for ( USHORT i
= 0; i
< rArr
.Count(); ++i
)
100 SwTblFmtCmp
*pCmp
= (SwTblFmtCmp
*)rArr
[i
];
101 if ( pCmp
->pOld
== pOld
&& pCmp
->nType
== nType
)
107 void SwTblFmtCmp::Delete( SvPtrarr
&rArr
)
109 for ( USHORT i
= 0; i
< rArr
.Count(); ++i
)
110 delete (SwTblFmtCmp
*)rArr
[i
];
113 void lcl_GetStartEndCell( const SwCursor
& rCrsr
,
114 SwLayoutFrm
*&prStart
, SwLayoutFrm
*&prEnd
)
116 ASSERT( rCrsr
.GetCntntNode() && rCrsr
.GetCntntNode( FALSE
),
117 "Tabselection nicht auf Cnt." );
119 Point aPtPos
, aMkPos
;
120 const SwShellCrsr
* pShCrsr
= dynamic_cast<const SwShellCrsr
*>(&rCrsr
);
123 aPtPos
= pShCrsr
->GetPtPos();
124 aMkPos
= pShCrsr
->GetMkPos();
128 SwCntntNode
* pPointNd
= rCrsr
.GetCntntNode();
129 SwCntntNode
* pMarkNd
= rCrsr
.GetCntntNode(FALSE
);
131 SwFrm
* pPointFrm
= pPointNd
? pPointNd
->GetFrm( &aPtPos
) : 0;
132 SwFrm
* pMarkFrm
= pMarkNd
? pMarkNd
->GetFrm( &aMkPos
) : 0;
134 prStart
= pPointFrm
? pPointFrm
->GetUpper() : 0;
135 prEnd
= pMarkFrm
? pMarkFrm
->GetUpper() : 0;
138 BOOL
lcl_GetBoxSel( const SwCursor
& rCursor
, SwSelBoxes
& rBoxes
,
139 BOOL bAllCrsr
= FALSE
)
141 const SwTableCursor
* pTblCrsr
=
142 dynamic_cast<const SwTableCursor
*>(&rCursor
);
144 ::GetTblSelCrs( *pTblCrsr
, rBoxes
);
147 const SwPaM
*pCurPam
= &rCursor
, *pSttPam
= pCurPam
;
149 const SwNode
* pNd
= pCurPam
->GetNode()->FindTableBoxStartNode();
152 SwTableBox
* pBox
= (SwTableBox
*)pNd
->FindTableNode()->GetTable().
153 GetTblBox( pNd
->GetIndex() );
154 rBoxes
.Insert( pBox
);
157 pSttPam
!= ( pCurPam
= (SwPaM
*)pCurPam
->GetNext()) );
159 return 0 != rBoxes
.Count();
162 /***********************************************************************
164 #* Methoden : SetRowHeight(), GetRowHeight()
165 #* Datum : MA 17. May. 93
166 #* Update : JP 28.04.98
167 #***********************************************************************/
168 //Die Zeilenhoehe wird ausgehend von der Selektion ermittelt/gesetzt.
169 //Ausgehend von jeder Zelle innerhalb der Selektion werden nach oben alle
170 //Zeilen abgeklappert, die oberste Zeile erhaelt den gewuenschten Wert alle
171 //tieferliegenden Zeilen einen entsprechenden Wert der sich aus der
172 //Relation der alten und neuen Groesse der obersten Zeile und ihrer
173 //eigenen Groesse ergiebt.
174 //Alle veraenderten Zeilen erhalten ggf. ein eigenes FrmFmt.
175 //Natuerlich darf jede Zeile nur einmal angefasst werden.
177 inline void InsertLine( SvPtrarr
& rLineArr
, SwTableLine
* pLine
)
179 if( USHRT_MAX
== rLineArr
.GetPos( (void*&)pLine
) )
180 rLineArr
.Insert( (void*&)pLine
, rLineArr
.Count() );
183 //-----------------------------------------------------------------------------
185 BOOL
lcl_IsAnLower( const SwTableLine
*pLine
, const SwTableLine
*pAssumed
)
187 const SwTableLine
*pTmp
= pAssumed
->GetUpper() ?
188 pAssumed
->GetUpper()->GetUpper() : 0;
193 pTmp
= pTmp
->GetUpper() ? pTmp
->GetUpper()->GetUpper() : 0;
197 //-----------------------------------------------------------------------------
202 const SwTable
&rTable
;
205 LinesAndTable( SvPtrarr
&rL
, const SwTable
&rTbl
) :
206 rLines( rL
), rTable( rTbl
), bInsertLines( TRUE
) {}
210 BOOL
_FindLine( const _FndLine
*& rpLine
, void* pPara
);
212 BOOL
_FindBox( const _FndBox
*& rpBox
, void* pPara
)
214 if ( rpBox
->GetLines().Count() )
216 ((LinesAndTable
*)pPara
)->bInsertLines
= TRUE
;
217 ((_FndBox
*)rpBox
)->GetLines().ForEach( _FindLine
, pPara
);
218 if ( ((LinesAndTable
*)pPara
)->bInsertLines
)
220 const SwTableLines
&rLines
= rpBox
->GetBox()
221 ? rpBox
->GetBox()->GetTabLines()
222 : ((LinesAndTable
*)pPara
)->rTable
.GetTabLines();
223 if ( rpBox
->GetLines().Count() == rLines
.Count() )
225 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
226 ::InsertLine( ((LinesAndTable
*)pPara
)->rLines
,
227 (SwTableLine
*)rLines
[i
] );
230 ((LinesAndTable
*)pPara
)->bInsertLines
= FALSE
;
233 else if ( rpBox
->GetBox() )
234 ::InsertLine( ((LinesAndTable
*)pPara
)->rLines
,
235 (SwTableLine
*)rpBox
->GetBox()->GetUpper() );
239 BOOL
_FindLine( const _FndLine
*& rpLine
, void* pPara
)
241 ((_FndLine
*)rpLine
)->GetBoxes().ForEach( _FindBox
, pPara
);
245 void lcl_CollectLines( SvPtrarr
&rArr
, const SwCursor
& rCursor
, bool bRemoveLines
)
247 //Zuerst die selektierten Boxen einsammeln.
249 if( !::lcl_GetBoxSel( rCursor
, aBoxes
))
252 //Die selektierte Struktur kopieren.
253 const SwTable
&rTable
= aBoxes
[0]->GetSttNd()->FindTableNode()->GetTable();
254 LinesAndTable
aPara( rArr
, rTable
);
255 _FndBox
aFndBox( 0, 0 );
257 _FndPara
aTmpPara( aBoxes
, &aFndBox
);
258 ((SwTableLines
&)rTable
.GetTabLines()).ForEach( &_FndLineCopyCol
, &aTmpPara
);
261 //Diejenigen Lines einsammeln, die nur selektierte Boxen enthalten.
262 const _FndBox
*pTmp
= &aFndBox
;
263 ::_FindBox( pTmp
, &aPara
);
265 // Remove lines, that have a common superordinate row.
266 // (Not for row split)
269 for ( USHORT i
= 0; i
< rArr
.Count(); ++i
)
271 SwTableLine
*pUpLine
= (SwTableLine
*)rArr
[i
];
272 for ( USHORT k
= 0; k
< rArr
.Count(); ++k
)
274 if ( k
!= i
&& ::lcl_IsAnLower( pUpLine
, (SwTableLine
*)rArr
[k
] ) )
286 //-----------------------------------------------------------------------------
288 void lcl_ProcessRowAttr( SvPtrarr
& rFmtCmp
, SwTableLine
* pLine
, const SfxPoolItem
& rNew
)
291 if ( 0 != (pNewFmt
= SwTblFmtCmp::FindNewFmt( rFmtCmp
, pLine
->GetFrmFmt(), 0 )))
292 pLine
->ChgFrmFmt( (SwTableLineFmt
*)pNewFmt
);
295 SwFrmFmt
*pOld
= pLine
->GetFrmFmt();
296 SwFrmFmt
*pNew
= pLine
->ClaimFrmFmt();
297 pNew
->SetFmtAttr( rNew
);
298 rFmtCmp
.Insert( new SwTblFmtCmp( pOld
, pNew
, 0 ), rFmtCmp
.Count());
302 //-----------------------------------------------------------------------------
304 void lcl_ProcessBoxSize( SvPtrarr
&rFmtCmp
, SwTableBox
*pBox
, const SwFmtFrmSize
&rNew
);
306 void lcl_ProcessRowSize( SvPtrarr
&rFmtCmp
, SwTableLine
*pLine
, const SwFmtFrmSize
&rNew
)
308 lcl_ProcessRowAttr( rFmtCmp
, pLine
, rNew
);
309 SwTableBoxes
&rBoxes
= pLine
->GetTabBoxes();
310 for ( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
311 ::lcl_ProcessBoxSize( rFmtCmp
, rBoxes
[i
], rNew
);
314 //-----------------------------------------------------------------------------
316 void lcl_ProcessBoxSize( SvPtrarr
&rFmtCmp
, SwTableBox
*pBox
, const SwFmtFrmSize
&rNew
)
318 SwTableLines
&rLines
= pBox
->GetTabLines();
319 if ( rLines
.Count() )
321 SwFmtFrmSize
aSz( rNew
);
322 aSz
.SetHeight( rNew
.GetHeight() ? rNew
.GetHeight() / rLines
.Count() : 0 );
323 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
324 ::lcl_ProcessRowSize( rFmtCmp
, rLines
[i
], aSz
);
328 //-----------------------------------------------------------------------------
330 /******************************************************************************
331 * void SwDoc::SetRowSplit()
332 ******************************************************************************/
333 void SwDoc::SetRowSplit( const SwCursor
& rCursor
, const SwFmtRowSplit
&rNew
)
335 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
338 SvPtrarr
aRowArr( 25, 50 ); //Zum sammeln Lines.
339 ::lcl_CollectLines( aRowArr
, rCursor
, false );
341 if( aRowArr
.Count() )
346 AppendUndo( new SwUndoAttrTbl( *pTblNd
));
349 SvPtrarr
aFmtCmp( Max( BYTE(255), BYTE(aRowArr
.Count()) ), 255 );
351 for( USHORT i
= 0; i
< aRowArr
.Count(); ++i
)
352 ::lcl_ProcessRowAttr( aFmtCmp
, (SwTableLine
*)aRowArr
[i
], rNew
);
354 SwTblFmtCmp::Delete( aFmtCmp
);
361 /******************************************************************************
362 * SwTwips SwDoc::GetRowSplit() const
363 ******************************************************************************/
364 void SwDoc::GetRowSplit( const SwCursor
& rCursor
, SwFmtRowSplit
*& rpSz
) const
368 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
371 SvPtrarr
aRowArr( 25, 50 ); //Zum sammeln der Lines.
372 ::lcl_CollectLines( aRowArr
, rCursor
, false );
374 if( aRowArr
.Count() )
376 rpSz
= &(SwFmtRowSplit
&)((SwTableLine
*)aRowArr
[0])->
377 GetFrmFmt()->GetRowSplit();
379 for ( USHORT i
= 1; i
< aRowArr
.Count() && rpSz
; ++i
)
381 if ( (*rpSz
).GetValue() != ((SwTableLine
*)aRowArr
[i
])->GetFrmFmt()->GetRowSplit().GetValue() )
385 rpSz
= new SwFmtRowSplit( *rpSz
);
391 /******************************************************************************
392 * void SwDoc::SetRowHeight( SwTwips nNew )
393 ******************************************************************************/
394 void SwDoc::SetRowHeight( const SwCursor
& rCursor
, const SwFmtFrmSize
&rNew
)
396 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
399 SvPtrarr
aRowArr( 25, 50 ); //Zum sammeln Lines.
400 ::lcl_CollectLines( aRowArr
, rCursor
, true );
402 if( aRowArr
.Count() )
407 AppendUndo( new SwUndoAttrTbl( *pTblNd
));
410 SvPtrarr
aFmtCmp( Max( BYTE(255), BYTE(aRowArr
.Count()) ), 255 );
411 for ( USHORT i
= 0; i
< aRowArr
.Count(); ++i
)
412 ::lcl_ProcessRowSize( aFmtCmp
, (SwTableLine
*)aRowArr
[i
], rNew
);
413 SwTblFmtCmp::Delete( aFmtCmp
);
421 /******************************************************************************
422 * SwTwips SwDoc::GetRowHeight() const
423 ******************************************************************************/
424 void SwDoc::GetRowHeight( const SwCursor
& rCursor
, SwFmtFrmSize
*& rpSz
) const
428 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
431 SvPtrarr
aRowArr( 25, 50 ); //Zum sammeln der Lines.
432 ::lcl_CollectLines( aRowArr
, rCursor
, true );
434 if( aRowArr
.Count() )
436 rpSz
= &(SwFmtFrmSize
&)((SwTableLine
*)aRowArr
[0])->
437 GetFrmFmt()->GetFrmSize();
439 for ( USHORT i
= 1; i
< aRowArr
.Count() && rpSz
; ++i
)
441 if ( *rpSz
!= ((SwTableLine
*)aRowArr
[i
])->GetFrmFmt()->GetFrmSize() )
445 rpSz
= new SwFmtFrmSize( *rpSz
);
450 BOOL
SwDoc::BalanceRowHeight( const SwCursor
& rCursor
, BOOL bTstOnly
)
453 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
456 SvPtrarr
aRowArr( 25, 50 ); //Zum sammeln der Lines.
457 ::lcl_CollectLines( aRowArr
, rCursor
, true );
459 if( 1 < aRowArr
.Count() )
466 for ( i
= 0; i
< aRowArr
.Count(); ++i
)
468 SwClientIter
aIter( *((SwTableLine
*)aRowArr
[i
])->GetFrmFmt() );
469 SwFrm
* pFrm
= (SwFrm
*)aIter
.First( TYPE(SwFrm
) );
472 nHeight
= Max( nHeight
, pFrm
->Frm().Height() );
473 pFrm
= (SwFrm
*)aIter
.Next();
476 SwFmtFrmSize
aNew( ATT_MIN_SIZE
, 0, nHeight
);
481 AppendUndo( new SwUndoAttrTbl( *pTblNd
));
484 SvPtrarr
aFmtCmp( Max( BYTE(255), BYTE(aRowArr
.Count()) ), 255 );
485 for( i
= 0; i
< aRowArr
.Count(); ++i
)
486 ::lcl_ProcessRowSize( aFmtCmp
, (SwTableLine
*)aRowArr
[i
], aNew
);
487 SwTblFmtCmp::Delete( aFmtCmp
);
497 /******************************************************************************
498 * void SwDoc::SetRowBackground()
499 ******************************************************************************/
500 void SwDoc::SetRowBackground( const SwCursor
& rCursor
, const SvxBrushItem
&rNew
)
502 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
505 SvPtrarr
aRowArr( 25, 50 ); //Zum sammeln Lines.
506 ::lcl_CollectLines( aRowArr
, rCursor
, true );
508 if( aRowArr
.Count() )
513 AppendUndo( new SwUndoAttrTbl( *pTblNd
));
516 SvPtrarr
aFmtCmp( Max( BYTE(255), BYTE(aRowArr
.Count()) ), 255 );
518 for( USHORT i
= 0; i
< aRowArr
.Count(); ++i
)
519 ::lcl_ProcessRowAttr( aFmtCmp
, (SwTableLine
*)aRowArr
[i
], rNew
);
521 SwTblFmtCmp::Delete( aFmtCmp
);
527 /******************************************************************************
528 * SwTwips SwDoc::GetRowBackground() const
529 ******************************************************************************/
530 BOOL
SwDoc::GetRowBackground( const SwCursor
& rCursor
, SvxBrushItem
&rToFill
) const
533 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
536 SvPtrarr
aRowArr( 25, 50 ); //Zum sammeln Lines.
537 ::lcl_CollectLines( aRowArr
, rCursor
, true );
539 if( aRowArr
.Count() )
541 rToFill
= ((SwTableLine
*)aRowArr
[0])->GetFrmFmt()->GetBackground();
544 for ( USHORT i
= 1; i
< aRowArr
.Count(); ++i
)
545 if ( rToFill
!= ((SwTableLine
*)aRowArr
[i
])->GetFrmFmt()->GetBackground() )
555 /***********************************************************************
557 #* Methoden : SetTabBorders(), GetTabBorders()
558 #* Datum : MA 18. May. 93
559 #* Update : JP 29.04.98
560 #***********************************************************************/
561 inline void InsertCell( SvPtrarr
& rCellArr
, SwCellFrm
* pCellFrm
)
563 if( USHRT_MAX
== rCellArr
.GetPos( (void*&)pCellFrm
) )
564 rCellArr
.Insert( (void*&)pCellFrm
, rCellArr
.Count() );
567 //-----------------------------------------------------------------------------
568 void lcl_CollectCells( SvPtrarr
&rArr
, const SwRect
&rUnion
,
571 SwLayoutFrm
*pCell
= pTab
->FirstCell();
574 // Wenn in der Zelle ein spaltiger Bereich sitzt, muessen wir
575 // uns erst wieder zur Zelle hochhangeln
576 while ( !pCell
->IsCellFrm() )
577 pCell
= pCell
->GetUpper();
578 ASSERT( pCell
, "Frame ist keine Zelle." );
579 if ( rUnion
.IsOver( pCell
->Frm() ) )
580 ::InsertCell( rArr
, (SwCellFrm
*)pCell
);
581 //Dafuer sorgen, dass die Zelle auch verlassen wird (Bereiche)
582 SwLayoutFrm
*pTmp
= pCell
;
584 { pTmp
= pTmp
->GetNextLayoutLeaf();
585 } while ( pCell
->IsAnLower( pTmp
) );
587 } while( pCell
&& pTab
->IsAnLower( pCell
) );
590 void SwDoc::SetTabBorders( const SwCursor
& rCursor
, const SfxItemSet
& rSet
)
592 SwCntntNode
* pCntNd
= rCursor
.GetPoint()->nNode
.GetNode().GetCntntNode();
593 SwTableNode
* pTblNd
= pCntNd
? pCntNd
->FindTableNode() : 0;
597 SwLayoutFrm
*pStart
, *pEnd
;
598 ::lcl_GetStartEndCell( rCursor
, pStart
, pEnd
);
601 ::MakeSelUnions( aUnions
, pStart
, pEnd
);
603 if( aUnions
.Count() )
605 SwTable
& rTable
= pTblNd
->GetTable();
609 AppendUndo( new SwUndoAttrTbl( *pTblNd
));
612 SvPtrarr
aFmtCmp( 255, 255 );
613 const SvxBoxItem
* pSetBox
;
614 const SvxBoxInfoItem
*pSetBoxInfo
;
616 const SvxBorderLine
* pLeft
= 0;
617 const SvxBorderLine
* pRight
= 0;
618 const SvxBorderLine
* pTop
= 0;
619 const SvxBorderLine
* pBottom
= 0;
620 const SvxBorderLine
* pHori
= 0;
621 const SvxBorderLine
* pVert
= 0;
622 BOOL bHoriValid
= TRUE
, bVertValid
= TRUE
,
623 bTopValid
= TRUE
, bBottomValid
= TRUE
,
624 bLeftValid
= TRUE
, bRightValid
= TRUE
;
626 // JP 21.07.95: die Flags im BoxInfo-Item entscheiden, wann eine
627 // BorderLine gueltig ist!!
628 if( SFX_ITEM_SET
== rSet
.GetItemState( SID_ATTR_BORDER_INNER
, FALSE
,
629 (const SfxPoolItem
**)&pSetBoxInfo
) )
631 pHori
= pSetBoxInfo
->GetHori();
632 pVert
= pSetBoxInfo
->GetVert();
634 bHoriValid
= pSetBoxInfo
->IsValid(VALID_HORI
);
635 bVertValid
= pSetBoxInfo
->IsValid(VALID_VERT
);
637 // wollen wir die auswerten ??
638 bTopValid
= pSetBoxInfo
->IsValid(VALID_TOP
);
639 bBottomValid
= pSetBoxInfo
->IsValid(VALID_BOTTOM
);
640 bLeftValid
= pSetBoxInfo
->IsValid(VALID_LEFT
);
641 bRightValid
= pSetBoxInfo
->IsValid(VALID_RIGHT
);
644 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOX
, FALSE
,
645 (const SfxPoolItem
**)&pSetBox
) )
647 pLeft
= pSetBox
->GetLeft();
648 pRight
= pSetBox
->GetRight();
649 pTop
= pSetBox
->GetTop();
650 pBottom
= pSetBox
->GetBottom();
654 // nicht gesetzt, also keine gueltigen Werte
655 bTopValid
= bBottomValid
= bLeftValid
= bRightValid
= FALSE
;
660 for ( USHORT i
= 0; i
< aUnions
.Count(); ++i
)
662 SwSelUnion
*pUnion
= aUnions
[i
];
663 SwTabFrm
*pTab
= pUnion
->GetTable();
664 const SwRect
&rUnion
= pUnion
->GetUnion();
665 const BOOL bLast
= i
== aUnions
.Count() - 1 ? TRUE
: FALSE
;
667 SvPtrarr
aCellArr( 255, 255 );
668 ::lcl_CollectCells( aCellArr
, pUnion
->GetUnion(), pTab
);
670 //Alle Zellenkanten, die mit dem UnionRect uebereinstimmen oder
671 //darueber hinausragen sind Aussenkanten. Alle anderen sind
673 //neu: Die Aussenkanten koennen abhaengig davon, ob es sich um eine
674 //Start/Mittlere/Folge -Tabelle (bei Selektionen ueber FollowTabs)
675 //handelt doch keine Aussenkanten sein.
676 //Aussenkanten werden links, rechts, oben und unten gesetzt.
677 //Innenkanten werden nur oben und links gesetzt.
678 for ( USHORT j
= 0; j
< aCellArr
.Count(); ++j
)
680 SwCellFrm
*pCell
= (SwCellFrm
*)aCellArr
[j
];
681 const sal_Bool bVert
= pTab
->IsVertical();
682 const sal_Bool bRTL
= pTab
->IsRightToLeft();
683 sal_Bool bTopOver
, bLeftOver
, bRightOver
, bBottomOver
;
686 bTopOver
= pCell
->Frm().Right() >= rUnion
.Right();
687 bLeftOver
= pCell
->Frm().Top() <= rUnion
.Top();
688 bRightOver
= pCell
->Frm().Bottom() >= rUnion
.Bottom();
689 bBottomOver
= pCell
->Frm().Left() <= rUnion
.Left();
693 bTopOver
= pCell
->Frm().Top() <= rUnion
.Top();
694 bLeftOver
= pCell
->Frm().Left() <= rUnion
.Left();
695 bRightOver
= pCell
->Frm().Right() >= rUnion
.Right();
696 bBottomOver
= pCell
->Frm().Bottom() >= rUnion
.Bottom();
701 sal_Bool bTmp
= bRightOver
;
702 bRightOver
= bLeftOver
;
706 //Grundsaetzlich nichts setzen in HeadlineRepeats.
707 if ( pTab
->IsFollow() &&
708 ( pTab
->IsInHeadline( *pCell
) ||
709 // --> FME 2006-02-07 #126092# Same holds for follow flow rows.
710 pCell
->IsInFollowFlowRow() ) )
714 SvxBoxItem
aBox( pCell
->GetFmt()->GetBox() );
721 if ( bFirst
&& bTopOver
)
723 aBox
.SetLine( pTop
, BOX_LINE_TOP
);
726 else if ( bHoriValid
)
728 aBox
.SetLine( 0, BOX_LINE_TOP
);
738 aBox
.SetLine( pLeft
, BOX_LINE_LEFT
);
742 else if( bVertValid
)
744 aBox
.SetLine( pVert
, BOX_LINE_LEFT
);
753 aBox
.SetLine( pRight
, BOX_LINE_RIGHT
);
756 else if ( bVertValid
)
758 aBox
.SetLine( 0, BOX_LINE_RIGHT
);
764 if ( bLast
&& bBottomOver
)
768 aBox
.SetLine( pBottom
, BOX_LINE_BOTTOM
);
772 else if( bHoriValid
)
774 aBox
.SetLine( pHori
, BOX_LINE_BOTTOM
);
780 static USHORT __READONLY_DATA aBorders
[] = {
781 BOX_LINE_BOTTOM
, BOX_LINE_TOP
,
782 BOX_LINE_RIGHT
, BOX_LINE_LEFT
};
783 const USHORT
* pBrd
= aBorders
;
784 for( int k
= 0; k
< 4; ++k
, ++pBrd
)
785 aBox
.SetDistance( pSetBox
->GetDistance( *pBrd
), *pBrd
);
788 SwTableBox
*pBox
= (SwTableBox
*)pCell
->GetTabBox();
790 if ( 0 != (pNewFmt
= SwTblFmtCmp::FindNewFmt( aFmtCmp
, pBox
->GetFrmFmt(), nType
)))
791 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)pNewFmt
);
794 SwFrmFmt
*pOld
= pBox
->GetFrmFmt();
795 SwFrmFmt
*pNew
= pBox
->ClaimFrmFmt();
796 pNew
->SetFmtAttr( aBox
);
797 aFmtCmp
.Insert( new SwTblFmtCmp( pOld
, pNew
, nType
), aFmtCmp
.Count());
804 SwHTMLTableLayout
*pTableLayout
= rTable
.GetHTMLTableLayout();
807 SwCntntFrm
* pFrm
= rCursor
.GetCntntNode()->GetFrm();
808 SwTabFrm
* pTabFrm
= pFrm
->ImplFindTabFrm();
810 pTableLayout
->BordersChanged(
811 pTableLayout
->GetBrowseWidthByTabFrm( *pTabFrm
), TRUE
);
813 SwTblFmtCmp::Delete( aFmtCmp
);
814 ::ClearFEShellTabCols();
819 void lcl_SetLineStyle( SvxBorderLine
*pToSet
,
820 const Color
*pColor
, const SvxBorderLine
*pBorderLine
)
826 Color
aTmp( pToSet
->GetColor() );
827 *pToSet
= *pBorderLine
;
828 pToSet
->SetColor( aTmp
);
831 *pToSet
= *pBorderLine
;
834 pToSet
->SetColor( *pColor
);
837 void SwDoc::SetTabLineStyle( const SwCursor
& rCursor
,
838 const Color
* pColor
, BOOL bSetLine
,
839 const SvxBorderLine
* pBorderLine
)
841 SwCntntNode
* pCntNd
= rCursor
.GetPoint()->nNode
.GetNode().GetCntntNode();
842 SwTableNode
* pTblNd
= pCntNd
? pCntNd
->FindTableNode() : 0;
846 SwLayoutFrm
*pStart
, *pEnd
;
847 ::lcl_GetStartEndCell( rCursor
, pStart
, pEnd
);
850 ::MakeSelUnions( aUnions
, pStart
, pEnd
);
852 if( aUnions
.Count() )
854 SwTable
& rTable
= pTblNd
->GetTable();
858 AppendUndo( new SwUndoAttrTbl( *pTblNd
));
861 for( USHORT i
= 0; i
< aUnions
.Count(); ++i
)
863 SwSelUnion
*pUnion
= aUnions
[i
];
864 SwTabFrm
*pTab
= pUnion
->GetTable();
865 SvPtrarr
aCellArr( 255, 255 );
866 ::lcl_CollectCells( aCellArr
, pUnion
->GetUnion(), pTab
);
868 for ( USHORT j
= 0; j
< aCellArr
.Count(); ++j
)
870 SwCellFrm
*pCell
= ( SwCellFrm
* )aCellArr
[j
];
872 //Grundsaetzlich nichts setzen in HeadlineRepeats.
873 if ( pTab
->IsFollow() && pTab
->IsInHeadline( *pCell
) )
876 ((SwTableBox
*)pCell
->GetTabBox())->ClaimFrmFmt();
877 SwFrmFmt
*pFmt
= pCell
->GetFmt();
878 SvxBoxItem
aBox( pFmt
->GetBox() );
880 if ( !pBorderLine
&& bSetLine
)
881 aBox
= *(SvxBoxItem
*)::GetDfltAttr( RES_BOX
);
885 ::lcl_SetLineStyle( (SvxBorderLine
*)aBox
.GetTop(),
886 pColor
, pBorderLine
);
887 if ( aBox
.GetBottom() )
888 ::lcl_SetLineStyle( (SvxBorderLine
*)aBox
.GetBottom(),
889 pColor
, pBorderLine
);
890 if ( aBox
.GetLeft() )
891 ::lcl_SetLineStyle( (SvxBorderLine
*)aBox
.GetLeft(),
892 pColor
, pBorderLine
);
893 if ( aBox
.GetRight() )
894 ::lcl_SetLineStyle( (SvxBorderLine
*)aBox
.GetRight(),
895 pColor
, pBorderLine
);
897 pFmt
->SetFmtAttr( aBox
);
901 SwHTMLTableLayout
*pTableLayout
= rTable
.GetHTMLTableLayout();
904 SwCntntFrm
* pFrm
= rCursor
.GetCntntNode()->GetFrm();
905 SwTabFrm
* pTabFrm
= pFrm
->ImplFindTabFrm();
907 pTableLayout
->BordersChanged(
908 pTableLayout
->GetBrowseWidthByTabFrm( *pTabFrm
), TRUE
);
910 ::ClearFEShellTabCols();
915 void SwDoc::GetTabBorders( const SwCursor
& rCursor
, SfxItemSet
& rSet
) const
917 SwCntntNode
* pCntNd
= rCursor
.GetPoint()->nNode
.GetNode().GetCntntNode();
918 SwTableNode
* pTblNd
= pCntNd
? pCntNd
->FindTableNode() : 0;
922 SwLayoutFrm
*pStart
, *pEnd
;
923 ::lcl_GetStartEndCell( rCursor
, pStart
, pEnd
);
926 ::MakeSelUnions( aUnions
, pStart
, pEnd
);
928 if( aUnions
.Count() )
930 SvxBoxItem
aSetBox ((const SvxBoxItem
&) rSet
.Get(RES_BOX
));
931 SvxBoxInfoItem
aSetBoxInfo((const SvxBoxInfoItem
&) rSet
.Get(SID_ATTR_BORDER_INNER
));
933 BOOL bTopSet
= FALSE
,
939 bDistanceSet
= FALSE
;
941 aSetBoxInfo
.ResetFlags();
943 for ( USHORT i
= 0; i
< aUnions
.Count(); ++i
)
945 SwSelUnion
*pUnion
= aUnions
[i
];
946 const SwTabFrm
*pTab
= pUnion
->GetTable();
947 const SwRect
&rUnion
= pUnion
->GetUnion();
948 const BOOL bFirst
= i
== 0 ? TRUE
: FALSE
;
949 const BOOL bLast
= i
== aUnions
.Count() - 1 ? TRUE
: FALSE
;
951 SvPtrarr
aCellArr( 255, 255 );
952 ::lcl_CollectCells( aCellArr
, rUnion
, (SwTabFrm
*)pTab
);
954 for ( USHORT j
= 0; j
< aCellArr
.Count(); ++j
)
956 const SwCellFrm
*pCell
= (const SwCellFrm
*)aCellArr
[j
];
957 const sal_Bool bVert
= pTab
->IsVertical();
958 const sal_Bool bRTL
= pTab
->IsRightToLeft();
959 sal_Bool bTopOver
, bLeftOver
, bRightOver
, bBottomOver
;
962 bTopOver
= pCell
->Frm().Right() >= rUnion
.Right();
963 bLeftOver
= pCell
->Frm().Top() <= rUnion
.Top();
964 bRightOver
= pCell
->Frm().Bottom() >= rUnion
.Bottom();
965 bBottomOver
= pCell
->Frm().Left() <= rUnion
.Left();
969 bTopOver
= pCell
->Frm().Top() <= rUnion
.Top();
970 bLeftOver
= pCell
->Frm().Left() <= rUnion
.Left();
971 bRightOver
= pCell
->Frm().Right() >= rUnion
.Right();
972 bBottomOver
= pCell
->Frm().Bottom() >= rUnion
.Bottom();
977 sal_Bool bTmp
= bRightOver
;
978 bRightOver
= bLeftOver
;
982 const SwFrmFmt
*pFmt
= pCell
->GetFmt();
983 const SvxBoxItem
&rBox
= pFmt
->GetBox();
986 if ( bFirst
&& bTopOver
)
988 if (aSetBoxInfo
.IsValid(VALID_TOP
))
992 aSetBox
.SetLine( rBox
.GetTop(), BOX_LINE_TOP
);
994 else if ((aSetBox
.GetTop() && rBox
.GetTop() &&
995 !(*aSetBox
.GetTop() == *rBox
.GetTop())) ||
996 ((!aSetBox
.GetTop()) ^ (!rBox
.GetTop()))) // XOR-Ausdruck ist TRUE, wenn genau einer der beiden Pointer 0 ist
998 aSetBoxInfo
.SetValid(VALID_TOP
, FALSE
);
999 aSetBox
.SetLine( 0, BOX_LINE_TOP
);
1007 if (aSetBoxInfo
.IsValid(VALID_LEFT
))
1011 aSetBox
.SetLine( rBox
.GetLeft(), BOX_LINE_LEFT
);
1013 else if ((aSetBox
.GetLeft() && rBox
.GetLeft() &&
1014 !(*aSetBox
.GetLeft() == *rBox
.GetLeft())) ||
1015 ((!aSetBox
.GetLeft()) ^ (!rBox
.GetLeft())))
1017 aSetBoxInfo
.SetValid(VALID_LEFT
, FALSE
);
1018 aSetBox
.SetLine( 0, BOX_LINE_LEFT
);
1024 if (aSetBoxInfo
.IsValid(VALID_VERT
))
1028 aSetBoxInfo
.SetLine( rBox
.GetLeft(), BOXINFO_LINE_VERT
);
1030 else if ((aSetBoxInfo
.GetVert() && rBox
.GetLeft() &&
1031 !(*aSetBoxInfo
.GetVert() == *rBox
.GetLeft())) ||
1032 ((!aSetBoxInfo
.GetVert()) ^ (!rBox
.GetLeft())))
1033 { aSetBoxInfo
.SetValid( VALID_VERT
, FALSE
);
1034 aSetBoxInfo
.SetLine( 0, BOXINFO_LINE_VERT
);
1040 if ( aSetBoxInfo
.IsValid(VALID_RIGHT
) && bRightOver
)
1044 aSetBox
.SetLine( rBox
.GetRight(), BOX_LINE_RIGHT
);
1046 else if ((aSetBox
.GetRight() && rBox
.GetRight() &&
1047 !(*aSetBox
.GetRight() == *rBox
.GetRight())) ||
1048 (!aSetBox
.GetRight() ^ !rBox
.GetRight()))
1049 { aSetBoxInfo
.SetValid( VALID_RIGHT
, FALSE
);
1050 aSetBox
.SetLine( 0, BOX_LINE_RIGHT
);
1055 if ( bLast
&& bBottomOver
)
1057 if ( aSetBoxInfo
.IsValid(VALID_BOTTOM
) )
1060 { bBottomSet
= TRUE
;
1061 aSetBox
.SetLine( rBox
.GetBottom(), BOX_LINE_BOTTOM
);
1063 else if ((aSetBox
.GetBottom() && rBox
.GetBottom() &&
1064 !(*aSetBox
.GetBottom() == *rBox
.GetBottom())) ||
1065 (!aSetBox
.GetBottom() ^ !rBox
.GetBottom()))
1066 { aSetBoxInfo
.SetValid( VALID_BOTTOM
, FALSE
);
1067 aSetBox
.SetLine( 0, BOX_LINE_BOTTOM
);
1071 //in allen Zeilen ausser der letzten werden die
1072 // horiz. Linien aus der Bottom-Linie entnommen
1075 if (aSetBoxInfo
.IsValid(VALID_HORI
))
1079 aSetBoxInfo
.SetLine( rBox
.GetBottom(), BOXINFO_LINE_HORI
);
1081 else if ((aSetBoxInfo
.GetHori() && rBox
.GetBottom() &&
1082 !(*aSetBoxInfo
.GetHori() == *rBox
.GetBottom())) ||
1083 ((!aSetBoxInfo
.GetHori()) ^ (!rBox
.GetBottom())))
1085 aSetBoxInfo
.SetValid( VALID_HORI
, FALSE
);
1086 aSetBoxInfo
.SetLine( 0, BOXINFO_LINE_HORI
);
1092 if (aSetBoxInfo
.IsValid(VALID_DISTANCE
))
1094 static USHORT __READONLY_DATA aBorders
[] = {
1095 BOX_LINE_BOTTOM
, BOX_LINE_TOP
,
1096 BOX_LINE_RIGHT
, BOX_LINE_LEFT
};
1097 const USHORT
* pBrd
= aBorders
;
1099 if( !bDistanceSet
) // bei 1. Durchlauf erstmal setzen
1101 bDistanceSet
= TRUE
;
1102 for( int k
= 0; k
< 4; ++k
, ++pBrd
)
1103 aSetBox
.SetDistance( rBox
.GetDistance( *pBrd
),
1108 for( int k
= 0; k
< 4; ++k
, ++pBrd
)
1109 if( aSetBox
.GetDistance( *pBrd
) !=
1110 rBox
.GetDistance( *pBrd
) )
1112 aSetBoxInfo
.SetValid( VALID_DISTANCE
, FALSE
);
1113 aSetBox
.SetDistance( (USHORT
) 0 );
1120 rSet
.Put( aSetBox
);
1121 rSet
.Put( aSetBoxInfo
);
1125 /***********************************************************************
1127 #* Methoden : SetBoxAttr
1128 #* Datum : MA 18. Dec. 96
1129 #* Update : JP 29.04.98
1130 #***********************************************************************/
1131 void SwDoc::SetBoxAttr( const SwCursor
& rCursor
, const SfxPoolItem
&rNew
)
1133 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
1135 if( pTblNd
&& ::lcl_GetBoxSel( rCursor
, aBoxes
, TRUE
) )
1137 SwTable
& rTable
= pTblNd
->GetTable();
1141 AppendUndo( new SwUndoAttrTbl( *pTblNd
));
1144 SvPtrarr
aFmtCmp( Max( BYTE(255), BYTE(aBoxes
.Count()) ), 255 );
1145 for ( USHORT i
= 0; i
< aBoxes
.Count(); ++i
)
1147 SwTableBox
*pBox
= aBoxes
[i
];
1150 if ( 0 != (pNewFmt
= SwTblFmtCmp::FindNewFmt( aFmtCmp
, pBox
->GetFrmFmt(), 0 )))
1151 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)pNewFmt
);
1154 SwFrmFmt
*pOld
= pBox
->GetFrmFmt();
1155 SwFrmFmt
*pNew
= pBox
->ClaimFrmFmt();
1156 pNew
->SetFmtAttr( rNew
);
1157 aFmtCmp
.Insert( new SwTblFmtCmp( pOld
, pNew
, 0 ), aFmtCmp
.Count());
1161 SwHTMLTableLayout
*pTableLayout
= rTable
.GetHTMLTableLayout();
1164 SwCntntFrm
* pFrm
= rCursor
.GetCntntNode()->GetFrm();
1165 SwTabFrm
* pTabFrm
= pFrm
->ImplFindTabFrm();
1167 pTableLayout
->Resize(
1168 pTableLayout
->GetBrowseWidthByTabFrm( *pTabFrm
), TRUE
);
1170 SwTblFmtCmp::Delete( aFmtCmp
);
1175 /***********************************************************************
1177 #* Methoden : GetBoxAttr()
1178 #* Datum : MA 01. Jun. 93
1179 #* Update : JP 29.04.98
1180 #***********************************************************************/
1182 BOOL
SwDoc::GetBoxAttr( const SwCursor
& rCursor
, SfxPoolItem
& rToFill
) const
1185 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
1187 if( pTblNd
&& lcl_GetBoxSel( rCursor
, aBoxes
))
1190 BOOL bOneFound
= FALSE
;
1191 const USHORT nWhich
= rToFill
.Which();
1192 for( USHORT i
= 0; i
< aBoxes
.Count(); ++i
)
1196 case RES_BACKGROUND
:
1198 const SvxBrushItem
&rBack
=
1199 aBoxes
[i
]->GetFrmFmt()->GetBackground();
1202 (SvxBrushItem
&)rToFill
= rBack
;
1205 else if( rToFill
!= rBack
)
1212 const SvxFrameDirectionItem
& rDir
=
1213 aBoxes
[i
]->GetFrmFmt()->GetFrmDir();
1216 (SvxFrameDirectionItem
&)rToFill
= rDir
;
1219 else if( rToFill
!= rDir
)
1224 if ( FALSE
== bRet
)
1231 /***********************************************************************
1233 #* Methoden : SetBoxAlign, SetBoxAlign
1234 #* Datum : MA 18. Dec. 96
1235 #* Update : JP 29.04.98
1236 #***********************************************************************/
1237 void SwDoc::SetBoxAlign( const SwCursor
& rCursor
, USHORT nAlign
)
1239 ASSERT( nAlign
== text::VertOrientation::NONE
||
1240 nAlign
== text::VertOrientation::CENTER
||
1241 nAlign
== text::VertOrientation::BOTTOM
, "wrong alignment" );
1242 SwFmtVertOrient
aVertOri( 0, nAlign
);
1243 SetBoxAttr( rCursor
, aVertOri
);
1246 USHORT
SwDoc::GetBoxAlign( const SwCursor
& rCursor
) const
1248 USHORT nAlign
= USHRT_MAX
;
1249 SwTableNode
* pTblNd
= rCursor
.GetPoint()->nNode
.GetNode().FindTableNode();
1251 if( pTblNd
&& ::lcl_GetBoxSel( rCursor
, aBoxes
))
1252 for( USHORT i
= 0; i
< aBoxes
.Count(); ++i
)
1254 const SwFmtVertOrient
&rOri
=
1255 aBoxes
[i
]->GetFrmFmt()->GetVertOrient();
1256 if( USHRT_MAX
== nAlign
)
1257 nAlign
= static_cast<USHORT
>(rOri
.GetVertOrient());
1258 else if( rOri
.GetVertOrient() != nAlign
)
1268 /***********************************************************************
1270 #* Methoden : AdjustCellWidth()
1271 #* Datum : MA 20. Feb. 95
1272 #* Update : JP 29.04.98
1273 #***********************************************************************/
1274 USHORT
lcl_CalcCellFit( const SwLayoutFrm
*pCell
)
1277 const SwFrm
*pFrm
= pCell
->Lower(); //Die ganze Zelle.
1281 const SwTwips nAdd
= (pFrm
->Frm().*fnRect
->fnGetWidth
)() -
1282 (pFrm
->Prt().*fnRect
->fnGetWidth
)();
1284 // --> FME 2005-12-02 #127801# pFrm does not necessarily have to be a SwTxtFrm!
1285 const SwTwips nCalcFitToContent
= pFrm
->IsTxtFrm() ?
1286 ((SwTxtFrm
*)pFrm
)->CalcFitToContent() :
1287 (pFrm
->Prt().*fnRect
->fnGetWidth
)();
1290 nRet
= Max( nRet
, nCalcFitToContent
+ nAdd
);
1291 pFrm
= pFrm
->GetNext();
1293 //Umrandung und linker/rechter Rand wollen mit kalkuliert werden.
1294 nRet
+= (pCell
->Frm().*fnRect
->fnGetWidth
)() -
1295 (pCell
->Prt().*fnRect
->fnGetWidth
)();
1297 //Um Rechenungenauikeiten, die spaeter bei SwTable::SetTabCols enstehen,
1298 //auszugleichen, addieren wir noch ein bischen.
1300 return (USHORT
)Max( long(MINLAY
), nRet
);
1303 /*Die Zelle ist in der Selektion, wird aber nicht von den TabCols beschrieben.
1304 *Das bedeutet, dass die Zelle aufgrund der zweidimensionalen Darstellung von
1305 *anderen Zellen "geteilt" wurde. Wir muessen also den Wunsch- bzw. Minimalwert
1306 *der Zelle auf die Spalten, durch die sie geteilt wurde verteilen.
1308 *Dazu sammeln wir zuerst die Spalten - nicht die Spaltentrenner! - ein, die
1309 *sich mit der Zelle ueberschneiden. Den Wunschwert der Zelle verteilen wir
1310 *dann anhand des Betrages der Ueberschneidung auf die Zellen.
1311 *Wenn eine Zelle bereits einen groesseren Wunschwert angemeldet hat, so bleibt
1312 *dieser erhalten, kleinere Wuensche werden ueberschrieben.
1315 void lcl_CalcSubColValues( SvUShorts
&rToFill
, const SwTabCols
&rCols
,
1316 const SwLayoutFrm
*pCell
, const SwLayoutFrm
*pTab
,
1319 const USHORT nWish
= bWishValues
?
1320 ::lcl_CalcCellFit( pCell
) :
1321 MINLAY
+ USHORT(pCell
->Frm().Width() - pCell
->Prt().Width());
1325 for ( USHORT i
= 0 ; i
<= rCols
.Count(); ++i
)
1327 long nColLeft
= i
== 0 ? rCols
.GetLeft() : rCols
[i
-1];
1328 long nColRight
= i
== rCols
.Count() ? rCols
.GetRight() : rCols
[i
];
1329 nColLeft
+= rCols
.GetLeftMin();
1330 nColRight
+= rCols
.GetLeftMin();
1332 //Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen.
1333 if ( rCols
.GetLeftMin() != USHORT((pTab
->Frm().*fnRect
->fnGetLeft
)()) )
1335 const long nDiff
= (pTab
->Frm().*fnRect
->fnGetLeft
)() - rCols
.GetLeftMin();
1339 const long nCellLeft
= (pCell
->Frm().*fnRect
->fnGetLeft
)();
1340 const long nCellRight
= (pCell
->Frm().*fnRect
->fnGetRight
)();
1342 //Ueberschneidungsbetrag ermitteln.
1344 if ( nColLeft
<= nCellLeft
&& nColRight
>= (nCellLeft
+COLFUZZY
) )
1345 nWidth
= nColRight
- nCellLeft
;
1346 else if ( nColLeft
<= (nCellRight
-COLFUZZY
) && nColRight
>= nCellRight
)
1347 nWidth
= nCellRight
- nColLeft
;
1348 else if ( nColLeft
>= nCellLeft
&& nColRight
<= nCellRight
)
1349 nWidth
= nColRight
- nColLeft
;
1350 if ( nWidth
&& pCell
->Frm().Width() )
1352 long nTmp
= nWidth
* nWish
/ pCell
->Frm().Width();
1353 if ( USHORT(nTmp
) > rToFill
[i
] )
1354 rToFill
[i
] = USHORT(nTmp
);
1359 /*Besorgt neue Werte zu Einstellung der TabCols.
1360 *Es wird nicht ueber die Eintrage in den TabCols itereriert, sondern
1361 *quasi ueber die Zwischenraeume, die ja die Zellen beschreiben.
1363 *bWishValues == TRUE: Es werden zur aktuellen Selektion bzw. zur aktuellen
1364 * Zelle die Wunschwerte aller betroffen Zellen ermittelt.
1365 * Sind mehrere Zellen in einer Spalte, so wird der
1366 * groesste Wunschwert als Ergebnis geliefert.
1367 * Fuer die TabCol-Eintraege, zu denen keine Zellen
1368 * ermittelt wurden, werden 0-en eingetragen.
1370 *bWishValues == FALSE: Die Selektion wird senkrecht ausgedehnt. Zu jeder
1371 * Spalte in den TabCols, die sich mit der Selektion
1372 * schneidet wird der Minimalwert ermittelt.
1375 void lcl_CalcColValues( SvUShorts
&rToFill
, const SwTabCols
&rCols
,
1376 const SwLayoutFrm
*pStart
, const SwLayoutFrm
*pEnd
,
1379 SwSelUnions aUnions
;
1380 ::MakeSelUnions( aUnions
, pStart
, pEnd
,
1381 bWishValues
? nsSwTblSearchType::TBLSEARCH_NONE
: nsSwTblSearchType::TBLSEARCH_COL
);
1383 for ( USHORT i2
= 0; i2
< aUnions
.Count(); ++i2
)
1385 SwSelUnion
*pSelUnion
= aUnions
[i2
];
1386 const SwTabFrm
*pTab
= pSelUnion
->GetTable();
1387 const SwRect
&rUnion
= pSelUnion
->GetUnion();
1390 sal_Bool bRTL
= pTab
->IsRightToLeft();
1392 const SwLayoutFrm
*pCell
= pTab
->FirstCell();
1395 if ( pCell
->IsCellFrm() && pCell
->FindTabFrm() == pTab
&& ::IsFrmInTblSel( rUnion
, pCell
) )
1397 const long nCLeft
= (pCell
->Frm().*fnRect
->fnGetLeft
)();
1398 const long nCRight
= (pCell
->Frm().*fnRect
->fnGetRight
)();
1400 BOOL bNotInCols
= TRUE
;
1402 for ( USHORT i
= 0; i
<= rCols
.Count(); ++i
)
1404 USHORT nFit
= rToFill
[i
];
1405 long nColLeft
= i
== 0 ? rCols
.GetLeft() : rCols
[i
-1];
1406 long nColRight
= i
== rCols
.Count() ? rCols
.GetRight() : rCols
[i
];
1410 long nTmpRight
= nColRight
;
1411 nColRight
= rCols
.GetRight() - nColLeft
;
1412 nColLeft
= rCols
.GetRight() - nTmpRight
;
1415 nColLeft
+= rCols
.GetLeftMin();
1416 nColRight
+= rCols
.GetLeftMin();
1418 //Werte auf die Verhaeltnisse der Tabelle (Follows) anpassen.
1419 long nLeftA
= nColLeft
;
1420 long nRightA
= nColRight
;
1421 if ( rCols
.GetLeftMin() != USHORT((pTab
->Frm().*fnRect
->fnGetLeft
)()) )
1423 const long nDiff
= (pTab
->Frm().*fnRect
->fnGetLeft
)() - rCols
.GetLeftMin();
1428 //Wir wollen nicht allzu genau hinsehen.
1429 if ( ::IsSame(nCLeft
, nLeftA
) && ::IsSame(nCRight
, nRightA
))
1434 const USHORT nWish
= ::lcl_CalcCellFit( pCell
);
1439 { const USHORT nMin
= MINLAY
+ USHORT(pCell
->Frm().Width() -
1440 pCell
->Prt().Width());
1441 if ( !nFit
|| nMin
< nFit
)
1444 if ( rToFill
[i
] < nFit
)
1449 ::lcl_CalcSubColValues( rToFill
, rCols
, pCell
, pTab
, bWishValues
);
1452 pCell
= pCell
->GetNextLayoutLeaf();
1453 }while( pCell
&& pCell
->Frm().Width() == 0 );
1454 } while ( pCell
&& pTab
->IsAnLower( pCell
) );
1459 void SwDoc::AdjustCellWidth( const SwCursor
& rCursor
, BOOL bBalance
)
1461 // pruefe ob vom aktuellen Crsr der Point/Mark in einer Tabelle stehen
1462 SwCntntNode
* pCntNd
= rCursor
.GetPoint()->nNode
.GetNode().GetCntntNode();
1463 SwTableNode
* pTblNd
= pCntNd
? pCntNd
->FindTableNode() : 0;
1467 SwLayoutFrm
*pStart
, *pEnd
;
1468 ::lcl_GetStartEndCell( rCursor
, pStart
, pEnd
);
1470 //TabCols besorgen, den ueber diese stellen wir die Tabelle neu ein.
1471 SwFrm
* pBoxFrm
= pStart
;
1472 while( pBoxFrm
&& !pBoxFrm
->IsCellFrm() )
1473 pBoxFrm
= pBoxFrm
->GetUpper();
1479 GetTabCols( aTabCols
, 0, (SwCellFrm
*)pBoxFrm
);
1481 if ( ! aTabCols
.Count() )
1484 const BYTE nTmp
= (BYTE
)Max( USHORT(255), USHORT(aTabCols
.Count() + 1) );
1485 SvUShorts
aWish( nTmp
, nTmp
),
1486 aMins( nTmp
, nTmp
);
1489 for ( i
= 0; i
<= aTabCols
.Count(); ++i
)
1491 aWish
.Insert( USHORT(0), aWish
.Count() );
1492 aMins
.Insert( USHORT(0), aMins
.Count() );
1494 ::lcl_CalcColValues( aWish
, aTabCols
, pStart
, pEnd
, TRUE
);
1496 //Es ist Robuster wenn wir die Min-Werte fuer die ganze Tabelle berechnen.
1497 const SwTabFrm
*pTab
= pStart
->ImplFindTabFrm();
1498 pStart
= (SwLayoutFrm
*)pTab
->FirstCell();
1499 pEnd
= (SwLayoutFrm
*)pTab
->FindLastCntnt()->GetUpper();
1500 while( !pEnd
->IsCellFrm() )
1501 pEnd
= pEnd
->GetUpper();
1502 ::lcl_CalcColValues( aMins
, aTabCols
, pStart
, pEnd
, FALSE
);
1506 //Alle Spalten, die makiert sind haben jetzt einen Wunschwert
1507 //eingtragen. Wir addieren die aktuellen Werte, teilen das Ergebnis
1508 //durch die Anzahl und haben eine Wunschwert fuer den ausgleich.
1509 USHORT nWish
= 0, nCnt
= 0;
1510 for ( i
= 0; i
<= aTabCols
.Count(); ++i
)
1512 int nDiff
= aWish
[i
];
1516 nWish
= static_cast<USHORT
>( nWish
+ aTabCols
[i
] - aTabCols
.GetLeft() );
1517 else if ( i
== aTabCols
.Count() )
1518 nWish
= static_cast<USHORT
>(nWish
+ aTabCols
.GetRight() - aTabCols
[i
-1] );
1520 nWish
= static_cast<USHORT
>(nWish
+ aTabCols
[i
] - aTabCols
[i
-1] );
1524 nWish
= nWish
/ nCnt
;
1525 for ( i
= 0; i
< aWish
.Count(); ++i
)
1530 const USHORT nOldRight
= static_cast<USHORT
>(aTabCols
.GetRight());
1532 //Um die Impl. einfach zu gestalten, aber trotzdem in den meissten Faellen
1533 //den Platz richtig auszunutzen laufen wir zweimal.
1534 //Problem: Erste Spalte wird breiter, die anderen aber erst danach
1535 //schmaler. Die Wunschbreite der ersten Spalte wuerde abgelehnt, weil
1536 //mit ihr die max. Breite der Tabelle ueberschritten wuerde.
1537 for ( USHORT k
= 0; k
< 2; ++k
)
1539 for ( i
= 0; i
<= aTabCols
.Count(); ++i
)
1541 int nDiff
= aWish
[i
];
1544 int nMin
= aMins
[i
];
1550 if( aTabCols
.Count() )
1551 nDiff
-= aTabCols
[0] - aTabCols
.GetLeft();
1553 nDiff
-= aTabCols
.GetRight() - aTabCols
.GetLeft();
1555 else if ( i
== aTabCols
.Count() )
1556 nDiff
-= aTabCols
.GetRight() - aTabCols
[i
-1];
1558 nDiff
-= aTabCols
[i
] - aTabCols
[i
-1];
1560 long nTabRight
= aTabCols
.GetRight() + nDiff
;
1562 //Wenn die Tabelle zu breit wuerde begrenzen wir die Anpassung
1563 //auf das erlaubte Maximum.
1564 if ( !bBalance
&& nTabRight
> aTabCols
.GetRightMax() )
1566 const long nTmpD
= nTabRight
- aTabCols
.GetRightMax();
1570 for ( USHORT i2
= i
; i2
< aTabCols
.Count(); ++i2
)
1571 aTabCols
[i2
] += nDiff
;
1572 aTabCols
.SetRight( nTabRight
);
1577 const USHORT nNewRight
= static_cast<USHORT
>(aTabCols
.GetRight());
1579 SwFrmFmt
*pFmt
= pTblNd
->GetTable().GetFrmFmt();
1580 const sal_Int16 nOriHori
= pFmt
->GetHoriOrient().GetHoriOrient();
1582 //So, die richtige Arbeit koennen wir jetzt der SwTable ueberlassen.
1583 SetTabCols( aTabCols
, FALSE
, 0, (SwCellFrm
*)pBoxFrm
);
1585 // i54248: lijian/fme
1586 // alignment might have been changed in SetTabCols, restore old value:
1587 const SwFmtHoriOrient
&rHori
= pFmt
->GetHoriOrient();
1588 SwFmtHoriOrient
aHori( rHori
);
1589 if ( aHori
.GetHoriOrient() != nOriHori
)
1591 aHori
.SetHoriOrient( nOriHori
);
1592 pFmt
->SetFmtAttr( aHori
);
1595 //Bei Automatischer Breite wird auf Linksbuendig umgeschaltet.
1596 //Bei Randattributen wird der Rechte Rand angepasst.
1597 if( !bBalance
&& nNewRight
< nOldRight
)
1599 if( aHori
.GetHoriOrient() == text::HoriOrientation::FULL
)
1601 aHori
.SetHoriOrient( text::HoriOrientation::LEFT
);
1602 pFmt
->SetFmtAttr( aHori
);