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: swtable.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"
35 #define private public
40 #include <hintids.hxx>
41 #include <hints.hxx> // fuer SwAttrSetChg
42 #include <svx/lrspitem.hxx>
43 #include <svx/shaditem.hxx>
44 #include <svx/adjitem.hxx>
45 #include <svx/colritem.hxx>
46 #include <svx/linkmgr.hxx>
47 #include <svx/boxitem.hxx>
50 #include <fmtfsize.hxx>
51 #include <fmtornt.hxx>
52 #include <fmtpdsc.hxx>
55 #include <docary.hxx> // fuer RedlineTbl()
57 #include <swtable.hxx>
61 #include <cellfrm.hxx>
66 #include <cellatr.hxx>
67 #include <txatbase.hxx>
68 #include <htmltbl.hxx>
69 #include <swtblfmt.hxx>
70 #include <ndindex.hxx>
71 #include <tblrwcl.hxx>
72 #include <shellres.hxx>
74 #include <redline.hxx>
78 #define CHECK_TABLE(t)
81 #define CHECK_TABLE(t) (t).CheckConsistency();
83 #define CHECK_TABLE(t)
87 using namespace com::sun::star
;
89 TYPEINIT1( SwTable
, SwClient
);
90 TYPEINIT1( SwTableBox
, SwClient
);
91 TYPEINIT1( SwTableLine
, SwClient
);
92 TYPEINIT1( SwTableFmt
, SwFrmFmt
);
93 TYPEINIT1( SwTableBoxFmt
, SwFrmFmt
);
94 TYPEINIT1( SwTableLineFmt
, SwFrmFmt
);
96 SV_IMPL_PTRARR(SwTableLines
,SwTableLine
*);
97 SV_IMPL_PTRARR(SwTableBoxes
,SwTableBox
*);
98 SV_IMPL_PTRARR_SORT(SwTableSortBoxes
,SwTableBoxPtr
);
100 SV_IMPL_REF( SwServerObject
)
104 //----------------------------------
106 class SwTableBox_Impl
108 Color
*mpUserColor
, *mpNumFmtColor
;
112 void SetNewCol( Color
** ppCol
, const Color
* pNewCol
);
114 SwTableBox_Impl() : mpUserColor(0), mpNumFmtColor(0), mnRowSpan(1),
115 mbDummyFlag( false ) {}
116 ~SwTableBox_Impl() { delete mpUserColor
; delete mpNumFmtColor
; }
118 const Color
* GetSaveUserColor() const { return mpUserColor
; }
119 const Color
* GetSaveNumFmtColor() const { return mpNumFmtColor
; }
120 void SetSaveUserColor(const Color
* p
) { SetNewCol( &mpUserColor
, p
); }
121 void SetSaveNumFmtColor( const Color
* p
) { SetNewCol( &mpNumFmtColor
, p
); }
122 long getRowSpan() const { return mnRowSpan
; }
123 void setRowSpan( long nNewRowSpan
) { mnRowSpan
= nNewRowSpan
; }
124 bool getDummyFlag() const { return mbDummyFlag
; }
125 void setDummyFlag( bool bDummy
) { mbDummyFlag
= bDummy
; }
128 // ----------- Inlines -----------------------------
130 inline const Color
* SwTableBox::GetSaveUserColor() const
132 return pImpl
? pImpl
->GetSaveUserColor() : 0;
135 inline const Color
* SwTableBox::GetSaveNumFmtColor() const
137 return pImpl
? pImpl
->GetSaveNumFmtColor() : 0;
140 inline void SwTableBox::SetSaveUserColor(const Color
* p
)
143 pImpl
->SetSaveUserColor( p
);
145 ( pImpl
= new SwTableBox_Impl
) ->SetSaveUserColor( p
);
148 inline void SwTableBox::SetSaveNumFmtColor( const Color
* p
)
151 pImpl
->SetSaveNumFmtColor( p
);
153 ( pImpl
= new SwTableBox_Impl
)->SetSaveNumFmtColor( p
);
156 long SwTableBox::getRowSpan() const
158 return pImpl
? pImpl
->getRowSpan() : 1;
161 void SwTableBox::setRowSpan( long nNewRowSpan
)
165 if( nNewRowSpan
== 1 )
167 pImpl
= new SwTableBox_Impl();
169 pImpl
->setRowSpan( nNewRowSpan
);
172 bool SwTableBox::getDummyFlag() const
174 return pImpl
? pImpl
->getDummyFlag() : false;
177 void SwTableBox::setDummyFlag( bool bDummy
)
183 pImpl
= new SwTableBox_Impl();
185 pImpl
->setDummyFlag( bDummy
);
188 //JP 15.09.98: Bug 55741 - Tabs beibehalten (vorne und hinten)
189 String
& lcl_TabToBlankAtSttEnd( String
& rTxt
)
194 for( n
= 0; n
< rTxt
.Len() && ' ' >= ( c
= rTxt
.GetChar( n
)); ++n
)
196 rTxt
.SetChar( n
, ' ' );
197 for( n
= rTxt
.Len(); n
&& ' ' >= ( c
= rTxt
.GetChar( --n
)); )
199 rTxt
.SetChar( n
, ' ' );
203 String
& lcl_DelTabsAtSttEnd( String
& rTxt
)
208 for( n
= 0; n
< rTxt
.Len() && ' ' >= ( c
= rTxt
.GetChar( n
)); ++n
)
210 rTxt
.Erase( n
--, 1 );
211 for( n
= rTxt
.Len(); n
&& ' ' >= ( c
= rTxt
.GetChar( --n
)); )
217 void _InsTblBox( SwDoc
* pDoc
, SwTableNode
* pTblNd
,
218 SwTableLine
* pLine
, SwTableBoxFmt
* pBoxFrmFmt
,
220 USHORT nInsPos
, USHORT nCnt
)
222 ASSERT( pBox
->GetSttNd(), "Box ohne Start-Node" );
223 SwNodeIndex
aIdx( *pBox
->GetSttNd(), +1 );
224 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
226 pCNd
= pDoc
->GetNodes().GoNext( &aIdx
);
227 ASSERT( pCNd
, "Box ohne ContentNode" );
229 if( pCNd
->IsTxtNode() )
231 if( pBox
->GetSaveNumFmtColor() && pCNd
->GetpSwAttrSet() )
233 SwAttrSet
aAttrSet( *pCNd
->GetpSwAttrSet() );
234 if( pBox
->GetSaveUserColor() )
235 aAttrSet
.Put( SvxColorItem( *pBox
->GetSaveUserColor(), RES_CHRATR_COLOR
));
237 aAttrSet
.ClearItem( RES_CHRATR_COLOR
);
238 pDoc
->GetNodes().InsBoxen( pTblNd
, pLine
, pBoxFrmFmt
,
239 ((SwTxtNode
*)pCNd
)->GetTxtColl(),
240 &aAttrSet
, nInsPos
, nCnt
);
243 pDoc
->GetNodes().InsBoxen( pTblNd
, pLine
, pBoxFrmFmt
,
244 ((SwTxtNode
*)pCNd
)->GetTxtColl(),
245 pCNd
->GetpSwAttrSet(),
249 pDoc
->GetNodes().InsBoxen( pTblNd
, pLine
, pBoxFrmFmt
,
250 (SwTxtFmtColl
*)pDoc
->GetDfltTxtFmtColl(), 0,
253 long nRowSpan
= pBox
->getRowSpan();
256 SwTableBoxes
& rTblBoxes
= pLine
->GetTabBoxes();
257 for( USHORT i
= 0; i
< nCnt
; ++i
)
259 pBox
= rTblBoxes
[ i
+ nInsPos
];
260 pBox
->setRowSpan( nRowSpan
);
265 /*************************************************************************
267 |* SwTable::SwTable()
269 |* Ersterstellung MA 09. Mar. 93
270 |* Letzte Aenderung MA 05. May. 93
272 |*************************************************************************/
273 SwTable::SwTable( SwTableFmt
* pFmt
)
277 nGrfsThatResize( 0 ),
279 bModifyLocked( FALSE
),
282 // default Wert aus den Optionen setzen
283 eTblChgMode
= (TblChgMode
)GetTblChgDefaultMode();
286 SwTable::SwTable( const SwTable
& rTable
)
287 : SwClient( rTable
.GetFrmFmt() ),
290 eTblChgMode( rTable
.eTblChgMode
),
291 nGrfsThatResize( 0 ),
292 nRowsToRepeat( rTable
.GetRowsToRepeat() ),
293 bModifyLocked( FALSE
),
294 bNewModel( rTable
.bNewModel
)
298 void DelBoxNode( SwTableSortBoxes
& rSortCntBoxes
)
300 for( USHORT n
= 0; n
< rSortCntBoxes
.Count(); ++n
)
301 rSortCntBoxes
[ n
]->pSttNd
= 0;
308 SwDoc
* pDoc
= GetFrmFmt()->GetDoc();
309 if( !pDoc
->IsInDtor() ) // dann aus der Liste entfernen
310 pDoc
->GetLinkManager().RemoveServer( &refObj
);
315 // ist die Tabelle der letzte Client im FrameFormat, kann dieses
317 SwTableFmt
* pFmt
= (SwTableFmt
*)GetFrmFmt();
318 pFmt
->Remove( this ); // austragen,
320 if( !pFmt
->GetDepends() )
321 pFmt
->GetDoc()->DelTblFrmFmt( pFmt
); // und loeschen
323 // Loesche die Pointer aus dem SortArray der Boxen, die
324 // Objecte bleiben erhalten und werden vom DTOR der Lines/Boxes
326 //JP: reicht leider nicht, es muessen die Pointer auf den StartNode
327 // der Section geloescht werden
328 DelBoxNode( aSortCntBoxes
);
329 aSortCntBoxes
.Remove( (USHORT
)0, aSortCntBoxes
.Count() );
334 /*************************************************************************
338 |* Ersterstellung JP ??
339 |* Letzte Aenderung MA 06. May. 93
341 |*************************************************************************/
342 inline void FmtInArr( SvPtrarr
& rFmtArr
, SwFmt
* pBoxFmt
)
344 BOOL bRet
= USHRT_MAX
!= rFmtArr
.GetPos( (VoidPtr
)pBoxFmt
);
346 rFmtArr
.Insert( (VoidPtr
)pBoxFmt
, rFmtArr
.Count() );
349 void lcl_ModifyBoxes( SwTableBoxes
&rBoxes
, const long nOld
,
350 const long nNew
, SvPtrarr
& rFmtArr
);
352 void lcl_ModifyLines( SwTableLines
&rLines
, const long nOld
,
353 const long nNew
, SvPtrarr
& rFmtArr
, const bool bCheckSum
)
355 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
356 ::lcl_ModifyBoxes( rLines
[i
]->GetTabBoxes(), nOld
, nNew
, rFmtArr
);
359 for( USHORT i
= 0; i
< rFmtArr
.Count(); ++i
)
361 SwFmt
* pFmt
= (SwFmt
*)rFmtArr
[i
];
362 sal_uInt64 nBox
= pFmt
->GetFrmSize().GetWidth();
365 SwFmtFrmSize
aNewBox( ATT_VAR_SIZE
, SwTwips(nBox
), 0 );
367 pFmt
->SetFmtAttr( aNewBox
);
368 pFmt
->UnlockModify();
373 void lcl_ModifyBoxes( SwTableBoxes
&rBoxes
, const long nOld
,
374 const long nNew
, SvPtrarr
& rFmtArr
)
376 sal_uInt64 nSum
= 0; // To avoid rounding errors we summarize all box widths
377 sal_uInt64 nOriginalSum
= 0; // Sum of original widths
378 for ( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
380 SwTableBox
&rBox
= *rBoxes
[i
];
381 if ( rBox
.GetTabLines().Count() )
383 // For SubTables the rounding problem will not be solved :-(
384 ::lcl_ModifyLines( rBox
.GetTabLines(), nOld
, nNew
, rFmtArr
, false );
387 SwFrmFmt
*pFmt
= rBox
.GetFrmFmt();
388 sal_uInt64 nBox
= pFmt
->GetFrmSize().GetWidth();
389 nOriginalSum
+= nBox
;
392 sal_uInt64 nWishedSum
= nOriginalSum
;
398 if( nBox
== nWishedSum
)
399 FmtInArr( rFmtArr
, pFmt
);
403 pFmt
= rBox
.ClaimFrmFmt();
404 SwFmtFrmSize
aNewBox( ATT_VAR_SIZE
, static_cast< SwTwips
>(nBox
), 0 );
406 pFmt
->SetFmtAttr( aNewBox
);
407 pFmt
->UnlockModify();
411 ASSERT( false, "Rounding error" );
417 void SwTable::Modify( SfxPoolItem
*pOld
, SfxPoolItem
*pNew
)
419 // fange SSize Aenderungen ab, um die Lines/Boxen anzupassen
420 USHORT nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0 ;
421 const SwFmtFrmSize
* pNewSize
= 0, *pOldSize
= 0;
423 if( RES_ATTRSET_CHG
== nWhich
)
425 if( SFX_ITEM_SET
== ((SwAttrSetChg
*)pNew
)->GetChgSet()->GetItemState(
426 RES_FRM_SIZE
, FALSE
, (const SfxPoolItem
**)&pNewSize
))
427 pOldSize
= &((SwAttrSetChg
*)pOld
)->GetChgSet()->GetFrmSize();
429 else if( RES_FRM_SIZE
== nWhich
)
431 pOldSize
= (const SwFmtFrmSize
*)pOld
;
432 pNewSize
= (const SwFmtFrmSize
*)pNew
;
435 if( pOldSize
|| pNewSize
)
437 if ( !IsModifyLocked() )
439 ASSERT( pOldSize
&& pOldSize
->Which() == RES_FRM_SIZE
&&
440 pNewSize
&& pNewSize
->Which() == RES_FRM_SIZE
,
441 "Kein Old oder New fuer FmtFrmSize-Modify der SwTable." );
442 AdjustWidths( pOldSize
->GetWidth(), pNewSize
->GetWidth() );
446 SwClient::Modify( pOld
, pNew
); // fuers ObjectDying
449 void SwTable::AdjustWidths( const long nOld
, const long nNew
)
451 SvPtrarr
aFmtArr( (BYTE
)aLines
[0]->GetTabBoxes().Count(), 1 );
452 ::lcl_ModifyLines( aLines
, nOld
, nNew
, aFmtArr
, true );
455 /*************************************************************************
457 |* SwTable::GetTabCols()
459 |* Ersterstellung MA 04. May. 93
460 |* Letzte Aenderung MA 30. Nov. 95
462 |*************************************************************************/
463 void lcl_RefreshHidden( SwTabCols
&rToFill
, USHORT nPos
)
465 for ( USHORT i
= 0; i
< rToFill
.Count(); ++i
)
467 if ( Abs((long)(nPos
- rToFill
[i
])) <= COLFUZZY
)
469 rToFill
.SetHidden( i
, FALSE
);
475 void lcl_SortedTabColInsert( SwTabCols
&rToFill
, const SwTableBox
*pBox
,
476 const SwFrmFmt
*pTabFmt
, const BOOL bHidden
,
477 const FASTBOOL bRefreshHidden
)
479 const long nWish
= pTabFmt
->GetFrmSize().GetWidth();
480 const long nAct
= rToFill
.GetRight() - rToFill
.GetLeft(); // +1 why?
482 //Der Wert fuer die linke Kante der Box errechnet sich aus den
483 //Breiten der vorhergehenden Boxen.
487 USHORT nRightMax
= 0;
488 const SwTableBox
*pCur
= pBox
;
489 const SwTableLine
*pLine
= pBox
->GetUpper();
491 { const SwTableBoxes
&rBoxes
= pLine
->GetTabBoxes();
492 for ( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
494 SwTwips nWidth
= rBoxes
[i
]->GetFrmFmt()->GetFrmSize().GetWidth();
495 nSum
= (USHORT
)(nSum
+ nWidth
);
496 sal_uInt64 nTmp
= nSum
;
499 if (rBoxes
[i
] != pCur
)
501 if ( pLine
== pBox
->GetUpper() || 0 == nLeftMin
)
502 nLeftMin
= (USHORT
)(nTmp
- nPos
);
507 nSum
= (USHORT
)(nSum
- nWidth
);
508 if ( 0 == nRightMax
)
509 nRightMax
= (USHORT
)(nTmp
- nPos
);
513 pCur
= pLine
->GetUpper();
514 pLine
= pCur
? pCur
->GetUpper() : 0;
517 BOOL bInsert
= !bRefreshHidden
;
518 for ( USHORT j
= 0; bInsert
&& (j
< rToFill
.Count()); ++j
)
520 long nCmp
= rToFill
[j
];
521 if ( (nPos
>= ((nCmp
>= COLFUZZY
) ? nCmp
- COLFUZZY
: nCmp
)) &&
522 (nPos
<= (nCmp
+ COLFUZZY
)) )
524 bInsert
= FALSE
; //Hat ihn schon.
526 else if ( nPos
< nCmp
)
529 rToFill
.Insert( nPos
, bHidden
, j
);
533 rToFill
.Insert( nPos
, bHidden
, rToFill
.Count() );
534 else if ( bRefreshHidden
)
535 ::lcl_RefreshHidden( rToFill
, nPos
);
537 if ( bHidden
&& !bRefreshHidden
)
539 // calculate minimum/maximum values for the existing entries:
540 nLeftMin
= nPos
- nLeftMin
;
541 nRightMax
= nPos
+ nRightMax
;
543 // check if nPos is entry:
544 bool bFoundPos
= false;
545 bool bFoundMax
= false;
546 for ( USHORT j
= 0; !(bFoundPos
&& bFoundMax
) && j
< rToFill
.Count(); ++j
)
548 SwTabColsEntry
& rEntry
= rToFill
.GetEntry( j
);
549 long nCmp
= rToFill
[j
];
551 if ( (nPos
>= ((nCmp
>= COLFUZZY
) ? nCmp
- COLFUZZY
: nCmp
)) &&
552 (nPos
<= (nCmp
+ COLFUZZY
)) )
554 // check if nLeftMin is > old minimum for entry nPos:
555 const long nOldMin
= rEntry
.nMin
;
556 if ( nLeftMin
> nOldMin
)
557 rEntry
.nMin
= nLeftMin
;
558 // check if nRightMin is < old maximum for entry nPos:
559 const long nOldMax
= rEntry
.nMax
;
560 if ( nRightMax
< nOldMax
)
561 rEntry
.nMax
= nRightMax
;
565 else if ( (nRightMax
>= ((nCmp
>= COLFUZZY
) ? nCmp
- COLFUZZY
: nCmp
)) &&
566 (nRightMax
<= (nCmp
+ COLFUZZY
)) )
568 // check if nPos is > old minimum for entry nRightMax:
569 const long nOldMin
= rEntry
.nMin
;
570 if ( nPos
> nOldMin
)
579 void lcl_ProcessBoxGet( const SwTableBox
*pBox
, SwTabCols
&rToFill
,
580 const SwFrmFmt
*pTabFmt
, FASTBOOL bRefreshHidden
)
582 if ( pBox
->GetTabLines().Count() )
584 const SwTableLines
&rLines
= pBox
->GetTabLines();
585 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
586 { const SwTableBoxes
&rBoxes
= rLines
[i
]->GetTabBoxes();
587 for ( USHORT j
= 0; j
< rBoxes
.Count(); ++j
)
588 ::lcl_ProcessBoxGet( rBoxes
[j
], rToFill
, pTabFmt
, bRefreshHidden
);
592 ::lcl_SortedTabColInsert( rToFill
, pBox
, pTabFmt
, FALSE
, bRefreshHidden
);
595 void lcl_ProcessLineGet( const SwTableLine
*pLine
, SwTabCols
&rToFill
,
596 const SwFrmFmt
*pTabFmt
)
598 for ( USHORT i
= 0; i
< pLine
->GetTabBoxes().Count(); ++i
)
600 const SwTableBox
*pBox
= pLine
->GetTabBoxes()[i
];
601 if ( pBox
->GetSttNd() )
602 ::lcl_SortedTabColInsert( rToFill
, pBox
, pTabFmt
, TRUE
, FALSE
);
604 for ( USHORT j
= 0; j
< pBox
->GetTabLines().Count(); ++j
)
605 ::lcl_ProcessLineGet( pBox
->GetTabLines()[j
], rToFill
, pTabFmt
);
609 // MS: Sonst Absturz auf der DEC-Kiste
611 #if defined(ALPHA) && defined(WNT)
612 #pragma optimize("", off)
615 void SwTable::GetTabCols( SwTabCols
&rToFill
, const SwTableBox
*pStart
,
616 BOOL bRefreshHidden
, BOOL bCurRowOnly
) const
618 //MA 30. Nov. 95: Opt: wenn bHidden gesetzt ist, wird nur das Hidden
619 //Array aktualisiert.
620 if ( bRefreshHidden
)
622 //Korrekturen entfernen
624 for ( i
= 0; i
< rToFill
.Count(); ++i
)
626 SwTabColsEntry
& rEntry
= rToFill
.GetEntry( i
);
627 rEntry
.nPos
-= rToFill
.GetLeft();
628 rEntry
.nMin
-= rToFill
.GetLeft();
629 rEntry
.nMax
-= rToFill
.GetLeft();
632 //Alle sind hidden, dann die sichtbaren eintragen.
633 for ( i
= 0; i
< rToFill
.Count(); ++i
)
634 rToFill
.SetHidden( i
, TRUE
);
638 rToFill
.Remove( 0, rToFill
.Count() );
641 //Eingetragen werden:
642 //1. Alle Boxen unterhalb der dem Start uebergeordneten Line sowie
643 // deren untergeordnete Boxen falls vorhanden.
644 //2. Ausgehend von der Line die uebergeordnete Box sowie deren Nachbarn;
645 // nicht aber deren untergeordnete.
646 //3. Mit der der Boxenkette uebergeordneten Line wieder wie 2. bis einer
647 // Line keine Box (sondern die Table) uebergeordnet ist.
648 //Es werden nur diejenigen Boxen eingetragen, die keine weiteren Zeilen
649 //enhalten. Die eintragende Funktion sorgt dafuer, dass keine doppelten
650 //eingetragen werden. Um dies zu gewaehrleisten wird mit einer gewissen
651 //Unschaerfe gearbeitet (um Rundungsfehler auszuschalten).
652 //Es werden nur die linken Kanten der Boxen eingetragen.
653 //Am Schluss wird der Erste wieder ausgetragen denn er ist bereits vom
656 //4. Nochmalige abscannen der Tabelle und eintragen _aller_ Boxen,
657 // jetzt aber als Hidden.
659 const SwFrmFmt
*pTabFmt
= GetFrmFmt();
662 const SwTableBoxes
&rBoxes
= pStart
->GetUpper()->GetTabBoxes();
665 for ( i
= 0; i
< rBoxes
.Count(); ++i
)
666 ::lcl_ProcessBoxGet( rBoxes
[i
], rToFill
, pTabFmt
, bRefreshHidden
);
669 const SwTableLine
*pLine
= pStart
->GetUpper()->GetUpper() ?
670 pStart
->GetUpper()->GetUpper()->GetUpper() : 0;
673 const SwTableBoxes
&rBoxes2
= pLine
->GetTabBoxes();
674 for ( USHORT k
= 0; k
< rBoxes2
.Count(); ++k
)
675 ::lcl_SortedTabColInsert( rToFill
, rBoxes2
[k
],
676 pTabFmt
, FALSE
, bRefreshHidden
);
677 pLine
= pLine
->GetUpper() ? pLine
->GetUpper()->GetUpper() : 0;
680 if ( !bRefreshHidden
)
685 for ( i
= 0; i
< aLines
.Count(); ++i
)
686 ::lcl_ProcessLineGet( aLines
[i
], rToFill
, pTabFmt
);
689 rToFill
.Remove( 0, 1 );
692 //Die Koordinaten sind jetzt relativ zum linken Rand der Tabelle - also
693 //relativ zum nLeft vom SwTabCols. Die Werte werden aber relativ zum
694 //linken Rand - also nLeftMin vom SwTabCols - erwartet.
695 //Alle Werte muessen also um nLeft erweitert werden.
696 for ( i
= 0; i
< rToFill
.Count(); ++i
)
698 SwTabColsEntry
& rEntry
= rToFill
.GetEntry( i
);
699 rEntry
.nPos
+= rToFill
.GetLeft();
700 rEntry
.nMin
+= rToFill
.GetLeft();
701 rEntry
.nMax
+= rToFill
.GetLeft();
705 #if defined(ALPHA) && defined(WNT)
706 #pragma optimize("", on)
709 /*************************************************************************
711 |* SwTable::SetTabCols()
713 |* Ersterstellung MA 04. May. 93
714 |* Letzte Aenderung MA 26. Aug. 98
716 |*************************************************************************/
717 //Struktur zur Parameteruebergabe
720 const SwTabCols
&rNew
;
721 const SwTabCols
&rOld
;
725 SwShareBoxFmts aShareFmts
;
727 Parm( const SwTabCols
&rN
, const SwTabCols
&rO
) :
728 rNew( rN
), rOld( rO
), aBoxArr( 10, 1 ) {}
730 inline BOOL
BoxInArr( SvPtrarr
& rArr
, SwTableBox
* pBox
)
732 BOOL bRet
= USHRT_MAX
!= rArr
.GetPos( (VoidPtr
)pBox
);
734 rArr
.Insert( (VoidPtr
)pBox
, rArr
.Count() );
738 void lcl_ProcessBoxSet( SwTableBox
*pBox
, Parm
&rParm
);
740 void lcl_ProcessLine( SwTableLine
*pLine
, Parm
&rParm
)
742 SwTableBoxes
&rBoxes
= pLine
->GetTabBoxes();
743 for ( int i
= rBoxes
.Count()-1; i
>= 0; --i
)
744 ::lcl_ProcessBoxSet( rBoxes
[ static_cast< USHORT
>(i
) ], rParm
);
747 void lcl_ProcessBoxSet( SwTableBox
*pBox
, Parm
&rParm
)
749 if ( pBox
->GetTabLines().Count() )
750 { SwTableLines
&rLines
= pBox
->GetTabLines();
751 for ( int i
= rLines
.Count()-1; i
>= 0; --i
)
752 lcl_ProcessLine( rLines
[ static_cast< USHORT
>(i
) ], rParm
);
756 //Aktuelle Position (linke und rechte Kante berechnen) und im
757 //alten TabCols suchen. Im neuen TabCols die Werte vergleichen und
758 //wenn es Unterschiede gibt die Box entsprechend anpassen.
759 //Wenn an der veraenderten Kante kein Nachbar existiert werden auch
760 //alle uebergeordneten Boxen angepasst.
762 const long nOldAct
= rParm
.rOld
.GetRight() -
763 rParm
.rOld
.GetLeft(); // +1 why?
765 //Der Wert fuer die linke Kante der Box errechnet sich aus den
766 //Breiten der vorhergehenden Boxen plus dem linken Rand
767 long nLeft
= rParm
.rOld
.GetLeft();
768 const SwTableBox
*pCur
= pBox
;
769 const SwTableLine
*pLine
= pBox
->GetUpper();
772 { const SwTableBoxes
&rBoxes
= pLine
->GetTabBoxes();
773 for ( USHORT i
= 0; (i
< rBoxes
.Count()) && (rBoxes
[i
] != pCur
); ++i
)
775 sal_uInt64 nWidth
= rBoxes
[i
]->GetFrmFmt()->
776 GetFrmSize().GetWidth();
778 nWidth
/= rParm
.nOldWish
;
779 nLeft
+= (USHORT
)nWidth
;
781 pCur
= pLine
->GetUpper();
782 pLine
= pCur
? pCur
->GetUpper() : 0;
786 if ( nLeft
!= rParm
.rOld
.GetLeft() ) //Es gibt noch Boxen davor.
788 //Rechte Kante ist linke Kante plus Breite.
789 sal_uInt64 nWidth
= pBox
->GetFrmFmt()->GetFrmSize().GetWidth();
791 nWidth
/= rParm
.nOldWish
;
792 long nRight
= nLeft
+ (long)nWidth
;
793 USHORT nLeftPos
= USHRT_MAX
,
794 nRightPos
= USHRT_MAX
;
795 for ( USHORT i
= 0; i
< rParm
.rOld
.Count(); ++i
)
797 if ( nLeft
>= (rParm
.rOld
[i
] - COLFUZZY
) &&
798 nLeft
<= (rParm
.rOld
[i
] + COLFUZZY
) )
800 else if ( nRight
>= (rParm
.rOld
[i
] - COLFUZZY
) &&
801 nRight
<= (rParm
.rOld
[i
] + COLFUZZY
) )
804 nLeftDiff
= nLeftPos
!= USHRT_MAX
?
805 (int)rParm
.rOld
[nLeftPos
] - (int)rParm
.rNew
[nLeftPos
] : 0;
806 nRightDiff
= nRightPos
!= USHRT_MAX
?
807 (int)rParm
.rNew
[nRightPos
] - (int)rParm
.rOld
[nRightPos
] : 0;
809 else //Die erste Box.
811 nLeftDiff
= (long)rParm
.rOld
.GetLeft() - (long)rParm
.rNew
.GetLeft();
812 if ( rParm
.rOld
.Count() )
814 //Differnz zu der Kante berechnen, von der die erste Box
816 sal_uInt64 nWidth
= pBox
->GetFrmFmt()->GetFrmSize().GetWidth();
818 nWidth
/= rParm
.nOldWish
;
819 long nTmp
= (long)nWidth
;
820 nTmp
+= rParm
.rOld
.GetLeft();
821 USHORT nLeftPos
= USHRT_MAX
;
822 for ( USHORT i
= 0; i
< rParm
.rOld
.Count() &&
823 nLeftPos
== USHRT_MAX
; ++i
)
825 if ( nTmp
>= (rParm
.rOld
[i
] - COLFUZZY
) &&
826 nTmp
<= (rParm
.rOld
[i
] + COLFUZZY
) )
829 if ( nLeftPos
!= USHRT_MAX
)
830 nRightDiff
= (long)rParm
.rNew
[nLeftPos
] -
831 (long)rParm
.rOld
[nLeftPos
];
833 //MA 11. Feb. 99: #61577# 0 sollte doch gerade richtig sein, weil die
834 //Kante doch schon in SetTabCols() korrigiert wurde.
836 // nRightDiff = (long)rParm.rNew.GetRight() -
837 // (long)rParm.rOld.GetRight();
840 if( pBox
->getRowSpan() == 1 )
842 SwTableBoxes
& rTblBoxes
= pBox
->GetUpper()->GetTabBoxes();
843 USHORT nPos
= rTblBoxes
.C40_GETPOS( SwTableBox
, pBox
);
844 if( nPos
&& rTblBoxes
[ nPos
- 1 ]->getRowSpan() != 1 )
846 if( nPos
+ 1 < rTblBoxes
.Count() &&
847 rTblBoxes
[ nPos
+ 1 ]->getRowSpan() != 1 )
851 nLeftDiff
= nRightDiff
= 0;
853 if ( nLeftDiff
|| nRightDiff
)
855 //Die Differenz ist der tatsaechliche Differenzbetrag; die
856 //Attribute der Boxen um diesen Betrag anzupassen macht keinen
857 //Sinn wenn die Tabelle gestrecht ist. Der Differenzbetrag muss
858 //entsprechend umgerechnet werden.
859 long nTmp
= rParm
.rNew
.GetRight() - rParm
.rNew
.GetLeft(); // +1 why?
860 nLeftDiff
*= rParm
.nNewWish
;
862 nRightDiff
*= rParm
.nNewWish
;
864 long nDiff
= nLeftDiff
+ nRightDiff
;
866 //Box und alle uebergeordneten um den Differenzbetrag anpassen.
869 SwFmtFrmSize
aFmtFrmSize( pBox
->GetFrmFmt()->GetFrmSize() );
870 aFmtFrmSize
.SetWidth( aFmtFrmSize
.GetWidth() + nDiff
);
871 if ( aFmtFrmSize
.GetWidth() < 0 )
872 aFmtFrmSize
.SetWidth( -aFmtFrmSize
.GetWidth() );
873 rParm
.aShareFmts
.SetSize( *pBox
, aFmtFrmSize
);
875 // The outer cells of the last row are responsible to adjust a surrounding cell.
877 if ( pBox
->GetUpper()->GetUpper() &&
878 pBox
->GetUpper() != pBox
->GetUpper()->GetUpper()->GetTabLines()
879 [pBox
->GetUpper()->GetUpper()->GetTabLines().Count()-1])
885 // Middle cell check:
886 if ( pBox
!= pBox
->GetUpper()->GetTabBoxes()[0] )
889 if ( pBox
!= pBox
->GetUpper()->GetTabBoxes()
890 [pBox
->GetUpper()->GetTabBoxes().Count()-1] )
893 pBox
= nDiff
? pBox
->GetUpper()->GetUpper() : 0;
900 void lcl_ProcessBoxPtr( SwTableBox
*pBox
, SvPtrarr
&rBoxArr
,
903 if ( pBox
->GetTabLines().Count() )
905 const SwTableLines
&rLines
= pBox
->GetTabLines();
906 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
908 const SwTableBoxes
&rBoxes
= rLines
[i
]->GetTabBoxes();
909 for ( USHORT j
= 0; j
< rBoxes
.Count(); ++j
)
910 ::lcl_ProcessBoxPtr( rBoxes
[j
], rBoxArr
, bBefore
);
914 rBoxArr
.Insert( (VoidPtr
)pBox
, 0 );
916 rBoxArr
.Insert( (VoidPtr
)pBox
, rBoxArr
.Count() );
919 void lcl_AdjustBox( SwTableBox
*pBox
, const long nDiff
, Parm
&rParm
);
921 void lcl_AdjustLines( SwTableLines
&rLines
, const long nDiff
, Parm
&rParm
)
923 for ( USHORT i
= 0; i
< rLines
.Count(); ++i
)
925 SwTableBox
*pBox
= rLines
[i
]->GetTabBoxes()
926 [rLines
[i
]->GetTabBoxes().Count()-1];
927 lcl_AdjustBox( pBox
, nDiff
, rParm
);
931 void lcl_AdjustBox( SwTableBox
*pBox
, const long nDiff
, Parm
&rParm
)
933 if ( pBox
->GetTabLines().Count() )
934 ::lcl_AdjustLines( pBox
->GetTabLines(), nDiff
, rParm
);
936 //Groesse der Box anpassen.
937 SwFmtFrmSize
aFmtFrmSize( pBox
->GetFrmFmt()->GetFrmSize() );
938 aFmtFrmSize
.SetWidth( aFmtFrmSize
.GetWidth() + nDiff
);
939 //#30009# if ( aFmtFrmSize.GetWidth() < 0 )
940 // aFmtFrmSize.SetWidth( -aFmtFrmSize.GetWidth() );
942 rParm
.aShareFmts
.SetSize( *pBox
, aFmtFrmSize
);
945 void SwTable::SetTabCols( const SwTabCols
&rNew
, const SwTabCols
&rOld
,
946 const SwTableBox
*pStart
, BOOL bCurRowOnly
)
950 SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
952 // FME: Made rOld const. The caller is responsible for passing correct
953 // values of rOld. Therefore we do not have to call GetTabCols anymore:
954 //GetTabCols( rOld, pStart );
956 Parm
aParm( rNew
, rOld
);
958 ASSERT( rOld
.Count() == rNew
.Count(), "Columnanzahl veraendert.");
960 //Raender verarbeiten. Groesse der Tabelle und ein paar Boxen mussen
961 //angepasst werden. Bei der Groesseneinstellung darf allerdings das
962 //Modify nicht verarbeitet werden - dieses wuerde alle Boxen anpassen
963 //und das koennen wir ueberhaupt nicht gebrauchen.
964 SwFrmFmt
*pFmt
= GetFrmFmt();
965 aParm
.nOldWish
= aParm
.nNewWish
= pFmt
->GetFrmSize().GetWidth();
966 if ( (rOld
.GetLeft() != rNew
.GetLeft()) ||
967 (rOld
.GetRight()!= rNew
.GetRight()) )
971 SvxLRSpaceItem
aLR( pFmt
->GetLRSpace() );
972 SvxShadowItem
aSh( pFmt
->GetShadow() );
974 SwTwips nShRight
= aSh
.CalcShadowSpace( SHADOW_RIGHT
);
975 SwTwips nShLeft
= aSh
.CalcShadowSpace( SHADOW_LEFT
);
977 aLR
.SetLeft ( rNew
.GetLeft() - nShLeft
);
978 aLR
.SetRight( rNew
.GetRightMax() - rNew
.GetRight() - nShRight
);
979 pFmt
->SetFmtAttr( aLR
);
981 //Die Ausrichtung der Tabelle muss entsprechend angepasst werden,
982 //das geschieht so, dass die Tabelle genauso stehenbleibt wie der
983 //Anwender sie gerade hingezuppelt hat.
984 SwFmtHoriOrient
aOri( pFmt
->GetHoriOrient() );
985 if(text::HoriOrientation::NONE
!= aOri
.GetHoriOrient())
987 const BOOL bLeftDist
= rNew
.GetLeft() != nShLeft
;
988 const BOOL bRightDist
= rNew
.GetRight() + nShRight
!= rNew
.GetRightMax();
989 if(!bLeftDist
&& !bRightDist
)
990 aOri
.SetHoriOrient( text::HoriOrientation::FULL
);
991 else if(!bRightDist
&& rNew
.GetLeft() > nShLeft
)
992 aOri
.SetHoriOrient( text::HoriOrientation::RIGHT
);
993 else if(!bLeftDist
&& rNew
.GetRight() + nShRight
< rNew
.GetRightMax())
994 aOri
.SetHoriOrient( text::HoriOrientation::LEFT
);
996 aOri
.SetHoriOrient( text::HoriOrientation::NONE
);
998 pFmt
->SetFmtAttr( aOri
);
1000 const long nAct
= rOld
.GetRight() - rOld
.GetLeft(); // +1 why?
1003 if ( rOld
.GetLeft() != rNew
.GetLeft() )
1005 nTabDiff
= rOld
.GetLeft() - rNew
.GetLeft();
1006 nTabDiff
*= aParm
.nOldWish
;
1009 if ( rOld
.GetRight() != rNew
.GetRight() )
1011 long nDiff
= rNew
.GetRight() - rOld
.GetRight();
1012 nDiff
*= aParm
.nOldWish
;
1016 ::lcl_AdjustLines( GetTabLines(), nDiff
, aParm
);
1019 //Groesse der Tabelle anpassen. Es muss beachtet werden, das die
1020 //Tabelle gestrecht sein kann.
1023 aParm
.nNewWish
+= nTabDiff
;
1024 if ( aParm
.nNewWish
< 0 )
1025 aParm
.nNewWish
= USHRT_MAX
; //Uuups! Eine Rolle rueckwaerts.
1026 SwFmtFrmSize
aSz( pFmt
->GetFrmSize() );
1027 if ( aSz
.GetWidth() != aParm
.nNewWish
)
1029 aSz
.SetWidth( aParm
.nNewWish
);
1030 aSz
.SetWidthPercent( 0 );
1031 pFmt
->SetFmtAttr( aSz
);
1038 NewSetTabCols( aParm
, rNew
, rOld
, pStart
, bCurRowOnly
);
1043 //Um die aktuelle Zeile anzupassen muessen wir analog zu dem
1044 //Verfahren zum fuellen der TabCols (siehe GetTabCols()) die
1045 //Boxen der aktuellen Zeile abklappern.
1046 //Leider muessen wir auch hier dafuer sorgen, dass die Boxen von
1047 //hinten nach vorne bzw. von innen nach aussen veraendert werden.
1048 //Der beste Weg hierzu scheint mir darin zu liegen die
1049 //entsprechenden Boxen in einem PtrArray vorzumerken.
1051 const SwTableBoxes
&rBoxes
= pStart
->GetUpper()->GetTabBoxes();
1052 for ( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
1053 ::lcl_ProcessBoxPtr( rBoxes
[i
], aParm
.aBoxArr
, FALSE
);
1055 const SwTableLine
*pLine
= pStart
->GetUpper()->GetUpper() ?
1056 pStart
->GetUpper()->GetUpper()->GetUpper() : 0;
1057 const SwTableBox
*pExcl
= pStart
->GetUpper()->GetUpper();
1060 const SwTableBoxes
&rBoxes2
= pLine
->GetTabBoxes();
1061 BOOL bBefore
= TRUE
;
1062 for ( USHORT i
= 0; i
< rBoxes2
.Count(); ++i
)
1064 if ( rBoxes2
[i
] != pExcl
)
1065 ::lcl_ProcessBoxPtr( rBoxes2
[i
], aParm
.aBoxArr
, bBefore
);
1069 pExcl
= pLine
->GetUpper();
1070 pLine
= pLine
->GetUpper() ? pLine
->GetUpper()->GetUpper() : 0;
1072 //Nachdem wir haufenweise Boxen (hoffentlich alle und in der richtigen
1073 //Reihenfolge) eingetragen haben, brauchen diese nur noch rueckwaerts
1074 //verarbeitet zu werden.
1075 for ( int j
= aParm
.aBoxArr
.Count()-1; j
>= 0; --j
)
1077 SwTableBox
*pBox
= (SwTableBox
*)aParm
.aBoxArr
[ static_cast< USHORT
>(j
)];
1078 ::lcl_ProcessBoxSet( pBox
, aParm
);
1082 { //Die gesamte Tabelle anzupassen ist 'einfach'.
1083 //Es werden alle Boxen, die keine Lines mehr enthalten angepasst.
1084 //Diese Boxen passen alle uebergeordneten Boxen entsprechend mit an.
1085 //Um uns nicht selbst hereinzulegen muss natuerlich rueckwaerst
1086 //gearbeitet werden!
1087 SwTableLines
&rLines
= GetTabLines();
1088 for ( int i
= rLines
.Count()-1; i
>= 0; --i
)
1089 ::lcl_ProcessLine( rLines
[ static_cast< USHORT
>(i
) ], aParm
);
1095 // steht im tblrwcl.cxx
1096 extern void _CheckBoxWidth( const SwTableLine
&, SwTwips
);
1097 // checke doch mal ob die Tabellen korrekte Breiten haben
1098 SwTwips nSize
= GetFrmFmt()->GetFrmSize().GetWidth();
1099 for( USHORT n
= 0; n
< aLines
.Count(); ++n
)
1100 _CheckBoxWidth( *aLines
[ n
], nSize
);
1105 typedef std::pair
<USHORT
, USHORT
> ColChange
;
1106 typedef std::list
< ColChange
> ChangeList
;
1108 static void lcl_AdjustWidthsInLine( SwTableLine
* pLine
, ChangeList
& rOldNew
,
1109 Parm
& rParm
, USHORT nColFuzzy
)
1111 ChangeList::iterator pCurr
= rOldNew
.begin();
1112 if( pCurr
== rOldNew
.end() )
1114 USHORT nCount
= pLine
->GetTabBoxes().Count();
1116 SwTwips nBorder
= 0;
1120 SwTableBox
* pBox
= pLine
->GetTabBoxes()[i
++];
1121 SwTwips nWidth
= pBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1122 SwTwips nNewWidth
= nWidth
- nRest
;
1125 if( pCurr
!= rOldNew
.end() && nBorder
+ nColFuzzy
>= pCurr
->first
)
1127 nBorder
-= nColFuzzy
;
1128 while( pCurr
!= rOldNew
.end() && nBorder
> pCurr
->first
)
1130 if( pCurr
!= rOldNew
.end() )
1132 nBorder
+= nColFuzzy
;
1133 if( nBorder
+ nColFuzzy
>= pCurr
->first
)
1135 if( pCurr
->second
== pCurr
->first
)
1138 nRest
= pCurr
->second
- nBorder
;
1144 if( nNewWidth
!= nWidth
)
1148 nRest
+= 1 - nNewWidth
;
1151 SwFmtFrmSize
aFmtFrmSize( pBox
->GetFrmFmt()->GetFrmSize() );
1152 aFmtFrmSize
.SetWidth( nNewWidth
);
1153 rParm
.aShareFmts
.SetSize( *pBox
, aFmtFrmSize
);
1158 static void lcl_CalcNewWidths( std::list
<USHORT
> &rSpanPos
, ChangeList
& rChanges
,
1159 SwTableLine
* pLine
, long nWish
, long nWidth
, bool bTop
)
1161 if( !rChanges
.size() )
1166 if( !rSpanPos
.size() )
1171 std::list
<USHORT
> aNewSpanPos
;
1172 ChangeList aNewChanges
;
1173 ChangeList::iterator pCurr
= rChanges
.begin();
1174 aNewChanges
.push_back( *pCurr
); // Nullposition
1175 std::list
<USHORT
>::iterator pSpan
= rSpanPos
.begin();
1178 bool bRowSpan
= false;
1179 USHORT nRowSpanCount
= 0;
1180 USHORT nCount
= pLine
->GetTabBoxes().Count();
1181 for( USHORT nCurrBox
= 0; nCurrBox
< nCount
; ++nCurrBox
)
1183 SwTableBox
* pBox
= pLine
->GetTabBoxes()[nCurrBox
];
1184 SwTwips nCurrWidth
= pBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1185 const long nRowSpan
= pBox
->getRowSpan();
1186 const bool bCurrRowSpan
= bTop
? nRowSpan
< 0 :
1187 ( nRowSpan
> 1 || nRowSpan
< -1 );
1188 if( bRowSpan
|| bCurrRowSpan
)
1189 aNewSpanPos
.push_back( nRowSpanCount
);
1190 bRowSpan
= bCurrRowSpan
;
1191 nOrgSum
= (USHORT
)(nOrgSum
+ nCurrWidth
);
1192 sal_uInt64 nSum
= nOrgSum
;
1197 USHORT nPos
= (USHORT
)nSum
;
1198 while( pCurr
!= rChanges
.end() && pCurr
->first
< nPos
)
1201 USHORT nTemp
= pCurr
->first
;
1202 nTemp
= pCurr
->second
;
1208 if( pCurr
!= rChanges
.end() && pCurr
->first
<= nPos
&&
1209 pCurr
->first
!= pCurr
->second
)
1211 while( pSpan
!= rSpanPos
.end() && *pSpan
< nCurr
)
1213 if( pSpan
!= rSpanPos
.end() && *pSpan
== nCurr
)
1215 aNewChanges
.push_back( *pCurr
);
1222 ColChange
aTmp( nPos
, nPos
);
1223 aNewChanges
.push_back( aTmp
);
1228 pCurr
= aNewChanges
.begin();
1229 ChangeList::iterator pLast
= pCurr
;
1230 ChangeList::iterator pLeftMove
= pCurr
;
1231 while( pCurr
!= aNewChanges
.end() )
1233 if( pLeftMove
== pCurr
)
1235 while( ++pLeftMove
!= aNewChanges
.end() && pLeftMove
->first
<= pLeftMove
->second
)
1238 if( pCurr
->second
== pCurr
->first
)
1240 if( pLeftMove
!= aNewChanges
.end() && pCurr
->second
> pLeftMove
->second
)
1242 if( pLeftMove
->first
== pLast
->first
)
1243 pCurr
->second
= pLeftMove
->second
;
1246 sal_uInt64 nTmp
= pCurr
->first
- pLast
->first
;
1247 nTmp
*= pLeftMove
->second
- pLast
->second
;
1248 nTmp
/= pLeftMove
->first
- pLast
->first
;
1249 nTmp
+= pLast
->second
;
1250 pCurr
->second
= (USHORT
)nTmp
;
1256 else if( pCurr
->second
> pCurr
->first
)
1260 ChangeList::iterator pNext
= pCurr
;
1261 while( pNext
!= pLeftMove
&& pNext
->second
== pNext
->first
&&
1262 pNext
->second
< pLast
->second
)
1264 while( pCurr
!= pNext
)
1266 if( pNext
== aNewChanges
.end() || pNext
->first
== pLast
->first
)
1267 pCurr
->second
= pLast
->second
;
1270 sal_uInt64 nTmp
= pCurr
->first
- pLast
->first
;
1271 nTmp
*= pNext
->second
- pLast
->second
;
1272 nTmp
/= pNext
->first
- pLast
->first
;
1273 nTmp
+= pLast
->second
;
1274 pCurr
->second
= (USHORT
)nTmp
;
1288 ChangeList::iterator pCopy
= aNewChanges
.begin();
1289 while( pCopy
!= aNewChanges
.end() )
1290 rChanges
.push_back( *pCopy
++ );
1292 std::list
<USHORT
>::iterator pSpCopy
= aNewSpanPos
.begin();
1293 while( pSpCopy
!= aNewSpanPos
.end() )
1294 rSpanPos
.push_back( *pSpCopy
++ );
1297 void SwTable::NewSetTabCols( Parm
&rParm
, const SwTabCols
&rNew
,
1298 const SwTabCols
&rOld
, const SwTableBox
*pStart
, BOOL bCurRowOnly
)
1301 static int nCallCount
= 0;
1304 // First step: evaluate which lines have been moved/which widths changed
1306 const long nNewWidth
= rParm
.rNew
.GetRight() - rParm
.rNew
.GetLeft();
1307 const long nOldWidth
= rParm
.rOld
.GetRight() - rParm
.rOld
.GetLeft();
1308 if( nNewWidth
< 1 || nOldWidth
< 1 )
1310 for( USHORT i
= 0; i
<= rOld
.Count(); ++i
)
1314 if( i
== rOld
.Count() )
1316 nOldPos
= rParm
.rOld
.GetRight() - rParm
.rOld
.GetLeft();
1317 nNewPos
= rParm
.rNew
.GetRight() - rParm
.rNew
.GetLeft();
1321 nOldPos
= rOld
[i
] - rParm
.rOld
.GetLeft();
1322 nNewPos
= rNew
[i
] - rParm
.rNew
.GetLeft();
1324 nNewPos
*= rParm
.nNewWish
;
1325 nNewPos
/= nNewWidth
;
1326 nOldPos
*= rParm
.nOldWish
;
1327 nOldPos
/= nOldWidth
;
1328 if( nOldPos
!= nNewPos
&& nNewPos
> 0 && nOldPos
> 0 )
1330 ColChange
aChg( (USHORT
)nOldPos
, (USHORT
)nNewPos
);
1331 aOldNew
.push_back( aChg
);
1334 // Finished first step
1335 int nCount
= aOldNew
.size();
1337 return; // no change, nothing to do
1338 SwTableLines
&rLines
= GetTabLines();
1341 const SwTableLine
* pCurrLine
= pStart
->GetUpper();
1342 USHORT nCurr
= rLines
.C40_GETPOS( SwTableLine
, pCurrLine
);
1343 if( nCurr
>= USHRT_MAX
)
1346 ColChange
aChg( 0, 0 );
1347 aOldNew
.push_front( aChg
);
1348 std::list
<USHORT
> aRowSpanPos
;
1352 ChangeList::iterator pCop
= aOldNew
.begin();
1354 while( pCop
!= aOldNew
.end() )
1356 aCopy
.push_back( *pCop
);
1358 aRowSpanPos
.push_back( nPos
++ );
1360 lcl_CalcNewWidths( aRowSpanPos
, aCopy
, rLines
[nCurr
],
1361 rParm
.nOldWish
, nOldWidth
, true );
1362 bool bGoOn
= aRowSpanPos
.size() > 0;
1366 lcl_CalcNewWidths( aRowSpanPos
, aCopy
, rLines
[--j
],
1367 rParm
.nOldWish
, nOldWidth
, true );
1368 lcl_AdjustWidthsInLine( rLines
[j
], aCopy
, rParm
, 0 );
1369 bGoOn
= aRowSpanPos
.size() > 0 && j
> 0;
1371 aRowSpanPos
.clear();
1373 if( nCurr
+1 < rLines
.Count() )
1376 ChangeList::iterator pCop
= aOldNew
.begin();
1378 while( pCop
!= aOldNew
.end() )
1380 aCopy
.push_back( *pCop
);
1382 aRowSpanPos
.push_back( nPos
++ );
1384 lcl_CalcNewWidths( aRowSpanPos
, aCopy
, rLines
[nCurr
],
1385 rParm
.nOldWish
, nOldWidth
, false );
1386 bool bGoOn
= aRowSpanPos
.size() > 0;
1390 lcl_CalcNewWidths( aRowSpanPos
, aCopy
, rLines
[++j
],
1391 rParm
.nOldWish
, nOldWidth
, false );
1392 lcl_AdjustWidthsInLine( rLines
[j
], aCopy
, rParm
, 0 );
1393 bGoOn
= aRowSpanPos
.size() > 0 && j
+1 < rLines
.Count();
1396 ::lcl_AdjustWidthsInLine( rLines
[nCurr
], aOldNew
, rParm
, 1 );
1398 else for( USHORT i
= 0; i
< rLines
.Count(); ++i
)
1399 ::lcl_AdjustWidthsInLine( rLines
[i
], aOldNew
, rParm
, COLFUZZY
);
1400 CHECK_TABLE( *this )
1404 /*************************************************************************
1406 |* const SwTableBox* SwTable::GetTblBox( const Strn?ng& rName ) const
1407 |* gebe den Pointer auf die benannte Box zurueck.
1409 |* Ersterstellung JP 30. Jun. 93
1410 |* Letzte Aenderung JP 30. Jun. 93
1412 |*************************************************************************/
1414 BOOL
IsValidRowName( const String
& rStr
)
1416 BOOL bIsValid
= TRUE
;
1417 xub_StrLen nLen
= rStr
.Len();
1418 for (xub_StrLen i
= 0; i
< nLen
&& bIsValid
; ++i
)
1420 const sal_Unicode cChar
= rStr
.GetChar(i
);
1421 if (cChar
< '0' || cChar
> '9')
1427 // --> OD 2007-08-03 #i80314#
1428 // add 3rd parameter and its handling
1429 USHORT
SwTable::_GetBoxNum( String
& rStr
, BOOL bFirstPart
,
1430 const bool bPerformValidCheck
)
1433 xub_StrLen nPos
= 0;
1434 if( bFirstPart
) // TRUE == column; FALSE == row
1436 // die 1. ist mit Buchstaben addressiert!
1439 while( 0 != ( cChar
= rStr
.GetChar( nPos
)) &&
1440 ( (cChar
>= 'A' && cChar
<= 'Z') ||
1441 (cChar
>= 'a' && cChar
<= 'z') ) )
1443 if( (cChar
-= 'A') >= 26 )
1449 nRet
= nRet
* 52 + cChar
;
1452 rStr
.Erase( 0, nPos
); // Zeichen aus dem String loeschen
1454 else if( STRING_NOTFOUND
== ( nPos
= rStr
.Search( aDotStr
) ))
1457 if ( !bPerformValidCheck
|| IsValidRowName( rStr
) )
1459 nRet
= static_cast<USHORT
>(rStr
.ToInt32());
1466 String
aTxt( rStr
.Copy( 0, nPos
) );
1467 if ( !bPerformValidCheck
|| IsValidRowName( aTxt
) )
1469 nRet
= static_cast<USHORT
>(aTxt
.ToInt32());
1471 rStr
.Erase( 0, nPos
+1 );
1477 // --> OD 2007-08-03 #i80314#
1478 // add 2nd parameter and its handling
1479 const SwTableBox
* SwTable::GetTblBox( const String
& rName
,
1480 const bool bPerformValidCheck
) const
1482 const SwTableBox
* pBox
= 0;
1483 const SwTableLine
* pLine
;
1484 const SwTableLines
* pLines
;
1485 const SwTableBoxes
* pBoxes
;
1488 String
aNm( rName
);
1491 nBox
= SwTable::_GetBoxNum( aNm
, 0 == pBox
, bPerformValidCheck
);
1494 pLines
= &GetTabLines();
1497 pLines
= &pBox
->GetTabLines();
1502 nLine
= SwTable::_GetBoxNum( aNm
, FALSE
, bPerformValidCheck
);
1504 // bestimme die Line
1505 if( !nLine
|| nLine
> pLines
->Count() )
1507 pLine
= (*pLines
)[ nLine
-1 ];
1510 pBoxes
= &pLine
->GetTabBoxes();
1511 if( nBox
>= pBoxes
->Count() )
1513 pBox
= (*pBoxes
)[ nBox
];
1516 // abpruefen, ob die gefundene Box auch wirklich eine Inhaltstragende
1518 if( pBox
&& !pBox
->GetSttNd() )
1520 ASSERT( FALSE
, "Box ohne Inhalt, suche die naechste !!" );
1521 // "herunterfallen lassen" bis zur ersten Box
1522 while( pBox
->GetTabLines().Count() )
1523 pBox
= pBox
->GetTabLines()[0]->GetTabBoxes()[0];
1528 SwTableBox
* SwTable::GetTblBox( ULONG nSttIdx
)
1530 //MA: Zur Optimierung nicht immer umstaendlich das ganze SortArray abhuenern.
1531 //OS: #102675# converting text to table tries und certain conditions
1532 // to ask for a table box of a table that is not yet having a format
1535 SwTableBox
* pRet
= 0;
1536 SwNodes
& rNds
= GetFrmFmt()->GetDoc()->GetNodes();
1537 ULONG nIndex
= nSttIdx
+ 1;
1538 SwCntntNode
* pCNd
= 0;
1539 SwTableNode
* pTblNd
= 0;
1541 while ( nIndex
< rNds
.Count() )
1543 pTblNd
= rNds
[ nIndex
]->GetTableNode();
1547 pCNd
= rNds
[ nIndex
]->GetCntntNode();
1554 if ( pCNd
|| pTblNd
)
1556 SwModify
* pModify
= pCNd
;
1557 // --> FME 2007-3-26 #144862# Better handling of table in table:
1558 if ( pTblNd
&& pTblNd
->GetTable().GetFrmFmt() )
1559 pModify
= pTblNd
->GetTable().GetFrmFmt();
1562 SwClientIter
aIter( *pModify
);
1563 SwFrm
*pFrm
= (SwFrm
*)aIter
.First( TYPE(SwFrm
) );
1564 while ( pFrm
&& !pFrm
->IsCellFrm() )
1565 pFrm
= pFrm
->GetUpper();
1567 pRet
= (SwTableBox
*)((SwCellFrm
*)pFrm
)->GetTabBox();
1570 //Falls es das Layout noch nicht gibt oder sonstwie etwas schieft geht.
1573 for( USHORT n
= aSortCntBoxes
.Count(); n
; )
1574 if( aSortCntBoxes
[ --n
]->GetSttIdx() == nSttIdx
)
1575 return aSortCntBoxes
[ n
];
1580 BOOL
SwTable::IsTblComplex() const
1582 // returnt TRUE wenn sich in der Tabelle Verschachtelungen befinden
1583 // steht eine Box nicht in der obersten Line, da wurde gesplittet/
1584 // gemergt und die Struktur ist komplexer.
1585 for( USHORT n
= 0; n
< aSortCntBoxes
.Count(); ++n
)
1586 if( aSortCntBoxes
[ n
]->GetUpper()->GetUpper() )
1593 /*************************************************************************
1595 |* SwTableLine::SwTableLine()
1597 |* Ersterstellung MA 09. Mar. 93
1598 |* Letzte Aenderung MA 09. Mar. 93
1600 |*************************************************************************/
1601 SwTableLine::SwTableLine( SwTableLineFmt
*pFmt
, USHORT nBoxes
,
1604 aBoxes( (BYTE
)nBoxes
, 1 ),
1609 SwTableLine::~SwTableLine()
1611 // ist die TabelleLine der letzte Client im FrameFormat, kann dieses
1613 SwModify
* pMod
= GetFrmFmt();
1614 pMod
->Remove( this ); // austragen,
1615 if( !pMod
->GetDepends() )
1616 delete pMod
; // und loeschen
1619 /*************************************************************************
1621 |* SwTableLine::ClaimFrmFmt(), ChgFrmFmt()
1623 |* Ersterstellung MA 03. May. 93
1624 |* Letzte Aenderung MA 07. Feb. 96
1626 |*************************************************************************/
1627 SwFrmFmt
* SwTableLine::ClaimFrmFmt()
1629 //Wenn noch andere TableLines ausser mir selbst an dem FrmFmt haengen,
1630 //sehe ich mich leider gezwungen mir ein eingenes zu machen und mich
1631 //bei diesem anzumelden.
1632 SwTableLineFmt
*pOld
= (SwTableLineFmt
*)GetFrmFmt();
1633 SwClientIter
aIter( *pOld
);
1637 for( pLast
= aIter
.First( TYPE( SwTableLine
)); pLast
&& pLast
== this;
1638 pLast
= aIter
.Next() )
1643 SwTableLineFmt
*pNewFmt
= pOld
->GetDoc()->MakeTableLineFmt();
1646 //Erstmal die Frms ummelden.
1647 for( pLast
= aIter
.First( TYPE( SwFrm
) ); pLast
; pLast
= aIter
.Next() )
1648 if( ((SwRowFrm
*)pLast
)->GetTabLine() == this )
1649 pNewFmt
->Add( pLast
);
1651 //Jetzt noch mich selbst ummelden.
1652 pNewFmt
->Add( this );
1659 void SwTableLine::ChgFrmFmt( SwTableLineFmt
*pNewFmt
)
1661 SwFrmFmt
*pOld
= GetFrmFmt();
1662 SwClientIter
aIter( *pOld
);
1665 //Erstmal die Frms ummelden.
1666 for( pLast
= aIter
.First( TYPE( SwFrm
) ); pLast
; pLast
= aIter
.Next() )
1668 SwRowFrm
*pRow
= (SwRowFrm
*)pLast
;
1669 if( pRow
->GetTabLine() == this )
1671 pNewFmt
->Add( pLast
);
1673 pRow
->InvalidateSize();
1674 pRow
->_InvalidatePrt();
1675 pRow
->SetCompletePaint();
1676 pRow
->ReinitializeFrmSizeAttrFlags();
1678 // --> FME 2004-10-27 #i35063#
1679 // consider 'split row allowed' attribute
1680 SwTabFrm
* pTab
= pRow
->FindTabFrm();
1681 bool bInFollowFlowRow
= false;
1682 const bool bInFirstNonHeadlineRow
= pTab
->IsFollow() &&
1683 pRow
== pTab
->GetFirstNonHeadlineRow();
1684 if ( bInFirstNonHeadlineRow
||
1686 0 != ( bInFollowFlowRow
= pRow
->IsInFollowFlowRow() ) ||
1687 0 != pRow
->IsInSplitTableRow() )
1689 if ( bInFirstNonHeadlineRow
|| bInFollowFlowRow
)
1690 pTab
= pTab
->FindMaster();
1692 pTab
->SetRemoveFollowFlowLinePending( TRUE
);
1693 pTab
->InvalidatePos();
1699 //Jetzt noch mich selbst ummelden.
1700 pNewFmt
->Add( this );
1702 if ( !aIter
.GoStart() )
1706 SwTwips
SwTableLine::GetTableLineHeight( bool& bLayoutAvailable
) const
1709 bLayoutAvailable
= false;
1710 SwClientIter
aIter( *GetFrmFmt() );
1711 // A row could appear several times in headers/footers so only one chain of master/follow tables
1712 // will be accepted...
1713 const SwTabFrm
* pChain
= NULL
; // My chain
1714 for( SwClient
* pLast
= aIter
.First( TYPE( SwFrm
) ); pLast
;
1715 pLast
= aIter
.Next() )
1717 if( ((SwRowFrm
*)pLast
)->GetTabLine() == this )
1719 const SwTabFrm
* pTab
= static_cast<SwRowFrm
*>(pLast
)->FindTabFrm();
1720 bLayoutAvailable
= ( pTab
&& pTab
->IsVertical() ) ?
1721 ( 0 < pTab
->Frm().Height() ) :
1722 ( 0 < pTab
->Frm().Width() );
1724 // The first one defines the chain, if a chain is defined, only members of the chain
1726 if( !pChain
|| pChain
->IsAnFollow( pTab
) || pTab
->IsAnFollow( pChain
) )
1728 pChain
= pTab
; // defines my chain (even it is already)
1729 if( pTab
->IsVertical() )
1730 nRet
+= static_cast<SwRowFrm
*>(pLast
)->Frm().Width();
1732 nRet
+= static_cast<SwRowFrm
*>(pLast
)->Frm().Height();
1733 // Optimization, if there are no master/follows in my chain, nothing more to add
1734 if( !pTab
->HasFollow() && !pTab
->IsFollow() )
1736 // This is not an optimization, this is necessary to avoid double additions of
1738 if( pTab
->IsInHeadline( *static_cast<SwRowFrm
*>(pLast
) ) )
1746 /*************************************************************************
1748 |* SwTableBox::SwTableBox()
1750 |* Ersterstellung MA 04. May. 93
1751 |* Letzte Aenderung MA 04. May. 93
1753 |*************************************************************************/
1754 SwTableBox::SwTableBox( SwTableBoxFmt
* pFmt
, USHORT nLines
, SwTableLine
*pUp
)
1756 aLines( (BYTE
)nLines
, 1 ),
1761 CheckBoxFmt( pFmt
)->Add( this );
1764 SwTableBox::SwTableBox( SwTableBoxFmt
* pFmt
, const SwNodeIndex
&rIdx
,
1771 SwDoc
* pDoc
= pFmt
->GetDoc();
1772 CheckBoxFmt( pFmt
)->Add( this );
1774 pSttNd
= pDoc
->GetNodes()[ rIdx
]->GetStartNode();
1776 // an der Table eintragen
1777 const SwTableNode
* pTblNd
= pSttNd
->FindTableNode();
1778 ASSERT( pTblNd
, "in welcher Tabelle steht denn die Box?" );
1779 SwTableSortBoxes
& rSrtArr
= (SwTableSortBoxes
&)pTblNd
->GetTable().
1781 SwTableBox
* p
= this; // error: &this
1782 rSrtArr
.Insert( p
); // eintragen
1785 SwTableBox::SwTableBox( SwTableBoxFmt
* pFmt
, const SwStartNode
& rSttNd
, SwTableLine
*pUp
) :
1792 CheckBoxFmt( pFmt
)->Add( this );
1794 // an der Table eintragen
1795 const SwTableNode
* pTblNd
= pSttNd
->FindTableNode();
1796 ASSERT( pTblNd
, "in welcher Tabelle steht denn die Box?" );
1797 SwTableSortBoxes
& rSrtArr
= (SwTableSortBoxes
&)pTblNd
->GetTable().
1799 SwTableBox
* p
= this; // error: &this
1800 rSrtArr
.Insert( p
); // eintragen
1803 SwTableBox::~SwTableBox()
1805 // Inhaltstragende Box ?
1806 if( !GetFrmFmt()->GetDoc()->IsInDtor() && pSttNd
)
1808 // an der Table austragen
1809 const SwTableNode
* pTblNd
= pSttNd
->FindTableNode();
1810 ASSERT( pTblNd
, "in welcher Tabelle steht denn die Box?" );
1811 SwTableSortBoxes
& rSrtArr
= (SwTableSortBoxes
&)pTblNd
->GetTable().
1813 SwTableBox
*p
= this; // error: &this
1814 rSrtArr
.Remove( p
); // austragen
1817 // ist die TabelleBox der letzte Client im FrameFormat, kann dieses
1819 SwModify
* pMod
= GetFrmFmt();
1820 pMod
->Remove( this ); // austragen,
1821 if( !pMod
->GetDepends() )
1822 delete pMod
; // und loeschen
1827 SwTableBoxFmt
* SwTableBox::CheckBoxFmt( SwTableBoxFmt
* pFmt
)
1829 // sollte das Format eine Formel oder einen Value tragen, dann muss die
1830 // Box alleine am Format haengen. Ggfs. muss ein neues angelegt werden.
1831 if( SFX_ITEM_SET
== pFmt
->GetItemState( RES_BOXATR_VALUE
, FALSE
) ||
1832 SFX_ITEM_SET
== pFmt
->GetItemState( RES_BOXATR_FORMULA
, FALSE
) )
1834 SwClient
* pOther
= SwClientIter( *pFmt
).First( TYPE( SwTableBox
));
1837 SwTableBoxFmt
* pNewFmt
= pFmt
->GetDoc()->MakeTableBoxFmt();
1838 pNewFmt
->LockModify();
1841 // Values und Formeln entfernen
1842 pNewFmt
->ResetFmtAttr( RES_BOXATR_FORMULA
, RES_BOXATR_VALUE
);
1843 pNewFmt
->UnlockModify();
1851 /*************************************************************************
1853 |* SwTableBox::ClaimFrmFmt(), ChgFrmFmt()
1855 |* Ersterstellung MA 04. May. 93
1856 |* Letzte Aenderung MA 07. Feb. 96
1858 |*************************************************************************/
1859 SwFrmFmt
* SwTableBox::ClaimFrmFmt()
1861 //Wenn noch andere TableBoxen ausser mir selbst an dem FrmFmt haengen,
1862 //sehe ich mich leider gezwungen mir ein eingenes zu machen und mich
1863 //bei diesem anzumelden.
1864 SwTableBoxFmt
*pOld
= (SwTableBoxFmt
*)GetFrmFmt();
1865 SwClientIter
aIter( *pOld
);
1868 for( pLast
= aIter
.First( TYPE( SwTableBox
)); pLast
&& pLast
== this;
1869 pLast
= aIter
.Next() )
1874 SwTableBoxFmt
* pNewFmt
= pOld
->GetDoc()->MakeTableBoxFmt();
1876 pNewFmt
->LockModify();
1879 // Values und Formeln nie kopieren
1880 pNewFmt
->ResetFmtAttr( RES_BOXATR_FORMULA
, RES_BOXATR_VALUE
);
1881 pNewFmt
->UnlockModify();
1883 //Erstmal die Frms ummelden.
1884 for( pLast
= aIter
.First( TYPE( SwFrm
) ); pLast
; pLast
= aIter
.Next() )
1885 if( ((SwCellFrm
*)pLast
)->GetTabBox() == this )
1886 pNewFmt
->Add( pLast
);
1888 //Jetzt noch mich selbst ummelden.
1889 pNewFmt
->Add( this );
1895 void SwTableBox::ChgFrmFmt( SwTableBoxFmt
* pNewFmt
)
1897 SwFrmFmt
*pOld
= GetFrmFmt();
1898 SwClientIter
aIter( *pOld
);
1901 //Erstmal die Frms ummelden.
1902 for( pLast
= aIter
.First( TYPE( SwFrm
) ); pLast
; pLast
= aIter
.Next() )
1904 SwCellFrm
*pCell
= (SwCellFrm
*)pLast
;
1905 if( pCell
->GetTabBox() == this )
1907 pNewFmt
->Add( pLast
);
1908 pCell
->InvalidateSize();
1909 pCell
->_InvalidatePrt();
1910 pCell
->SetCompletePaint();
1911 pCell
->SetDerivedVert( FALSE
);
1912 pCell
->CheckDirChange();
1914 // --> FME 2005-04-15 #i47489#
1915 // make sure that the row will be formatted, in order
1916 // to have the correct Get(Top|Bottom)MarginForLowers values
1918 const SwTabFrm
* pTab
= pCell
->FindTabFrm();
1919 if ( pTab
&& pTab
->IsCollapsingBorders() )
1921 SwFrm
* pRow
= pCell
->GetUpper();
1922 pRow
->_InvalidateSize();
1923 pRow
->_InvalidatePrt();
1929 //Jetzt noch mich selbst ummelden.
1930 pNewFmt
->Add( this );
1932 if( !aIter
.GoStart() )
1936 /*************************************************************************
1938 |* String SwTableBox::GetName() const
1939 |* gebe den Namen dieser Box zurueck. Dieser wird dynamisch bestimmt
1940 |* und ergibt sich aus der Position in den Lines/Boxen/Tabelle
1942 |* Ersterstellung JP 30. Jun. 93
1943 |* Letzte Aenderung JP 30. Jun. 93
1945 |*************************************************************************/
1946 void lcl_GetTblBoxColStr( USHORT nCol
, String
& rNm
)
1948 const USHORT coDiff
= 52; // 'A'-'Z' 'a' - 'z'
1952 nCalc
= nCol
% coDiff
;
1954 rNm
.Insert( sal_Unicode('a' - 26 + nCalc
), 0 );
1956 rNm
.Insert( sal_Unicode('A' + nCalc
), 0 );
1958 if( 0 == (nCol
= nCol
- nCalc
) )
1965 String
SwTableBox::GetName() const
1967 if( !pSttNd
) // keine Content Box ??
1969 // die naechste erste Box suchen ??
1973 const SwTable
& rTbl
= pSttNd
->FindTableNode()->GetTable();
1976 const SwTableBox
* pBox
= this;
1978 const SwTableBoxes
* pBoxes
= &pBox
->GetUpper()->GetTabBoxes();
1979 const SwTableLine
* pLine
= pBox
->GetUpper();
1980 // auf oberstere Ebene ?
1981 const SwTableLines
* pLines
= pLine
->GetUpper()
1982 ? &pLine
->GetUpper()->GetTabLines() : &rTbl
.GetTabLines();
1984 sTmp
= String::CreateFromInt32( nPos
= pLines
->GetPos( pLine
) + 1 );
1986 sNm
.Insert( aDotStr
, 0 ).Insert( sTmp
, 0 );
1990 sTmp
= String::CreateFromInt32(( nPos
= pBoxes
->GetPos( pBox
)) + 1 );
1991 if( 0 != ( pBox
= pLine
->GetUpper()) )
1992 sNm
.Insert( aDotStr
, 0 ).Insert( sTmp
, 0 );
1994 ::lcl_GetTblBoxColStr( nPos
, sNm
);
2000 BOOL
SwTableBox::IsInHeadline( const SwTable
* pTbl
) const
2002 if( !GetUpper() ) // sollte nur beim Merge vorkommen.
2006 pTbl
= &pSttNd
->FindTableNode()->GetTable();
2008 const SwTableLine
* pLine
= GetUpper();
2009 while( pLine
->GetUpper() )
2010 pLine
= pLine
->GetUpper()->GetUpper();
2013 return pTbl
->GetTabLines()[ 0 ] == pLine
;
2018 ULONG
SwTableBox::GetSttIdx() const
2020 return pSttNd
? pSttNd
->GetIndex() : 0;
2024 // erfrage vom Client Informationen
2025 BOOL
SwTable::GetInfo( SfxPoolItem
& rInfo
) const
2027 switch( rInfo
.Which() )
2029 case RES_AUTOFMT_DOCNODE
:
2031 const SwTableNode
* pTblNode
= GetTableNode();
2032 if( pTblNode
&& &pTblNode
->GetNodes() == ((SwAutoFmtGetDocNode
&)rInfo
).pNodes
)
2034 if ( aSortCntBoxes
.Count() )
2036 SwNodeIndex
aIdx( *aSortCntBoxes
[ 0 ]->GetSttNd() );
2037 ((SwAutoFmtGetDocNode
&)rInfo
).pCntntNode
=
2038 GetFrmFmt()->GetDoc()->GetNodes().GoNext( &aIdx
);
2044 case RES_FINDNEARESTNODE
:
2045 if( GetFrmFmt() && ((SwFmtPageDesc
&)GetFrmFmt()->GetFmtAttr(
2046 RES_PAGEDESC
)).GetPageDesc() &&
2047 aSortCntBoxes
.Count() &&
2048 aSortCntBoxes
[ 0 ]->GetSttNd()->GetNodes().IsDocNodes() )
2049 ((SwFindNearestNode
&)rInfo
).CheckNode( *
2050 aSortCntBoxes
[ 0 ]->GetSttNd()->FindTableNode() );
2053 case RES_CONTENT_VISIBLE
:
2055 ((SwPtrMsgPoolItem
&)rInfo
).pObject
=
2056 SwClientIter( *GetFrmFmt() ).First( TYPE(SwFrm
) );
2063 SwTable
* SwTable::FindTable( SwFrmFmt
* pFmt
)
2065 return pFmt
? (SwTable
*)SwClientIter( *pFmt
).First( TYPE(SwTable
) ) : 0;
2068 SwTableNode
* SwTable::GetTableNode() const
2070 return GetTabSortBoxes().Count() ?
2071 (SwTableNode
*)GetTabSortBoxes()[ 0 ]->GetSttNd()->FindTableNode() :
2075 void SwTable::SetRefObject( SwServerObject
* pObj
)
2084 void SwTable::SetHTMLTableLayout( SwHTMLTableLayout
*p
)
2091 void ChgTextToNum( SwTableBox
& rBox
, const String
& rTxt
, const Color
* pCol
,
2094 ULONG nNdPos
= rBox
.IsValidNumTxtNd( TRUE
);
2095 if( ULONG_MAX
!= nNdPos
)
2097 SwDoc
* pDoc
= rBox
.GetFrmFmt()->GetDoc();
2098 SwTxtNode
* pTNd
= pDoc
->GetNodes()[ nNdPos
]->GetTxtNode();
2099 const SfxPoolItem
* pItem
;
2101 // Ausrichtung umsetzen
2104 pItem
= &pTNd
->SwCntntNode::GetAttr( RES_PARATR_ADJUST
);
2105 SvxAdjust eAdjust
= ((SvxAdjustItem
*)pItem
)->GetAdjust();
2106 if( SVX_ADJUST_LEFT
== eAdjust
|| SVX_ADJUST_BLOCK
== eAdjust
)
2108 SvxAdjustItem
aAdjust( *(SvxAdjustItem
*)pItem
);
2109 aAdjust
.SetAdjust( SVX_ADJUST_RIGHT
);
2110 pTNd
->SetAttr( aAdjust
);
2114 // Farbe umsetzen oder "Benutzer Farbe" sichern
2115 if( !pTNd
->GetpSwAttrSet() || SFX_ITEM_SET
!= pTNd
->GetpSwAttrSet()->
2116 GetItemState( RES_CHRATR_COLOR
, FALSE
, &pItem
))
2119 const Color
* pOldNumFmtColor
= rBox
.GetSaveNumFmtColor();
2120 const Color
* pNewUserColor
= pItem
? &((SvxColorItem
*)pItem
)->GetValue() : 0;
2122 if( ( pNewUserColor
&& pOldNumFmtColor
&&
2123 *pNewUserColor
== *pOldNumFmtColor
) ||
2124 ( !pNewUserColor
&& !pOldNumFmtColor
))
2126 // User Color nicht veraendern aktuellen Werte setzen
2127 // ggfs. die alte NumFmtColor loeschen
2129 // ggfs. die Farbe setzen
2130 pTNd
->SetAttr( SvxColorItem( *pCol
, RES_CHRATR_COLOR
));
2133 pNewUserColor
= rBox
.GetSaveUserColor();
2135 pTNd
->SetAttr( SvxColorItem( *pNewUserColor
, RES_CHRATR_COLOR
));
2137 pTNd
->ResetAttr( RES_CHRATR_COLOR
);
2142 // User Color merken, ggfs. die NumFormat Color setzen, aber
2143 // nie die Farbe zurueck setzen
2144 rBox
.SetSaveUserColor( pNewUserColor
);
2147 // ggfs. die Farbe setzen
2148 pTNd
->SetAttr( SvxColorItem( *pCol
, RES_CHRATR_COLOR
));
2151 rBox
.SetSaveNumFmtColor( pCol
);
2153 if( pTNd
->GetTxt() != rTxt
)
2156 //JP 15.09.98: Bug 55741 - Tabs beibehalten (vorne und hinten!)
2157 const String
& rOrig
= pTNd
->GetTxt();
2160 for( n
= 0; n
< rOrig
.Len() && '\x9' == rOrig
.GetChar( n
); ++n
)
2162 SwIndex
aIdx( pTNd
, n
);
2163 for( n
= rOrig
.Len(); n
&& '\x9' == rOrig
.GetChar( --n
); )
2165 n
-= aIdx
.GetIndex() - 1;
2167 //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen
2168 // zuruecksetzen, damit sie wieder aufgespannt werden
2170 SwIndex
aResetIdx( aIdx
, n
);
2171 pTNd
->DontExpandFmt( aResetIdx
, FALSE
, FALSE
);
2174 if( !pDoc
->IsIgnoreRedline() && pDoc
->GetRedlineTbl().Count() )
2176 SwPaM
aTemp(*pTNd
, 0, *pTNd
, rOrig
.Len());
2177 pDoc
->DeleteRedline(aTemp
, true, USHRT_MAX
);
2180 pTNd
->EraseText( aIdx
, n
,
2181 IDocumentContentOperations::INS_EMPTYEXPAND
);
2182 pTNd
->InsertText( rTxt
, aIdx
,
2183 IDocumentContentOperations::INS_EMPTYEXPAND
);
2185 if( pDoc
->IsRedlineOn() )
2187 SwPaM
aTemp(*pTNd
, 0, *pTNd
, rTxt
.Len());
2188 pDoc
->AppendRedline(new SwRedline(nsRedlineType_t::REDLINE_INSERT
, aTemp
), true);
2192 // vertikale Ausrichtung umsetzen
2194 ( SFX_ITEM_SET
!= rBox
.GetFrmFmt()->GetItemState(
2195 RES_VERT_ORIENT
, TRUE
, &pItem
) ||
2196 text::VertOrientation::TOP
== ((SwFmtVertOrient
*)pItem
)->GetVertOrient() ))
2198 rBox
.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::BOTTOM
));
2203 void ChgNumToText( SwTableBox
& rBox
, ULONG nFmt
)
2205 ULONG nNdPos
= rBox
.IsValidNumTxtNd( FALSE
);
2206 if( ULONG_MAX
!= nNdPos
)
2208 SwDoc
* pDoc
= rBox
.GetFrmFmt()->GetDoc();
2209 SwTxtNode
* pTNd
= pDoc
->GetNodes()[ nNdPos
]->GetTxtNode();
2210 BOOL bChgAlign
= pDoc
->IsInsTblAlignNum();
2211 const SfxPoolItem
* pItem
;
2214 if( NUMBERFORMAT_TEXT
!= nFmt
)
2216 // speziellen Textformat:
2217 String sTmp
, sTxt( pTNd
->GetTxt() );
2218 pDoc
->GetNumberFormatter()->GetOutputString( sTxt
, nFmt
, sTmp
, &pCol
);
2222 SwIndex
aIdx( pTNd
, sTxt
.Len() );
2223 //JP 06.04.99: Bug 64321 - DontExpand-Flags vorm Austauschen
2224 // zuruecksetzen, damit sie wieder aufgespannt werden
2225 pTNd
->DontExpandFmt( aIdx
, FALSE
, FALSE
);
2227 pTNd
->EraseText( aIdx
, STRING_LEN
,
2228 IDocumentContentOperations::INS_EMPTYEXPAND
);
2229 pTNd
->InsertText( sTmp
, aIdx
,
2230 IDocumentContentOperations::INS_EMPTYEXPAND
);
2234 const SfxItemSet
* pAttrSet
= pTNd
->GetpSwAttrSet();
2236 // Ausrichtung umsetzen
2237 if( bChgAlign
&& pAttrSet
&& SFX_ITEM_SET
== pAttrSet
->GetItemState(
2238 RES_PARATR_ADJUST
, FALSE
, &pItem
) &&
2239 SVX_ADJUST_RIGHT
== ((SvxAdjustItem
*)pItem
)->GetAdjust() )
2241 pTNd
->SetAttr( SvxAdjustItem( SVX_ADJUST_LEFT
, RES_PARATR_ADJUST
) );
2244 // Farbe umsetzen oder "Benutzer Farbe" sichern
2245 if( !pAttrSet
|| SFX_ITEM_SET
!= pAttrSet
->
2246 GetItemState( RES_CHRATR_COLOR
, FALSE
, &pItem
))
2249 const Color
* pOldNumFmtColor
= rBox
.GetSaveNumFmtColor();
2250 const Color
* pNewUserColor
= pItem
? &((SvxColorItem
*)pItem
)->GetValue() : 0;
2252 if( ( pNewUserColor
&& pOldNumFmtColor
&&
2253 *pNewUserColor
== *pOldNumFmtColor
) ||
2254 ( !pNewUserColor
&& !pOldNumFmtColor
))
2256 // User Color nicht veraendern aktuellen Werte setzen
2257 // ggfs. die alte NumFmtColor loeschen
2259 // ggfs. die Farbe setzen
2260 pTNd
->SetAttr( SvxColorItem( *pCol
, RES_CHRATR_COLOR
));
2263 pNewUserColor
= rBox
.GetSaveUserColor();
2265 pTNd
->SetAttr( SvxColorItem( *pNewUserColor
, RES_CHRATR_COLOR
));
2267 pTNd
->ResetAttr( RES_CHRATR_COLOR
);
2272 // User Color merken, ggfs. die NumFormat Color setzen, aber
2273 // nie die Farbe zurueck setzen
2274 rBox
.SetSaveUserColor( pNewUserColor
);
2277 // ggfs. die Farbe setzen
2278 pTNd
->SetAttr( SvxColorItem( *pCol
, RES_CHRATR_COLOR
));
2281 rBox
.SetSaveNumFmtColor( pCol
);
2284 // vertikale Ausrichtung umsetzen
2286 SFX_ITEM_SET
== rBox
.GetFrmFmt()->GetItemState(
2287 RES_VERT_ORIENT
, FALSE
, &pItem
) &&
2288 text::VertOrientation::BOTTOM
== ((SwFmtVertOrient
*)pItem
)->GetVertOrient() )
2290 rBox
.GetFrmFmt()->SetFmtAttr( SwFmtVertOrient( 0, text::VertOrientation::TOP
));
2295 // zum Erkennen von Veraenderungen (haupts. TableBoxAttribute)
2296 void SwTableBoxFmt::Modify( SfxPoolItem
* pOld
, SfxPoolItem
* pNew
)
2298 if( !IsModifyLocked() && !IsInDocDTOR() )
2300 const SwTblBoxNumFormat
*pNewFmt
= 0;
2301 const SwTblBoxFormula
*pNewFml
= 0;
2302 const SwTblBoxValue
*pNewVal
= 0;
2303 double aOldValue
= 0;
2304 ULONG nOldFmt
= NUMBERFORMAT_TEXT
;
2306 switch( pNew
? pNew
->Which() : 0 )
2308 case RES_ATTRSET_CHG
:
2310 const SfxItemSet
& rSet
= *((SwAttrSetChg
*)pNew
)->GetChgSet();
2311 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_FORMAT
,
2312 FALSE
, (const SfxPoolItem
**)&pNewFmt
) )
2313 nOldFmt
= ((SwTblBoxNumFormat
&)((SwAttrSetChg
*)pOld
)->
2314 GetChgSet()->Get( RES_BOXATR_FORMAT
)).GetValue();
2315 rSet
.GetItemState( RES_BOXATR_FORMULA
, FALSE
,
2316 (const SfxPoolItem
**)&pNewFml
);
2317 if( SFX_ITEM_SET
== rSet
.GetItemState( RES_BOXATR_VALUE
,
2318 FALSE
, (const SfxPoolItem
**)&pNewVal
) )
2319 aOldValue
= ((SwTblBoxValue
&)((SwAttrSetChg
*)pOld
)->
2320 GetChgSet()->Get( RES_BOXATR_VALUE
)).GetValue();
2324 case RES_BOXATR_FORMAT
:
2325 pNewFmt
= (SwTblBoxNumFormat
*)pNew
;
2326 nOldFmt
= ((SwTblBoxNumFormat
*)pOld
)->GetValue();
2328 case RES_BOXATR_FORMULA
:
2329 pNewFml
= (SwTblBoxFormula
*)pNew
;
2331 case RES_BOXATR_VALUE
:
2332 pNewVal
= (SwTblBoxValue
*)pNew
;
2333 aOldValue
= ((SwTblBoxValue
*)pOld
)->GetValue();
2337 // es hat sich etwas getan und im Set ist noch irgendein BoxAttribut
2339 if( pNewFmt
|| pNewFml
|| pNewVal
)
2341 GetDoc()->SetFieldsDirty(true, NULL
, 0);
2343 if( SFX_ITEM_SET
== GetItemState( RES_BOXATR_FORMAT
, FALSE
) ||
2344 SFX_ITEM_SET
== GetItemState( RES_BOXATR_VALUE
, FALSE
) ||
2345 SFX_ITEM_SET
== GetItemState( RES_BOXATR_FORMULA
, FALSE
) )
2348 SwClientIter
aIter( *this );
2349 SwTableBox
* pBox
= (SwTableBox
*)aIter
.First( TYPE( SwTableBox
) );
2352 ASSERT( !aIter
.Next(), "keine Box oder mehrere am Format" );
2357 nNewFmt
= pNewFmt
->GetValue();
2359 // ist es neuer oder wurde der akt. entfernt?
2360 if( SFX_ITEM_SET
!= GetItemState( RES_BOXATR_VALUE
, FALSE
))
2365 // das akt. Item besorgen
2366 GetItemState( RES_BOXATR_FORMAT
, FALSE
,
2367 (const SfxPoolItem
**)&pNewFmt
);
2368 nOldFmt
= GetTblBoxNumFmt().GetValue();
2369 nNewFmt
= pNewFmt
? pNewFmt
->GetValue() : nOldFmt
;
2372 // ist es neuer oder wurde der akt. entfernt?
2375 if( NUMBERFORMAT_TEXT
!= nNewFmt
)
2377 if( SFX_ITEM_SET
== GetItemState(
2378 RES_BOXATR_VALUE
, FALSE
))
2379 nOldFmt
= NUMBERFORMAT_TEXT
;
2381 nNewFmt
= NUMBERFORMAT_TEXT
;
2383 else if( NUMBERFORMAT_TEXT
== nNewFmt
)
2388 // ValueAenderung: -> "simuliere" eine FormatAenderung!
2390 // Text -> !Text oder FormatAenderung:
2391 // - Ausrichtung auf RECHTS, wenn LINKS oder Blocksatz
2392 // - vertikale Ausrichtung auf UNTEN wenn OBEN oder nicht
2394 // - Text ersetzen (Farbe?? neg. Zahlen ROT??)
2396 // - Ausrichtung auf LINKS, wenn RECHTS
2397 // - vertikale Ausrichtung auf OEBN, wenn UNTEN gesetzt ist
2399 SvNumberFormatter
* pNumFmtr
= GetDoc()->GetNumberFormatter();
2400 BOOL bNewIsTxtFmt
= pNumFmtr
->IsTextFormat( nNewFmt
) ||
2401 NUMBERFORMAT_TEXT
== nNewFmt
;
2403 if( !bNewIsTxtFmt
&& nOldFmt
!= nNewFmt
|| pNewFml
)
2405 BOOL bChgTxt
= TRUE
;
2407 if( !pNewVal
&& SFX_ITEM_SET
!= GetItemState(
2408 RES_BOXATR_VALUE
, FALSE
, (const SfxPoolItem
**)&pNewVal
))
2410 // es wurde noch nie ein Wert gesetzt, dann versuche
2411 // doch mal den Inhalt auszuwerten
2412 ULONG nNdPos
= pBox
->IsValidNumTxtNd( TRUE
);
2413 if( ULONG_MAX
!= nNdPos
)
2415 sal_uInt32 nTmpFmtIdx
= nNewFmt
;
2416 String
aTxt( GetDoc()->GetNodes()[ nNdPos
]
2417 ->GetTxtNode()->GetRedlineTxt());
2422 //JP 15.09.98: Bug 55741 - Tabs beibehalten
2423 lcl_TabToBlankAtSttEnd( aTxt
);
2425 // JP 22.04.98: Bug 49659 -
2426 // Sonderbehandlung fuer Prozent
2427 BOOL bIsNumFmt
= FALSE
;
2428 if( NUMBERFORMAT_PERCENT
==
2429 pNumFmtr
->GetType( nNewFmt
))
2431 sal_uInt32 nTmpFmt
= 0;
2432 if( pNumFmtr
->IsNumberFormat(
2433 aTxt
, nTmpFmt
, fVal
))
2435 if( NUMBERFORMAT_NUMBER
==
2436 pNumFmtr
->GetType( nTmpFmt
))
2439 bIsNumFmt
= pNumFmtr
->IsNumberFormat(
2440 aTxt
, nTmpFmtIdx
, fVal
);
2444 bIsNumFmt
= pNumFmtr
->IsNumberFormat(
2445 aTxt
, nTmpFmtIdx
, fVal
);
2449 // dann setze den Value direkt in den Set -
2451 int bIsLockMod
= IsModifyLocked();
2453 SetFmtAttr( SwTblBoxValue( fVal
));
2461 fVal
= pNewVal
->GetValue();
2463 // den Inhalt mit dem neuen Wert Formtieren und in den Absatz
2467 if( DBL_MAX
== fVal
)
2468 sNewTxt
= ViewShell::GetShellRes()->aCalc_Error
;
2471 pNumFmtr
->GetOutputString( fVal
, nNewFmt
, sNewTxt
, &pCol
);
2478 ChgTextToNum( *pBox
, sNewTxt
, pCol
,
2479 GetDoc()->IsInsTblAlignNum() );
2482 else if( bNewIsTxtFmt
&& nOldFmt
!= nNewFmt
)
2484 // auf jedenfall muessen jetzt die Formeln/Values
2485 // geloescht werden!
2487 // ResetAttr( RES_BOXATR_FORMULA, RES_BOXATR_VALUE );
2491 ChgNumToText( *pBox
, nNewFmt
);
2497 // Und die Basis-Klasse rufen
2498 SwFrmFmt::Modify( pOld
, pNew
);
2501 BOOL
SwTableBox::HasNumCntnt( double& rNum
, sal_uInt32
& rFmtIndex
,
2502 BOOL
& rIsEmptyTxtNd
) const
2505 ULONG nNdPos
= IsValidNumTxtNd( TRUE
);
2506 if( ULONG_MAX
!= nNdPos
)
2508 String
aTxt( pSttNd
->GetNodes()[ nNdPos
]->GetTxtNode()->
2510 //JP 15.09.98: Bug 55741 - Tabs beibehalten
2511 lcl_TabToBlankAtSttEnd( aTxt
);
2512 rIsEmptyTxtNd
= 0 == aTxt
.Len();
2513 SvNumberFormatter
* pNumFmtr
= GetFrmFmt()->GetDoc()->GetNumberFormatter();
2515 const SfxPoolItem
* pItem
;
2516 if( SFX_ITEM_SET
== GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT
,
2519 rFmtIndex
= ((SwTblBoxNumFormat
*)pItem
)->GetValue();
2520 // JP 22.04.98: Bug 49659 - Sonderbehandlung fuer Prozent
2521 if( !rIsEmptyTxtNd
&&
2522 NUMBERFORMAT_PERCENT
== pNumFmtr
->GetType( rFmtIndex
))
2524 sal_uInt32 nTmpFmt
= 0;
2525 if( pNumFmtr
->IsNumberFormat( aTxt
, nTmpFmt
, rNum
) &&
2526 NUMBERFORMAT_NUMBER
== pNumFmtr
->GetType( nTmpFmt
))
2533 bRet
= pNumFmtr
->IsNumberFormat( aTxt
, rFmtIndex
, rNum
);
2536 // wie bekommt man aus dem neuen String den neuen Wert?
2537 // denn der Numberformater erkennt aus "123.--DM" kein Zahlenformat!
2538 if( !bRet && rFmtIndex && !pNumFmtr->IsTextFormat( rFmtIndex ) &&
2539 SFX_ITEM_SET == GetFrmFmt()->GetItemState( RES_BOXATR_VALUE,
2544 pNumFmtr->GetOutputString( ((SwTblBoxValue*)pItem)->GetValue(),
2545 rFmtIndex, sNewTxt, &pCol );
2546 bRet = aTxt == sNewTxt;
2551 rIsEmptyTxtNd
= FALSE
;
2555 BOOL
SwTableBox::IsNumberChanged() const
2559 if( SFX_ITEM_SET
== GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA
, FALSE
))
2561 const SwTblBoxNumFormat
*pNumFmt
;
2562 const SwTblBoxValue
*pValue
;
2564 if( SFX_ITEM_SET
!= GetFrmFmt()->GetItemState( RES_BOXATR_VALUE
, FALSE
,
2565 (const SfxPoolItem
**)&pValue
))
2567 if( SFX_ITEM_SET
!= GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT
, FALSE
,
2568 (const SfxPoolItem
**)&pNumFmt
))
2572 if( pNumFmt
&& pValue
&&
2573 ULONG_MAX
!= ( nNdPos
= IsValidNumTxtNd( TRUE
) ) )
2575 String sNewTxt
, sOldTxt( pSttNd
->GetNodes()[ nNdPos
]->
2576 GetTxtNode()->GetRedlineTxt() );
2577 lcl_DelTabsAtSttEnd( sOldTxt
);
2580 GetFrmFmt()->GetDoc()->GetNumberFormatter()->GetOutputString(
2581 pValue
->GetValue(), pNumFmt
->GetValue(), sNewTxt
, &pCol
);
2583 bRet
= sNewTxt
!= sOldTxt
||
2584 !( ( !pCol
&& !GetSaveNumFmtColor() ) ||
2585 ( pCol
&& GetSaveNumFmtColor() &&
2586 *pCol
== *GetSaveNumFmtColor() ));
2592 ULONG
SwTableBox::IsValidNumTxtNd( BOOL bCheckAttr
) const
2594 ULONG nPos
= ULONG_MAX
;
2597 SwNodeIndex
aIdx( *pSttNd
);
2598 ULONG nIndex
= aIdx
.GetIndex();
2599 const ULONG nIndexEnd
= pSttNd
->GetNodes()[ nIndex
]->EndOfSectionIndex();
2600 const SwTxtNode
*pTextNode
= 0;
2601 while( ++nIndex
< nIndexEnd
)
2603 const SwNode
* pNode
= pSttNd
->GetNodes()[nIndex
];
2604 if( pNode
->IsTableNode() )
2605 { /*return ULONG_MAX if the cell contains a table(in table)*/
2609 if( pNode
->IsTxtNode() )
2612 { /*return ULONG_MAX if the cell contains complex paragraphs*/
2618 pTextNode
= pNode
->GetTxtNode();
2627 const SwpHints
* pHts
= pTextNode
->GetpSwpHints();
2628 const String
& rTxt
= pTextNode
->GetTxt();
2629 // dann teste doch mal, ob das wirklich nur Text im Node steht!
2633 for( USHORT n
= 0; n
< pHts
->Count(); ++n
)
2635 const SwTxtAttr
* pAttr
= (*pHts
)[ n
];
2636 if( RES_TXTATR_NOEND_BEGIN
<= pAttr
->Which() ||
2637 *pAttr
->GetStart() ||
2638 *pAttr
->GetAnyEnd() < rTxt
.Len() )
2653 // ist das eine FormelBox oder eine Box mit numerischen Inhalt (AutoSum)
2654 USHORT
SwTableBox::IsFormulaOrValueBox() const
2657 const SwTxtNode
* pTNd
;
2658 SwFrmFmt
* pFmt
= GetFrmFmt();
2659 if( SFX_ITEM_SET
== pFmt
->GetItemState( RES_BOXATR_FORMULA
, FALSE
))
2660 nWhich
= RES_BOXATR_FORMULA
;
2661 else if( SFX_ITEM_SET
== pFmt
->GetItemState( RES_BOXATR_VALUE
, FALSE
) &&
2662 !pFmt
->GetDoc()->GetNumberFormatter()->IsTextFormat(
2663 pFmt
->GetTblBoxNumFmt().GetValue() ))
2664 nWhich
= RES_BOXATR_VALUE
;
2665 else if( pSttNd
&& pSttNd
->GetIndex() + 2 == pSttNd
->EndOfSectionIndex()
2666 && 0 != ( pTNd
= pSttNd
->GetNodes()[ pSttNd
->GetIndex() + 1 ]
2667 ->GetTxtNode() ) && !pTNd
->GetTxt().Len() )
2673 void SwTableBox::ActualiseValueBox()
2675 const SfxPoolItem
*pFmtItem
, *pValItem
;
2676 SwFrmFmt
* pFmt
= GetFrmFmt();
2677 if( SFX_ITEM_SET
== pFmt
->GetItemState( RES_BOXATR_FORMAT
, TRUE
, &pFmtItem
)
2678 && SFX_ITEM_SET
== pFmt
->GetItemState( RES_BOXATR_VALUE
, TRUE
, &pValItem
))
2680 const ULONG nFmtId
= ((SwTblBoxNumFormat
*)pFmtItem
)->GetValue();
2681 ULONG nNdPos
= ULONG_MAX
;
2682 SvNumberFormatter
* pNumFmtr
= pFmt
->GetDoc()->GetNumberFormatter();
2684 if( !pNumFmtr
->IsTextFormat( nFmtId
) &&
2685 ULONG_MAX
!= (nNdPos
= IsValidNumTxtNd( TRUE
)) )
2687 double fVal
= ((SwTblBoxValue
*)pValItem
)->GetValue();
2690 pNumFmtr
->GetOutputString( fVal
, nFmtId
, sNewTxt
, &pCol
);
2692 const String
& rTxt
= pSttNd
->GetNodes()[ nNdPos
]->GetTxtNode()->GetTxt();
2693 if( rTxt
!= sNewTxt
)
2694 ChgTextToNum( *this, sNewTxt
, pCol
, FALSE
);
2699 void SwTableBox_Impl::SetNewCol( Color
** ppCol
, const Color
* pNewCol
)
2701 if( *ppCol
!= pNewCol
)
2705 *ppCol
= new Color( *pNewCol
);