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: tblsel.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"
33 #include <hintids.hxx>
34 #include <svx/boxitem.hxx>
35 #include <svx/protitem.hxx>
36 #include <fmtanchr.hxx>
37 #include <fmtfsize.hxx>
46 #include <swtable.hxx>
50 #include <cellfrm.hxx>
51 #include <pagefrm.hxx>
52 #include <rootfrm.hxx>
54 #include <swtblfmt.hxx>
57 // OD 26.08.2003 #i18103#
58 #include <sectfrm.hxx>
59 #include <frmtool.hxx>
61 //siehe auch swtable.cxx
64 // defines, die bestimmen, wie Tabellen Boxen gemergt werden:
65 // - 1. alle leeren Zeilen entfernen, alle Boxen werden mit Blank,
66 // alle Lines mit ParaBreak getrennt
67 // - 2. alle leeren Zeilen und alle leeren Boxen am Anfang und Ende
68 // entfernen, alle Boxen werden mit Blank,
69 // alle Lines mit ParaBreak getrennt
70 // - 3. alle leeren Boxen entfernen, alle Boxen werden mit Blank,
71 // alle Lines mit ParaBreak getrennt
73 #undef DEL_ONLY_EMPTY_LINES
74 #undef DEL_EMPTY_BOXES_AT_START_AND_END
75 #define DEL_ALL_EMPTY_BOXES
78 _SV_IMPL_SORTAR_ALG( SwSelBoxes
, SwTableBoxPtr
)
79 BOOL
SwSelBoxes::Seek_Entry( const SwTableBoxPtr rSrch
, USHORT
* pFndPos
) const
81 ULONG nIdx
= rSrch
->GetSttIdx();
83 USHORT nO
= Count(), nM
, nU
= 0;
89 nM
= nU
+ ( nO
- nU
) / 2;
90 if( (*this)[ nM
]->GetSttNd() == rSrch
->GetSttNd() )
96 else if( (*this)[ nM
]->GetSttIdx() < nIdx
)
114 SV_IMPL_PTRARR( SwCellFrms
, SwCellFrm
* )
119 const SwTableBox
* pSelBox
;
122 _CmpLPt( const Point
& rPt
, const SwTableBox
* pBox
, BOOL bVertical
);
124 BOOL
operator==( const _CmpLPt
& rCmp
) const
125 { return X() == rCmp
.X() && Y() == rCmp
.Y() ? TRUE
: FALSE
; }
127 BOOL
operator<( const _CmpLPt
& rCmp
) const
130 return X() > rCmp
.X() || ( X() == rCmp
.X() && Y() < rCmp
.Y() )
133 return Y() < rCmp
.Y() || ( Y() == rCmp
.Y() && X() < rCmp
.X() )
137 long X() const { return aPos
.X(); }
138 long Y() const { return aPos
.Y(); }
142 SV_DECL_VARARR_SORT( _MergePos
, _CmpLPt
, 0, 40 )
143 SV_IMPL_VARARR_SORT( _MergePos
, _CmpLPt
)
145 SV_IMPL_PTRARR( _FndBoxes
, _FndBox
* )
146 SV_IMPL_PTRARR( _FndLines
, _FndLine
* )
151 const SwCellFrm
* pFrm
;
153 _Sort_CellFrm( const SwCellFrm
& rCFrm
)
157 SV_DECL_VARARR( _Sort_CellFrms
, _Sort_CellFrm
, 16, 16 )
158 SV_IMPL_VARARR( _Sort_CellFrms
, _Sort_CellFrm
)
160 SV_IMPL_PTRARR( SwChartBoxes
, SwTableBoxPtr
);
161 SV_IMPL_PTRARR( SwChartLines
, SwChartBoxes
* );
163 const SwLayoutFrm
*lcl_FindCellFrm( const SwLayoutFrm
*pLay
)
165 while ( pLay
&& !pLay
->IsCellFrm() )
166 pLay
= pLay
->GetUpper();
170 const SwLayoutFrm
*lcl_FindNextCellFrm( const SwLayoutFrm
*pLay
)
172 //Dafuer sorgen, dass die Zelle auch verlassen wird (Bereiche)
173 const SwLayoutFrm
*pTmp
= pLay
;
175 pTmp
= pTmp
->GetNextLayoutLeaf();
176 } while( pLay
->IsAnLower( pTmp
) );
178 while( pTmp
&& !pTmp
->IsCellFrm() )
179 pTmp
= pTmp
->GetUpper();
183 void GetTblSelCrs( const SwCrsrShell
&rShell
, SwSelBoxes
& rBoxes
)
186 rBoxes
.Remove( USHORT(0), rBoxes
.Count() );
187 if( rShell
.IsTableMode() && ((SwCrsrShell
&)rShell
).UpdateTblSelBoxes())
188 rBoxes
.Insert( &rShell
.GetTableCrsr()->GetBoxes() );
191 void GetTblSelCrs( const SwTableCursor
& rTblCrsr
, SwSelBoxes
& rBoxes
)
194 rBoxes
.Remove( USHORT(0), rBoxes
.Count() );
196 if( rTblCrsr
.IsChgd() || !rTblCrsr
.GetBoxesCount() )
198 SwTableCursor
* pTCrsr
= (SwTableCursor
*)&rTblCrsr
;
199 pTCrsr
->GetDoc()->GetRootFrm()->MakeTblCrsrs( *pTCrsr
);
202 if( rTblCrsr
.GetBoxesCount() )
203 rBoxes
.Insert( &rTblCrsr
.GetBoxes() );
206 void GetTblSel( const SwCrsrShell
& rShell
, SwSelBoxes
& rBoxes
,
207 const SwTblSearchType eSearchType
)
209 //Start- und Endzelle besorgen und den naechsten fragen.
210 if ( !rShell
.IsTableMode() )
213 GetTblSel( *rShell
.getShellCrsr(false), rBoxes
, eSearchType
);
216 void GetTblSel( const SwCursor
& rCrsr
, SwSelBoxes
& rBoxes
,
217 const SwTblSearchType eSearchType
)
219 //Start- und Endzelle besorgen und den naechsten fragen.
220 ASSERT( rCrsr
.GetCntntNode() && rCrsr
.GetCntntNode( FALSE
),
221 "Tabselection nicht auf Cnt." );
224 // teste ob Tabelle komplex ist. Wenn ja, dann immer uebers Layout
225 // die selektierten Boxen zusammen suchen. Andernfalls ueber die
226 // Tabellen-Struktur (fuer Makros !!)
227 const SwCntntNode
* pContentNd
= rCrsr
.GetNode()->GetCntntNode();
228 const SwTableNode
* pTblNd
= pContentNd
? pContentNd
->FindTableNode() : 0;
229 if( pTblNd
&& pTblNd
->GetTable().IsNewModel() )
231 SwTable::SearchType eSearch
;
232 switch( nsSwTblSearchType::TBLSEARCH_COL
& eSearchType
)
234 case nsSwTblSearchType::TBLSEARCH_ROW
: eSearch
= SwTable::SEARCH_ROW
; break;
235 case nsSwTblSearchType::TBLSEARCH_COL
: eSearch
= SwTable::SEARCH_COL
; break;
236 default: eSearch
= SwTable::SEARCH_NONE
; break;
238 const bool bChkP
= 0 != ( nsSwTblSearchType::TBLSEARCH_PROTECT
& eSearchType
);
239 pTblNd
->GetTable().CreateSelection( rCrsr
, rBoxes
, eSearch
, bChkP
);
242 if( nsSwTblSearchType::TBLSEARCH_ROW
== ((~nsSwTblSearchType::TBLSEARCH_PROTECT
) & eSearchType
) &&
243 pTblNd
&& !pTblNd
->GetTable().IsTblComplex() )
245 const SwTable
& rTbl
= pTblNd
->GetTable();
246 const SwTableLines
& rLines
= rTbl
.GetTabLines();
248 const SwNode
* pMarkNode
= rCrsr
.GetNode( FALSE
);
249 const ULONG nMarkSectionStart
= pMarkNode
->StartOfSectionIndex();
250 const SwTableBox
* pMarkBox
= rTbl
.GetTblBox( nMarkSectionStart
);
252 ASSERT( pMarkBox
, "Point in table, mark outside?" )
254 const SwTableLine
* pLine
= pMarkBox
? pMarkBox
->GetUpper() : 0;
255 USHORT nSttPos
= rLines
.GetPos( pLine
);
256 ASSERT( USHRT_MAX
!= nSttPos
, "Wo ist meine Zeile in der Tabelle?" );
257 pLine
= rTbl
.GetTblBox( rCrsr
.GetNode( TRUE
)->StartOfSectionIndex() )->GetUpper();
258 USHORT nEndPos
= rLines
.GetPos( pLine
);
259 ASSERT( USHRT_MAX
!= nEndPos
, "Wo ist meine Zeile in der Tabelle?" );
260 // pb: #i20193# if tableintable then nSttPos == nEndPos == USHRT_MAX
261 if ( nSttPos
!= USHRT_MAX
&& nEndPos
!= USHRT_MAX
)
263 if( nEndPos
< nSttPos
) // vertauschen
265 USHORT nTmp
= nSttPos
; nSttPos
= nEndPos
; nEndPos
= nTmp
;
268 int bChkProtected
= nsSwTblSearchType::TBLSEARCH_PROTECT
& eSearchType
;
269 for( ; nSttPos
<= nEndPos
; ++nSttPos
)
271 pLine
= rLines
[ nSttPos
];
272 for( USHORT n
= pLine
->GetTabBoxes().Count(); n
; )
274 SwTableBox
* pBox
= pLine
->GetTabBoxes()[ --n
];
275 // Zellenschutzt beachten ??
276 if( !bChkProtected
||
277 !pBox
->GetFrmFmt()->GetProtect().IsCntntProtected() )
278 rBoxes
.Insert( pBox
);
285 Point aPtPos
, aMkPos
;
286 const SwShellCrsr
* pShCrsr
= dynamic_cast<const SwShellCrsr
*>(&rCrsr
);
289 aPtPos
= pShCrsr
->GetPtPos();
290 aMkPos
= pShCrsr
->GetMkPos();
292 const SwCntntNode
*pCntNd
= rCrsr
.GetCntntNode();
293 const SwLayoutFrm
*pStart
= pCntNd
?
294 pCntNd
->GetFrm( &aPtPos
)->GetUpper() : 0;
295 pCntNd
= rCrsr
.GetCntntNode(FALSE
);
296 const SwLayoutFrm
*pEnd
= pCntNd
?
297 pCntNd
->GetFrm( &aMkPos
)->GetUpper() : 0;
299 GetTblSel( pStart
, pEnd
, rBoxes
, 0, eSearchType
);
303 void GetTblSel( const SwLayoutFrm
* pStart
, const SwLayoutFrm
* pEnd
,
304 SwSelBoxes
& rBoxes
, SwCellFrms
* pCells
,
305 const SwTblSearchType eSearchType
)
308 const SwTabFrm
* pStartTab
= pStart
->FindTabFrm();
311 ASSERT( false, "GetTblSel without start table" )
315 int bChkProtected
= nsSwTblSearchType::TBLSEARCH_PROTECT
& eSearchType
;
318 // --> FME 2006-01-25 #i55421# Reduced value 10
319 int nLoopMax
= 10; //JP 28.06.99: max 100 loops - Bug 67292
326 //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
328 ::MakeSelUnions( aUnions
, pStart
, pEnd
, eSearchType
);
330 Point
aCurrentTopLeft( LONG_MAX
, LONG_MAX
);
331 Point
aCurrentTopRight( 0, LONG_MAX
);
332 Point
aCurrentBottomLeft( LONG_MAX
, 0 );
333 Point
aCurrentBottomRight( 0, 0 );
334 const SwCellFrm
* pCurrentTopLeftFrm
= 0;
335 const SwCellFrm
* pCurrentTopRightFrm
= 0;
336 const SwCellFrm
* pCurrentBottomLeftFrm
= 0;
337 const SwCellFrm
* pCurrentBottomRightFrm
= 0;
339 //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen.
340 for( i
= 0; i
< aUnions
.Count() && bTblIsValid
; ++i
)
342 SwSelUnion
*pUnion
= aUnions
[i
];
343 const SwTabFrm
*pTable
= pUnion
->GetTable();
344 if( !pTable
->IsValid() && nLoopMax
)
350 // Skip any repeated headlines in the follow:
351 const SwLayoutFrm
* pRow
= pTable
->IsFollow() ?
352 pTable
->GetFirstNonHeadlineRow() :
353 (const SwLayoutFrm
*)pTable
->Lower();
355 while( pRow
&& bTblIsValid
)
357 if( !pRow
->IsValid() && nLoopMax
)
363 if ( pRow
->Frm().IsOver( pUnion
->GetUnion() ) )
365 const SwLayoutFrm
*pCell
= pRow
->FirstCell();
367 while( bTblIsValid
&& pCell
&& pRow
->IsAnLower( pCell
) )
369 if( !pCell
->IsValid() && nLoopMax
)
375 ASSERT( pCell
->IsCellFrm(), "Frame ohne Celle" );
376 if( ::IsFrmInTblSel( pUnion
->GetUnion(), pCell
) )
378 SwTableBox
* pBox
= (SwTableBox
*)
379 ((SwCellFrm
*)pCell
)->GetTabBox();
380 // Zellenschutzt beachten ??
381 if( !bChkProtected
||
382 !pBox
->GetFrmFmt()->GetProtect().IsCntntProtected() )
383 rBoxes
.Insert( pBox
);
387 const Point
aTopLeft( pCell
->Frm().TopLeft() );
388 const Point
aTopRight( pCell
->Frm().TopRight() );
389 const Point
aBottomLeft( pCell
->Frm().BottomLeft() );
390 const Point
aBottomRight( pCell
->Frm().BottomRight() );
392 if ( aTopLeft
.Y() < aCurrentTopLeft
.Y() ||
393 ( aTopLeft
.Y() == aCurrentTopLeft
.Y() &&
394 aTopLeft
.X() < aCurrentTopLeft
.X() ) )
396 aCurrentTopLeft
= aTopLeft
;
397 pCurrentTopLeftFrm
= static_cast<const SwCellFrm
*>( pCell
);
400 if ( aTopRight
.Y() < aCurrentTopRight
.Y() ||
401 ( aTopRight
.Y() == aCurrentTopRight
.Y() &&
402 aTopRight
.X() > aCurrentTopRight
.X() ) )
404 aCurrentTopRight
= aTopRight
;
405 pCurrentTopRightFrm
= static_cast<const SwCellFrm
*>( pCell
);
408 if ( aBottomLeft
.Y() > aCurrentBottomLeft
.Y() ||
409 ( aBottomLeft
.Y() == aCurrentBottomLeft
.Y() &&
410 aBottomLeft
.X() < aCurrentBottomLeft
.X() ) )
412 aCurrentBottomLeft
= aBottomLeft
;
413 pCurrentBottomLeftFrm
= static_cast<const SwCellFrm
*>( pCell
);
416 if ( aBottomRight
.Y() > aCurrentBottomRight
.Y() ||
417 ( aBottomRight
.Y() == aCurrentBottomRight
.Y() &&
418 aBottomRight
.X() > aCurrentBottomRight
.X() ) )
420 aCurrentBottomRight
= aBottomRight
;
421 pCurrentBottomRightFrm
= static_cast<const SwCellFrm
*>( pCell
);
426 if ( pCell
->GetNext() )
428 pCell
= (const SwLayoutFrm
*)pCell
->GetNext();
429 if ( pCell
->Lower() && pCell
->Lower()->IsRowFrm() )
430 pCell
= pCell
->FirstCell();
433 pCell
= ::lcl_FindNextCellFrm( pCell
);
436 pRow
= (const SwLayoutFrm
*)pRow
->GetNext();
442 pCells
->Remove( 0, pCells
->Count() );
443 pCells
->Insert( pCurrentTopLeftFrm
, 0 );
444 pCells
->Insert( pCurrentTopRightFrm
, 1 );
445 pCells
->Insert( pCurrentBottomLeftFrm
, 2 );
446 pCells
->Insert( pCurrentBottomRightFrm
, 3 );
452 SwDeletionChecker
aDelCheck( pStart
);
454 // ansonsten das Layout der Tabelle kurz "kalkulieren" lassen
455 // und nochmals neu aufsetzen
456 SwTabFrm
*pTable
= aUnions
[0]->GetTable();
459 if( pTable
->IsValid() )
460 pTable
->InvalidatePos();
461 pTable
->SetONECalcLowers();
463 pTable
->SetCompletePaint();
464 if( 0 == (pTable
= pTable
->GetFollow()) )
468 // --> FME 2005-10-13 #125337# Make code robust, check if pStart has
469 // been deleted due to the formatting of the table:
470 if ( aDelCheck
.HasBeenDeleted() )
472 ASSERT( false, "Current box has been deleted during GetTblSel()" )
478 rBoxes
.Remove( i
, rBoxes
.Count() );
482 ASSERT( nLoopMax
, "das Layout der Tabelle wurde nicht valide!" );
487 BOOL
ChkChartSel( const SwNode
& rSttNd
, const SwNode
& rEndNd
,
488 SwChartLines
* pGetCLines
)
490 const SwTableNode
* pTNd
= rSttNd
.FindTableNode();
495 SwNodeIndex
aIdx( rSttNd
);
496 const SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
498 pCNd
= aIdx
.GetNodes().GoNextSection( &aIdx
, FALSE
, FALSE
);
500 // #109394# if table is invisible, return
501 // (layout needed for forming table selection further down, so we can't
502 // continue with invisible tables)
503 // OD 07.11.2003 #i22135# - Also the content of the table could be
504 // invisible - e.g. in a hidden section
505 // Robust: check, if content was found (e.g. empty table cells)
506 if ( !pCNd
|| pCNd
->GetFrm() == NULL
)
509 const SwLayoutFrm
*pStart
= pCNd
? pCNd
->GetFrm( &aNullPos
)->GetUpper() : 0;
510 ASSERT( pStart
, "ohne Frame geht gar nichts" );
513 pCNd
= aIdx
.GetNode().GetCntntNode();
515 pCNd
= aIdx
.GetNodes().GoNextSection( &aIdx
, FALSE
, FALSE
);
517 // OD 07.11.2003 #i22135# - Robust: check, if content was found and if it's visible
518 if ( !pCNd
|| pCNd
->GetFrm() == NULL
)
523 const SwLayoutFrm
*pEnd
= pCNd
? pCNd
->GetFrm( &aNullPos
)->GetUpper() : 0;
524 ASSERT( pEnd
, "ohne Frame geht gar nichts" );
527 BOOL bTblIsValid
, bValidChartSel
;
528 // --> FME 2006-01-25 #i55421# Reduced value 10
529 int nLoopMax
= 10; //JP 28.06.99: max 100 loops - Bug 67292
535 bValidChartSel
= TRUE
;
537 USHORT nRowCells
= USHRT_MAX
;
539 //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
541 ::MakeSelUnions( aUnions
, pStart
, pEnd
, nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT
);
543 //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen.
544 for( i
= 0; i
< aUnions
.Count() && bTblIsValid
&&
545 bValidChartSel
; ++i
)
547 SwSelUnion
*pUnion
= aUnions
[i
];
548 const SwTabFrm
*pTable
= pUnion
->GetTable();
551 sal_Bool bRTL
= pTable
->IsRightToLeft();
553 if( !pTable
->IsValid() && nLoopMax
)
559 _Sort_CellFrms aCellFrms
;
561 // Skip any repeated headlines in the follow:
562 const SwLayoutFrm
* pRow
= pTable
->IsFollow() ?
563 pTable
->GetFirstNonHeadlineRow() :
564 (const SwLayoutFrm
*)pTable
->Lower();
566 while( pRow
&& bTblIsValid
&& bValidChartSel
)
568 if( !pRow
->IsValid() && nLoopMax
)
574 if( pRow
->Frm().IsOver( pUnion
->GetUnion() ) )
576 const SwLayoutFrm
*pCell
= pRow
->FirstCell();
578 while( bValidChartSel
&& bTblIsValid
&& pCell
&&
579 pRow
->IsAnLower( pCell
) )
581 if( !pCell
->IsValid() && nLoopMax
)
587 ASSERT( pCell
->IsCellFrm(), "Frame ohne Celle" );
588 const SwRect
& rUnion
= pUnion
->GetUnion(),
589 & rFrmRect
= pCell
->Frm();
591 const long nUnionRight
= rUnion
.Right();
592 const long nUnionBottom
= rUnion
.Bottom();
593 const long nFrmRight
= rFrmRect
.Right();
594 const long nFrmBottom
= rFrmRect
.Bottom();
596 // liegt das FrmRect ausserhalb der Union, kann es
599 const long nXFuzzy
= bVert
? 0 : 20;
600 const long nYFuzzy
= bVert
? 20 : 0;
602 if( !( rUnion
.Top() + nYFuzzy
> nFrmBottom
||
603 nUnionBottom
< rFrmRect
.Top() + nYFuzzy
||
604 rUnion
.Left() + nXFuzzy
> nFrmRight
||
605 nUnionRight
< rFrmRect
.Left() + nXFuzzy
))
607 // ok, rUnion is _not_ completely outside of rFrmRect
609 // wenn es aber nicht komplett in der Union liegt,
610 // dann ist es fuers Chart eine ungueltige
612 if( rUnion
.Left() <= rFrmRect
.Left() + nXFuzzy
&&
613 rFrmRect
.Left() <= nUnionRight
&&
614 rUnion
.Left() <= nFrmRight
&&
615 nFrmRight
<= nUnionRight
+ nXFuzzy
&&
616 rUnion
.Top() <= rFrmRect
.Top() + nYFuzzy
&&
617 rFrmRect
.Top() <= nUnionBottom
&&
618 rUnion
.Top() <= nFrmBottom
&&
619 nFrmBottom
<= nUnionBottom
+ nYFuzzy
)
622 _Sort_CellFrm( *(SwCellFrm
*)pCell
),
626 bValidChartSel
= FALSE
;
630 if ( pCell
->GetNext() )
632 pCell
= (const SwLayoutFrm
*)pCell
->GetNext();
633 if ( pCell
->Lower() && pCell
->Lower()->IsRowFrm() )
634 pCell
= pCell
->FirstCell();
637 pCell
= ::lcl_FindNextCellFrm( pCell
);
640 pRow
= (const SwLayoutFrm
*)pRow
->GetNext();
643 if( !bValidChartSel
)
646 // alle Zellen der (Teil-)Tabelle zusammen. Dann teste mal ob
647 // all huebsch nebeneinander liegen.
648 USHORT n
, nEnd
, nCellCnt
= 0;
649 long nYPos
= LONG_MAX
;
653 for( n
= 0, nEnd
= aCellFrms
.Count(); n
< nEnd
; ++n
)
655 const _Sort_CellFrm
& rCF
= aCellFrms
[ n
];
656 if( (rCF
.pFrm
->Frm().*fnRect
->fnGetTop
)() != nYPos
)
661 if( USHRT_MAX
== nRowCells
) // 1. Zeilenwechsel
662 nRowCells
= nCellCnt
;
663 else if( nRowCells
!= nCellCnt
)
665 bValidChartSel
= FALSE
;
670 nYPos
= (rCF
.pFrm
->Frm().*fnRect
->fnGetTop
)();
671 nHeight
= (rCF
.pFrm
->Frm().*fnRect
->fnGetHeight
)();
674 (rCF
.pFrm
->Frm().*fnRect
->fnGetLeft
)() :
675 (rCF
.pFrm
->Frm().*fnRect
->fnGetRight
)();
677 else if( nXPos
== ( bRTL
?
678 (rCF
.pFrm
->Frm().*fnRect
->fnGetRight
)() :
679 (rCF
.pFrm
->Frm().*fnRect
->fnGetLeft
)() ) &&
680 nHeight
== (rCF
.pFrm
->Frm().*fnRect
->fnGetHeight
)() )
682 nXPos
+= ( bRTL
? (-1) : 1 ) *
683 (rCF
.pFrm
->Frm().*fnRect
->fnGetWidth
)();
688 bValidChartSel
= FALSE
;
694 if( USHRT_MAX
== nRowCells
)
695 nRowCells
= nCellCnt
;
696 else if( nRowCells
!= nCellCnt
)
697 bValidChartSel
= FALSE
;
700 if( bValidChartSel
&& pGetCLines
)
703 SwChartBoxes
* pBoxes
= 0;
704 for( n
= 0, nEnd
= aCellFrms
.Count(); n
< nEnd
; ++n
)
706 const _Sort_CellFrm
& rCF
= aCellFrms
[ n
];
707 if( (rCF
.pFrm
->Frm().*fnRect
->fnGetTop
)() != nYPos
)
709 pBoxes
= new SwChartBoxes( 255 < nRowCells
710 ? 255 : (BYTE
)nRowCells
);
711 pGetCLines
->C40_INSERT( SwChartBoxes
, pBoxes
, pGetCLines
->Count() );
712 nYPos
= (rCF
.pFrm
->Frm().*fnRect
->fnGetTop
)();
714 SwTableBoxPtr pBox
= (SwTableBox
*)rCF
.pFrm
->GetTabBox();
715 pBoxes
->Insert( pBox
, pBoxes
->Count() );
723 // ansonsten das Layout der Tabelle kurz "kalkulieren" lassen
724 // und nochmals neu aufsetzen
725 SwTabFrm
*pTable
= aUnions
[0]->GetTable();
726 for( i
= 0; i
< aUnions
.Count(); ++i
)
728 if( pTable
->IsValid() )
729 pTable
->InvalidatePos();
730 pTable
->SetONECalcLowers();
732 pTable
->SetCompletePaint();
733 if( 0 == (pTable
= pTable
->GetFollow()) )
738 pGetCLines
->DeleteAndDestroy( 0, pGetCLines
->Count() );
741 ASSERT( nLoopMax
, "das Layout der Tabelle wurde nicht valide!" );
743 if( !bValidChartSel
&& pGetCLines
)
744 pGetCLines
->DeleteAndDestroy( 0, pGetCLines
->Count() );
746 return bValidChartSel
;
750 BOOL
IsFrmInTblSel( const SwRect
& rUnion
, const SwFrm
* pCell
)
752 ASSERT( pCell
->IsCellFrm(), "Frame ohne Gazelle" );
754 if( pCell
->FindTabFrm()->IsVertical() )
755 return ( rUnion
.Right() >= pCell
->Frm().Right() &&
756 rUnion
.Left() <= pCell
->Frm().Left() &&
757 (( rUnion
.Top() <= pCell
->Frm().Top()+20 &&
758 rUnion
.Bottom() > pCell
->Frm().Top() ) ||
759 ( rUnion
.Top() >= pCell
->Frm().Top() &&
760 rUnion
.Bottom() < pCell
->Frm().Bottom() )) ? TRUE
: FALSE
);
763 rUnion
.Top() <= pCell
->Frm().Top() &&
764 rUnion
.Bottom() >= pCell
->Frm().Bottom() &&
766 (( rUnion
.Left() <= pCell
->Frm().Left()+20 &&
767 rUnion
.Right() > pCell
->Frm().Left() ) ||
769 ( rUnion
.Left() >= pCell
->Frm().Left() &&
770 rUnion
.Right() < pCell
->Frm().Right() )) ? TRUE
: FALSE
);
773 BOOL
GetAutoSumSel( const SwCrsrShell
& rShell
, SwCellFrms
& rBoxes
)
775 SwShellCrsr
* pCrsr
= rShell
.pCurCrsr
;
776 if ( rShell
.IsTableMode() )
777 pCrsr
= rShell
.pTblCrsr
;
779 const SwLayoutFrm
*pStart
= pCrsr
->GetCntntNode()->GetFrm(
780 &pCrsr
->GetPtPos() )->GetUpper(),
781 *pEnd
= pCrsr
->GetCntntNode(FALSE
)->GetFrm(
782 &pCrsr
->GetMkPos() )->GetUpper();
784 const SwLayoutFrm
* pSttCell
= pStart
;
785 while( pSttCell
&& !pSttCell
->IsCellFrm() )
786 pSttCell
= pSttCell
->GetUpper();
788 //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
791 // default erstmal nach oben testen, dann nach links
792 ::MakeSelUnions( aUnions
, pStart
, pEnd
, nsSwTblSearchType::TBLSEARCH_COL
);
794 BOOL bTstRow
= TRUE
, bFound
= FALSE
;
797 // 1. teste ob die darueber liegende Box Value/Formel enhaelt:
798 for( i
= 0; i
< aUnions
.Count(); ++i
)
800 SwSelUnion
*pUnion
= aUnions
[i
];
801 const SwTabFrm
*pTable
= pUnion
->GetTable();
803 // Skip any repeated headlines in the follow:
804 const SwLayoutFrm
* pRow
= pTable
->IsFollow() ?
805 pTable
->GetFirstNonHeadlineRow() :
806 (const SwLayoutFrm
*)pTable
->Lower();
810 if( pRow
->Frm().IsOver( pUnion
->GetUnion() ) )
812 const SwCellFrm
* pUpperCell
= 0;
813 const SwLayoutFrm
*pCell
= pRow
->FirstCell();
815 while( pCell
&& pRow
->IsAnLower( pCell
) )
817 if( pCell
== pSttCell
)
820 for( USHORT n
= rBoxes
.Count(); n
; )
821 if( USHRT_MAX
!= ( nWhichId
= rBoxes
[ --n
]
822 ->GetTabBox()->IsFormulaOrValueBox() ))
825 // alle Boxen zusammen, nicht mehr die Zeile
826 // pruefen, wenn eine Formel oder Value gefunden wurde
827 bTstRow
= 0 == nWhichId
|| USHRT_MAX
== nWhichId
;
832 ASSERT( pCell
->IsCellFrm(), "Frame ohne Celle" );
833 if( ::IsFrmInTblSel( pUnion
->GetUnion(), pCell
) )
834 pUpperCell
= (SwCellFrm
*)pCell
;
836 if( pCell
->GetNext() )
838 pCell
= (const SwLayoutFrm
*)pCell
->GetNext();
839 if ( pCell
->Lower() && pCell
->Lower()->IsRowFrm() )
840 pCell
= pCell
->FirstCell();
843 pCell
= ::lcl_FindNextCellFrm( pCell
);
847 rBoxes
.Insert( pUpperCell
, rBoxes
.Count() );
854 pRow
= (const SwLayoutFrm
*)pRow
->GetNext();
859 // 2. teste ob die links liegende Box Value/Formel enhaelt:
864 rBoxes
.Remove( 0, rBoxes
.Count() );
865 aUnions
.DeleteAndDestroy( 0, aUnions
.Count() );
866 ::MakeSelUnions( aUnions
, pStart
, pEnd
, nsSwTblSearchType::TBLSEARCH_ROW
);
868 for( i
= 0; i
< aUnions
.Count(); ++i
)
870 SwSelUnion
*pUnion
= aUnions
[i
];
871 const SwTabFrm
*pTable
= pUnion
->GetTable();
873 // Skip any repeated headlines in the follow:
874 const SwLayoutFrm
* pRow
= pTable
->IsFollow() ?
875 pTable
->GetFirstNonHeadlineRow() :
876 (const SwLayoutFrm
*)pTable
->Lower();
880 if( pRow
->Frm().IsOver( pUnion
->GetUnion() ) )
882 const SwLayoutFrm
*pCell
= pRow
->FirstCell();
884 while( pCell
&& pRow
->IsAnLower( pCell
) )
886 if( pCell
== pSttCell
)
889 for( USHORT n
= rBoxes
.Count(); n
; )
890 if( USHRT_MAX
!= ( nWhichId
= rBoxes
[ --n
]
891 ->GetTabBox()->IsFormulaOrValueBox() ))
894 // alle Boxen zusammen, nicht mehr die Zeile
895 // pruefen, wenn eine Formel oder Value gefunden wurde
896 bFound
= 0 != nWhichId
&& USHRT_MAX
!= nWhichId
;
901 ASSERT( pCell
->IsCellFrm(), "Frame ohne Celle" );
902 if( ::IsFrmInTblSel( pUnion
->GetUnion(), pCell
) )
904 const SwCellFrm
* pC
= (SwCellFrm
*)pCell
;
905 rBoxes
.Insert( pC
, rBoxes
.Count() );
907 if( pCell
->GetNext() )
909 pCell
= (const SwLayoutFrm
*)pCell
->GetNext();
910 if ( pCell
->Lower() && pCell
->Lower()->IsRowFrm() )
911 pCell
= pCell
->FirstCell();
914 pCell
= ::lcl_FindNextCellFrm( pCell
);
923 pRow
= (const SwLayoutFrm
*)pRow
->GetNext();
931 BOOL
HasProtectedCells( const SwSelBoxes
& rBoxes
)
934 for( USHORT n
= 0, nCnt
= rBoxes
.Count(); n
< nCnt
; ++n
)
935 if( rBoxes
[ n
]->GetFrmFmt()->GetProtect().IsCntntProtected() )
944 _CmpLPt::_CmpLPt( const Point
& rPt
, const SwTableBox
* pBox
, BOOL bVertical
)
945 : aPos( rPt
), pSelBox( pBox
), bVert( bVertical
)
948 void lcl_InsTblBox( SwTableNode
* pTblNd
, SwDoc
* pDoc
, SwTableBox
* pBox
,
949 USHORT nInsPos
, USHORT nCnt
= 1 )
951 ASSERT( pBox
->GetSttNd(), "Box ohne Start-Node" );
952 SwCntntNode
* pCNd
= pDoc
->GetNodes()[ pBox
->GetSttIdx() + 1 ]
954 if( pCNd
&& pCNd
->IsTxtNode() )
955 pDoc
->GetNodes().InsBoxen( pTblNd
, pBox
->GetUpper(),
956 (SwTableBoxFmt
*)pBox
->GetFrmFmt(),
957 ((SwTxtNode
*)pCNd
)->GetTxtColl(),
958 pCNd
->GetpSwAttrSet(),
961 pDoc
->GetNodes().InsBoxen( pTblNd
, pBox
->GetUpper(),
962 (SwTableBoxFmt
*)pBox
->GetFrmFmt(),
963 (SwTxtFmtColl
*)pDoc
->GetDfltTxtFmtColl(), 0,
967 BOOL
IsEmptyBox( const SwTableBox
& rBox
, SwPaM
& rPam
)
969 rPam
.GetPoint()->nNode
= *rBox
.GetSttNd()->EndOfSectionNode();
970 rPam
.Move( fnMoveBackward
, fnGoCntnt
);
972 rPam
.GetPoint()->nNode
= *rBox
.GetSttNd();
973 rPam
.Move( fnMoveForward
, fnGoCntnt
);
974 BOOL bRet
= *rPam
.GetMark() == *rPam
.GetPoint()
975 && ( rBox
.GetSttNd()->GetIndex() + 1 == rPam
.GetPoint()->nNode
.GetIndex() );
979 // dann teste mal auf absatzgebundenen Flys
980 const SwSpzFrmFmts
& rFmts
= *rPam
.GetDoc()->GetSpzFrmFmts();
981 ULONG nSttIdx
= rPam
.GetPoint()->nNode
.GetIndex(),
982 nEndIdx
= rBox
.GetSttNd()->EndOfSectionIndex(),
985 for( USHORT n
= 0; n
< rFmts
.Count(); ++n
)
987 const SwPosition
* pAPos
;
988 const SwFmtAnchor
& rAnchor
= rFmts
[n
]->GetAnchor();
989 if( ( FLY_AT_CNTNT
== rAnchor
.GetAnchorId() ||
990 FLY_AUTO_CNTNT
== rAnchor
.GetAnchorId() ) &&
991 0 != ( pAPos
= rAnchor
.GetCntntAnchor() ) &&
992 nSttIdx
<= ( nIdx
= pAPos
->nNode
.GetIndex() ) &&
1004 void GetMergeSel( const SwPaM
& rPam
, SwSelBoxes
& rBoxes
,
1005 SwTableBox
** ppMergeBox
, SwUndoTblMerge
* pUndo
)
1007 if( rBoxes
.Count() )
1008 rBoxes
.Remove( USHORT(0), rBoxes
.Count() );
1010 //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
1011 ASSERT( rPam
.GetCntntNode() && rPam
.GetCntntNode( FALSE
),
1012 "Tabselection nicht auf Cnt." );
1014 //JP 24.09.96: Merge mit wiederholenden TabellenHeadline funktioniert nicht
1015 // richtig. Warum nicht Point 0,0 benutzen? Dann ist garantiert,
1016 // das die 1. Headline mit drin ist.
1017 // Point aPt( rShell.GetCharRect().Pos() );
1019 const SwLayoutFrm
*pStart
= rPam
.GetCntntNode()->GetFrm(
1021 *pEnd
= rPam
.GetCntntNode(FALSE
)->GetFrm(
1024 SwSelUnions aUnions
;
1025 ::MakeSelUnions( aUnions
, pStart
, pEnd
);
1026 if( !aUnions
.Count() )
1029 const SwTable
*pTable
= aUnions
[0]->GetTable()->GetTable();
1030 SwDoc
* pDoc
= (SwDoc
*)pStart
->GetFmt()->GetDoc();
1031 SwTableNode
* pTblNd
= (SwTableNode
*)pTable
->GetTabSortBoxes()[ 0 ]->
1032 GetSttNd()->FindTableNode();
1034 _MergePos aPosArr
; // Sort-Array mit den Positionen der Frames
1036 SwTableBox
* pLastBox
= 0;
1038 SWRECTFN( pStart
->GetUpper() )
1040 for ( USHORT i
= 0; i
< aUnions
.Count(); ++i
)
1042 const SwTabFrm
*pTabFrm
= aUnions
[i
]->GetTable();
1044 SwRect
&rUnion
= aUnions
[i
]->GetUnion();
1046 // Skip any repeated headlines in the follow:
1047 const SwLayoutFrm
* pRow
= pTabFrm
->IsFollow() ?
1048 pTabFrm
->GetFirstNonHeadlineRow() :
1049 (const SwLayoutFrm
*)pTabFrm
->Lower();
1053 if ( pRow
->Frm().IsOver( rUnion
) )
1055 const SwLayoutFrm
*pCell
= pRow
->FirstCell();
1057 while ( pCell
&& pRow
->IsAnLower( pCell
) )
1059 ASSERT( pCell
->IsCellFrm(), "Frame ohne Celle" );
1060 // in der vollen Breite ueberlappend ?
1061 if( rUnion
.Top() <= pCell
->Frm().Top() &&
1062 rUnion
.Bottom() >= pCell
->Frm().Bottom() )
1064 SwTableBox
* pBox
=(SwTableBox
*)((SwCellFrm
*)pCell
)->GetTabBox();
1066 // nur nach rechts ueberlappend
1067 if( ( rUnion
.Left() - COLFUZZY
) <= pCell
->Frm().Left() &&
1068 ( rUnion
.Right() - COLFUZZY
) > pCell
->Frm().Left() )
1070 if( ( rUnion
.Right() + COLFUZZY
) < pCell
->Frm().Right() )
1072 USHORT nInsPos
= pBox
->GetUpper()->
1073 GetTabBoxes().C40_GETPOS( SwTableBox
, pBox
)+1;
1074 lcl_InsTblBox( pTblNd
, pDoc
, pBox
, nInsPos
);
1075 pBox
->ClaimFrmFmt();
1077 pBox
->GetFrmFmt()->GetFrmSize() );
1078 nWidth
= rUnion
.Right() - pCell
->Frm().Left();
1079 nWidth
= nWidth
* aNew
.GetWidth() /
1080 pCell
->Frm().Width();
1081 long nTmpWidth
= aNew
.GetWidth() - nWidth
;
1082 aNew
.SetWidth( nWidth
);
1083 pBox
->GetFrmFmt()->SetFmtAttr( aNew
);
1084 // diese Box ist selektiert
1086 rBoxes
.Insert( pBox
);
1088 _CmpLPt( (pCell
->Frm().*fnRect
->fnGetPos
)(),
1091 pBox
= pBox
->GetUpper()->GetTabBoxes()[ nInsPos
];
1092 aNew
.SetWidth( nTmpWidth
);
1093 pBox
->ClaimFrmFmt();
1094 pBox
->GetFrmFmt()->SetFmtAttr( aNew
);
1097 pUndo
->AddNewBox( pBox
->GetSttIdx() );
1101 // diese Box ist selektiert
1103 rBoxes
.Insert( pBox
);
1104 #if OSL_DEBUG_LEVEL > 1
1105 Point
aInsPoint( (pCell
->Frm().*fnRect
->fnGetPos
)() );
1108 _CmpLPt( (pCell
->Frm().*fnRect
->fnGetPos
)(),
1112 // oder rechts und links ueberlappend
1113 else if( ( rUnion
.Left() - COLFUZZY
) >= pCell
->Frm().Left() &&
1114 ( rUnion
.Right() + COLFUZZY
) < pCell
->Frm().Right() )
1116 USHORT nInsPos
= pBox
->GetUpper()->GetTabBoxes().
1117 C40_GETPOS( SwTableBox
, pBox
)+1;
1118 lcl_InsTblBox( pTblNd
, pDoc
, pBox
, nInsPos
, 2 );
1119 pBox
->ClaimFrmFmt();
1121 pBox
->GetFrmFmt()->GetFrmSize() );
1122 long nLeft
= rUnion
.Left() - pCell
->Frm().Left();
1123 nLeft
= nLeft
* aNew
.GetWidth() /
1124 pCell
->Frm().Width();
1125 long nRight
= pCell
->Frm().Right() - rUnion
.Right();
1126 nRight
= nRight
* aNew
.GetWidth() /
1127 pCell
->Frm().Width();
1128 nWidth
= aNew
.GetWidth() - nLeft
- nRight
;
1130 aNew
.SetWidth( nLeft
);
1131 pBox
->GetFrmFmt()->SetFmtAttr( aNew
);
1134 const SfxPoolItem
* pItem
;
1135 if( SFX_ITEM_SET
== pBox
->GetFrmFmt()->GetAttrSet()
1136 .GetItemState( RES_BOX
, FALSE
, &pItem
))
1138 SvxBoxItem
aBox( *(SvxBoxItem
*)pItem
);
1139 aBox
.SetLine( 0, BOX_LINE_RIGHT
);
1140 pBox
->GetFrmFmt()->SetFmtAttr( aBox
);
1144 pBox
= pBox
->GetUpper()->GetTabBoxes()[ nInsPos
];
1145 aNew
.SetWidth( nWidth
);
1146 pBox
->ClaimFrmFmt();
1147 pBox
->GetFrmFmt()->SetFmtAttr( aNew
);
1150 pUndo
->AddNewBox( pBox
->GetSttIdx() );
1152 // diese Box ist selektiert
1154 rBoxes
.Insert( pBox
);
1156 _CmpLPt( (pCell
->Frm().*fnRect
->fnGetPos
)(),
1159 pBox
= pBox
->GetUpper()->GetTabBoxes()[ nInsPos
+1 ];
1160 aNew
.SetWidth( nRight
);
1161 pBox
->ClaimFrmFmt();
1162 pBox
->GetFrmFmt()->SetFmtAttr( aNew
);
1165 pUndo
->AddNewBox( pBox
->GetSttIdx() );
1167 // oder reicht die rechte Kante der Box in den
1168 // selektierten Bereich?
1169 else if( ( pCell
->Frm().Right() - COLFUZZY
) < rUnion
.Right() &&
1170 ( pCell
->Frm().Right() - COLFUZZY
) > rUnion
.Left() &&
1171 ( pCell
->Frm().Left() + COLFUZZY
) < rUnion
.Left() )
1173 // dann muss eine neue Box einfuegt und die
1174 // Breiten angepasst werden
1175 USHORT nInsPos
= pBox
->GetUpper()->GetTabBoxes().
1176 C40_GETPOS( SwTableBox
, pBox
)+1;
1177 lcl_InsTblBox( pTblNd
, pDoc
, pBox
, nInsPos
, 1 );
1179 SwFmtFrmSize
aNew(pBox
->GetFrmFmt()->GetFrmSize() );
1180 long nLeft
= rUnion
.Left() - pCell
->Frm().Left(),
1181 nRight
= pCell
->Frm().Right() - rUnion
.Left();
1183 nLeft
= nLeft
* aNew
.GetWidth() /
1184 pCell
->Frm().Width();
1185 nRight
= nRight
* aNew
.GetWidth() /
1186 pCell
->Frm().Width();
1188 aNew
.SetWidth( nLeft
);
1189 pBox
->ClaimFrmFmt()->SetFmtAttr( aNew
);
1191 // diese Box ist selektiert
1192 pBox
= pBox
->GetUpper()->GetTabBoxes()[ nInsPos
];
1193 aNew
.SetWidth( nRight
);
1194 pBox
->ClaimFrmFmt();
1195 pBox
->GetFrmFmt()->SetFmtAttr( aNew
);
1198 rBoxes
.Insert( pBox
);
1199 aPosArr
.Insert( _CmpLPt( Point( rUnion
.Left(),
1200 pCell
->Frm().Top()), pBox
, bVert
));
1203 pUndo
->AddNewBox( pBox
->GetSttIdx() );
1206 if ( pCell
->GetNext() )
1208 pCell
= (const SwLayoutFrm
*)pCell
->GetNext();
1209 // --> FME 2005-11-03 #125288# Check if table cell is not empty
1210 if ( pCell
->Lower() && pCell
->Lower()->IsRowFrm() )
1211 pCell
= pCell
->FirstCell();
1214 pCell
= ::lcl_FindNextCellFrm( pCell
);
1217 pRow
= (const SwLayoutFrm
*)pRow
->GetNext();
1221 // keine SSelection / keine gefundenen Boxen
1222 if( 1 >= rBoxes
.Count() )
1225 // dann suche mal alle Boxen, die nebeneinander liegen, und verbinde
1226 // deren Inhalte mit Blanks. Alle untereinander liegende werden als
1227 // Absaetze zusammengefasst
1229 // 1. Loesung: gehe ueber das Array und
1230 // alle auf der gleichen Y-Ebene werden mit Blanks getrennt
1231 // alle anderen werden als Absaetze getrennt.
1232 BOOL bCalcWidth
= TRUE
;
1233 const SwTableBox
* pFirstBox
= aPosArr
[ 0 ].pSelBox
;
1235 // JP 27.03.98: Optimierung - falls die Boxen einer Line leer sind,
1236 // dann werden jetzt dafuer keine Blanks und
1237 // kein Umbruch mehr eingefuegt.
1238 //Block damit SwPaM, SwPosition vom Stack geloescht werden
1240 SwPaM
aPam( pDoc
->GetNodes() );
1242 #if defined( DEL_ONLY_EMPTY_LINES )
1243 nWidth
= pFirstBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1244 BOOL bEmptyLine
= TRUE
;
1245 USHORT n
, nSttPos
= 0;
1247 for( n
= 0; n
< aPosArr
.Count(); ++n
)
1249 const _CmpLPt
& rPt
= aPosArr
[ n
];
1250 if( n
&& aPosArr
[ n
- 1 ].Y() == rPt
.Y() ) // gleiche Ebene ?
1252 if( bEmptyLine
&& !IsEmptyBox( *rPt
.pSelBox
, aPam
))
1255 nWidth
+= rPt
.pSelBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1259 if( bCalcWidth
&& n
)
1260 bCalcWidth
= FALSE
; // eine Zeile fertig
1262 if( bEmptyLine
&& nSttPos
< n
)
1264 // dann ist die gesamte Line leer und braucht
1265 // nicht mit Blanks aufgefuellt und als Absatz
1266 // eingefuegt werden.
1268 for( USHORT i
= nSttPos
; i
< n
; ++i
)
1269 pUndo
->SaveCollection( *aPosArr
[ i
].pSelBox
);
1271 aPosArr
.Remove( nSttPos
, n
- nSttPos
);
1277 bEmptyLine
= IsEmptyBox( *aPosArr
[n
].pSelBox
, aPam
);
1280 if( bEmptyLine
&& nSttPos
< n
)
1283 for( USHORT i
= nSttPos
; i
< n
; ++i
)
1284 pUndo
->SaveCollection( *aPosArr
[ i
].pSelBox
);
1285 aPosArr
.Remove( nSttPos
, n
- nSttPos
);
1287 #elsif defined( DEL_EMPTY_BOXES_AT_START_AND_END )
1289 nWidth
= pFirstBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1290 USHORT n
, nSttPos
= 0, nSEndPos
= 0, nESttPos
= 0;
1292 for( n
= 0; n
< aPosArr
.Count(); ++n
)
1294 const _CmpLPt
& rPt
= aPosArr
[ n
];
1295 if( n
&& aPosArr
[ n
- 1 ].Y() == rPt
.Y() ) // gleiche Ebene ?
1297 BOOL bEmptyBox
= IsEmptyBox( *rPt
.pSelBox
, aPam
);
1300 if( nSEndPos
== n
) // der Anfang ist leer
1301 nESttPos
= ++nSEndPos
;
1303 else // das Ende kann leer sein
1307 nWidth
+= rPt
.pSelBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1311 if( bCalcWidth
&& n
)
1312 bCalcWidth
= FALSE
; // eine Zeile fertig
1314 // zuerst die vom Anfang
1315 if( nSttPos
< nSEndPos
)
1317 // dann ist der vorder Teil der Line leer und braucht
1318 // nicht mit Blanks aufgefuellt werden.
1320 for( USHORT i
= nSttPos
; i
< nSEndPos
; ++i
)
1321 pUndo
->SaveCollection( *aPosArr
[ i
].pSelBox
);
1323 USHORT nCnt
= nSEndPos
- nSttPos
;
1324 aPosArr
.Remove( nSttPos
, nCnt
);
1331 // dann ist der vorder Teil der Line leer und braucht
1332 // nicht mit Blanks aufgefuellt werden.
1334 for( USHORT i
= nESttPos
; i
< n
; ++i
)
1335 pUndo
->SaveCollection( *aPosArr
[ i
].pSelBox
);
1337 USHORT nCnt
= n
- nESttPos
;
1338 aPosArr
.Remove( nESttPos
, nCnt
);
1342 nSttPos
= nSEndPos
= nESttPos
= n
;
1343 if( IsEmptyBox( *aPosArr
[n
].pSelBox
, aPam
))
1350 // zuerst die vom Anfang
1351 if( nSttPos
< nSEndPos
)
1353 // dann ist der vorder Teil der Line leer und braucht
1354 // nicht mit Blanks aufgefuellt werden.
1356 for( USHORT i
= nSttPos
; i
< nSEndPos
; ++i
)
1357 pUndo
->SaveCollection( *aPosArr
[ i
].pSelBox
);
1359 USHORT nCnt
= nSEndPos
- nSttPos
;
1360 aPosArr
.Remove( nSttPos
, nCnt
);
1366 // dann ist der vorder Teil der Line leer und braucht
1367 // nicht mit Blanks aufgefuellt werden.
1369 for( USHORT i
= nESttPos
; i
< n
; ++i
)
1370 pUndo
->SaveCollection( *aPosArr
[ i
].pSelBox
);
1372 USHORT nCnt
= n
- nESttPos
;
1373 aPosArr
.Remove( nESttPos
, nCnt
);
1376 // DEL_ALL_EMPTY_BOXES
1379 long nY
= aPosArr
.Count() ?
1382 aPosArr
[ 0 ].Y() ) :
1385 for( USHORT n
= 0; n
< aPosArr
.Count(); ++n
)
1387 const _CmpLPt
& rPt
= aPosArr
[ n
];
1390 if( nY
== ( bVert
? rPt
.X() : rPt
.Y() ) ) // gleiche Ebene ?
1391 nWidth
+= rPt
.pSelBox
->GetFrmFmt()->GetFrmSize().GetWidth();
1393 bCalcWidth
= FALSE
; // eine Zeile fertig
1396 if( IsEmptyBox( *rPt
.pSelBox
, aPam
) )
1399 pUndo
->SaveCollection( *rPt
.pSelBox
);
1401 aPosArr
.Remove( n
, 1 );
1408 // lege schon mal die neue Box an
1410 SwTableBox
* pTmpBox
= rBoxes
[0];
1411 SwTableLine
* pInsLine
= pTmpBox
->GetUpper();
1412 USHORT nInsPos
= pInsLine
->GetTabBoxes().C40_GETPOS( SwTableBox
, pTmpBox
);
1414 lcl_InsTblBox( pTblNd
, pDoc
, pTmpBox
, nInsPos
);
1415 (*ppMergeBox
) = pInsLine
->GetTabBoxes()[ nInsPos
];
1416 pInsLine
->GetTabBoxes().Remove( nInsPos
); // wieder austragen
1417 (*ppMergeBox
)->SetUpper( 0 );
1418 (*ppMergeBox
)->ClaimFrmFmt();
1420 // setze die Umrandung: von der 1. Box die linke/obere von der
1421 // letzten Box die rechte/untere Kante:
1422 if( pLastBox
&& pFirstBox
)
1424 SvxBoxItem
aBox( pFirstBox
->GetFrmFmt()->GetBox() );
1425 const SvxBoxItem
& rBox
= pLastBox
->GetFrmFmt()->GetBox();
1426 aBox
.SetLine( rBox
.GetRight(), BOX_LINE_RIGHT
);
1427 aBox
.SetLine( rBox
.GetBottom(), BOX_LINE_BOTTOM
);
1428 if( aBox
.GetLeft() || aBox
.GetTop() ||
1429 aBox
.GetRight() || aBox
.GetBottom() )
1430 (*ppMergeBox
)->GetFrmFmt()->SetFmtAttr( aBox
);
1434 //Block damit SwPaM, SwPosition vom Stack geloescht werden
1435 if( aPosArr
.Count() )
1437 SwTxtNode
* pTxtNd
= 0;
1438 SwPosition
aInsPos( *(*ppMergeBox
)->GetSttNd() );
1439 SwNodeIndex
& rInsPosNd
= aInsPos
.nNode
;
1441 SwPaM
aPam( aInsPos
);
1443 for( USHORT n
= 0; n
< aPosArr
.Count(); ++n
)
1445 const _CmpLPt
& rPt
= aPosArr
[ n
];
1446 aPam
.GetPoint()->nNode
.Assign( *rPt
.pSelBox
->GetSttNd()->
1447 EndOfSectionNode(), -1 );
1448 SwCntntNode
* pCNd
= aPam
.GetCntntNode();
1449 USHORT nL
= pCNd
? pCNd
->Len() : 0;
1450 aPam
.GetPoint()->nContent
.Assign( pCNd
, nL
);
1452 SwNodeIndex
aSttNdIdx( *rPt
.pSelBox
->GetSttNd(), 1 );
1453 // ein Node muss in der Box erhalten bleiben (sonst wird beim
1454 // Move die gesamte Section geloescht)
1456 pDoc
->DoUndo( FALSE
);
1457 pDoc
->AppendTxtNode( *aPam
.GetPoint() );
1459 pDoc
->DoUndo( TRUE
);
1460 SwNodeRange
aRg( aSttNdIdx
, aPam
.GetPoint()->nNode
);
1463 pUndo
->MoveBoxCntnt( pDoc
, aRg
, rInsPosNd
);
1466 pDoc
->MoveNodeRange( aRg
, rInsPosNd
,
1467 IDocumentContentOperations::DOC_MOVEDEFAULT
);
1469 // wo steht jetzt aInsPos ??
1472 bCalcWidth
= FALSE
; // eine Zeile fertig
1474 // den initialen TextNode ueberspringen
1475 rInsPosNd
.Assign( pDoc
->GetNodes(),
1476 rInsPosNd
.GetNode().EndOfSectionIndex() - 2 );
1477 pTxtNd
= rInsPosNd
.GetNode().GetTxtNode();
1479 aInsPos
.nContent
.Assign( pTxtNd
, pTxtNd
->GetTxt().Len() );
1482 // in der MergeBox sollte jetzt der gesamte Text stehen
1483 // loesche jetzt noch den initialen TextNode
1484 ASSERT( (*ppMergeBox
)->GetSttIdx()+2 <
1485 (*ppMergeBox
)->GetSttNd()->EndOfSectionIndex(),
1487 SwNodeIndex
aIdx( *(*ppMergeBox
)->GetSttNd()->EndOfSectionNode(), -1 );
1488 pDoc
->GetNodes().Delete( aIdx
, 1 );
1491 // setze die Breite der Box
1492 (*ppMergeBox
)->GetFrmFmt()->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE
, nWidth
, 0 ));
1494 pUndo
->AddNewBox( (*ppMergeBox
)->GetSttIdx() );
1498 static BOOL
lcl_CheckCol( const _FndBox
*& rpFndBox
, void* pPara
);
1500 static BOOL
lcl_CheckRow( const _FndLine
*& rpFndLine
, void* pPara
)
1502 ((_FndLine
*)rpFndLine
)->GetBoxes().ForEach( &lcl_CheckCol
, pPara
);
1503 return *(BOOL
*)pPara
;
1506 static BOOL
lcl_CheckCol( const _FndBox
*& rpFndBox
, void* pPara
)
1508 if( !rpFndBox
->GetBox()->GetSttNd() )
1510 if( rpFndBox
->GetLines().Count() !=
1511 rpFndBox
->GetBox()->GetTabLines().Count() )
1512 *((BOOL
*)pPara
) = FALSE
;
1514 ((_FndBox
*)rpFndBox
)->GetLines().ForEach( &lcl_CheckRow
, pPara
);
1516 // Box geschuetzt ??
1517 else if( rpFndBox
->GetBox()->GetFrmFmt()->GetProtect().IsCntntProtected() )
1518 *((BOOL
*)pPara
) = FALSE
;
1519 return *(BOOL
*)pPara
;
1523 USHORT
CheckMergeSel( const SwPaM
& rPam
)
1526 //JP 24.09.96: Merge mit wiederholenden TabellenHeadline funktioniert nicht
1527 // richtig. Warum nicht Point 0,0 benutzen? Dann ist garantiert,
1528 // das die 1. Headline mit drin ist.
1530 const SwLayoutFrm
*pStart
= rPam
.GetCntntNode()->GetFrm(
1532 *pEnd
= rPam
.GetCntntNode(FALSE
)->GetFrm(
1534 GetTblSel( pStart
, pEnd
, aBoxes
, 0 );
1535 return CheckMergeSel( aBoxes
);
1538 USHORT
CheckMergeSel( const SwSelBoxes
& rBoxes
)
1540 USHORT eRet
= TBLMERGE_NOSELECTION
;
1541 if( rBoxes
.Count() )
1545 _FndBox
aFndBox( 0, 0 );
1546 _FndPara
aPara( rBoxes
, &aFndBox
);
1547 const SwTableNode
* pTblNd
= aPara
.rBoxes
[0]->GetSttNd()->FindTableNode();
1548 ((SwTable
&)pTblNd
->GetTable()).GetTabLines().ForEach(
1549 &_FndLineCopyCol
, &aPara
);
1550 if( aFndBox
.GetLines().Count() )
1552 BOOL bMergeSelOk
= TRUE
;
1553 _FndBox
* pFndBox
= &aFndBox
;
1554 _FndLine
* pFndLine
= 0;
1555 while( pFndBox
&& 1 == pFndBox
->GetLines().Count() )
1557 pFndLine
= pFndBox
->GetLines()[0];
1558 if( 1 == pFndLine
->GetBoxes().Count() )
1559 pFndBox
= pFndLine
->GetBoxes()[0];
1564 pFndBox
->GetLines().ForEach( &lcl_CheckRow
, &bMergeSelOk
);
1566 pFndLine
->GetBoxes().ForEach( &lcl_CheckCol
, &bMergeSelOk
);
1568 eRet
= TBLMERGE_TOOCOMPLEX
;
1571 eRet
= TBLMERGE_NOSELECTION
;
1576 //Ermittelt die von einer Tabellenselektion betroffenen Tabellen und die
1577 //Union-Rechteckte der Selektionen - auch fuer aufgespaltene Tabellen.
1578 SV_IMPL_PTRARR( SwSelUnions
, SwSelUnion
* );
1580 SwTwips
lcl_CalcWish( const SwLayoutFrm
*pCell
, long nWish
,
1583 const SwLayoutFrm
*pTmp
= pCell
;
1587 const sal_Bool bRTL
= pCell
->IsRightToLeft();
1588 SwTwips nRet
= bRTL
?
1589 nAct
- pCell
->Frm().Width() :
1594 while ( pTmp
->GetPrev() )
1596 pTmp
= (SwLayoutFrm
*)pTmp
->GetPrev();
1597 long nTmp
= pTmp
->GetFmt()->GetFrmSize().GetWidth();
1598 nRet
+= ( bRTL
? ( -1 ) : 1 ) * nTmp
* nAct
/ nWish
;
1600 pTmp
= pTmp
->GetUpper()->GetUpper();
1601 if ( pTmp
&& !pTmp
->IsCellFrm() )
1607 /* MA: 20. Sep. 93 wird nicht mehr gebraucht.
1608 static const SwLayoutFrm *GetPrevCell( const SwLayoutFrm *pCell )
1610 const SwLayoutFrm *pLay = pCell->GetPrevLayoutLeaf();
1611 if ( pLay && pLay->IsLayoutFrm() && !pLay->IsTab() )
1613 //GetPrevLayoutLeaf() liefert ggf. auch die Umgebung einer Tab zurueck
1614 //(naehmlich genau dann, wenn die Zelle noch Vorgaenger hat).
1615 const SwFrm *pFrm = pLay->Lower();
1616 while ( pFrm->GetNext() )
1617 pFrm = pFrm->GetNext();
1618 pLay = pFrm->IsTabFrm() ? (SwLayoutFrm*)pFrm : 0;
1620 if ( pLay && pLay->IsTabFrm() )
1622 //GetPrevLayoutLeaf() liefert ggf. auch Tabellen zurueck die letzte
1623 //Zelle dieser Tabelle ist das das gesuchte Blatt.
1624 pLay = ((SwTabFrm*)pLay)->FindLastCntnt()->GetUpper();
1625 while ( !pLay->IsCellFrm() )
1626 pLay = pLay->GetUpper();
1632 void lcl_FindStartEndRow( const SwLayoutFrm
*&rpStart
,
1633 const SwLayoutFrm
*&rpEnd
,
1634 const int bChkProtected
)
1636 //Start an den Anfang seiner Zeile setzen.
1637 //End an das Ende seiner Zeile setzen.
1638 rpStart
= (SwLayoutFrm
*)rpStart
->GetUpper()->Lower();
1639 while ( rpEnd
->GetNext() )
1640 rpEnd
= (SwLayoutFrm
*)rpEnd
->GetNext();
1642 SvPtrarr
aSttArr( 8, 8 ), aEndArr( 8, 8 );
1643 const SwLayoutFrm
*pTmp
;
1644 for( pTmp
= rpStart
; (FRM_CELL
|FRM_ROW
) & pTmp
->GetType();
1645 pTmp
= pTmp
->GetUpper() )
1647 void* p
= (void*)pTmp
;
1648 aSttArr
.Insert( p
, 0 );
1650 for( pTmp
= rpEnd
; (FRM_CELL
|FRM_ROW
) & pTmp
->GetType();
1651 pTmp
= pTmp
->GetUpper() )
1653 void* p
= (void*)pTmp
;
1654 aEndArr
.Insert( p
, 0 );
1657 for( USHORT n
= 0; n
< aEndArr
.Count() && n
< aSttArr
.Count(); ++n
)
1658 if( aSttArr
[ n
] != aEndArr
[ n
] )
1660 // first unequal line or box - all odds are
1661 if( n
& 1 ) // 1, 3, 5, ... are boxes
1663 rpStart
= (SwLayoutFrm
*)aSttArr
[ n
];
1664 rpEnd
= (SwLayoutFrm
*)aEndArr
[ n
];
1666 else // 0, 2, 4, ... are lines
1668 // check if start & end line are the first & last Line of the
1669 // box. If not return these cells.
1670 // Else the hole line with all Boxes has to be deleted.
1671 rpStart
= (SwLayoutFrm
*)aSttArr
[ n
+1 ];
1672 rpEnd
= (SwLayoutFrm
*)aEndArr
[ n
+1 ];
1675 const SwCellFrm
* pCellFrm
= (SwCellFrm
*)aSttArr
[ n
-1 ];
1676 const SwTableLines
& rLns
= pCellFrm
->
1677 GetTabBox()->GetTabLines();
1678 if( rLns
[ 0 ] == ((SwRowFrm
*)aSttArr
[ n
])->GetTabLine() &&
1679 rLns
[ rLns
.Count() - 1 ] ==
1680 ((SwRowFrm
*)aEndArr
[ n
])->GetTabLine() )
1682 rpStart
= rpEnd
= pCellFrm
;
1683 while ( rpStart
->GetPrev() )
1684 rpStart
= (SwLayoutFrm
*)rpStart
->GetPrev();
1685 while ( rpEnd
->GetNext() )
1686 rpEnd
= (SwLayoutFrm
*)rpEnd
->GetNext();
1693 if( !bChkProtected
) // geschuetzte Zellen beachten ?
1697 //Anfang und Ende duerfen nicht auf geschuetzten Zellen liegen.
1698 while ( rpStart
->GetFmt()->GetProtect().IsCntntProtected() )
1699 rpStart
= (SwLayoutFrm
*)rpStart
->GetNext();
1700 while ( rpEnd
->GetFmt()->GetProtect().IsCntntProtected() )
1701 rpEnd
= (SwLayoutFrm
*)rpEnd
->GetPrev();
1705 void lcl_FindStartEndCol( const SwLayoutFrm
*&rpStart
,
1706 const SwLayoutFrm
*&rpEnd
,
1707 const int bChkProtected
)
1709 //Start und End senkrecht bis an den Rand der Tabelle denken; es muss
1710 //die Gesamttabelle betrachtet werden, also inklusive Masters und
1712 //Fuer den Start brauchen wir den Mutter-TabellenFrm.
1715 const SwTabFrm
*pOrg
= rpStart
->FindTabFrm();
1716 const SwTabFrm
*pTab
= pOrg
;
1720 sal_Bool bRTL
= pTab
->IsRightToLeft();
1721 const long nTmpWish
= pOrg
->GetFmt()->GetFrmSize().GetWidth();
1722 const long nWish
= ( nTmpWish
> 0 ) ? nTmpWish
: 1;
1724 while ( pTab
->IsFollow() )
1726 const SwFrm
*pTmp
= pTab
->FindPrev();
1727 ASSERT( pTmp
->IsTabFrm(), "Vorgaenger vom Follow nicht der Master." );
1728 pTab
= (const SwTabFrm
*)pTmp
;
1734 if ( pTab
->GetTable()->IsNewModel() )
1736 nSX
= (rpStart
->Frm().*fnRect
->fnGetLeft
)();
1737 nSX2
= (rpStart
->Frm().*fnRect
->fnGetRight
)();
1741 const SwTwips nPrtWidth
= (pTab
->Prt().*fnRect
->fnGetWidth
)();
1742 nSX
= ::lcl_CalcWish( rpStart
, nWish
, nPrtWidth
) + (pTab
->*fnRect
->fnGetPrtLeft
)();
1743 nSX2
= nSX
+ (rpStart
->GetFmt()->GetFrmSize().GetWidth() * nPrtWidth
/ nWish
);
1746 const SwLayoutFrm
*pTmp
= pTab
->FirstCell();
1749 (!pTmp
->IsCellFrm() ||
1750 ( ( ! bRTL
&& (pTmp
->Frm().*fnRect
->fnGetLeft
)() < nSX
&&
1751 (pTmp
->Frm().*fnRect
->fnGetRight
)()< nSX2
) ||
1752 bRTL
&& (pTmp
->Frm().*fnRect
->fnGetLeft
)() > nSX
&&
1753 (pTmp
->Frm().*fnRect
->fnGetRight
)()> nSX2
) ) )
1754 pTmp
= pTmp
->GetNextLayoutLeaf();
1761 const SwTabFrm
* pLastValidTab
= pTab
;
1762 while ( pTab
->GetFollow() )
1765 // Check if pTab->GetFollow() is a valid follow table:
1766 // Only follow tables with at least on non-FollowFlowLine
1767 // should be considered.
1769 if ( pTab
->HasFollowFlowLine() )
1771 pTab
= pTab
->GetFollow();
1772 const SwFrm
* pTmpRow
= pTab
->GetFirstNonHeadlineRow();
1773 if ( pTmpRow
&& pTmpRow
->GetNext() )
1774 pLastValidTab
= pTab
;
1777 pLastValidTab
= pTab
= pTab
->GetFollow();
1779 pTab
= pLastValidTab
;
1783 if ( pTab
->GetTable()->IsNewModel() )
1785 nEX
= (rpEnd
->Frm().*fnRect
->fnGetLeft
)();
1789 const SwTwips nPrtWidth
= (pTab
->Prt().*fnRect
->fnGetWidth
)();
1790 nEX
= ::lcl_CalcWish( rpEnd
, nWish
, nPrtWidth
) + (pTab
->*fnRect
->fnGetPrtLeft
)();
1793 const SwCntntFrm
* pLastCntnt
= pTab
->FindLastCntnt();
1794 rpEnd
= pLastCntnt
? pLastCntnt
->GetUpper() : 0;
1795 // --> FME 2006-07-17 #134385# Made code robust. If pTab does not have a lower,
1796 // we would crash here.
1797 if ( !pLastCntnt
) return;
1800 while( !rpEnd
->IsCellFrm() )
1801 rpEnd
= rpEnd
->GetUpper();
1803 while ( ( bRTL
&& (rpEnd
->Frm().*fnRect
->fnGetLeft
)() < nEX
) ||
1804 ( ! bRTL
&& (rpEnd
->Frm().*fnRect
->fnGetLeft
)() > nEX
) )
1806 const SwLayoutFrm
* pTmpLeaf
= rpEnd
->GetPrevLayoutLeaf();
1807 if( !pTmpLeaf
|| !pTab
->IsAnLower( pTmpLeaf
) )
1812 if( !bChkProtected
) // geschuetzte Zellen beachten ?
1815 //Anfang und Ende duerfen nicht auf geschuetzten Zellen liegen.
1816 //Also muss ggf. nocheinmal rueckwaerts gesucht werden.
1817 while ( rpStart
->GetFmt()->GetProtect().IsCntntProtected() )
1819 const SwLayoutFrm
*pTmpLeaf
= rpStart
;
1820 pTmpLeaf
= pTmpLeaf
->GetNextLayoutLeaf();
1821 while ( pTmpLeaf
&& (pTmpLeaf
->Frm().*fnRect
->fnGetLeft
)() > nEX
)//erstmal die Zeile ueberspr.
1822 pTmpLeaf
= pTmpLeaf
->GetNextLayoutLeaf();
1823 while ( pTmpLeaf
&& (pTmpLeaf
->Frm().*fnRect
->fnGetLeft
)() < nSX
&&
1824 (pTmpLeaf
->Frm().*fnRect
->fnGetRight
)()< nSX2
)
1825 pTmpLeaf
= pTmpLeaf
->GetNextLayoutLeaf();
1826 const SwTabFrm
*pTmpTab
= rpStart
->FindTabFrm();
1827 if ( !pTmpTab
->IsAnLower( pTmpLeaf
) )
1829 pTmpTab
= pTmpTab
->GetFollow();
1830 rpStart
= pTmpTab
->FirstCell();
1831 while ( (rpStart
->Frm().*fnRect
->fnGetLeft
)() < nSX
&&
1832 (rpStart
->Frm().*fnRect
->fnGetRight
)()< nSX2
)
1833 rpStart
= rpStart
->GetNextLayoutLeaf();
1838 while ( rpEnd
->GetFmt()->GetProtect().IsCntntProtected() )
1840 const SwLayoutFrm
*pTmpLeaf
= rpEnd
;
1841 pTmpLeaf
= pTmpLeaf
->GetPrevLayoutLeaf();
1842 while ( pTmpLeaf
&& (pTmpLeaf
->Frm().*fnRect
->fnGetLeft
)() < nEX
)//erstmal die Zeile ueberspr.
1843 pTmpLeaf
= pTmpLeaf
->GetPrevLayoutLeaf();
1844 while ( pTmpLeaf
&& (pTmpLeaf
->Frm().*fnRect
->fnGetLeft
)() > nEX
)
1845 pTmpLeaf
= pTmpLeaf
->GetPrevLayoutLeaf();
1846 const SwTabFrm
*pTmpTab
= rpEnd
->FindTabFrm();
1847 if ( !pTmpLeaf
|| !pTmpTab
->IsAnLower( pTmpLeaf
) )
1849 pTmpTab
= (const SwTabFrm
*)pTmpTab
->FindPrev();
1850 ASSERT( pTmpTab
->IsTabFrm(), "Vorgaenger vom Follow nicht der Master.");
1851 rpEnd
= pTmpTab
->FindLastCntnt()->GetUpper();
1852 while( !rpEnd
->IsCellFrm() )
1853 rpEnd
= rpEnd
->GetUpper();
1854 while ( (rpEnd
->Frm().*fnRect
->fnGetLeft
)() > nEX
)
1855 rpEnd
= rpEnd
->GetPrevLayoutLeaf();
1863 void MakeSelUnions( SwSelUnions
& rUnions
, const SwLayoutFrm
*pStart
,
1864 const SwLayoutFrm
*pEnd
, const SwTblSearchType eSearchType
)
1866 while ( pStart
&& !pStart
->IsCellFrm() )
1867 pStart
= pStart
->GetUpper();
1868 while ( pEnd
&& !pEnd
->IsCellFrm() )
1869 pEnd
= pEnd
->GetUpper();
1872 if ( !pStart
|| !pEnd
)
1874 ASSERT( false, "MakeSelUnions with pStart or pEnd not in CellFrm" )
1878 const SwTabFrm
*pTable
= pStart
->FindTabFrm();
1879 const SwTabFrm
*pEndTable
= pEnd
->FindTabFrm();
1880 if( !pTable
|| !pEndTable
)
1882 BOOL bExchange
= FALSE
;
1884 if ( pTable
!= pEndTable
)
1886 if ( !pTable
->IsAnFollow( pEndTable
) )
1888 ASSERT( pEndTable
->IsAnFollow( pTable
), "Tabkette verknotet." );
1895 long nSttTop
= (pStart
->Frm().*fnRect
->fnGetTop
)();
1896 long nEndTop
= (pEnd
->Frm().*fnRect
->fnGetTop
)();
1897 if( nSttTop
== nEndTop
)
1899 if( (pStart
->Frm().*fnRect
->fnGetLeft
)() >
1900 (pEnd
->Frm().*fnRect
->fnGetLeft
)() )
1903 else if( bVert
== ( nSttTop
< nEndTop
) )
1908 const SwLayoutFrm
*pTmp
= pStart
;
1911 //pTable und pEndTable nicht umsortieren, werden unten neu gesetzt.
1912 //MA: 28. Dec. 93 Bug: 5190
1915 //Start und End sind jetzt huebsch sortiert, jetzt muessen sie falls
1916 //erwuenscht noch versetzt werden.
1917 if( nsSwTblSearchType::TBLSEARCH_ROW
== ((~nsSwTblSearchType::TBLSEARCH_PROTECT
) & eSearchType
) )
1918 ::lcl_FindStartEndRow( pStart
, pEnd
, nsSwTblSearchType::TBLSEARCH_PROTECT
& eSearchType
);
1919 else if( nsSwTblSearchType::TBLSEARCH_COL
== ((~nsSwTblSearchType::TBLSEARCH_PROTECT
) & eSearchType
) )
1920 ::lcl_FindStartEndCol( pStart
, pEnd
, nsSwTblSearchType::TBLSEARCH_PROTECT
& eSearchType
);
1922 // --> FME 2006-07-17 #134385# Made code robust.
1923 if ( !pEnd
) return;
1926 //neu besorgen, da sie jetzt verschoben sind. MA: 28. Dec. 93 Bug 5190
1927 pTable
= pStart
->FindTabFrm();
1928 pEndTable
= pEnd
->FindTabFrm();
1930 const long nStSz
= pStart
->GetFmt()->GetFrmSize().GetWidth();
1931 const long nEdSz
= pEnd
->GetFmt()->GetFrmSize().GetWidth();
1932 const long nWish
= Max( 1L, pTable
->GetFmt()->GetFrmSize().GetWidth() );
1936 const long nOfst
= (pTable
->*fnRect
->fnGetPrtLeft
)();
1937 const long nPrtWidth
= (pTable
->Prt().*fnRect
->fnGetWidth
)();
1938 long nSt1
= ::lcl_CalcWish( pStart
, nWish
, nPrtWidth
) + nOfst
;
1939 long nEd1
= ::lcl_CalcWish( pEnd
, nWish
, nPrtWidth
) + nOfst
;
1942 nEd1
+= (long)((nEdSz
* nPrtWidth
) / nWish
) - 1;
1944 nSt1
+= (long)((nStSz
* nPrtWidth
) / nWish
) - 1;
1948 if( pTable
->IsAnLower( pStart
) )
1949 nSt2
= (pStart
->Frm().*fnRect
->fnGetTop
)();
1951 nSt2
= (pTable
->Frm().*fnRect
->fnGetTop
)();
1952 if( pTable
->IsAnLower( pEnd
) )
1953 nEd2
= (pEnd
->Frm().*fnRect
->fnGetBottom
)();
1955 nEd2
= (pTable
->Frm().*fnRect
->fnGetBottom
)();
1971 aSt
= Point( nSt2
, nSt1
);
1972 aEd
= Point( nEd2
, nEd1
);
1976 aSt
= Point( nSt1
, nSt2
);
1977 aEd
= Point( nEd1
, nEd2
);
1980 const Point
aDiff( aEd
- aSt
);
1981 SwRect
aUnion( aSt
, Size( aDiff
.X(), aDiff
.Y() ) );
1985 if( !(nsSwTblSearchType::TBLSEARCH_NO_UNION_CORRECT
& eSearchType
))
1987 //Leider ist die Union jetzt mit Rundungsfehlern behaftet und dadurch
1988 //wuerden beim Split/Merge fehlertraechtige Umstaende entstehen.
1989 //Um dies zu vermeiden werden jetzt fuer die Table die erste und
1990 //letzte Zelle innerhalb der Union ermittelt und aus genau deren
1991 //Werten wird die Union neu gebildet.
1992 const SwLayoutFrm
* pRow
= pTable
->IsFollow() ?
1993 pTable
->GetFirstNonHeadlineRow() :
1994 (const SwLayoutFrm
*)pTable
->Lower();
1996 while ( pRow
&& !pRow
->Frm().IsOver( aUnion
) )
1997 pRow
= (SwLayoutFrm
*)pRow
->GetNext();
1999 // --> FME 2004-07-26 #i31976#
2000 // A follow flow row may contain emtpy cells. These are not
2001 // considered by FirstCell(). Therefore we have to find
2002 // the first cell manually:
2003 const SwFrm
* pTmpCell
= 0;
2004 if ( pTable
->IsFollow() && pRow
&& pRow
->IsInFollowFlowRow() )
2006 const SwFrm
* pTmpRow
= pRow
;
2007 while ( pTmpRow
&& pTmpRow
->IsRowFrm() )
2009 pTmpCell
= static_cast<const SwRowFrm
*>(pTmpRow
)->Lower();
2010 pTmpRow
= static_cast<const SwCellFrm
*>(pTmpCell
)->Lower();
2012 ASSERT( !pTmpCell
|| pTmpCell
->IsCellFrm(), "Lower of rowframe != cellframe?!" )
2016 const SwLayoutFrm
* pFirst
= pTmpCell
?
2017 static_cast<const SwLayoutFrm
*>(pTmpCell
) :
2022 while ( pFirst
&& !::IsFrmInTblSel( aUnion
, pFirst
) )
2024 if ( pFirst
->GetNext() )
2026 pFirst
= (const SwLayoutFrm
*)pFirst
->GetNext();
2027 if ( pFirst
->Lower() && pFirst
->Lower()->IsRowFrm() )
2028 pFirst
= pFirst
->FirstCell();
2031 pFirst
= ::lcl_FindNextCellFrm( pFirst
);
2033 const SwLayoutFrm
* pLast
= 0;
2034 const SwFrm
* pLastCntnt
= pTable
->FindLastCntnt();
2036 pLast
= ::lcl_FindCellFrm( pLastCntnt
->GetUpper() );
2038 while ( pLast
&& !::IsFrmInTblSel( aUnion
, pLast
) )
2039 pLast
= ::lcl_FindCellFrm( pLast
->GetPrevLayoutLeaf() );
2041 if ( pFirst
&& pLast
) //Robust
2043 aUnion
= pFirst
->Frm();
2044 aUnion
.Union( pLast
->Frm() );
2050 if( (aUnion
.*fnRect
->fnGetWidth
)() )
2052 SwSelUnion
*pTmp
= new SwSelUnion( aUnion
, (SwTabFrm
*)pTable
);
2053 rUnions
.C40_INSERT( SwSelUnion
, pTmp
, rUnions
.Count() );
2056 pTable
= pTable
->GetFollow();
2057 if ( pTable
!= pEndTable
&& pEndTable
->IsAnFollow( pTable
) )
2062 BOOL
CheckSplitCells( const SwCrsrShell
& rShell
, USHORT nDiv
,
2063 const SwTblSearchType eSearchType
)
2065 if( !rShell
.IsTableMode() )
2068 return CheckSplitCells( *rShell
.getShellCrsr(false), nDiv
, eSearchType
);
2071 BOOL
CheckSplitCells( const SwCursor
& rCrsr
, USHORT nDiv
,
2072 const SwTblSearchType eSearchType
)
2077 USHORT nMinValue
= nDiv
* MINLAY
;
2079 //Start- und Endzelle besorgen und den naechsten fragen.
2080 Point aPtPos
, aMkPos
;
2081 const SwShellCrsr
* pShCrsr
= dynamic_cast<const SwShellCrsr
*>(&rCrsr
);
2084 aPtPos
= pShCrsr
->GetPtPos();
2085 aMkPos
= pShCrsr
->GetMkPos();
2087 const SwLayoutFrm
*pStart
= rCrsr
.GetCntntNode()->GetFrm(
2088 &aPtPos
)->GetUpper(),
2089 *pEnd
= rCrsr
.GetCntntNode(FALSE
)->GetFrm(
2090 &aMkPos
)->GetUpper();
2092 SWRECTFN( pStart
->GetUpper() )
2094 //Zuerst lassen wir uns die Tabellen und die Rechtecke heraussuchen.
2095 SwSelUnions aUnions
;
2097 ::MakeSelUnions( aUnions
, pStart
, pEnd
, eSearchType
);
2099 //Jetzt zu jedem Eintrag die Boxen herausfischen und uebertragen.
2100 for ( USHORT i
= 0; i
< aUnions
.Count(); ++i
)
2102 SwSelUnion
*pUnion
= aUnions
[i
];
2103 const SwTabFrm
*pTable
= pUnion
->GetTable();
2105 // Skip any repeated headlines in the follow:
2106 const SwLayoutFrm
* pRow
= pTable
->IsFollow() ?
2107 pTable
->GetFirstNonHeadlineRow() :
2108 (const SwLayoutFrm
*)pTable
->Lower();
2112 if ( pRow
->Frm().IsOver( pUnion
->GetUnion() ) )
2114 const SwLayoutFrm
*pCell
= pRow
->FirstCell();
2116 while ( pCell
&& pRow
->IsAnLower( pCell
) )
2118 ASSERT( pCell
->IsCellFrm(), "Frame ohne Celle" );
2119 if( ::IsFrmInTblSel( pUnion
->GetUnion(), pCell
) )
2121 if( (pCell
->Frm().*fnRect
->fnGetWidth
)() < nMinValue
)
2125 if ( pCell
->GetNext() )
2127 pCell
= (const SwLayoutFrm
*)pCell
->GetNext();
2128 if ( pCell
->Lower() && pCell
->Lower()->IsRowFrm() )
2129 pCell
= pCell
->FirstCell();
2132 pCell
= ::lcl_FindNextCellFrm( pCell
);
2135 pRow
= (const SwLayoutFrm
*)pRow
->GetNext();
2141 // -------------------------------------------------------------------
2142 // Diese Klassen kopieren die aktuelle Tabellen-Selektion (rBoxes)
2143 // unter Beibehaltung der Tabellen-Struktur in eine eigene Struktur
2144 // neu: SS zum gezielten Loeschen/Retaurieren des Layouts.
2146 void lcl_InsertRow( SwTableLine
&rLine
, SwLayoutFrm
*pUpper
, SwFrm
*pSibling
)
2148 SwRowFrm
*pRow
= new SwRowFrm( rLine
);
2149 if ( pUpper
->IsTabFrm() && ((SwTabFrm
*)pUpper
)->IsFollow() )
2151 SwTabFrm
* pTabFrm
= (SwTabFrm
*)pUpper
;
2152 pTabFrm
->FindMaster()->InvalidatePos(); //kann die Zeile vielleicht aufnehmen
2154 if ( pSibling
&& pTabFrm
->IsInHeadline( *pSibling
) )
2156 // Skip any repeated headlines in the follow:
2157 pSibling
= pTabFrm
->GetFirstNonHeadlineRow();
2160 pRow
->Paste( pUpper
, pSibling
);
2165 BOOL
_FndBoxCopyCol( const SwTableBox
*& rpBox
, void* pPara
)
2167 _FndPara
* pFndPara
= (_FndPara
*)pPara
;
2168 _FndBox
* pFndBox
= new _FndBox( (SwTableBox
*)rpBox
, pFndPara
->pFndLine
);
2169 if( rpBox
->GetTabLines().Count() )
2171 _FndPara
aPara( *pFndPara
, pFndBox
);
2172 pFndBox
->GetBox()->GetTabLines().ForEach( &_FndLineCopyCol
, &aPara
);
2173 if( !pFndBox
->GetLines().Count() )
2181 SwTableBoxPtr pSrch
= (SwTableBoxPtr
)rpBox
;
2183 if( !pFndPara
->rBoxes
.Seek_Entry( pSrch
, &nFndPos
))
2189 pFndPara
->pFndLine
->GetBoxes().C40_INSERT( _FndBox
, pFndBox
,
2190 pFndPara
->pFndLine
->GetBoxes().Count() );
2194 BOOL
_FndLineCopyCol( const SwTableLine
*& rpLine
, void* pPara
)
2196 _FndPara
* pFndPara
= (_FndPara
*)pPara
;
2197 _FndLine
* pFndLine
= new _FndLine( (SwTableLine
*)rpLine
, pFndPara
->pFndBox
);
2198 _FndPara
aPara( *pFndPara
, pFndLine
);
2199 pFndLine
->GetLine()->GetTabBoxes().ForEach( &_FndBoxCopyCol
, &aPara
);
2200 if( pFndLine
->GetBoxes().Count() )
2202 pFndPara
->pFndBox
->GetLines().C40_INSERT( _FndLine
, pFndLine
,
2203 pFndPara
->pFndBox
->GetLines().Count() );
2210 void _FndBox::SetTableLines( const SwSelBoxes
&rBoxes
, const SwTable
&rTable
)
2212 //Pointer auf die Lines vor und hinter den zu verarbeitenden Bereich
2213 //setzen. Wenn die erste/letzte Zeile in den Bereich eingeschlossen
2214 //sind, so bleiben die Pointer eben einfach 0.
2215 //Gesucht werden zunachst die Positionen der ersten/letzten betroffenen
2216 //Line im Array der SwTable. Damit die 0 fuer 'keine Line' verwand werden
2217 //kann werden die Positionen um 1 nach oben versetzt!
2219 USHORT nStPos
= USHRT_MAX
;
2222 for ( USHORT i
= 0; i
< rBoxes
.Count(); ++i
)
2224 SwTableLine
*pLine
= rBoxes
[i
]->GetUpper();
2225 while ( pLine
->GetUpper() )
2226 pLine
= pLine
->GetUpper()->GetUpper();
2227 const USHORT nPos
= rTable
.GetTabLines().GetPos(
2228 (const SwTableLine
*&)pLine
) + 1;
2230 ASSERT( nPos
!= USHRT_MAX
, "TableLine not found." );
2235 if( nEndPos
< nPos
)
2239 pLineBefore
= rTable
.GetTabLines()[nStPos
- 2];
2240 if ( nEndPos
< rTable
.GetTabLines().Count() )
2241 pLineBehind
= rTable
.GetTabLines()[nEndPos
];
2244 void _FndBox::SetTableLines( const SwTable
&rTable
)
2246 // Pointer auf die Lines vor und hinter den zu verarbeitenden Bereich
2247 // setzen. Wenn die erste/letzte Zeile in den Bereich eingeschlossen
2248 // sind, so bleiben die Pointer eben einfach 0.
2249 // Die Positionen der ersten/letzten betroffenen Line im Array der
2250 // SwTable steht in der FndBox. Damit die 0 fuer 'keine Line' verwand
2251 // werdenkann werden die Positionen um 1 nach oben versetzt!
2253 if( !GetLines().Count() )
2256 SwTableLine
* pTmpLine
= GetLines()[0]->GetLine();
2257 USHORT nPos
= rTable
.GetTabLines().C40_GETPOS( SwTableLine
, pTmpLine
);
2258 ASSERT( USHRT_MAX
!= nPos
, "Line steht nicht in der Tabelle" );
2260 pLineBefore
= rTable
.GetTabLines()[ nPos
- 1 ];
2262 pTmpLine
= GetLines()[GetLines().Count()-1]->GetLine();
2263 nPos
= rTable
.GetTabLines().C40_GETPOS( SwTableLine
, pTmpLine
);
2264 ASSERT( USHRT_MAX
!= nPos
, "Line steht nicht in der Tabelle" );
2265 if( ++nPos
< rTable
.GetTabLines().Count() )
2266 pLineBehind
= rTable
.GetTabLines()[nPos
];
2269 inline void UnsetFollow( SwFlowFrm
*pTab
)
2271 pTab
->bIsFollow
= FALSE
;
2274 void _FndBox::DelFrms( SwTable
&rTable
)
2276 //Alle Lines zwischen pLineBefore und pLineBehind muessen aus dem
2277 //Layout ausgeschnitten und geloescht werden.
2278 //Entstehen dabei leere Follows so muessen diese vernichtet werden.
2279 //Wird ein Master vernichtet, so muss der Follow Master werden.
2280 //Ein TabFrm muss immer uebrigbleiben.
2283 USHORT nEndPos
= rTable
.GetTabLines().Count() - 1;
2284 if( rTable
.IsNewModel() && pLineBefore
)
2285 rTable
.CheckRowSpan( pLineBefore
, true );
2288 nStPos
= rTable
.GetTabLines().GetPos(
2289 (const SwTableLine
*&)pLineBefore
);
2290 ASSERT( nStPos
!= USHRT_MAX
, "Fuchs Du hast die Line gestohlen!" );
2293 if( rTable
.IsNewModel() && pLineBehind
)
2294 rTable
.CheckRowSpan( pLineBehind
, false );
2297 nEndPos
= rTable
.GetTabLines().GetPos(
2298 (const SwTableLine
*&)pLineBehind
);
2299 ASSERT( nEndPos
!= USHRT_MAX
, "Fuchs Du hast die Line gestohlen!" );
2303 for ( USHORT i
= nStPos
; i
<= nEndPos
; ++i
)
2305 SwFrmFmt
*pFmt
= rTable
.GetTabLines()[i
]->GetFrmFmt();
2306 SwClientIter
aIter( *pFmt
);
2307 SwClient
* pLast
= aIter
.GoStart();
2311 SwFrm
*pFrm
= PTR_CAST( SwFrm
, pLast
);
2313 ((SwRowFrm
*)pFrm
)->GetTabLine() == rTable
.GetTabLines()[i
] )
2316 SwTabFrm
*pUp
= !pFrm
->GetPrev() && !pFrm
->GetNext() ?
2317 (SwTabFrm
*)pFrm
->GetUpper() : 0;
2320 const USHORT nRepeat
=
2321 ((SwTabFrm
*)pFrm
->GetUpper())->GetTable()->GetRowsToRepeat();
2323 ((SwTabFrm
*)pFrm
->GetUpper())->IsFollow() )
2325 if ( !pFrm
->GetNext() )
2327 SwRowFrm
* pFirstNonHeadline
=
2328 ((SwTabFrm
*)pFrm
->GetUpper())->GetFirstNonHeadlineRow();
2329 if ( pFirstNonHeadline
== pFrm
)
2331 pUp
= (SwTabFrm
*)pFrm
->GetUpper();
2338 SwTabFrm
*pFollow
= pUp
->GetFollow();
2339 SwTabFrm
*pPrev
= pUp
->IsFollow() ? pUp
: 0;
2342 SwFrm
*pTmp
= pPrev
->FindPrev();
2343 ASSERT( pTmp
->IsTabFrm(),
2344 "Vorgaenger vom Follow kein Master.");
2345 pPrev
= (SwTabFrm
*)pTmp
;
2349 pPrev
->SetFollow( pFollow
);
2350 // --> FME 2006-01-31 #i60340# Do not transfer the
2351 // flag from pUp to pPrev. pUp may still have the
2352 // flag set although there is not more follow flow
2353 // line associated with pUp.
2354 pPrev
->SetFollowFlowLine( FALSE
);
2358 ::UnsetFollow( pFollow
);
2360 //Ein TabellenFrm muss immer stehenbleiben!
2361 if ( pPrev
|| pFollow
)
2363 // OD 26.08.2003 #i18103# - if table is in a section,
2364 // lock the section, to avoid its delete.
2366 SwSectionFrm
* pSctFrm
= pUp
->FindSctFrm();
2367 bool bOldSectLock
= false;
2370 bOldSectLock
= pSctFrm
->IsColLocked();
2374 if ( pSctFrm
&& !bOldSectLock
)
2376 pSctFrm
->ColUnlock();
2380 bDel
= FALSE
;//Die Row wird mit in den Abgrund
2386 SwFrm
* pTabFrm
= pFrm
->GetUpper();
2387 if ( pTabFrm
->IsTabFrm() &&
2389 ((SwTabFrm
*)pTabFrm
)->GetFollow() )
2391 // We do not delete the follow flow line,
2392 // this will be done automatically in the
2394 ((SwTabFrm
*)pTabFrm
)->SetFollowFlowLine( FALSE
);
2401 } while( 0 != ( pLast
= aIter
++ ));
2406 BOOL
lcl_IsLineOfTblFrm( const SwTabFrm
& rTable
, const SwFrm
& rChk
)
2408 const SwTabFrm
* pTblFrm
= rChk
.FindTabFrm();
2409 if( pTblFrm
->IsFollow() )
2410 pTblFrm
= pTblFrm
->FindMaster( true );
2411 return &rTable
== pTblFrm
;
2415 * lcl_UpdateRepeatedHeadlines
2417 void lcl_UpdateRepeatedHeadlines( SwTabFrm
& rTabFrm
, bool bCalcLowers
)
2419 ASSERT( rTabFrm
.IsFollow(), "lcl_UpdateRepeatedHeadlines called for non-follow tab" )
2421 // Delete remaining headlines:
2422 SwRowFrm
* pLower
= 0;
2423 while ( 0 != ( pLower
= (SwRowFrm
*)rTabFrm
.Lower() ) && pLower
->IsRepeatedHeadline() )
2429 // Insert fresh set of headlines:
2430 pLower
= (SwRowFrm
*)rTabFrm
.Lower();
2431 SwTable
& rTable
= *rTabFrm
.GetTable();
2432 const USHORT nRepeat
= rTable
.GetRowsToRepeat();
2433 for ( USHORT nIdx
= 0; nIdx
< nRepeat
; ++nIdx
)
2435 SwRowFrm
* pHeadline
= new SwRowFrm(
2436 *rTable
.GetTabLines()[ nIdx
] );
2437 pHeadline
->SetRepeatedHeadline( true );
2438 pHeadline
->Paste( &rTabFrm
, pLower
);
2439 pHeadline
->RegistFlys();
2443 rTabFrm
.SetCalcLowers();
2446 void _FndBox::MakeFrms( SwTable
&rTable
)
2448 //Alle Lines zwischen pLineBefore und pLineBehind muessen im Layout
2449 //wieder neu erzeugt werden.
2450 //Und Zwar fuer alle Auspraegungen der Tabelle (mehrere z.B. im Kopf/Fuss).
2453 USHORT nEndPos
= rTable
.GetTabLines().Count() - 1;
2456 nStPos
= rTable
.GetTabLines().GetPos(
2457 (const SwTableLine
*&)pLineBefore
);
2458 ASSERT( nStPos
!= USHRT_MAX
, "Fuchs Du hast die Line gestohlen!" );
2464 nEndPos
= rTable
.GetTabLines().GetPos(
2465 (const SwTableLine
*&)pLineBehind
);
2466 ASSERT( nEndPos
!= USHRT_MAX
, "Fuchs Du hast die Line gestohlen!" );
2469 //Jetzt die grosse Einfuegeoperation fuer alle Tabllen.
2470 SwClientIter
aTabIter( *rTable
.GetFrmFmt() );
2471 for ( SwTabFrm
*pTable
= (SwTabFrm
*)aTabIter
.First( TYPE(SwFrm
) ); pTable
;
2472 pTable
= (SwTabFrm
*)aTabIter
.Next() )
2474 if ( !pTable
->IsFollow() )
2476 SwFrm
*pSibling
= 0;
2477 SwFrm
*pUpperFrm
= 0;
2479 for ( i
= rTable
.GetTabLines().Count()-1;
2480 i
>= 0 && !pSibling
; --i
)
2482 SwTableLine
*pLine
= pLineBehind
? pLineBehind
:
2483 rTable
.GetTabLines()[static_cast<USHORT
>(i
)];
2484 SwClientIter
aIter( *pLine
->GetFrmFmt() );
2485 pSibling
= (SwFrm
*)aIter
.First( TYPE(SwFrm
) );
2486 while ( pSibling
&& (
2487 static_cast<SwRowFrm
*>(pSibling
)->GetTabLine() != pLine
||
2488 !lcl_IsLineOfTblFrm( *pTable
, *pSibling
) ||
2489 static_cast<SwRowFrm
*>(pSibling
)->IsRepeatedHeadline() ||
2490 // --> FME 2005-08-24 #i53647# If !pLineBehind,
2491 // IsInSplitTableRow() should be checked.
2492 ( pLineBehind
&& pSibling
->IsInFollowFlowRow() ) ||
2493 (!pLineBehind
&& pSibling
->IsInSplitTableRow() ) ) )
2496 pSibling
= (SwFrm
*)aIter
.Next();
2501 pUpperFrm
= pSibling
->GetUpper();
2506 // ???? oder das der Letzte Follow der Tabelle ????
2509 for ( i
= nStPos
; (USHORT
)i
<= nEndPos
; ++i
)
2510 ::lcl_InsertRow( *rTable
.GetTabLines()[static_cast<USHORT
>(i
)],
2511 (SwLayoutFrm
*)pUpperFrm
, pSibling
);
2512 if ( pUpperFrm
->IsTabFrm() )
2513 ((SwTabFrm
*)pUpperFrm
)->SetCalcLowers();
2515 else if ( rTable
.GetRowsToRepeat() > 0 )
2517 // Insert new headlines:
2518 lcl_UpdateRepeatedHeadlines( *pTable
, true );
2523 void _FndBox::MakeNewFrms( SwTable
&rTable
, const USHORT nNumber
,
2524 const BOOL bBehind
)
2526 //Frms fuer neu eingefuege Zeilen erzeugen.
2527 //bBehind == TRUE: vor pLineBehind
2528 // == FALSE: hinter pLineBefore
2529 const USHORT nBfPos
= pLineBefore
?
2530 rTable
.GetTabLines().GetPos( (const SwTableLine
*&)pLineBefore
) :
2532 const USHORT nBhPos
= pLineBehind
?
2533 rTable
.GetTabLines().GetPos( (const SwTableLine
*&)pLineBehind
) :
2536 //nNumber: wie oft ist eingefuegt worden.
2537 //nCnt: wieviele sind nNumber mal eingefuegt worden.
2540 ((nBhPos
!= USHRT_MAX
? nBhPos
: rTable
.GetTabLines().Count()) -
2541 (nBfPos
!= USHRT_MAX
? nBfPos
+ 1 : 0)) / (nNumber
+ 1);
2543 //Den Master-TabFrm suchen
2544 SwClientIter
aTabIter( *rTable
.GetFrmFmt() );
2546 for ( pTable
= (SwTabFrm
*)aTabIter
.First( TYPE(SwFrm
) ); pTable
;
2547 pTable
= (SwTabFrm
*)aTabIter
.Next() )
2549 if( !pTable
->IsFollow() )
2551 SwFrm
*pSibling
= 0;
2552 SwLayoutFrm
*pUpperFrm
= 0;
2557 SwClientIter
aIter( *pLineBehind
->GetFrmFmt() );
2558 pSibling
= (SwFrm
*)aIter
.First( TYPE(SwFrm
) );
2559 while ( pSibling
&& (
2560 // only consider row frames associated with pLineBehind:
2561 static_cast<SwRowFrm
*>(pSibling
)->GetTabLine() != pLineBehind
||
2562 // only consider row frames that are in pTables Master-Follow chain:
2563 !lcl_IsLineOfTblFrm( *pTable
, *pSibling
) ||
2564 // only consider row frames that are not repeated headlines:
2565 static_cast<SwRowFrm
*>(pSibling
)->IsRepeatedHeadline() ||
2566 // only consider row frames that are not follow flow rows
2567 pSibling
->IsInFollowFlowRow() ) )
2569 pSibling
= (SwFrm
*)aIter
.Next();
2573 pUpperFrm
= pSibling
->GetUpper();
2576 while( pTable
->GetFollow() )
2577 pTable
= pTable
->GetFollow();
2580 const USHORT nMax
= nBhPos
!= USHRT_MAX
?
2581 nBhPos
: rTable
.GetTabLines().Count();
2583 USHORT i
= nBfPos
!= USHRT_MAX
? nBfPos
+ 1 + nCnt
: nCnt
;
2585 for ( ; i
< nMax
; ++i
)
2586 ::lcl_InsertRow( *rTable
.GetTabLines()[i
], pUpperFrm
, pSibling
);
2587 if ( pUpperFrm
->IsTabFrm() )
2588 ((SwTabFrm
*)pUpperFrm
)->SetCalcLowers();
2590 else //davor einfuegen
2594 // We are looking for the frame that is behind the row frame
2595 // that should be inserted.
2596 for ( i
= 0; !pSibling
; ++i
)
2598 SwTableLine
* pLine
= pLineBefore
? pLineBefore
: rTable
.GetTabLines()[i
];
2600 SwClientIter
aIter( *pLine
->GetFrmFmt() );
2601 pSibling
= (SwFrm
*)aIter
.First( TYPE(SwFrm
) );
2603 while ( pSibling
&& (
2604 // only consider row frames associated with pLineBefore:
2605 static_cast<SwRowFrm
*>(pSibling
)->GetTabLine() != pLine
||
2606 // only consider row frames that are in pTables Master-Follow chain:
2607 !lcl_IsLineOfTblFrm( *pTable
, *pSibling
) ||
2608 // only consider row frames that are not repeated headlines:
2609 static_cast<SwRowFrm
*>(pSibling
)->IsRepeatedHeadline() ||
2610 // 1. case: pLineBefore == 0:
2611 // only consider row frames that are not follow flow rows
2612 // 2. case: pLineBefore != 0:
2613 // only consider row frames that are not split table rows
2614 // --> FME 2004-11-23 #i37476# If !pLineBefore,
2615 // check IsInFollowFlowRow instead of IsInSplitTableRow.
2616 ( ( !pLineBefore
&& pSibling
->IsInFollowFlowRow() ) ||
2617 ( pLineBefore
&& pSibling
->IsInSplitTableRow() ) ) ) )
2620 pSibling
= (SwFrm
*)aIter
.Next();
2624 pUpperFrm
= pSibling
->GetUpper();
2626 pSibling
= pSibling
->GetNext();
2628 USHORT nMax
= nBhPos
!= USHRT_MAX
?
2630 rTable
.GetTabLines().Count() - nCnt
;
2632 i
= nBfPos
!= USHRT_MAX
? nBfPos
+ 1 : 0;
2633 for ( ; i
< nMax
; ++i
)
2634 ::lcl_InsertRow( *rTable
.GetTabLines()[i
],
2635 pUpperFrm
, pSibling
);
2636 if ( pUpperFrm
->IsTabFrm() )
2637 ((SwTabFrm
*)pUpperFrm
)->SetCalcLowers();
2642 //Die Headlines mussen ggf. auch verarbeitet werden. Um gut arbeitenden
2643 //Code nicht zu zerfasern wird hier nochmals iteriert.
2644 const USHORT nRowsToRepeat
= rTable
.GetRowsToRepeat();
2645 if ( nRowsToRepeat
> 0 &&
2646 ( ( !bBehind
&& ( nBfPos
== USHRT_MAX
|| nBfPos
+ 1 < nRowsToRepeat
) ) ||
2647 ( bBehind
&& ( ( nBfPos
== USHRT_MAX
&& nRowsToRepeat
> 1 ) || nBfPos
+ 2 < nRowsToRepeat
) ) ) )
2649 for ( pTable
= (SwTabFrm
*)aTabIter
.First( TYPE(SwFrm
) ); pTable
;
2650 pTable
= (SwTabFrm
*)aTabIter
.Next() )
2652 if ( pTable
->Lower() )
2654 if ( pTable
->IsFollow() )
2656 lcl_UpdateRepeatedHeadlines( *pTable
, true );
2659 ASSERT( ((SwRowFrm
*)pTable
->Lower())->GetTabLine() ==
2660 rTable
.GetTabLines()[0], "MakeNewFrms: Table corruption!" )
2666 BOOL
_FndBox::AreLinesToRestore( const SwTable
&rTable
) const
2668 //Lohnt es sich MakeFrms zu rufen?
2670 if ( !pLineBefore
&& !pLineBehind
&& rTable
.GetTabLines().Count() )
2676 const SwTableLine
* rLBefore
= (const SwTableLine
*)pLineBefore
;
2677 nBfPos
= rTable
.GetTabLines().GetPos( rLBefore
);
2685 const SwTableLine
* rLBehind
= (const SwTableLine
*)pLineBehind
;
2686 nBhPos
= rTable
.GetTabLines().GetPos( rLBehind
);
2691 if ( nBfPos
== nBhPos
) //Duerfte eigentlich nie vorkommen.
2693 ASSERT( FALSE
, "Table, Loeschen auf keinem Bereich !?!" );
2697 if ( rTable
.GetRowsToRepeat() > 0 )
2699 // ups. sollte unsere zu wiederholende Kopfzeile geloescht worden
2701 SwClientIter
aIter( *rTable
.GetFrmFmt() );
2702 for( SwTabFrm
* pTable
= (SwTabFrm
*)aIter
.First( TYPE( SwFrm
));
2703 pTable
; pTable
= (SwTabFrm
*)aIter
.Next() )
2705 if( pTable
->IsFollow() )
2707 // Insert new headlines:
2708 lcl_UpdateRepeatedHeadlines( *pTable
, false );
2713 // Some adjacent lines at the beginning of the table have been deleted:
2714 if ( nBfPos
== USHRT_MAX
&& nBhPos
== 0 )
2717 // Some adjacent lines at the end of the table have been deleted:
2718 if ( nBhPos
== USHRT_MAX
&& nBfPos
== (rTable
.GetTabLines().Count() - 1) )
2721 // Some adjacent lines in the middle of the table have been deleted:
2722 if ( nBfPos
!= USHRT_MAX
&& nBhPos
!= USHRT_MAX
&& (nBfPos
+ 1) == nBhPos
)
2725 // The structure of the deleted lines is more complex due to split lines.
2726 // A call of MakeFrms() is necessary.