xref: /aoo41x/main/sw/source/core/layout/tabfrm.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 #include "pagefrm.hxx"
31 #include "rootfrm.hxx"
32 #include "cntfrm.hxx"
33 #include "viewsh.hxx"
34 #include "doc.hxx"
35 #include "docsh.hxx"
36 #include "viewimp.hxx"
37 #include "swtable.hxx"
38 #include "dflyobj.hxx"
39 #include "flyfrm.hxx"
40 #include "frmtool.hxx"
41 #include "frmfmt.hxx"
42 #include "dcontact.hxx"
43 #include <anchoreddrawobject.hxx>
44 #include <fmtanchr.hxx>
45 #include "viewopt.hxx"
46 #include "hints.hxx"
47 #include "dbg_lay.hxx"
48 #include <ftnidx.hxx>
49 #include <svl/itemiter.hxx>
50 #include <docary.hxx>
51 #include <editeng/keepitem.hxx>
52 #include <editeng/ulspitem.hxx>
53 #include <editeng/lrspitem.hxx>
54 #include <editeng/brshitem.hxx>
55 #include <editeng/boxitem.hxx>
56 #include <vcl/outdev.hxx>
57 #include <fmtlsplt.hxx>
58 #include <fmtrowsplt.hxx>
59 #include <fmtsrnd.hxx>
60 #include <fmtornt.hxx>
61 #include <fmtpdsc.hxx>
62 #include <fmtfsize.hxx>
63 #include <swtblfmt.hxx>
64 #include <ndtxt.hxx>
65 #include "tabfrm.hxx"
66 #include "rowfrm.hxx"
67 #include "cellfrm.hxx"
68 #include "flyfrms.hxx"
69 #include "txtfrm.hxx"		//HasFtn()
70 #include "htmltbl.hxx"
71 #include "sectfrm.hxx"	//SwSectionFrm
72 #include <fmtfollowtextflow.hxx>
73 #include <sortedobjs.hxx>
74 #include <objectformatter.hxx>
75 #include <layouter.hxx>
76 #include <switerator.hxx>
77 
78 extern void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
79 						SwFrm *pFrm, SwPageFrm *pPage );
80 
81 using namespace ::com::sun::star;
82 
83 
84 /*************************************************************************
85 |*
86 |*	SwTabFrm::SwTabFrm(), ~SwTabFrm()
87 |*
88 |*	Ersterstellung		MA 09. Mar. 93
89 |*	Letzte Aenderung	MA 30. May. 96
90 |*
91 |*************************************************************************/
92 SwTabFrm::SwTabFrm( SwTable &rTab, SwFrm* pSib ):
93 	SwLayoutFrm( rTab.GetFrmFmt(), pSib ),
94 	SwFlowFrm( (SwFrm&)*this ),
95     pTable( &rTab )
96 {
97 	bComplete = bCalcLowers = bONECalcLowers = bLowersFormatted = bLockBackMove =
98     bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
99     bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
100     // --> OD 2004-10-04 #i26945#
101     bConsiderObjsForMinCellHeight = sal_True;
102     bObjsDoesFit = sal_True;
103     // <--
104     bFixSize = sal_False;     //Nicht nochmal auf die Importfilter hereinfallen.
105     nType = FRMC_TAB;
106 
107 	//Gleich die Zeilen erzeugen und einfuegen.
108 	const SwTableLines &rLines = rTab.GetTabLines();
109     SwFrm *pTmpPrev = 0;
110 	for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
111 	{
112 		SwRowFrm *pNew = new SwRowFrm( *rLines[i], this );
113 		if( pNew->Lower() )
114 		{
115             pNew->InsertBehind( this, pTmpPrev );
116             pTmpPrev = pNew;
117 		}
118 		else
119 			delete pNew;
120 	}
121 	ASSERT( Lower() && Lower()->IsRowFrm(), "SwTabFrm::SwTabFrm: No rows." );
122 }
123 
124 SwTabFrm::SwTabFrm( SwTabFrm &rTab ) :
125 	SwLayoutFrm( rTab.GetFmt(), &rTab ),
126 	SwFlowFrm( (SwFrm&)*this ),
127     pTable( rTab.GetTable() )
128 {
129 	bIsFollow = sal_True;
130 	bLockJoin = bComplete = bONECalcLowers = bCalcLowers = bLowersFormatted = bLockBackMove =
131     bResizeHTMLTable = bHasFollowFlowLine = bIsRebuildLastLine =
132     bRestrictTableGrowth = bRemoveFollowFlowLinePending = sal_False;
133     // --> OD 2004-10-04 #i26945#
134     bConsiderObjsForMinCellHeight = sal_True;
135     bObjsDoesFit = sal_True;
136     // <--
137     bFixSize = sal_False;     //Nicht nochmal auf die Importfilter hereinfallen.
138     nType = FRMC_TAB;
139 
140 	SetFollow( rTab.GetFollow() );
141 	rTab.SetFollow( this );
142 }
143 
144 extern const SwTable   *pColumnCacheLastTable;
145 extern const SwTabFrm  *pColumnCacheLastTabFrm;
146 extern const SwFrm     *pColumnCacheLastCellFrm;
147 extern const SwTable   *pRowCacheLastTable;
148 extern const SwTabFrm  *pRowCacheLastTabFrm;
149 extern const SwFrm     *pRowCacheLastCellFrm;
150 
151 SwTabFrm::~SwTabFrm()
152 {
153     // There is some terrible code in fetab.cxx, that
154     // makes use of these global pointers. Obviously
155     // this code did not consider that a TabFrm can be
156     // deleted.
157     if ( this == pColumnCacheLastTabFrm )
158     {
159         pColumnCacheLastTable  = NULL;
160         pColumnCacheLastTabFrm = NULL;
161         pColumnCacheLastCellFrm= NULL;
162         pRowCacheLastTable  = NULL;
163         pRowCacheLastTabFrm = NULL;
164         pRowCacheLastCellFrm= NULL;
165     }
166 }
167 
168 /*************************************************************************
169 |*
170 |*	SwTabFrm::JoinAndDelFollows()
171 |*
172 |*	Ersterstellung		MA 30. May. 96
173 |*	Letzte Aenderung	MA 30. May. 96
174 |*
175 |*************************************************************************/
176 void SwTabFrm::JoinAndDelFollows()
177 {
178 	SwTabFrm *pFoll = GetFollow();
179 	if ( pFoll->HasFollow() )
180 		pFoll->JoinAndDelFollows();
181 	pFoll->Cut();
182 	SetFollow( pFoll->GetFollow() );
183 	delete pFoll;
184 }
185 
186 /*************************************************************************
187 |*
188 |*	SwTabFrm::RegistFlys()
189 |*
190 |*	Ersterstellung		MA 08. Jul. 93
191 |*	Letzte Aenderung	MA 27. Jan. 99
192 |*
193 |*************************************************************************/
194 void SwTabFrm::RegistFlys()
195 {
196 	ASSERT( Lower() && Lower()->IsRowFrm(), "Keine Zeilen." );
197 
198 	SwPageFrm *pPage = FindPageFrm();
199 	if ( pPage )
200 	{
201 		SwRowFrm *pRow = (SwRowFrm*)Lower();
202 		do
203 		{
204             pRow->RegistFlys( pPage );
205 			pRow = (SwRowFrm*)pRow->GetNext();
206 		} while ( pRow );
207 	}
208 }
209 
210 /*************************************************************************
211 |*  Some prototypes
212 |*************************************************************************/
213 void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom );
214 void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom );
215 sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva );
216 // --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
217 // that only row and cell frames are formatted.
218 sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm,
219                                       long nBottom,
220                                       bool _bOnlyRowsAndCells = false );
221 // <--
222 // OD 2004-02-18 #106629# - correct type of 1st parameter
223 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
224 // control, if floating screen objects have to be considered for the minimal
225 // cell height.
226 SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm *pRow,
227                                           const sal_Bool _bConsiderObjs );
228 // <--
229 SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm&, const SwBorderAttrs& );
230 
231 /*************************************************************************
232 |*  START: local helper functions for repeated headlines
233 |*************************************************************************/
234 
235 SwTwips lcl_GetHeightOfRows( const SwFrm* pStart, long nCount )
236 {
237     if ( !nCount || !pStart)
238         return 0;
239 
240     SwTwips nRet = 0;
241     SWRECTFN( pStart )
242     while ( pStart && nCount > 0 )
243     {
244         nRet += (pStart->Frm().*fnRect->fnGetHeight)();
245         pStart = pStart->GetNext();
246         --nCount;
247     }
248 
249     return nRet;
250 }
251 
252 /*************************************************************************
253 |*  END: local helper functions for repeated headlines
254 |*************************************************************************/
255 
256 /*************************************************************************
257 |*  START: local helper functions for splitting row frames
258 |*************************************************************************/
259 
260 //
261 // Local helper function to insert a new follow flow line
262 //
263 SwRowFrm* lcl_InsertNewFollowFlowLine( SwTabFrm& rTab, const SwFrm& rTmpRow, bool bRowSpanLine )
264 {
265     ASSERT( rTmpRow.IsRowFrm(), "No row frame to copy for FollowFlowLine" )
266     const SwRowFrm& rRow = (SwRowFrm&)rTmpRow;
267 
268     rTab.SetFollowFlowLine( sal_True );
269     SwRowFrm *pFollowFlowLine = new SwRowFrm(*rRow.GetTabLine(), &rTab, false );
270     pFollowFlowLine->SetRowSpanLine( bRowSpanLine );
271     SwFrm* pFirstRow = rTab.GetFollow()->GetFirstNonHeadlineRow();
272     pFollowFlowLine->InsertBefore( rTab.GetFollow(), pFirstRow );
273     return pFollowFlowLine;
274 }
275 
276 // --> OD 2004-11-05 #i26945# - local helper function to invalidate all lower
277 // objects. By parameter <_bMoveObjsOutOfRange> it can be controlled, if
278 // additionally the objects are moved 'out of range'.
279 void lcl_InvalidateLowerObjs( SwLayoutFrm& _rLayoutFrm,
280                               const bool _bMoveObjsOutOfRange = false,
281                               SwPageFrm* _pPageFrm = 0L )
282 {
283     // determine page frame, if needed
284     if ( !_pPageFrm )
285     {
286         _pPageFrm = _rLayoutFrm.FindPageFrm();
287         ASSERT( _pPageFrm,
288                 "<lcl_InvalidateLowerObjs(..)> - missing page frame -> no move of lower objects out of range" );
289         if ( !_pPageFrm )
290         {
291             return;
292         }
293     }
294 
295     // loop on lower frames
296     SwFrm* pLowerFrm = _rLayoutFrm.Lower();
297     while ( pLowerFrm )
298     {
299         if ( pLowerFrm->IsLayoutFrm() )
300         {
301             ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pLowerFrm)),
302                                        _bMoveObjsOutOfRange, _pPageFrm );
303         }
304         if ( pLowerFrm->GetDrawObjs() )
305         {
306             for ( sal_uInt16 i = 0; i < pLowerFrm->GetDrawObjs()->Count(); ++i )
307             {
308                 SwAnchoredObject* pAnchoredObj = (*pLowerFrm->GetDrawObjs())[i];
309 
310                 // invalidate position of anchored object
311                 pAnchoredObj->SetTmpConsiderWrapInfluence( false );
312                 pAnchoredObj->SetConsiderForTextWrap( false );
313                 pAnchoredObj->UnlockPosition();
314                 pAnchoredObj->InvalidateObjPos();
315 
316                 // move anchored object 'out of range'
317                 if ( _bMoveObjsOutOfRange )
318                 {
319                     // indicate, that positioning is progress to avoid
320                     // modification of the anchored object resp. its attributes
321                     // due to the movement
322                     SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
323                     pAnchoredObj->SetObjLeft( _pPageFrm->Frm().Right() );
324                     // --> OD 2004-11-24 #115759# - reset character rectangle,
325                     // top of line and relative position in order to assure,
326                     // that anchored object is correctly positioned.
327                     pAnchoredObj->ClearCharRectAndTopOfLine();
328                     pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
329                     if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
330                             == FLY_AS_CHAR )
331                     {
332                         pAnchoredObj->AnchorFrm()
333                                 ->Prepare( PREP_FLY_ATTR_CHG,
334                                            &(pAnchoredObj->GetFrmFmt()) );
335                     }
336                     // <--
337                     if ( pAnchoredObj->ISA(SwFlyFrm) )
338                     {
339                         SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
340                         pFly->GetVirtDrawObj()->SetRectsDirty();
341                         pFly->GetVirtDrawObj()->SetChanged();
342                     }
343                 }
344 
345                 // If anchored object is a fly frame, invalidate its lower objects
346                 if ( pAnchoredObj->ISA(SwFlyFrm) )
347                 {
348                     SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
349                     ::lcl_InvalidateLowerObjs( *pFly, _bMoveObjsOutOfRange, _pPageFrm );
350                 }
351             }
352         }
353         pLowerFrm = pLowerFrm->GetNext();
354     }
355 }
356 // <--
357 //
358 // Local helper function to shrink all lowers of rRow to 0 height
359 //
360 void lcl_ShrinkCellsAndAllContent( SwRowFrm& rRow )
361 {
362     SwCellFrm* pCurrMasterCell = static_cast<SwCellFrm*>(rRow.Lower());
363     SWRECTFN( pCurrMasterCell )
364 
365     while ( pCurrMasterCell )
366     {
367         // NEW TABLES
368         SwCellFrm& rToAdjust = pCurrMasterCell->GetTabBox()->getRowSpan() < 1 ?
369                                const_cast<SwCellFrm&>(pCurrMasterCell->FindStartEndOfRowSpanCell( true, true )) :
370                                *pCurrMasterCell;
371 
372         // --> OD 2004-10-04 #i26945#
373         // all lowers should have the correct position
374         lcl_ArrangeLowers( &rToAdjust,
375                            (rToAdjust.*fnRect->fnGetPrtTop)(),
376                            sal_False );
377         // <--
378         // TODO: Optimize number of frames which are set to 0 height
379         // we have to start with the last lower frame, otherwise
380         // the shrink will not shrink the current cell
381         SwFrm* pTmp = rToAdjust.GetLastLower();
382 
383         if ( pTmp && pTmp->IsRowFrm() )
384         {
385             SwRowFrm* pTmpRow = (SwRowFrm*)pTmp;
386             lcl_ShrinkCellsAndAllContent( *pTmpRow );
387         }
388         else
389         {
390             // TODO: Optimize number of frames which are set to 0 height
391             while ( pTmp )
392             {
393                 // the frames have to be shrunk
394                 if ( pTmp && pTmp->IsTabFrm() )
395                 {
396                     SwRowFrm* pTmpRow = (SwRowFrm*)((SwTabFrm*)pTmp)->Lower();
397                     while ( pTmpRow )
398                     {
399                         lcl_ShrinkCellsAndAllContent( *pTmpRow );
400                         pTmpRow = (SwRowFrm*)pTmpRow->GetNext();
401                     }
402                 }
403                 else
404                 {
405                     pTmp->Shrink( (pTmp->Frm().*fnRect->fnGetHeight)() );
406                     (pTmp->Prt().*fnRect->fnSetTop)( 0 );
407                     (pTmp->Prt().*fnRect->fnSetHeight)( 0 );
408                 }
409 
410                 pTmp = pTmp->GetPrev();
411             }
412 
413             // all lowers should have the correct position
414             lcl_ArrangeLowers( &rToAdjust,
415                                (rToAdjust.*fnRect->fnGetPrtTop)(),
416                                sal_False );
417         }
418 
419         pCurrMasterCell = static_cast<SwCellFrm*>(pCurrMasterCell->GetNext());
420     }
421 }
422 
423 //
424 // Local helper function to move the content from rSourceLine to rDestLine
425 // The content is inserted behind the last content in the corresponding
426 // cell in rDestLine.
427 //
428 void lcl_MoveRowContent( SwRowFrm& rSourceLine, SwRowFrm& rDestLine )
429 {
430     SwCellFrm* pCurrDestCell = (SwCellFrm*)rDestLine.Lower();
431     SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
432 
433     // Move content of follow cells into master cells
434     while ( pCurrSourceCell )
435     {
436         if ( pCurrSourceCell->Lower() && pCurrSourceCell->Lower()->IsRowFrm() )
437         {
438             SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
439             while ( pTmpSourceRow )
440             {
441                 // --> FME 2006-01-10 #125926# Achtung! It is possible,
442                 // that pTmpSourceRow->IsFollowFlowRow() but pTmpDestRow
443                 // cannot be found. In this case, we have to move the complete
444                 // row.
445                 SwRowFrm* pTmpDestRow = (SwRowFrm*)pCurrDestCell->Lower();
446                 // <--
447 
448                 if ( pTmpSourceRow->IsFollowFlowRow() && pTmpDestRow )
449                 {
450                     // move content from follow flow row to pTmpDestRow:
451                     while ( pTmpDestRow->GetNext() )
452                         pTmpDestRow = (SwRowFrm*)pTmpDestRow->GetNext();
453 
454                     ASSERT( pTmpDestRow->GetFollowRow() == pTmpSourceRow, "Knoten in der Tabelle" )
455 
456                     lcl_MoveRowContent( *pTmpSourceRow, *pTmpDestRow );
457                     pTmpDestRow->SetFollowRow( pTmpSourceRow->GetFollowRow() );
458                     pTmpSourceRow->Remove();
459                     delete pTmpSourceRow;
460                 }
461                 else
462                 {
463                     // move complete row:
464                     pTmpSourceRow->Remove();
465                     pTmpSourceRow->InsertBefore( pCurrDestCell, 0 );
466                 }
467 
468                 pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
469             }
470         }
471         else
472         {
473             SwFrm *pTmp = ::SaveCntnt( (SwCellFrm*)pCurrSourceCell );
474             if ( pTmp )
475             {
476                 // NEW TABLES
477                 SwCellFrm* pDestCell = static_cast<SwCellFrm*>(pCurrDestCell);
478                 if ( pDestCell->GetTabBox()->getRowSpan() < 1 )
479                     pDestCell = & const_cast<SwCellFrm&>(pDestCell->FindStartEndOfRowSpanCell( true, true ));
480 
481                 // Find last content
482                 SwFrm* pFrm = pDestCell->GetLastLower();
483                 ::RestoreCntnt( pTmp, pDestCell, pFrm, true );
484             }
485         }
486         pCurrDestCell = (SwCellFrm*)pCurrDestCell->GetNext();
487         pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
488     }
489 }
490 
491 //
492 // Local helper function to move all footnotes in rRowFrm from
493 // the footnote boss of rSource to the footnote boss of rDest.
494 //
495 void lcl_MoveFootnotes( SwTabFrm& rSource, SwTabFrm& rDest, SwLayoutFrm& rRowFrm )
496 {
497     if ( 0 != rSource.GetFmt()->GetDoc()->GetFtnIdxs().Count() )
498     {
499         SwFtnBossFrm* pOldBoss = rSource.FindFtnBossFrm( sal_True );
500         SwFtnBossFrm* pNewBoss = rDest.FindFtnBossFrm( sal_True );
501         rRowFrm.MoveLowerFtns( 0, pOldBoss, pNewBoss, sal_True );
502     }
503 }
504 
505 //
506 // Local helper function to handle nested table cells before the split process
507 //
508 void lcl_PreprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine,
509                                 SwRowFrm& rFollowFlowLine, SwTwips nRemain )
510 {
511     SwCellFrm* pCurrLastLineCell = (SwCellFrm*)rLastLine.Lower();
512     SwCellFrm* pCurrFollowFlowLineCell = (SwCellFrm*)rFollowFlowLine.Lower();
513 
514     SWRECTFN( pCurrLastLineCell )
515 
516     //
517     // Move content of follow cells into master cells
518     //
519     while ( pCurrLastLineCell )
520     {
521         if ( pCurrLastLineCell->Lower() && pCurrLastLineCell->Lower()->IsRowFrm() )
522         {
523             SwTwips nTmpCut = nRemain;
524             SwRowFrm* pTmpLastLineRow = (SwRowFrm*)pCurrLastLineCell->Lower();
525 
526             // --> OD 2004-10-04 #i26945#
527             SwTwips nCurrentHeight =
528                     lcl_CalcMinRowHeight( pTmpLastLineRow,
529                                           rTab.IsConsiderObjsForMinCellHeight() );
530             // <--
531             while ( pTmpLastLineRow && pTmpLastLineRow->GetNext() && nTmpCut > nCurrentHeight )
532             {
533                 nTmpCut -= nCurrentHeight;
534                 pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
535                 // --> OD 2004-10-04 #i26945#
536                 nCurrentHeight =
537                     lcl_CalcMinRowHeight( pTmpLastLineRow,
538                                           rTab.IsConsiderObjsForMinCellHeight() );
539                 // <--
540             }
541 
542             //
543             // pTmpLastLineRow does not fit to the line or it is the last line
544             //
545             if ( pTmpLastLineRow )
546             {
547                 //
548                 // Check if we can move pTmpLastLineRow to the follow table,
549                 // or if we have to split the line:
550                 //
551                 SwFrm* pCell = pTmpLastLineRow->Lower();
552                 bool bTableLayoutToComplex = false;
553                 long nMinHeight = 0;
554 
555                 //
556                 // We have to take into account:
557                 // 1. The fixed height of the row
558                 // 2. The borders of the cells inside the row
559                 // 3. The minimum height of the row
560                 //
561                 if ( pTmpLastLineRow->HasFixSize() )
562                     nMinHeight = (pTmpLastLineRow->Frm().*fnRect->fnGetHeight)();
563                 else
564                 {
565                     while ( pCell )
566                     {
567                         if ( ((SwCellFrm*)pCell)->Lower() &&
568                              ((SwCellFrm*)pCell)->Lower()->IsRowFrm() )
569                         {
570                             bTableLayoutToComplex = true;
571                             break;
572                         }
573 
574                 		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
575 	        	        const SwBorderAttrs &rAttrs = *aAccess.Get();
576                         nMinHeight = Max( nMinHeight, lcl_CalcTopAndBottomMargin( *(SwLayoutFrm*)pCell, rAttrs ) );
577                         pCell = pCell->GetNext();
578                     }
579 
580                 	const SwFmtFrmSize &rSz = pTmpLastLineRow->GetFmt()->GetFrmSize();
581                     if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE )
582 		                nMinHeight = Max( nMinHeight, rSz.GetHeight() );
583                 }
584 
585                 //
586                 // 1. Case:
587                 // The line completely fits into the master table.
588                 // Nevertheless, we build a follow (otherwise painting problems
589                 // with empty cell).
590                 //
591                 // 2. Case:
592                 // The line has to be split, the minimum height still fits into
593                 // the master table, and the table structure is not to complex.
594                 //
595                 if ( nTmpCut > nCurrentHeight ||
596                      ( pTmpLastLineRow->IsRowSplitAllowed() &&
597                       !bTableLayoutToComplex && nMinHeight < nTmpCut ) )
598                 {
599                     // The line has to be split:
600                     SwRowFrm* pNewRow = new SwRowFrm( *pTmpLastLineRow->GetTabLine(), &rTab, false );
601                     pNewRow->SetFollowFlowRow( true );
602                     pNewRow->SetFollowRow( pTmpLastLineRow->GetFollowRow() );
603                     pTmpLastLineRow->SetFollowRow( pNewRow );
604                     pNewRow->InsertBehind( pCurrFollowFlowLineCell, 0 );
605                     pTmpLastLineRow = (SwRowFrm*)pTmpLastLineRow->GetNext();
606                 }
607 
608                 //
609                 // The following lines have to be moved:
610                 //
611                 while ( pTmpLastLineRow )
612                 {
613                     SwRowFrm* pTmp = (SwRowFrm*)pTmpLastLineRow->GetNext();
614                     lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pTmpLastLineRow );
615                     pTmpLastLineRow->Remove();
616                     pTmpLastLineRow->InsertBefore( pCurrFollowFlowLineCell, 0 );
617                     pTmpLastLineRow->Shrink( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
618                     pCurrFollowFlowLineCell->Grow( ( pTmpLastLineRow->Frm().*fnRect->fnGetHeight)() );
619                     pTmpLastLineRow = pTmp;
620                 }
621             }
622         }
623 
624         pCurrLastLineCell = (SwCellFrm*)pCurrLastLineCell->GetNext();
625         pCurrFollowFlowLineCell = (SwCellFrm*)pCurrFollowFlowLineCell->GetNext();
626     }
627 }
628 
629 //
630 // Local helper function to handle nested table cells after the split process
631 //
632 void lcl_PostprocessRowsInCells( SwTabFrm& rTab, SwRowFrm& rLastLine )
633 {
634     SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
635     while ( pCurrMasterCell )
636     {
637         if ( pCurrMasterCell->Lower() &&
638              pCurrMasterCell->Lower()->IsRowFrm() )
639         {
640             SwRowFrm* pRowFrm = static_cast<SwRowFrm*>(pCurrMasterCell->GetLastLower());
641 
642             if ( NULL != pRowFrm->GetPrev() && !pRowFrm->ContainsCntnt() )
643             {
644                 ASSERT( pRowFrm->GetFollowRow(), "Deleting row frame without follow" )
645 
646                 // The footnotes have to be moved:
647                 lcl_MoveFootnotes( rTab, *rTab.GetFollow(), *pRowFrm );
648                 pRowFrm->Cut();
649                 SwRowFrm* pFollowRow = pRowFrm->GetFollowRow();
650                 pRowFrm->Paste( pFollowRow->GetUpper(), pFollowRow );
651                 pRowFrm->SetFollowRow( pFollowRow->GetFollowRow() );
652                 lcl_MoveRowContent( *pFollowRow, *pRowFrm );
653                 pFollowRow->Cut();
654                 delete pFollowRow;
655                 ::SwInvalidateAll( pCurrMasterCell, LONG_MAX );
656             }
657         }
658 
659         pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
660     }
661 }
662 
663 //
664 // Local helper function to re-calculate the split line.
665 //
666 inline void TableSplitRecalcLock( SwFlowFrm *pTab ) { pTab->LockJoin(); }
667 inline void TableSplitRecalcUnlock( SwFlowFrm *pTab ) { pTab->UnlockJoin(); }
668 
669 bool lcl_RecalcSplitLine( SwRowFrm& rLastLine, SwRowFrm& rFollowLine,
670                           SwTwips nRemainingSpaceForLastRow )
671 {
672     bool bRet = true;
673 
674     SwTabFrm& rTab = (SwTabFrm&)*rLastLine.GetUpper();
675 
676     //
677     // If there are nested cells in rLastLine, the recalculation of the last
678     // line needs some preprocessing.
679     //
680     lcl_PreprocessRowsInCells( rTab, rLastLine, rFollowLine, nRemainingSpaceForLastRow );
681 
682     //
683     // Here the recalculation process starts:
684     //
685     rTab.SetRebuildLastLine( sal_True );
686     // --> OD 2004-10-15 #i26945#
687     rTab.SetDoesObjsFit( sal_True );
688     // <--
689     SWRECTFN( rTab.GetUpper() )
690 
691     // --> OD 2004-11-05 #i26945# - invalidate and move floating screen
692     // objects 'out of range'
693     ::lcl_InvalidateLowerObjs( rLastLine, true );
694     // <--
695     //
696     // manipulate row and cell sizes
697     //
698     // --> OD 2004-10-04 #i26945# - Do *not* consider floating screen objects
699     // for the minimal cell height.
700     rTab.SetConsiderObjsForMinCellHeight( sal_False );
701     ::lcl_ShrinkCellsAndAllContent( rLastLine );
702     rTab.SetConsiderObjsForMinCellHeight( sal_True );
703     // <--
704 
705     //
706     // invalidate last line
707     //
708     ::SwInvalidateAll( &rLastLine, LONG_MAX );
709 
710     //
711     // Lock this tab frame and its follow
712     //
713     bool bUnlockMaster = false;
714     bool bUnlockFollow = false;
715     SwTabFrm* pMaster = rTab.IsFollow() ? (SwTabFrm*)rTab.FindMaster() : 0;
716     if ( pMaster && !pMaster->IsJoinLocked() )
717     {
718         bUnlockMaster = true;
719         ::TableSplitRecalcLock( pMaster );
720     }
721     if ( !rTab.GetFollow()->IsJoinLocked() )
722     {
723         bUnlockFollow = true;
724         ::TableSplitRecalcLock( rTab.GetFollow() );
725     }
726 
727     //
728     // TODO: e.g., for i71806: What shall we do if the table already
729     // exceeds its upper? I think we have to adjust the heights of the
730     // table, rLastRow and all cells in rLastRow
731     //
732     /*SwTwips nDistanceToUpperPrtBottom =
733             (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)());
734 
735     if ( nDistanceToUpperPrtBottom < 0 )
736     {
737         (rTab.Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
738         (rTab.Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
739 
740         (rLastLine.Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
741         (rLastLine.Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
742 
743         SwFrm* pTmpCell = rLastLine.Lower();
744         while ( pTmpCell )
745         {
746             (pTmpCell->Frm().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
747             (pTmpCell->Prt().*fnRect->fnAddBottom)( nDistanceToUpperPrtBottom );
748 
749             pTmpCell = pTmpCell->GetNext();
750         }
751     }*/
752 
753     //
754     // Do the recalculation
755     //
756     lcl_RecalcRow( rLastLine, LONG_MAX );
757     // --> OD 2004-11-23 #115759# - force a format of the last line in order to
758     // get the correct height.
759     rLastLine.InvalidateSize();
760     rLastLine.Calc();
761     // <--
762 
763     //
764     // Unlock this tab frame and its follow
765     //
766     if ( bUnlockFollow )
767         ::TableSplitRecalcUnlock( rTab.GetFollow() );
768     if ( bUnlockMaster )
769         ::TableSplitRecalcUnlock( pMaster );
770 
771     //
772     // If there are nested cells in rLastLine, the recalculation of the last
773     // line needs some postprocessing.
774     //
775     lcl_PostprocessRowsInCells( rTab, rLastLine );
776 
777     //
778     // Do a couple of checks on the current situation.
779     //
780     // If we are not happy with the current situation we return false.
781     // This will start a new try to split the table, this time we do not
782     // try to split the table rows.
783     //
784 
785     //
786     // 1. Check if table fits to its upper.
787     // --> OD 2004-10-15 #i26945# - include check, if objects fit
788     //
789     const SwTwips nDistanceToUpperPrtBottom =
790             (rTab.Frm().*fnRect->fnBottomDist)( (rTab.GetUpper()->*fnRect->fnGetPrtBottom)());
791     if ( nDistanceToUpperPrtBottom < 0 || !rTab.DoesObjsFit() )
792         bRet = false;
793     // <--
794 
795     //
796     // 2. Check if each cell in the last line has at least one content frame.
797     //
798     // Note: a FollowFlowRow may contains empty cells!
799     //
800     if ( bRet )
801     {
802         if ( !rLastLine.IsInFollowFlowRow() )
803         {
804             SwCellFrm* pCurrMasterCell = (SwCellFrm*)rLastLine.Lower();
805             while ( pCurrMasterCell )
806             {
807                 if ( !pCurrMasterCell->ContainsCntnt() && pCurrMasterCell->GetTabBox()->getRowSpan() >= 1 )
808                 {
809                     bRet = false;
810                     break;
811                 }
812                 pCurrMasterCell = (SwCellFrm*)pCurrMasterCell->GetNext();
813             }
814         }
815     }
816 
817     //
818     // 3. Check if last line does not contain any content:
819     //
820     if ( bRet )
821     {
822         if ( !rLastLine.ContainsCntnt() )
823         {
824             bRet = false;
825         }
826     }
827 
828 
829     //
830     // 4. Check if follow flow line does not contain content:
831     //
832     if ( bRet )
833     {
834         if ( !rFollowLine.IsRowSpanLine() && !rFollowLine.ContainsCntnt() )
835         {
836             bRet = false;
837         }
838     }
839 
840     if ( bRet )
841     {
842         //
843         // Everything looks fine. Splitting seems to be successful. We invalidate
844         // rFollowLine to force a new formatting.
845         //
846         ::SwInvalidateAll( &rFollowLine, LONG_MAX );
847     }
848     else
849     {
850         //
851         // Splitting the table row gave us an unexpected result.
852         // Everything has to be prepared for a second try to split
853         // the table, this time without splitting the row.
854         //
855         ::SwInvalidateAll( &rLastLine, LONG_MAX );
856     }
857 
858     rTab.SetRebuildLastLine( sal_False );
859     // --> OD 2004-10-15 #i26945#
860     rTab.SetDoesObjsFit( sal_True );
861     // <--
862 
863     return bRet;
864 }
865 
866 //
867 // Sets the correct height for all spanned cells
868 //
869 void lcl_AdjustRowSpanCells( SwRowFrm* pRow )
870 {
871     SWRECTFN( pRow )
872     SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pRow->GetLower());
873     while ( pCellFrm )
874     {
875         const long nLayoutRowSpan = pCellFrm->GetLayoutRowSpan();
876         if ( nLayoutRowSpan > 1 )
877         {
878             // calculate height of cell:
879             const long nNewCellHeight = lcl_GetHeightOfRows( pRow, nLayoutRowSpan );
880             const long nDiff = nNewCellHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
881             if ( nDiff )
882                 (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
883         }
884 
885         pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
886     }
887 }
888 
889 //
890 // Returns the maximum layout row span of the row
891 // Looking for the next row that contains no covered cells:
892 long lcl_GetMaximumLayoutRowSpan( const SwRowFrm& rRow )
893 {
894     long nRet = 1;
895 
896     const SwRowFrm* pCurrentRowFrm = static_cast<const SwRowFrm*>(rRow.GetNext());
897     bool bNextRow = false;
898 
899     while ( pCurrentRowFrm )
900     {
901         // if there is any covered cell, we proceed to the next row frame
902         const SwCellFrm* pLower = static_cast<const SwCellFrm*>( pCurrentRowFrm->Lower());
903         while ( pLower )
904         {
905             if ( pLower->GetTabBox()->getRowSpan() < 0 )
906             {
907                 ++nRet;
908                 bNextRow = true;
909                 break;
910             }
911             pLower = static_cast<const SwCellFrm*>(pLower->GetNext());
912         }
913         pCurrentRowFrm = bNextRow ?
914                          static_cast<const SwRowFrm*>(pCurrentRowFrm->GetNext() ) :
915                          0;
916     }
917 
918     return nRet;
919 }
920 
921 /*************************************************************************
922 |*  END: local helper functions for splitting row frames
923 |*************************************************************************/
924 
925 //
926 // Function to remove the FollowFlowLine of rTab.
927 // The content of the FollowFlowLine is moved to the associated line in the
928 // master table.
929 //
930 bool SwTabFrm::RemoveFollowFlowLine()
931 {
932     // find FollowFlowLine
933     SwRowFrm* pFollowFlowLine = static_cast<SwRowFrm*>(GetFollow()->GetFirstNonHeadlineRow());
934 
935     // find last row in master
936     SwFrm* pLastLine = GetLastLower();
937 
938     ASSERT( HasFollowFlowLine() &&
939             pFollowFlowLine &&
940             pLastLine, "There should be a flowline in the follow" )
941 
942     // We have to reset the flag here, because lcl_MoveRowContent
943     // calls a GrowFrm(), which has a different bahavior if
944     // this flag is set.
945     SetFollowFlowLine( sal_False );
946 
947     // --> FME 2007-07-19 #140081# Make code robust.
948     if ( !pFollowFlowLine || !pLastLine )
949         return true;
950 
951     // Move content
952     lcl_MoveRowContent( *pFollowFlowLine, *(SwRowFrm*)pLastLine );
953 
954     // NEW TABLES
955     // If a row span follow flow line is removed, we want to move the whole span
956     // to the master:
957     SwTwips nGrow = 0;
958     long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pFollowFlowLine );
959 
960     if ( nRowsToMove > 1 )
961     {
962         SWRECTFN( this )
963         SwFrm* pRow = pFollowFlowLine->GetNext();
964         SwFrm* pInsertBehind = GetLastLower();
965 
966         while ( pRow && nRowsToMove-- > 1 )
967 		{
968 			SwFrm* pNxt = pRow->GetNext();
969             nGrow += (pRow->Frm().*fnRect->fnGetHeight)();
970 
971             // The footnotes have to be moved:
972             lcl_MoveFootnotes( *GetFollow(), *this, (SwRowFrm&)*pRow );
973 
974             pRow->Remove();
975             pRow->InsertBehind( this, pInsertBehind );
976 			pRow->_InvalidateAll();
977             pRow->CheckDirChange();
978             pInsertBehind = pRow;
979             pRow = pNxt;
980         }
981 
982         SwFrm* pFirstRow = Lower();
983         while ( pFirstRow )
984         {
985             lcl_AdjustRowSpanCells( static_cast<SwRowFrm*>(pFirstRow) );
986             pFirstRow = pFirstRow->GetNext();
987         }
988 
989         Grow( nGrow );
990         GetFollow()->Shrink( nGrow );
991     }
992 
993     bool bJoin = !pFollowFlowLine->GetNext();
994     pFollowFlowLine->Cut();
995     delete pFollowFlowLine;
996 
997     return bJoin;
998 }
999 
1000 // --> OD 2004-10-04 #i26945# - Floating screen objects are no longer searched.
1001 bool lcl_FindSectionsInRow( const SwRowFrm& rRow )
1002 {
1003     bool bRet = false;
1004     SwCellFrm* pLower = (SwCellFrm*)rRow.Lower();
1005     while ( pLower )
1006     {
1007         if ( pLower->IsVertical() != rRow.IsVertical() )
1008             return true;
1009 
1010         SwFrm* pTmpFrm = pLower->Lower();
1011         while ( pTmpFrm )
1012         {
1013             if ( pTmpFrm->IsRowFrm() )
1014             {
1015                 bRet = lcl_FindSectionsInRow( *(SwRowFrm*)pTmpFrm );
1016             }
1017             else
1018             {
1019                 // --> OD 2004-10-04 #i26945# - search only for sections
1020                 bRet = pTmpFrm->IsSctFrm();
1021                 // <--
1022             }
1023 
1024             if ( bRet )
1025                 return true;
1026             pTmpFrm = pTmpFrm->GetNext();
1027         }
1028 
1029         pLower = (SwCellFrm*)pLower->GetNext();
1030     }
1031     return bRet;
1032 }
1033 
1034 /*************************************************************************
1035 |*
1036 |*	SwTabFrm::Split(), Join()
1037 |*
1038 |*	Ersterstellung		MA 03. Jun. 93
1039 |*	Letzte Aenderung	MA 03. Sep. 96
1040 |*
1041 |*************************************************************************/
1042 bool SwTabFrm::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowKeep )
1043 {
1044     bool bRet = true;
1045 
1046     SWRECTFN( this )
1047     //ASSERT( bVert ? nCutPos >= Frm().Left() &&
1048     //                nCutPos <= Frm().Left() + Frm().Width() :
1049     //                nCutPos >= Frm().Top() && nCutPos <= Frm().Bottom(), "SplitLine out of table." );
1050 
1051     // --> OD 2004-10-14 #i26745# - format row and cell frames of table
1052     {
1053         this->Lower()->_InvalidatePos();
1054         // --> OD 2005-03-30 #i43913# - correction:
1055         // call method <lcl_InnerCalcLayout> with first lower.
1056         lcl_InnerCalcLayout( this->Lower(), LONG_MAX, true );
1057         // <--
1058     }
1059     // <--
1060 
1061     //Um die Positionen der Zellen mit der CutPos zu vergleichen muessen sie
1062 	//ausgehend von der Tabelle nacheinander berechnet werden. Sie koennen
1063 	//wg. Positionsaenderungen der Tabelle durchaus ungueltig sein.
1064 	SwRowFrm *pRow = static_cast<SwRowFrm*>(Lower());
1065 	if( !pRow )
1066         return bRet;
1067 
1068     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
1069     sal_uInt16 nRowCount = 0;           // pRow currently points to the first row
1070 
1071     SwTwips nRemainingSpaceForLastRow =
1072         (*fnRect->fnYDiff)( nCutPos, (Frm().*fnRect->fnGetTop)() );
1073     nRemainingSpaceForLastRow -= (this->*fnRect->fnGetTopMargin)();
1074 
1075     //
1076     // Make pRow point to the line that does not fit anymore:
1077     //
1078     while( pRow->GetNext() &&
1079            nRemainingSpaceForLastRow >= ( (pRow->Frm().*fnRect->fnGetHeight)() +
1080                                            (IsCollapsingBorders() ?
1081                                             pRow->GetBottomLineSize() :
1082                                             0 ) ) )
1083 	{
1084 		if( bTryToSplit || !pRow->IsRowSpanLine() ||
1085 			0 != (pRow->Frm().*fnRect->fnGetHeight)() )
1086 			++nRowCount;
1087         nRemainingSpaceForLastRow -= (pRow->Frm().*fnRect->fnGetHeight)();
1088 		pRow = static_cast<SwRowFrm*>(pRow->GetNext());
1089     }
1090 
1091     //
1092     // bSplitRowAllowed: Row may be split according to its attributes.
1093     // bTryToSplit:      Row will never be split if bTryToSplit = false.
1094     //                   This can either be passed as a parameter, indicating
1095     //                   that we are currently doing the second try to split the
1096     //                   table, or it will be set to falseunder certain
1097     //                   conditions that are not suitable for splitting
1098     //                   the row.
1099     //
1100     bool bSplitRowAllowed = pRow->IsRowSplitAllowed();
1101 
1102     // --> FME 2004-06-03 #i29438#
1103     // --> OD 2004-10-04 #i26945# - Floating screen objects no longer forbid
1104     // a splitting of the table row.
1105     // Special DoNotSplit case 1:
1106     // Search for sections inside pRow:
1107     //
1108     if ( lcl_FindSectionsInRow( *pRow ) )
1109     {
1110         bTryToSplit = false;
1111     }
1112     // <--
1113 
1114     // --> FME 2004-06-07 #i29771#
1115     // To avoid loops, we do some checks before actually trying to split
1116     // the row. Maybe we should keep the next row in this table.
1117     // Note: This is only done if we are at the beginning of our upper
1118     bool bKeepNextRow = false;
1119     if ( nRowCount < nRepeat )
1120     {
1121         //
1122         // First case: One of the repeated headline does not fit to the page anymore.
1123         // At least one more non-heading row has to stay in this table in
1124         // order to avoid loops:
1125         //
1126         ASSERT( !GetIndPrev(), "Table is supposed to be at beginning" )
1127         bKeepNextRow = true;
1128     }
1129     else if ( !GetIndPrev() && nRepeat == nRowCount )
1130     {
1131         //
1132         // Second case: The first non-headline row does not fit to the page.
1133         // If it is not allowed to be split, or it contains a sub-row that
1134         // is not allowed to be split, we keep the row in this table:
1135         //
1136         if ( bTryToSplit && bSplitRowAllowed )
1137         {
1138             // Check if there are (first) rows inside this row,
1139             // which are not allowed to be split.
1140             SwCellFrm* pLowerCell = pRow ? (SwCellFrm*)pRow->Lower() : 0;
1141             while ( pLowerCell )
1142             {
1143                 if ( pLowerCell->Lower() && pLowerCell->Lower()->IsRowFrm() )
1144                 {
1145                     const SwRowFrm* pLowerRow = (SwRowFrm*)pLowerCell->Lower();
1146                     if ( !pLowerRow->IsRowSplitAllowed() &&
1147                         (pLowerRow->Frm().*fnRect->fnGetHeight)() >
1148                         nRemainingSpaceForLastRow )
1149                     {
1150                         bKeepNextRow = true;
1151                         break;
1152                     }
1153                 }
1154                 pLowerCell = (SwCellFrm*)pLowerCell->GetNext();
1155             }
1156         }
1157         else
1158             bKeepNextRow = true;
1159     }
1160 
1161     //
1162     // Better keep the next row in this table:
1163     //
1164     if ( bKeepNextRow )
1165     {
1166         pRow = GetFirstNonHeadlineRow();
1167 		if( pRow && pRow->IsRowSpanLine() && 0 == (pRow->Frm().*fnRect->fnGetHeight)() )
1168             pRow = static_cast<SwRowFrm*>(pRow->GetNext());
1169         if ( pRow )
1170         {
1171             pRow = static_cast<SwRowFrm*>(pRow->GetNext());
1172             ++nRowCount;
1173         }
1174     }
1175 
1176     //
1177     // No more row to split or to move to follow table:
1178     //
1179     if ( !pRow )
1180         return bRet;
1181 
1182     //
1183     // We try to split the row if
1184     // - the attributes of the row are set accordingly and
1185     // - we are allowed to do so
1186     // - the it should not keep with the next row
1187     //
1188     bSplitRowAllowed = bSplitRowAllowed && bTryToSplit &&
1189                        ( !bTableRowKeep ||
1190                          !pRow->ShouldRowKeepWithNext() );
1191 
1192     // Adjust pRow according to the keep-with-next attribute:
1193     if ( !bSplitRowAllowed && bTableRowKeep )
1194     {
1195         SwRowFrm* pTmpRow = static_cast<SwRowFrm*>(pRow->GetPrev());
1196         SwRowFrm* pOldRow = pRow;
1197         while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() &&
1198                 nRowCount > nRepeat )
1199         {
1200             pRow = pTmpRow;
1201             --nRowCount;
1202             pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetPrev());
1203         }
1204 
1205         // loop prevention
1206         if ( nRowCount == nRepeat && !GetIndPrev())
1207         {
1208             pRow = pOldRow;
1209         }
1210     }
1211 
1212     //
1213     // If we do not indent to split pRow, we check if we are
1214     // allowed to move pRow to a follow. Otherwise we return
1215     // false, indicating an error
1216     //
1217     if ( !bSplitRowAllowed )
1218     {
1219         SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
1220         if ( pRow == pFirstNonHeadlineRow )
1221             return false;
1222 
1223         // --> OD 2008-10-21 #i91764#
1224         // Ignore row span lines
1225         SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
1226         while ( pTmpRow && pTmpRow->IsRowSpanLine() )
1227         {
1228             pTmpRow = static_cast<SwRowFrm*>(pTmpRow->GetNext());
1229         }
1230         if ( !pTmpRow || pRow == pTmpRow )
1231         {
1232             return false;
1233         }
1234         // <--
1235     }
1236 
1237     //
1238     // Build follow table if not already done:
1239     //
1240     sal_Bool bNewFollow;
1241 	SwTabFrm *pFoll;
1242 	if ( GetFollow() )
1243 	{
1244         pFoll = GetFollow();
1245 		bNewFollow = sal_False;
1246 	}
1247 	else
1248 	{
1249         bNewFollow = sal_True;
1250 		pFoll = new SwTabFrm( *this );
1251 
1252         //
1253         // We give the follow table an initial width.
1254         //
1255         (pFoll->Frm().*fnRect->fnAddWidth)( (Frm().*fnRect->fnGetWidth)() );
1256         (pFoll->Prt().*fnRect->fnAddWidth)( (Prt().*fnRect->fnGetWidth)() );
1257         (pFoll->Frm().*fnRect->fnSetLeft)( (Frm().*fnRect->fnGetLeft)() );
1258 
1259         //
1260         // Insert the new follow table
1261         //
1262         pFoll->InsertBehind( GetUpper(), this );
1263 
1264         //
1265         // Repeat the headlines.
1266         //
1267         for ( nRowCount = 0; nRowCount < nRepeat; ++nRowCount )
1268         {
1269             // Insert new headlines:
1270             bDontCreateObjects = sal_True;              //frmtool
1271             SwRowFrm* pHeadline = new SwRowFrm(
1272                                     *GetTable()->GetTabLines()[ nRowCount ], this );
1273             pHeadline->SetRepeatedHeadline( true );
1274             bDontCreateObjects = sal_False;
1275             pHeadline->InsertBefore( pFoll, 0 );
1276 
1277 			SwPageFrm *pPage = pHeadline->FindPageFrm();
1278 			const SwSpzFrmFmts *pTbl = GetFmt()->GetDoc()->GetSpzFrmFmts();
1279 			if( pTbl->Count() )
1280 			{
1281 				sal_uLong nIndex;
1282 				SwCntntFrm* pFrm = pHeadline->ContainsCntnt();
1283 				while( pFrm )
1284 				{
1285 					nIndex = pFrm->GetNode()->GetIndex();
1286 					AppendObjs( pTbl, nIndex, pFrm, pPage );
1287 					pFrm = pFrm->GetNextCntntFrm();
1288 					if( !pHeadline->IsAnLower( pFrm ) )
1289 						break;
1290 				}
1291 			}
1292         }
1293     }
1294 
1295     SwRowFrm* pLastRow = 0;     // will point to the last remaining line in master
1296     SwRowFrm* pFollowRow = 0;   // points to either the follow flow line of the
1297                                 // first regular line in the follow
1298 
1299     if ( bSplitRowAllowed )
1300     {
1301         // If the row that does not fit anymore is allowed
1302         // to be split, the next row has to be moved to the follow table.
1303         pLastRow = pRow;
1304         pRow = static_cast<SwRowFrm*>(pRow->GetNext());
1305 
1306         // new follow flow line for last row of master table
1307         pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, false );
1308     }
1309     else
1310     {
1311         pFollowRow = pRow;
1312 
1313         // NEW TABLES
1314         // check if we will break a row span by moving pFollowRow to the follow:
1315         // In this case we want to reformat the last line.
1316         const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>(pFollowRow->GetLower());
1317         while ( pCellFrm )
1318         {
1319             if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
1320             {
1321                 pLastRow = static_cast<SwRowFrm*>(pRow->GetPrev());
1322                 break;
1323             }
1324 
1325             pCellFrm = static_cast<const SwCellFrm*>(pCellFrm->GetNext());
1326         }
1327 
1328         // new follow flow line for last row of master table
1329         if ( pLastRow )
1330             pFollowRow = lcl_InsertNewFollowFlowLine( *this, *pLastRow, true );
1331     }
1332 
1333     SwTwips nRet = 0;
1334 
1335 	//Optimierung beim neuen Follow braucht's kein Paste und dann kann
1336 	//das Optimierte Insert verwendet werden (nur dann treten gluecklicher weise
1337 	//auch groessere Mengen von Rows auf).
1338 	if ( bNewFollow )
1339 	{
1340         SwFrm* pNxt = 0;
1341         SwFrm* pInsertBehind = pFoll->GetLastLower();
1342 
1343         while ( pRow )
1344 		{
1345 			pNxt = pRow->GetNext();
1346             nRet += (pRow->Frm().*fnRect->fnGetHeight)();
1347             // The footnotes do not have to be moved, this is done in the
1348             // MoveFwd of the follow table!!!
1349             pRow->Remove();
1350             pRow->InsertBehind( pFoll, pInsertBehind );
1351 			pRow->_InvalidateAll();
1352 			pInsertBehind = pRow;
1353 			pRow = static_cast<SwRowFrm*>(pNxt);
1354 		}
1355     }
1356 	else
1357 	{
1358         SwFrm* pNxt = 0;
1359         SwFrm* pPasteBefore = HasFollowFlowLine() ?
1360                               pFollowRow->GetNext() :
1361                               pFoll->GetFirstNonHeadlineRow();
1362 
1363         while ( pRow )
1364 		{
1365 			pNxt = pRow->GetNext();
1366             nRet += (pRow->Frm().*fnRect->fnGetHeight)();
1367 
1368             // The footnotes have to be moved:
1369             lcl_MoveFootnotes( *this, *GetFollow(), *pRow );
1370 
1371             pRow->Remove();
1372 			pRow->Paste( pFoll, pPasteBefore );
1373 
1374             pRow->CheckDirChange();
1375 			pRow = static_cast<SwRowFrm*>(pNxt);
1376 		}
1377     }
1378 
1379     Shrink( nRet );
1380 
1381     // we rebuild the last line to assure that it will be fully formatted
1382     if ( pLastRow )
1383     {
1384         // recalculate the split line
1385         bRet = lcl_RecalcSplitLine( *pLastRow, *pFollowRow, nRemainingSpaceForLastRow );
1386 
1387         // NEW TABLES
1388         // check if each cell in the row span line has a good height
1389         if ( bRet && pFollowRow->IsRowSpanLine() )
1390             lcl_AdjustRowSpanCells( pFollowRow );
1391 
1392         // We The RowSplitLine stuff did not work. In this case we conceal the split error:
1393         if ( !bRet && !bSplitRowAllowed )
1394         {
1395             bRet = true;
1396         }
1397     }
1398 
1399     return bRet;
1400 }
1401 
1402 bool SwTabFrm::Join()
1403 {
1404     ASSERT( !HasFollowFlowLine(), "Joining follow flow line" )
1405 
1406     SwTabFrm *pFoll = GetFollow();
1407 	SwTwips nHeight = 0;	//Gesamthoehe der eingefuegten Zeilen als Return.
1408 
1409 	if ( !pFoll->IsJoinLocked() )
1410 	{
1411         SWRECTFN( this )
1412 		pFoll->Cut();	//Erst ausschneiden um unuetze Benachrichtigungen zu
1413 						//minimieren.
1414 
1415         SwFrm *pRow = pFoll->GetFirstNonHeadlineRow(),
1416 			  *pNxt;
1417 
1418         SwFrm* pPrv = GetLastLower();
1419 
1420 		while ( pRow )
1421 		{
1422 			pNxt = pRow->GetNext();
1423             nHeight += (pRow->Frm().*fnRect->fnGetHeight)();
1424 			pRow->Remove();
1425 			pRow->_InvalidateAll();
1426 			pRow->InsertBehind( this, pPrv );
1427             pRow->CheckDirChange();
1428 			pPrv = pRow;
1429 			pRow = pNxt;
1430 		}
1431 
1432 		SetFollow( pFoll->GetFollow() );
1433         SetFollowFlowLine( pFoll->HasFollowFlowLine() );
1434         delete pFoll;
1435 
1436         Grow( nHeight );
1437 	}
1438 
1439     return true;
1440 }
1441 
1442 /*************************************************************************
1443 |*
1444 |*	SwTabFrm::MakeAll()
1445 |*
1446 |*	Ersterstellung		MA 09. Mar. 93
1447 |*	Letzte Aenderung	MA 10. Apr. 97
1448 |*
1449 |*************************************************************************/
1450 void MA_FASTCALL SwInvalidatePositions( SwFrm *pFrm, long nBottom )
1451 {
1452     // LONG_MAX == nBottom means we have to calculate all
1453     sal_Bool bAll = LONG_MAX == nBottom;
1454     SWRECTFN( pFrm )
1455 	do
1456 	{	pFrm->_InvalidatePos();
1457 		pFrm->_InvalidateSize();
1458 		if( pFrm->IsLayoutFrm() )
1459 		{
1460 			if ( ((SwLayoutFrm*)pFrm)->Lower() )
1461             {
1462 				::SwInvalidatePositions( ((SwLayoutFrm*)pFrm)->Lower(), nBottom);
1463                 // --> OD 2004-11-05 #i26945#
1464                 ::lcl_InvalidateLowerObjs( *(static_cast<SwLayoutFrm*>(pFrm)) );
1465                 // <--
1466             }
1467 		}
1468 		else
1469 			pFrm->Prepare( PREP_ADJUST_FRM );
1470 		pFrm = pFrm->GetNext();
1471     } while ( pFrm &&
1472               ( bAll ||
1473               (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
1474 }
1475 
1476 void MA_FASTCALL SwInvalidateAll( SwFrm *pFrm, long nBottom )
1477 {
1478     // LONG_MAX == nBottom means we have to calculate all
1479     sal_Bool bAll = LONG_MAX == nBottom;
1480     SWRECTFN( pFrm )
1481 	do
1482 	{
1483         pFrm->_InvalidatePos();
1484 		pFrm->_InvalidateSize();
1485 		pFrm->_InvalidatePrt();
1486 		if( pFrm->IsLayoutFrm() )
1487 		{
1488             // NEW TABLES
1489             SwLayoutFrm* pToInvalidate = static_cast<SwLayoutFrm*>(pFrm);
1490             SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
1491             if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
1492             {
1493                 pToInvalidate = & const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
1494 	            pToInvalidate->_InvalidatePos();
1495 		        pToInvalidate->_InvalidateSize();
1496 		        pToInvalidate->_InvalidatePrt();
1497             }
1498 
1499             if ( pToInvalidate->Lower() )
1500                 ::SwInvalidateAll( pToInvalidate->Lower(), nBottom);
1501         }
1502 		else
1503 			pFrm->Prepare( PREP_CLEAR );
1504 
1505 		pFrm = pFrm->GetNext();
1506     } while ( pFrm &&
1507               ( bAll ||
1508               (*fnRect->fnYDiff)( (pFrm->Frm().*fnRect->fnGetTop)(), nBottom ) < 0 ) );
1509 }
1510 
1511 // --> collapsing borders FME 2005-05-27 #i29550#
1512 void lcl_InvalidateAllLowersPrt( SwLayoutFrm* pLayFrm )
1513 {
1514     pLayFrm->_InvalidatePrt();
1515     pLayFrm->_InvalidateSize();
1516     pLayFrm->SetCompletePaint();
1517 
1518     SwFrm* pFrm = pLayFrm->Lower();
1519 
1520     while ( pFrm )
1521     {
1522         if ( pFrm->IsLayoutFrm() )
1523             lcl_InvalidateAllLowersPrt( (SwLayoutFrm*)pFrm );
1524         else
1525         {
1526             pFrm->_InvalidatePrt();
1527             pFrm->_InvalidateSize();
1528             pFrm->SetCompletePaint();
1529         }
1530 
1531         pFrm = pFrm->GetNext();
1532     }
1533 }
1534 // <-- collapsing
1535 
1536 bool SwCntntFrm::CalcLowers( SwLayoutFrm* pLay, const SwLayoutFrm* pDontLeave,
1537                                  long nBottom, bool bSkipRowSpanCells )
1538 {
1539     if ( !pLay )
1540         return sal_True;
1541 
1542     // LONG_MAX == nBottom means we have to calculate all
1543     bool bAll = LONG_MAX == nBottom;
1544     bool bRet = sal_False;
1545 	SwCntntFrm *pCnt = pLay->ContainsCntnt();
1546     SWRECTFN( pLay )
1547 
1548     // FME 2007-08-30 #i81146# new loop control
1549     sal_uInt16 nLoopControlRuns = 0;
1550     const sal_uInt16 nLoopControlMax = 10;
1551     const SwModify* pLoopControlCond = 0;
1552 
1553     while ( pCnt && pDontLeave->IsAnLower( pCnt ) )
1554 	{
1555         // --> OD 2004-11-23 #115759# - check, if a format of content frame is
1556         // possible. Thus, 'copy' conditions, found at the beginning of
1557         // <SwCntntFrm::MakeAll(..)>, and check these.
1558         const bool bFormatPossible = !pCnt->IsJoinLocked() &&
1559                                      ( !pCnt->IsTxtFrm() ||
1560                                        !static_cast<SwTxtFrm*>(pCnt)->IsLocked() ) &&
1561                                      ( pCnt->IsFollow() || !StackHack::IsLocked() );
1562 
1563         // NEW TABLES
1564         bool bSkipContent = false;
1565         if ( bSkipRowSpanCells && pCnt->IsInTab() )
1566         {
1567             const SwFrm* pCell = pCnt->GetUpper();
1568             while ( pCell && !pCell->IsCellFrm() )
1569                 pCell = pCell->GetUpper();
1570             if ( pCell && 1 != static_cast<const SwCellFrm*>( pCell )->GetLayoutRowSpan() )
1571                 bSkipContent = true;
1572         }
1573 
1574         if ( bFormatPossible && !bSkipContent )
1575         {
1576             bRet |= !pCnt->IsValid();
1577             // --> OD 2004-10-06 #i26945# - no extra invalidation of floating
1578             // screen objects needed.
1579             // Thus, delete call of method <SwFrm::InvalidateObjs( true )>
1580             // <--
1581             pCnt->Calc();
1582             // OD 2004-05-11 #i28701# - usage of new method <::FormatObjsAtFrm(..)>
1583             // to format the floating screen objects
1584             // --> OD 2005-05-03 #i46941# - frame has to be valid
1585             // Note: frame could be invalid after calling its format, if it's locked.
1586             ASSERT( !pCnt->IsTxtFrm() ||
1587                     pCnt->IsValid() ||
1588                     static_cast<SwTxtFrm*>(pCnt)->IsJoinLocked(),
1589                     "<SwCntntFrm::CalcLowers(..)> - text frame invalid and not locked." );
1590             if ( pCnt->IsTxtFrm() && pCnt->IsValid() )
1591             {
1592                 // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame to
1593                 // the object formatter
1594                 if ( !SwObjectFormatter::FormatObjsAtFrm( *pCnt,
1595                                                           *(pCnt->FindPageFrm()) ) )
1596                 // <--
1597                 {
1598                     if ( pCnt->GetRegisteredIn() == pLoopControlCond )
1599                         ++nLoopControlRuns;
1600                     else
1601                     {
1602                         nLoopControlRuns = 0;
1603                         pLoopControlCond = pCnt->GetRegisteredIn();
1604                     }
1605 
1606                     if ( nLoopControlRuns < nLoopControlMax )
1607                     {
1608                         // restart format with first content
1609                         pCnt = pLay->ContainsCntnt();
1610                         continue;
1611                     }
1612 
1613 #if OSL_DEBUG_LEVEL > 1
1614                     ASSERT( false, "LoopControl in SwCntntFrm::CalcLowers" )
1615 #endif
1616                 }
1617             }
1618             pCnt->GetUpper()->Calc();
1619         }
1620         // <--
1621         if( ! bAll && (*fnRect->fnYDiff)((pCnt->Frm().*fnRect->fnGetTop)(), nBottom) > 0 )
1622 			break;
1623 		pCnt = pCnt->GetNextCntntFrm();
1624 	}
1625 	return bRet;
1626 }
1627 
1628 // --> OD 2004-10-15 #i26945# - add parameter <_bOnlyRowsAndCells> to control
1629 // that only row and cell frames are formatted.
1630 sal_Bool MA_FASTCALL lcl_InnerCalcLayout( SwFrm *pFrm,
1631                                       long nBottom,
1632                                       bool _bOnlyRowsAndCells )
1633 {
1634     // LONG_MAX == nBottom means we have to calculate all
1635     sal_Bool bAll = LONG_MAX == nBottom;
1636 	sal_Bool bRet = sal_False;
1637     const SwFrm* pOldUp = pFrm->GetUpper();
1638     SWRECTFN( pFrm )
1639 	do
1640 	{
1641         // --> OD 2004-10-15 #i26945# - parameter <_bOnlyRowsAndCells> controls,
1642         // if only row and cell frames are formatted.
1643         if ( pFrm->IsLayoutFrm() &&
1644              ( !_bOnlyRowsAndCells || pFrm->IsRowFrm() || pFrm->IsCellFrm() ) )
1645         // <--
1646 		{
1647             // --> FME 2006-02-23 #130744# An invalid locked table frame will
1648             // not be calculated => It will not become valid =>
1649             // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet.
1650             bRet |= !pFrm->IsValid() && ( !pFrm->IsTabFrm() || !static_cast<SwTabFrm*>(pFrm)->IsJoinLocked() );
1651             // <--
1652             pFrm->Calc();
1653             if( static_cast<SwLayoutFrm*>(pFrm)->Lower() )
1654                 bRet |= lcl_InnerCalcLayout( static_cast<SwLayoutFrm*>(pFrm)->Lower(), nBottom);
1655 
1656             // NEW TABLES
1657             SwCellFrm* pThisCell = dynamic_cast<SwCellFrm*>(pFrm);
1658             if ( pThisCell && pThisCell->GetTabBox()->getRowSpan() < 1 )
1659             {
1660                 SwCellFrm& rToCalc = const_cast<SwCellFrm&>(pThisCell->FindStartEndOfRowSpanCell( true, true ));
1661                 bRet |= !rToCalc.IsValid();
1662                 rToCalc.Calc();
1663                 if ( rToCalc.Lower() )
1664                     bRet |= lcl_InnerCalcLayout( rToCalc.Lower(), nBottom);
1665             }
1666 		}
1667 		pFrm = pFrm->GetNext();
1668     } while( pFrm &&
1669             ( bAll ||
1670               (*fnRect->fnYDiff)((pFrm->Frm().*fnRect->fnGetTop)(), nBottom) < 0 )
1671             && pFrm->GetUpper() == pOldUp );
1672 	return bRet;
1673 }
1674 
1675 void MA_FASTCALL lcl_RecalcRow( SwRowFrm& rRow, long nBottom )
1676 {
1677     // --> OD 2004-10-05 #i26945# - For correct appliance of the 'straightforward
1678     // object positioning process, it's needed to notify that the page frame,
1679     // on which the given layout frame is in, is in its layout process.
1680     SwPageFrm* pPageFrm = rRow.FindPageFrm();
1681     if ( pPageFrm && !pPageFrm->IsLayoutInProgress() )
1682         pPageFrm->SetLayoutInProgress( true );
1683     else
1684         pPageFrm = 0L;
1685     // <--
1686 
1687     // FME 2007-08-30 #i81146# new loop control
1688     sal_uInt16 nLoopControlRuns_1 = 0;
1689     sal_uInt16 nLoopControlStage_1 = 0;
1690     const sal_uInt16 nLoopControlMax = 10;
1691 
1692     bool bCheck = true;
1693     do
1694     {
1695         // FME 2007-08-30 #i81146# new loop control
1696         sal_uInt16 nLoopControlRuns_2 = 0;
1697         sal_uInt16 nLoopControlStage_2 = 0;
1698 
1699         while( lcl_InnerCalcLayout( &rRow, nBottom ) )
1700         {
1701             if ( ++nLoopControlRuns_2 > nLoopControlMax )
1702             {
1703 #if OSL_DEBUG_LEVEL > 1
1704                 ASSERT( 0 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 1!" );
1705                 ASSERT( 1 != nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 2!!" );
1706                 ASSERT( 2 >  nLoopControlStage_2, "LoopControl_2 in lcl_RecalcRow: Stage 3!!!" );
1707 #endif
1708                 rRow.ValidateThisAndAllLowers( nLoopControlStage_2++ );
1709                 nLoopControlRuns_2 = 0;
1710                 if( nLoopControlStage_2 > 2 )
1711                     break;
1712             }
1713 
1714             bCheck = true;
1715         }
1716 
1717         if( bCheck )
1718         {
1719             // --> OD 2004-11-23 #115759# - force another format of the
1720             // lowers, if at least one of it was invalid.
1721             bCheck = SwCntntFrm::CalcLowers( &rRow, rRow.GetUpper(), nBottom, true );
1722             // <--
1723 
1724             // NEW TABLES
1725             // First we calculate the cells with row span of < 1, afterwards
1726             // all cells with row span of > 1:
1727             for ( int i = 0; i < 2; ++i )
1728             {
1729                 SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(rRow.Lower());
1730                 while ( pCellFrm )
1731                 {
1732                     const bool bCalc = 0 == i ?
1733                                        pCellFrm->GetLayoutRowSpan() < 1 :
1734                                        pCellFrm->GetLayoutRowSpan() > 1;
1735 
1736                     if ( bCalc )
1737                     {
1738                         SwCellFrm& rToRecalc = 0 == i ?
1739                                                const_cast<SwCellFrm&>(pCellFrm->FindStartEndOfRowSpanCell( true, true )) :
1740                                                *pCellFrm;
1741                         bCheck  |= SwCntntFrm::CalcLowers( &rToRecalc, &rToRecalc, nBottom, false );
1742                     }
1743 
1744                     pCellFrm = static_cast<SwCellFrm*>(pCellFrm->GetNext());
1745                 }
1746             }
1747 
1748             if ( bCheck )
1749             {
1750                 if ( ++nLoopControlRuns_1 > nLoopControlMax )
1751                 {
1752 #if OSL_DEBUG_LEVEL > 1
1753                     ASSERT( 0 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 1!" );
1754                     ASSERT( 1 != nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 2!!" );
1755                     ASSERT( 2 >  nLoopControlStage_1, "LoopControl_1 in lcl_RecalcRow: Stage 3!!!" );
1756 #endif
1757                     rRow.ValidateThisAndAllLowers( nLoopControlStage_1++ );
1758                     nLoopControlRuns_1 = 0;
1759                     if( nLoopControlStage_1 > 2 )
1760                         break;
1761                 }
1762 
1763                 continue;
1764             }
1765         }
1766         break;
1767     } while( true );
1768 
1769     // --> OD 2004-10-05 #i26945#
1770     if ( pPageFrm )
1771         pPageFrm->SetLayoutInProgress( false );
1772     // <--
1773 }
1774 
1775 void MA_FASTCALL lcl_RecalcTable( SwTabFrm& rTab,
1776                                   SwLayoutFrm *pFirstRow,
1777                                   SwLayNotify &rNotify )
1778 {
1779     if ( rTab.Lower() )
1780 	{
1781         if ( !pFirstRow )
1782 		{
1783             pFirstRow = (SwLayoutFrm*)rTab.Lower();
1784 			rNotify.SetLowersComplete( sal_True );
1785 		}
1786 		::SwInvalidatePositions( pFirstRow, LONG_MAX );
1787         lcl_RecalcRow( static_cast<SwRowFrm&>(*pFirstRow), LONG_MAX );
1788     }
1789 }
1790 
1791 // This is a new function to check the first condition whether
1792 // a tab frame may move backward. It replaces the formerly used
1793 // GetIndPrev(), which did not work correctly for #i5947#
1794 bool lcl_NoPrev( const SwFrm& rFrm )
1795 {
1796     // --> OD 2007-09-04 #i79774#, #b6596954#
1797     // skip empty sections on investigation of direct previous frame.
1798     // use information, that at least one empty section is skipped in the following code.
1799     bool bSkippedDirectPrevEmptySection( false );
1800     if ( rFrm.GetPrev() )
1801     {
1802         const SwFrm* pPrev( rFrm.GetPrev() );
1803         while ( pPrev &&
1804                 pPrev->IsSctFrm() &&
1805                 !dynamic_cast<const SwSectionFrm*>(pPrev)->GetSection() )
1806         {
1807             pPrev = pPrev->GetPrev();
1808             bSkippedDirectPrevEmptySection = true;
1809         }
1810         if ( pPrev )
1811         {
1812             return false;
1813         }
1814     }
1815 
1816     if ( ( !bSkippedDirectPrevEmptySection && !rFrm.GetIndPrev() ) ||
1817          ( bSkippedDirectPrevEmptySection &&
1818            ( !rFrm.IsInSct() || !rFrm._GetIndPrev() ) ) )
1819     {
1820         return true;
1821     }
1822     // <--
1823 
1824     // I do not have a direct prev, but I have an indirect prev.
1825     // In section frames I have to check if I'm located inside
1826     // the first column:
1827     if ( rFrm.IsInSct() )
1828     {
1829         const SwFrm* pSct = rFrm.GetUpper();
1830         if ( pSct && pSct->IsColBodyFrm() &&
1831             (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() )
1832         {
1833             const SwFrm* pPrevCol = rFrm.GetUpper()->GetUpper()->GetPrev();
1834             if ( pPrevCol )
1835                 // I'm not inside the first column and do not have a direct
1836                 // prev. I can try to go backward.
1837                 return true;
1838         }
1839     }
1840 
1841     return false;
1842 }
1843 
1844 #define KEEPTAB ( !GetFollow() && !IsFollow() )
1845 
1846 // --> OD 2005-09-28 #b6329202# - helper method to find next content frame of
1847 // a table frame and format it to assure keep attribute.
1848 // method return true, if a next content frame is formatted.
1849 // Precondition: The given table frame hasn't a follow and isn't a follow.
1850 SwFrm* lcl_FormatNextCntntForKeep( SwTabFrm* pTabFrm )
1851 {
1852     // find next content, table or section
1853     SwFrm* pNxt = pTabFrm->FindNext();
1854 
1855     // skip empty sections
1856     while ( pNxt && pNxt->IsSctFrm() &&
1857             !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
1858     {
1859         pNxt = pNxt->FindNext();
1860     }
1861 
1862     // if found next frame is a section, get its first content.
1863     if ( pNxt && pNxt->IsSctFrm() )
1864     {
1865         pNxt = static_cast<SwSectionFrm*>(pNxt)->ContainsAny();
1866     }
1867 
1868     // format found next frame.
1869     // if table frame is inside another table, method <SwFrm::MakeAll()> is
1870     // called to avoid that the superior table frame is formatted.
1871     if ( pNxt )
1872     {
1873         if ( pTabFrm->GetUpper()->IsInTab() )
1874             pNxt->MakeAll();
1875         else
1876             pNxt->Calc();
1877     }
1878 
1879     return pNxt;
1880 }
1881 
1882 void SwTabFrm::MakeAll()
1883 {
1884 	if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
1885 		return;
1886 
1887     if ( HasFollow() )
1888     {
1889         SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow();
1890         ASSERT( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(),
1891                 "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" )
1892         if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() )
1893             return;
1894     }
1895 
1896     PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
1897 
1898     LockJoin(); //Ich lass mich nicht unterwegs vernichten.
1899 	SwLayNotify aNotify( this );	//uebernimmt im DTor die Benachrichtigung
1900     // If pos is invalid, we have to call a SetInvaKeep at aNotify.
1901     // Otherwise the keep atribute would not work in front of a table.
1902     const sal_Bool bOldValidPos = GetValidPosFlag();
1903 
1904 	//Wenn mein direkter Nachbar gleichzeitig mein Follow ist
1905 	//verleibe ich mir das Teil ein.
1906     // OD 09.04.2003 #108698# - join all follows, which are placed on the
1907     // same page/column.
1908     // OD 29.04.2003 #109213# - join follow, only if join for the follow
1909     // is not locked. Otherwise, join will not be performed and this loop
1910     // will be endless.
1911     while ( GetNext() && GetNext() == GetFollow() &&
1912             !GetFollow()->IsJoinLocked()
1913           )
1914     {
1915         if ( HasFollowFlowLine() )
1916             RemoveFollowFlowLine();
1917         Join();
1918     }
1919 
1920     // The bRemoveFollowFlowLinePending is set if the split attribute of the
1921     // last line is set:
1922     if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() )
1923     {
1924         if ( RemoveFollowFlowLine() )
1925             Join();
1926         SetRemoveFollowFlowLinePending( sal_False );
1927     }
1928 
1929 	if ( bResizeHTMLTable )	//Optimiertes Zusammenspiel mit Grow/Shrink des Inhaltes
1930 	{
1931 		bResizeHTMLTable = sal_False;
1932 		SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
1933 		if ( pLayout )
1934 			bCalcLowers = pLayout->Resize(
1935 							pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
1936 	}
1937 
1938 
1939 	sal_Bool bMakePage	= sal_True;		//solange sal_True kann eine neue Seite
1940 								//angelegt werden (genau einmal)
1941 	sal_Bool bMovedBwd	= sal_False;	//Wird sal_True wenn der Frame zurueckfliesst
1942 	sal_Bool bMovedFwd	= sal_False;	//solange sal_False kann der Frm zurueck-
1943 								//fliessen (solange, bis er einmal
1944 								//vorwaerts ge'moved wurde).
1945 	sal_Bool bSplit		= sal_False;	//Wird sal_True wenn der Frm gesplittet wurde.
1946     const sal_Bool bFtnsInDoc = 0 != GetFmt()->GetDoc()->GetFtnIdxs().Count();
1947 	sal_Bool bMoveable;
1948 	const sal_Bool bFly		= IsInFly();
1949 
1950 	SwBorderAttrAccess  *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
1951 	const SwBorderAttrs *pAttrs = pAccess->Get();
1952 
1953     // The beloved keep attribute
1954     const bool bKeep = IsKeep( pAttrs->GetAttrSet() );
1955 
1956     // All rows should keep together
1957     // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next
1958     const bool bDontSplit = !IsFollow() &&
1959                             ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep );
1960 
1961     // The number of repeated headlines
1962     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
1963 
1964     // This flag indicates that we are allowed to try to split the
1965     // table rows.
1966     bool bTryToSplit = true;
1967 
1968     // --> FME 2006-02-16 #131283#
1969     // Indicates that two individual rows may keep together, based on the keep
1970     // attribute set at the first paragraph in the first cell.
1971     const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP);
1972 
1973     // The Magic Move: Used for the table row keep feature.
1974     // If only the last row of the table wants to keep (implicitely by setting
1975     // keep for the first paragraph in the first cell), and this table does
1976     // not have a next, the last line will be cut. Loop prevention: Only
1977     // one try.
1978     bool bLastRowHasToMoveToFollow = false;
1979     bool bLastRowMoveNoMoreTries = false;
1980 
1981     // Join follow table, if this table is not allowed to split:
1982 	if ( bDontSplit )
1983     {
1984 		while ( GetFollow() && !GetFollow()->IsJoinLocked() )
1985         {
1986             if ( HasFollowFlowLine() )
1987                 RemoveFollowFlowLine();
1988             Join();
1989         }
1990     }
1991 
1992     // Join follow table, if this does not have enough (repeated) lines:
1993     if ( nRepeat )
1994     {
1995         if( GetFollow() && !GetFollow()->IsJoinLocked() &&
1996             0 == GetFirstNonHeadlineRow() )
1997         {
1998             if ( HasFollowFlowLine() )
1999                 RemoveFollowFlowLine();
2000             Join();
2001         }
2002     }
2003 
2004     // Join follow table, if last row of this table should keep:
2005     if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() )
2006     {
2007         const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower());
2008         if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
2009         {
2010             if ( HasFollowFlowLine() )
2011                 RemoveFollowFlowLine();
2012             Join();
2013         }
2014     }
2015 
2016     //Einen Frischling moven wir gleich schon einmal vorwaerts...
2017 	if ( !Frm().Top() && IsFollow() )
2018 	{
2019 		SwFrm *pPre = GetPrev();
2020 		if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
2021 		{
2022 			if ( !MoveFwd( bMakePage, sal_False ) )
2023 				bMakePage = sal_False;
2024 			bMovedFwd = sal_True;
2025 		}
2026 	}
2027 
2028 	int nUnSplitted = 5; // Just another loop control :-(
2029     SWRECTFN( this )
2030 	while ( !bValidPos || !bValidSize || !bValidPrtArea )
2031 	{
2032 		if ( sal_True == (bMoveable = IsMoveable()) )
2033 			if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) )
2034 			{
2035 				bMovedFwd = sal_True;
2036 				bCalcLowers = sal_True;
2037                 // --> OD 2009-08-12 #i99267#
2038                 // reset <bSplit> after forward move to assure that follows
2039                 // can be joined, if further space is available.
2040                 bSplit = sal_False;
2041                 // <--
2042 			}
2043 
2044         Point aOldPos( (Frm().*fnRect->fnGetPos)() );
2045 		MakePos();
2046 
2047         if ( aOldPos != (Frm().*fnRect->fnGetPos)() )
2048 		{
2049             if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() )
2050 			{
2051 				SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
2052 				if( pLayout )
2053 				{
2054 					delete pAccess;
2055 					bCalcLowers |= pLayout->Resize(
2056 						pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
2057                     pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
2058 					pAttrs = pAccess->Get();
2059 				}
2060 
2061 				bValidPrtArea = sal_False;
2062 				aNotify.SetLowersComplete( sal_False );
2063 			}
2064 			SwFrm *pPre;
2065 			if ( bKeep || (0 != (pPre = FindPrev()) &&
2066 						   pPre->GetAttrSet()->GetKeep().GetValue()) )
2067 			{
2068 				bCalcLowers = sal_True;
2069 			}
2070 		}
2071 
2072 		//Wir muessen die Hoehe der ersten Zeile kennen, denn nur wenn diese
2073 		//kleiner wird muss ggf. der Master angestossen werden um noetigenfalls
2074 		//die Zeile aufzunehmen.
2075 		long n1StLineHeight = 0;
2076 		if ( IsFollow() )
2077 		{
2078             SwFrm* pFrm = GetFirstNonHeadlineRow();
2079             if ( pFrm )
2080                 n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
2081 		}
2082 
2083 		if ( !bValidSize || !bValidPrtArea )
2084 		{
2085             const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)();
2086             const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)();
2087             const Point aOldPrtPos  = (Prt().*fnRect->fnGetPos)();
2088 			Format( pAttrs );
2089 
2090 			SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
2091 			if ( pLayout &&
2092                  ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth ||
2093                   (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) )
2094             {
2095 				delete pAccess;
2096 				bCalcLowers |= pLayout->Resize(
2097 						pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
2098 //					GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() ? sal_False : sal_True );
2099 				pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2100 				pAttrs = pAccess->Get();
2101 			}
2102             if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() )
2103 				aNotify.SetLowersComplete( sal_False );
2104 		}
2105 
2106 		//Wenn ich der erste einer Kette bin koennte ich mal sehen ob
2107 		//ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
2108 		//Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
2109 		//geflosssen sein.
2110         if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) )
2111 		{
2112 			//Bei Follows muss der Master benachrichtigt
2113 			//werden. Der Follow muss nur dann Moven, wenn er leere Blaetter
2114 			//ueberspringen muss.
2115 			if ( IsFollow() )
2116 			{
2117 				//Nur wenn die Hoehe der ersten Zeile kleiner geworder ist.
2118                 SwFrm *pFrm = GetFirstNonHeadlineRow();
2119                 if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() )
2120 				{
2121 					SwTabFrm *pMaster = (SwTabFrm*)FindMaster();
2122 					sal_Bool bDummy;
2123 					if ( ShouldBwdMoved( pMaster->GetUpper(), sal_False, bDummy ) )
2124 						pMaster->InvalidatePos();
2125 				}
2126 			}
2127 			SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( sal_True ) : 0;
2128 			sal_Bool bReformat;
2129 			if ( MoveBwd( bReformat ) )
2130 			{
2131                 SWREFRESHFN( this )
2132 				bMovedBwd = sal_True;
2133 				aNotify.SetLowersComplete( sal_False );
2134 				if ( bFtnsInDoc )
2135 					MoveLowerFtns( 0, pOldBoss, 0, sal_True );
2136 				if ( bReformat || bKeep )
2137 				{
2138                     long nOldTop = (Frm().*fnRect->fnGetTop)();
2139                     MakePos();
2140                     if( nOldTop != (Frm().*fnRect->fnGetTop)() )
2141 					{
2142                         SwHTMLTableLayout *pHTMLLayout =
2143 							GetTable()->GetHTMLTableLayout();
2144                         if( pHTMLLayout )
2145 						{
2146 							delete pAccess;
2147                             bCalcLowers |= pHTMLLayout->Resize(
2148                                 pHTMLLayout->GetBrowseWidthByTabFrm( *this ),
2149 								sal_False );
2150 
2151                             pAccess= new SwBorderAttrAccess(
2152 										SwFrm::GetCache(), this );
2153 							pAttrs = pAccess->Get();
2154 						}
2155 
2156 						bValidPrtArea = sal_False;
2157 						Format( pAttrs );
2158 					}
2159                     lcl_RecalcTable( *this, 0, aNotify );
2160 					bLowersFormatted = sal_True;
2161 					if ( bKeep && KEEPTAB )
2162 					{
2163                         // --> OD 2005-09-28 #b6329202#
2164                         // Consider case that table is inside another table,
2165                         // because it has to be avoided, that superior table
2166                         // is formatted.
2167                         // Thus, find next content, table or section
2168                         // and, if a section is found, get its first
2169                         // content.
2170 //                        SwFrm *pNxt = FindNextCnt();
2171 //                        if( pNxt && pNxt->IsInTab() )
2172 //                            pNxt = pNxt->FindTabFrm();
2173 //                        if ( pNxt )
2174 //                        {
2175 //                            pNxt->Calc();
2176 //                            if ( !GetNext() )
2177 //                                bValidPos = sal_False;
2178 //                        }
2179                         if ( 0 != lcl_FormatNextCntntForKeep( this ) && !GetNext() )
2180                         {
2181                             bValidPos = sal_False;
2182                         }
2183                         // <--
2184 					}
2185 				}
2186 			}
2187 		}
2188 
2189 		//Wieder ein Wert ungueltig? - dann nochmal das ganze...
2190 		if ( !bValidPos || !bValidSize || !bValidPrtArea )
2191 			continue;
2192 
2193         // check, if calculation of table frame is ready.
2194 
2195         /// OD 23.10.2002 #103517# - Local variable <nDistanceToUpperPrtBottom>
2196         ///     Introduce local variable and init it with the distance from the
2197         ///     table frame bottom to the bottom of the upper printing area.
2198         /// Note: negative values denotes the situation that table frame doesn't
2199         ///     fit in its upper.
2200 
2201         SwTwips nDistanceToUpperPrtBottom =
2202                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
2203 
2204         /// OD 23.10.2002 #103517# - In online layout try to grow upper of table
2205         /// frame, if table frame doesn't fit in its upper.
2206         const ViewShell *pSh = getRootFrm()->GetCurrShell();
2207         const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
2208         if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode )
2209         {
2210             if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) )
2211             {
2212                 // upper is grown --> recalculate <nDistanceToUpperPrtBottom>
2213                 nDistanceToUpperPrtBottom =
2214                     (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
2215             }
2216         }
2217 
2218         // If there is still some space left in the upper, we check if we
2219         // can join some rows of the follow.
2220         // Setting bLastRowHasToMoveToFollow to true means we want to force
2221         // the table to be split! Only skip this if condition once.
2222         if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow )
2223         {
2224             // OD 23.10.2002 - translate german commentary
2225             // If there is space left in the upper printing area, join as for trial
2226             // at least one further row of an existing follow.
2227 			if ( !bSplit && GetFollow() )
2228 			{
2229 				sal_Bool bDummy;
2230 				if ( GetFollow()->ShouldBwdMoved( GetUpper(), sal_False, bDummy ) )
2231 				{
2232                     SwFrm *pTmp = GetUpper();
2233                     SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)();
2234                     if ( bBrowseMode )
2235                         nDeadLine += pTmp->Grow( LONG_MAX, sal_True );
2236                     if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 )
2237 					{
2238                         //
2239                         // First, we remove an existing follow flow line.
2240                         //
2241                         if ( HasFollowFlowLine() )
2242                         {
2243                             SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower());
2244                             RemoveFollowFlowLine();
2245                             // invalidate and rebuild last row
2246                             if ( pLastLine )
2247                             {
2248                                 ::SwInvalidateAll( pLastLine, LONG_MAX );
2249                                 SetRebuildLastLine( sal_True );
2250                                 lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX );
2251                                 SetRebuildLastLine( sal_False );
2252                             }
2253 
2254                             SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow();
2255 
2256                             if ( !pRow || !pRow->GetNext() )
2257     							//Der Follow wird leer und damit ueberfluessig.
2258                                 Join();
2259 
2260                             continue;
2261                         }
2262 
2263                         //
2264                         // If there is no follow flow line, we move the first
2265                         // row in the follow table to the master table.
2266                         //
2267                         SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow();
2268 
2269   						//Der Follow wird leer und damit ueberfluessig.
2270            				if ( !pRow )
2271                         {
2272                             Join();
2273                             continue;
2274                         }
2275 
2276                         const SwTwips nOld = (Frm().*fnRect->fnGetHeight)();
2277                         long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow );
2278                         SwFrm* pRowToMove = pRow;
2279 
2280                         while ( pRowToMove && nRowsToMove-- > 0 )
2281                         {
2282 						    const sal_Bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked();
2283 
2284                             SwFtnBossFrm *pOldBoss = 0;
2285 					    	if ( bMoveFtns )
2286 				    			pOldBoss = pRowToMove->FindFtnBossFrm( sal_True );
2287 
2288                             SwFrm* pNextRow = pRowToMove->GetNext();
2289 
2290 		    				if ( !pNextRow )
2291 	    						//Der Follow wird leer und damit ueberfluessig.
2292                                 Join();
2293                             else
2294 						    {
2295 							    pRowToMove->Cut();
2296 							    pRowToMove->Paste( this );
2297                             }
2298 
2299 						    //Die Fussnoten verschieben!
2300 						    if ( bMoveFtns )
2301 							    if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns(
2302 							    	 0, pOldBoss, FindFtnBossFrm( sal_True ), sal_True ) )
2303 						    		GetUpper()->Calc();
2304 
2305                             pRowToMove = pNextRow;
2306                         }
2307 
2308                         if ( nOld != (Frm().*fnRect->fnGetHeight)() )
2309                             lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify );
2310 
2311                         continue;
2312 					}
2313 				}
2314 			}
2315 			else if ( KEEPTAB )
2316 			{
2317                 bool bFormat = false;
2318                 if ( bKeep )
2319                     bFormat = true;
2320                 else if ( bTableRowKeep && !bLastRowMoveNoMoreTries )
2321                 {
2322                     // We only want to give the last row one chance to move
2323                     // to the follow table. Set the flag as early as possible:
2324                     bLastRowMoveNoMoreTries = true;
2325 
2326                     // The last line of the table has to be cut off if:
2327                     // 1. The table does not want to keep with its next
2328                     // 2. The compatibility option is set and the table is allowed to split
2329                     // 3. We did not already cut off the last row
2330                     // 4. There is not break after attribute set at the table
2331                     // 5. There is no break before attribute set behind the table
2332                     // 6. There is no section change behind the table (see IsKeep)
2333                     // 7. The last table row wants to keep with its next.
2334                     const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower());
2335                     if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) &&
2336                          pLastRow->ShouldRowKeepWithNext() )
2337                         bFormat = true;
2338                 }
2339 
2340                 if ( bFormat )
2341                 {
2342                     delete pAccess;
2343 
2344                     // --> OD 2005-09-28 #b6329202#
2345                     // Consider case that table is inside another table, because
2346                     // it has to be avoided, that superior table is formatted.
2347                     // Thus, find next content, table or section and, if a section
2348                     // is found, get its first content.
2349                     const SwFrm* pTmpNxt = lcl_FormatNextCntntForKeep( this );
2350                     // <--
2351 
2352                     pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2353                     pAttrs = pAccess->Get();
2354 
2355                     // The last row wants to keep with the frame behind the table.
2356                     // Check if the next frame is on a different page and valid.
2357                     // In this case we do a magic trick:
2358                     if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() )
2359                     {
2360                         bValidPos = sal_False;
2361                         bLastRowHasToMoveToFollow = true;
2362                     }
2363                 }
2364 			}
2365 
2366 			if ( IsValid() )
2367 			{
2368 				if ( bCalcLowers )
2369 				{
2370                     lcl_RecalcTable( *this, 0, aNotify );
2371 					bLowersFormatted = sal_True;
2372 					bCalcLowers = sal_False;
2373 				}
2374 				else if ( bONECalcLowers )
2375 				{
2376                     lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2377 					bONECalcLowers = sal_False;
2378 				}
2379 			}
2380 			continue;
2381 		}
2382 
2383         //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
2384 		//an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
2385 
2386 		//Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
2387 		//ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
2388 		//mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
2389 		//zwar mit aller Kraft.
2390 		if ( !bMoveable )
2391 		{
2392 			if ( bCalcLowers && IsValid() )
2393 			{
2394                 lcl_RecalcTable( *this, 0, aNotify );
2395 				bLowersFormatted = sal_True;
2396 				bCalcLowers = sal_False;
2397 			}
2398 			else if ( bONECalcLowers )
2399 			{
2400                 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2401 				bONECalcLowers = sal_False;
2402 			}
2403 
2404             // It does not make sense to cut off the last line if we are
2405             // not moveable:
2406             bLastRowHasToMoveToFollow = false;
2407 
2408 			continue;
2409 		}
2410 
2411         if ( bCalcLowers && IsValid() )
2412 		{
2413             lcl_RecalcTable( *this, 0, aNotify );
2414 			bLowersFormatted = sal_True;
2415 			bCalcLowers = sal_False;
2416             if( !IsValid() )
2417                 continue;
2418 		}
2419 
2420         //
2421         // First try to split the table. Condition:
2422         // 1. We have at least one non headline row
2423         // 2. If this row wants to keep, we need an additional row
2424         // 3. The table is allowed to split or we do not have an pIndPrev:
2425         //
2426 		SwFrm* pIndPrev = GetIndPrev();
2427         const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
2428 
2429         if ( pFirstNonHeadlineRow && nUnSplitted > 0 &&
2430              ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() ) &&
2431              ( !bDontSplit || !pIndPrev ) )
2432         {
2433             // --> FME 2004-06-03 #i29438#
2434             // Special DoNotSplit case:
2435             // We better avoid splitting of a row frame if we are inside a columned
2436             // section which has a height of 0, because this is not growable and thus
2437             // all kinds of unexpected things could happen.
2438             const SwSectionFrm* pTmpSct = 0;
2439             if ( IsInSct() &&
2440                 (pTmpSct = FindSctFrm())->Lower()->IsColumnFrm() &&
2441                 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)()  )
2442             {
2443                 bTryToSplit = false;
2444             }
2445             // <--
2446 
2447             // 1. Try: bTryToSplit = true  => Try to split the row.
2448             // 2. Try: bTryToSplit = false => Split the table between the rows.
2449 			if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit )
2450             {
2451                 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
2452                 if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE)
2453                     nDeadLine = (*fnRect->fnYInc)( nDeadLine,
2454                                         GetUpper()->Grow( LONG_MAX, sal_True ) );
2455 
2456                 ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine );
2457                 bLowersFormatted = sal_True;
2458                 aNotify.SetLowersComplete( sal_True );
2459 
2460                 // One more check if its really necessary to split the table.
2461                 // 1. The table either has to exceed the deadline or
2462                 // 2. We explicitly want to cut off the last row.
2463                 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow )
2464                 {
2465                     continue;
2466                 }
2467 
2468                 // Set to false again as early as possible.
2469                 bLastRowHasToMoveToFollow = false;
2470 
2471                 // --> FME 2005-08-03 #i52781#
2472                 // YaSC - Yet another special case:
2473                 // If our upper is inside a table cell which is not allowed
2474                 // to split, we do not try to split:
2475                 if ( GetUpper()->IsInTab() )
2476                 {
2477                     const SwFrm* pTmpRow = GetUpper();
2478                     while ( pTmpRow && !pTmpRow->IsRowFrm() )
2479                        pTmpRow = pTmpRow->GetUpper();
2480                     if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() )
2481                         continue;
2482                 }
2483                 // <--
2484 
2485                 sal_uInt16 nMinNumOfLines = nRepeat;
2486 
2487                 if ( bTableRowKeep )
2488                 {
2489                     const SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
2490                     while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
2491                     {
2492                         ++nMinNumOfLines;
2493                         pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext());
2494                     }
2495                     // Check if all lines want to keep together and we
2496                     // have a pIndPrev. In this case we set nDeadLine
2497                     // to 0, forcing the table to move forward.
2498                     if ( !pTmpRow && pIndPrev )
2499                         nDeadLine = 0;
2500                 }
2501 
2502                 if ( !bTryToSplit )
2503                     ++nMinNumOfLines;
2504 
2505                 const SwTwips nBreakLine = (*fnRect->fnYInc)(
2506                         (Frm().*fnRect->fnGetTop)(),
2507                         (this->*fnRect->fnGetTopMargin)() +
2508                          lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) );
2509 
2510                 // Some more checks if we want to call the split algorithm or not:
2511                 // The repeating lines / keeping lines still fit into the upper or
2512                 // if we do not have an (in)direkt Prev, we split anyway.
2513                 if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev )
2514                 {
2515                     aNotify.SetLowersComplete( sal_False );
2516                     bSplit = sal_True;
2517 
2518                     //
2519                     // An existing follow flow line has to be removed.
2520                     //
2521                     if ( HasFollowFlowLine() )
2522 						RemoveFollowFlowLine();
2523 
2524                     const bool bSplitError = !Split( nDeadLine, bTryToSplit, bTableRowKeep );
2525 					if( !bTryToSplit && !bSplitError && nUnSplitted > 0 )
2526 						--nUnSplitted;
2527 
2528                     // --> FME 2004-06-09 #i29771# Two tries to split the table:
2529                     // If an error occured during splitting. We start a second
2530                     // try, this time without splitting of table rows.
2531                     if ( bSplitError )
2532                     {
2533                         if ( HasFollowFlowLine() )
2534                             RemoveFollowFlowLine();
2535                     }
2536 
2537                     // --> FME 2005-02-10 #119477#
2538                     // If splitting the table was successfull or not,
2539                     // we do not want to have 'empty' follow tables.
2540                     if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() )
2541                         Join();
2542                     // <--
2543 
2544 
2545                     // We want to restore the situation before the failed
2546                     // split operation as good as possible. Therefore we
2547                     // do some more calculations. Note: Restricting this
2548                     // to nDeadLine may not be enough.
2549                     if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426
2550                     {
2551                         lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2552                         bValidPos = sal_False;
2553     					bTryToSplit = false;
2554                         continue;
2555                     }
2556                     // <--
2557 
2558   					bTryToSplit = !bSplitError;
2559 
2560                     //Damit es nicht zu Oszillationen kommt, muss der
2561                     //Follow gleich gueltig gemacht werden.
2562                     if ( GetFollow() )
2563                     {
2564                         // --> OD 2007-11-30 #i80924#
2565                         // After a successful split assure that the first row
2566                         // is invalid. When graphics are present, this isn't hold.
2567                         // Note: defect i80924 could also be fixed, if it is
2568                         // assured, that <SwLayNotify::bLowersComplete> is only
2569                         // set, if all lower are valid *and* are correct laid out.
2570                         if ( !bSplitError && GetFollow()->GetLower() )
2571                         {
2572                             GetFollow()->GetLower()->InvalidatePos();
2573                         }
2574                         // <--
2575                         SWRECTFNX( GetFollow() )
2576 
2577                         static sal_uInt8 nStack = 0;
2578                         if ( !StackHack::IsLocked() && nStack < 4 )
2579                         {
2580                             ++nStack;
2581                             StackHack aHack;
2582                             delete pAccess;
2583 
2584                             GetFollow()->MakeAll();
2585 
2586                             pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2587                             pAttrs = pAccess->Get();
2588 
2589                             ((SwTabFrm*)GetFollow())->SetLowersFormatted(sal_False);
2590                             // --> OD 2005-03-30 #i43913# - lock follow table
2591                             // to avoid its formatting during the format of
2592                             // its content.
2593                             const bool bOldJoinLock =  GetFollow()->IsJoinLocked();
2594                             GetFollow()->LockJoin();
2595                             // <--
2596                             ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()),
2597                                              (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() );
2598                             // --> OD 2005-03-30 #i43913#
2599                             // --> FME 2006-04-05 #i63632# Do not unlock the
2600                             // follow if it wasn't locked before.
2601                             if ( !bOldJoinLock )
2602                                 GetFollow()->UnlockJoin();
2603                             // <--
2604 
2605                             if ( !GetFollow()->GetFollow() )
2606                             {
2607                                 SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext();
2608                                 if ( pNxt )
2609                                 {
2610                                     // OD 26.08.2003 #i18103# - no formatting
2611                                     // of found next frame, if its a follow
2612                                     // section of the 'ColLocked' section,
2613                                     // the follow table is in.
2614                                     bool bCalcNxt = true;
2615                                     if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() )
2616                                     {
2617                                         SwSectionFrm* pSct = GetFollow()->FindSctFrm();
2618                                         if ( pSct->IsColLocked() &&
2619                                              pSct->GetFollow() == pNxt )
2620                                         {
2621                                             bCalcNxt = false;
2622                                         }
2623                                     }
2624                                     if ( bCalcNxt )
2625                                     {
2626                                         pNxt->Calc();
2627                                     }
2628                                 }
2629                             }
2630                             --nStack;
2631                         }
2632                         else if ( GetFollow() == GetNext() )
2633                             ((SwTabFrm*)GetFollow())->MoveFwd( sal_True, sal_False );
2634                     }
2635                     continue;
2636                 }
2637             }
2638         }
2639 
2640         // Set to false again as early as possible.
2641         bLastRowHasToMoveToFollow = false;
2642 
2643 		if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() &&
2644 			GetUpper()->GetUpper()->GetUpper()->IsSctFrm() &&
2645 			( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) &&
2646 			((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) )
2647 			bMovedFwd = sal_False;
2648 
2649         // --> FME 2004-06-09 #i29771# Reset bTryToSplit flag on change of upper
2650         const SwFrm* pOldUpper = GetUpper();
2651         // <--
2652 
2653         //Mal sehen ob ich irgenwo Platz finde...
2654         if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
2655             bMakePage = sal_False;
2656 
2657         // --> FME 2004-06-09 #i29771# Reset bSplitError flag on change of upper
2658         if ( GetUpper() != pOldUpper )
2659 		{
2660             bTryToSplit = true;
2661 			nUnSplitted = 5;
2662 		}
2663         // <--
2664 
2665         SWREFRESHFN( this )
2666         bMovedFwd = bCalcLowers = sal_True;
2667         aNotify.SetLowersComplete( sal_False );
2668 		if ( IsFollow() )
2669 		{	//Um Oszillationen zu vermeiden sollte kein ungueltiger Master
2670 			//zurueckbleiben.
2671 			SwTabFrm *pTab = FindMaster();
2672 			if ( pTab->GetUpper() )
2673 				pTab->GetUpper()->Calc();
2674 			pTab->Calc();
2675 			pTab->SetLowersFormatted( sal_False );
2676 		}
2677 
2678 		//Wenn mein direkter Nachbar jetzt gleichzeitig mein Follow ist
2679 		//verleibe ich mir das Teil ein.
2680 		if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() )
2681         {
2682             if ( HasFollowFlowLine() )
2683                 RemoveFollowFlowLine();
2684             if ( GetFollow() )
2685                 Join();
2686         }
2687 
2688 		if ( bMovedBwd && GetUpper() )
2689 			//Beim zurueckfliessen wurde der Upper angeregt sich vollstaendig
2690 			//zu Painten, dass koennen wir uns jetzt nach dem hin und her
2691 			//fliessen sparen.
2692 			GetUpper()->ResetCompletePaint();
2693 
2694         if ( bCalcLowers && IsValid() )
2695 		{
2696             // --> OD 2005-05-11 #i44910# - format of lower frames unnecessary
2697             // and can cause layout loops, if table doesn't fit and isn't
2698             // allowed to split.
2699             SwTwips nDistToUpperPrtBottom =
2700                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
2701             if ( nDistToUpperPrtBottom >= 0 || bTryToSplit )
2702             {
2703                 lcl_RecalcTable( *this, 0, aNotify );
2704                 bLowersFormatted = sal_True;
2705                 bCalcLowers = sal_False;
2706             }
2707 #if OSL_DEBUG_LEVEL > 1
2708             else
2709             {
2710                 ASSERT( false, "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" );
2711             }
2712 #endif
2713             // <--
2714 		}
2715 
2716 	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )
2717 
2718 	//Wenn mein direkter Vorgaenger jetzt mein Master ist, so kann er mich
2719 	//bei der nachstbesten Gelegenheit vernichten.
2720 	if ( IsFollow() )
2721 	{
2722 		SwFrm *pPre = GetPrev();
2723 		if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
2724 			pPre->InvalidatePos();
2725 	}
2726 
2727 	bCalcLowers = bONECalcLowers = sal_False;
2728 	delete pAccess;
2729 	UnlockJoin();
2730     if ( bMovedFwd || bMovedBwd || !bOldValidPos )
2731 		aNotify.SetInvaKeep();
2732 }
2733 
2734 /*************************************************************************
2735 |*
2736 |*	SwTabFrm::CalcFlyOffsets()
2737 |*
2738 |*	Beschreibung:		Berechnet die Offsets, die durch FlyFrames
2739 |*						entstehen.
2740 |*	Ersterstellung		MA/MIB 14. Apr. 99
2741 |*	Letzte Aenderung
2742 |*
2743 |*************************************************************************/
2744 sal_Bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper,
2745 							   long& rLeftOffset,
2746 							   long& rRightOffset ) const
2747 {
2748 	sal_Bool bInvalidatePrtArea = sal_False;
2749 	const SwPageFrm *pPage = FindPageFrm();
2750 	const SwFlyFrm* pMyFly = FindFlyFrm();
2751 
2752     // --> #108724# Page header/footer content doesn't have to wrap around
2753     //              floating screen objects
2754 
2755     const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess();
2756     const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ||
2757                                 ( !IsInFtn() && 0 == FindFooterOrHeader() );
2758     // <--
2759 
2760 	if ( pPage->GetSortedObjs() && bWrapAllowed )
2761 	{
2762         SWRECTFN( this )
2763         const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
2764         long nPrtPos = (Frm().*fnRect->fnGetTop)();
2765         nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper );
2766 		SwRect aRect( Frm() );
2767         long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper );
2768         if( nYDiff > 0 )
2769             (aRect.*fnRect->fnAddBottom)( -nYDiff );
2770 		for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
2771 		{
2772             SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
2773             if ( pAnchoredObj->ISA(SwFlyFrm) )
2774 			{
2775                 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
2776                 const SwRect aFlyRect = pFly->GetObjRectWithSpaces();
2777                 // --> OD 2004-10-07 #i26945# - correction of conditions,
2778                 // if Writer fly frame has to be considered:
2779                 // - no need to check, if top of Writer fly frame differs
2780                 //   from WEIT_WECH, because its also check, if the Writer
2781                 //   fly frame rectangle overlaps with <aRect>
2782                 // - no check, if bottom of anchor frame is prior the top of
2783                 //   the table, because Writer fly frames can be negative positioned.
2784                 // - correct check, if the Writer fly frame is an lower of the
2785                 //   table, because table lines/rows can split and a at-character
2786                 //   anchored Writer fly frame could be positioned in the follow
2787                 //   flow line.
2788                 // - add condition, that an existing anchor character text frame
2789                 //   has to be on the same page as the table.
2790                 //   E.g., it could happen, that the fly frame is still registered
2791                 //   at the page frame, the table is on, but it's anchor character
2792                 //   text frame has already changed its page.
2793                 //if ( WEIT_WECH != (pFly->Frm().*fnRect->fnGetTop)() &&
2794                 //     pFly->IsFlyAtCntFrm() && aFlyRect.IsOver( aRect ) &&
2795                 //     // OD 25.02.2003 #i9040# - use '<=' instead of '<'
2796                 //     (*fnRect->fnYDiff)(
2797                 //            (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetBottom)(),
2798                 //            (Frm().*fnRect->fnGetTop)() ) <= 0 &&
2799                 //     !IsAnLower( pFly ) && !pFly->IsAnLower( this ) &&
2800                 //     ( !pMyFly || pMyFly->IsAnLower( pFly ) ) &&
2801                 //     pPage->GetPhyPageNum() >=
2802                 //     pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
2803                 //     // anchor should be in same page body/header/footer
2804                 //     ( pFly->GetAnchorFrm()->FindFooterOrHeader() ==
2805                 //       FindFooterOrHeader() ) )
2806                 const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm();
2807                 bool bConsiderFly =
2808                     // --> OD 2005-04-06 #i46807# - do not consider invalid
2809                     // Writer fly frames.
2810                     pFly->IsValid() &&
2811                     // <--
2812                     // fly anchored at character
2813                     pFly->IsFlyAtCntFrm() &&
2814                     // fly overlaps with corresponding table rectangle
2815                     aFlyRect.IsOver( aRect ) &&
2816                     // fly isn't lower of table and
2817                     // anchor character frame of fly isn't lower of table
2818                     ( !IsAnLower( pFly ) &&
2819                       ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) &&
2820                     // table isn't lower of fly
2821                     !pFly->IsAnLower( this ) &&
2822                     // fly is lower of fly, the table is in
2823                     // --> OD 2005-05-31 #123274# - correction:
2824                     // assure that fly isn't a lower of a fly, the table isn't in.
2825                     // E.g., a table in the body doesn't wrap around a graphic,
2826                     // which is inside a frame.
2827                     ( ( !pMyFly ||
2828                         pMyFly->IsAnLower( pFly ) ) &&
2829                       pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) &&
2830                     // <--
2831                     // anchor frame not on following page
2832                     pPage->GetPhyPageNum() >=
2833                       pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
2834                     // anchor character text frame on same page
2835                     ( !pAnchorCharFrm ||
2836                       pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() ==
2837                         pPage->GetPhyPageNum() );
2838 
2839                 if ( bConsiderFly )
2840                 {
2841                     const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader();
2842                     const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader();
2843 
2844                     if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm &&
2845                         // --> FME 2007-07-02 #148493# If bConsiderWrapOnObjPos is set,
2846                         // we want to consider the fly if it is located in the header and
2847                         // the table is located in the body:
2848                          ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) )
2849                         bConsiderFly = false;
2850                         // <--
2851                 }
2852 
2853                 if ( bConsiderFly )
2854                 // <--
2855 				{
2856 					const SwFmtSurround   &rSur = pFly->GetFmt()->GetSurround();
2857 					const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient();
2858 					if ( SURROUND_NONE == rSur.GetSurround() )
2859 					{
2860                         long nBottom = (aFlyRect.*fnRect->fnGetBottom)();
2861                         if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 )
2862                             nPrtPos = nBottom;
2863 						bInvalidatePrtArea = sal_True;
2864 					}
2865 					if ( (SURROUND_RIGHT	== rSur.GetSurround() ||
2866 						  SURROUND_PARALLEL == rSur.GetSurround())&&
2867                          text::HoriOrientation::LEFT == rHori.GetHoriOrient() )
2868 					{
2869                         const long nWidth = (*fnRect->fnXDiff)(
2870                             (aFlyRect.*fnRect->fnGetRight)(),
2871                             (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() );
2872 						rLeftOffset = Max( rLeftOffset, nWidth );
2873 						bInvalidatePrtArea = sal_True;
2874 					}
2875 					if ( (SURROUND_LEFT		== rSur.GetSurround() ||
2876 						  SURROUND_PARALLEL == rSur.GetSurround())&&
2877                          text::HoriOrientation::RIGHT == rHori.GetHoriOrient() )
2878 					{
2879                         const long nWidth = (*fnRect->fnXDiff)(
2880                             (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(),
2881                             (aFlyRect.*fnRect->fnGetLeft)() );
2882 						rRightOffset = Max( rRightOffset, nWidth );
2883 						bInvalidatePrtArea = sal_True;
2884 					}
2885 				}
2886 			}
2887 		}
2888         rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() );
2889 	}
2890 
2891 	return bInvalidatePrtArea;
2892 }
2893 
2894 /*************************************************************************
2895 |*
2896 |*	SwTabFrm::Format()
2897 |*
2898 |*	Beschreibung:		"Formatiert" den Frame; Frm und PrtArea
2899 |*						Die Fixsize wird hier nicht eingestellt.
2900 |*	Ersterstellung		MA 09. Mar. 93
2901 |*	Letzte Aenderung	MA 18. Jun. 97
2902 |*
2903 |*************************************************************************/
2904 void SwTabFrm::Format( const SwBorderAttrs *pAttrs )
2905 {
2906 	ASSERT( pAttrs, "TabFrm::Format, pAttrs ist 0." );
2907 
2908     SWRECTFN( this )
2909 	if ( !bValidSize )
2910     {
2911         long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() -
2912                      (Frm().*fnRect->fnGetWidth)();
2913         if( nDiff )
2914             (aFrm.*fnRect->fnAddRight)( nDiff );
2915     }
2916 
2917 	//VarSize ist immer die Hoehe.
2918 	//Fuer den oberen/unteren Rand gelten die selben Regeln wie fuer
2919 	//cntfrms (sie MakePrtArea() von diesen).
2920 
2921 	SwTwips nUpper = CalcUpperSpace( pAttrs );
2922 
2923 	//Wir wollen Rahmen ausweichen. Zwei Moeglichkeiten:
2924 	//1. Es gibt Rahmen mit SurroundNone, diesen wird vollsaendig ausgewichen
2925 	//2. Es gibt Rahmen mit Umlauf nur rechts bzw. nur links und diese sind
2926 	//   rechts bzw. links ausgerichtet, diese geben ein Minimum fuer die
2927 	//	 Raender vor.
2928 	long nTmpRight = -1000000,
2929 		 nLeftOffset  = 0;
2930 	if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
2931 		bValidPrtArea = sal_False;
2932 	long nRightOffset = Max( 0L, nTmpRight );
2933 
2934 	SwTwips nLower = pAttrs->CalcBottomLine();
2935     // --> collapsing borders FME 2005-05-27 #i29550#
2936     if ( IsCollapsingBorders() )
2937         nLower += GetBottomLineSize();
2938     // <-- collapsing
2939 
2940     if ( !bValidPrtArea )
2941 	{	bValidPrtArea = sal_True;
2942 
2943 		//Die Breite der PrtArea wird vom FrmFmt vorgegeben, die Raender
2944 		//sind entsprechend einzustellen.
2945 		//Mindestraender werden von Umrandung und Schatten vorgegeben.
2946 		//Die Rander werden so eingestellt, dass die PrtArea nach dem
2947 		//angegebenen Adjustment im Frm ausgerichtet wird.
2948 		//Wenn das Adjustment 0 ist, so werden die Rander anhand des
2949 		//Randattributes eingestellt.
2950 
2951         const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)();
2952         const SwTwips nMax = (aFrm.*fnRect->fnGetWidth)();
2953 
2954         // OD 14.03.2003 #i9040# - adjust variable names.
2955         const SwTwips nLeftLine  = pAttrs->CalcLeftLine();
2956         const SwTwips nRightLine = pAttrs->CalcRightLine();
2957 
2958 		//Die Breite ist evtl. eine Prozentangabe. Wenn die Tabelle irgendwo
2959 		//'drinsteckt bezieht sie sich auf die Umgebung. Ist es der Body, so
2960 		//bezieht sie sich in der BrowseView auf die Bildschirmbreite.
2961 		const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
2962         // OD 14.03.2003 #i9040# - adjust variable name.
2963         const SwTwips nWishedTableWidth = CalcRel( rSz, sal_True );
2964 
2965 		sal_Bool bCheckBrowseWidth = sal_False;
2966 
2967         // OD 14.03.2003 #i9040# - insert new variables for left/right spacing.
2968         SwTwips nLeftSpacing  = 0;
2969         SwTwips nRightSpacing = 0;
2970         switch ( GetFmt()->GetHoriOrient().GetHoriOrient() )
2971 		{
2972             case text::HoriOrientation::LEFT:
2973 				{
2974                     // left indent:
2975                     nLeftSpacing = nLeftLine + nLeftOffset;
2976                     // OD 06.03.2003 #i9040# - correct calculation of right indent:
2977                     // - Consider right indent given by right line attributes.
2978                     // - Consider negative right indent.
2979                     // wished right indent determined by wished table width and
2980                     // left offset given by surround fly frames on the left:
2981                     const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset;
2982                     if ( nRightOffset > 0 )
2983                     {
2984                         // surrounding fly frames on the right
2985                         // -> right indent is maximun of given right offset
2986                         //    and wished right offset.
2987                         nRightSpacing = nRightLine + Max( nRightOffset, nWishRight );
2988                     }
2989                     else
2990                     {
2991                         // no surrounding fly frames on the right
2992                         // If intrinsic right indent (intrinsic means not considering
2993                         // determined left indent) is negative,
2994                         //      then hold this intrinsic indent,
2995                         //      otherwise non negative wished right indent is hold.
2996                         nRightSpacing = nRightLine +
2997                                         ( ( (nWishRight+nLeftOffset) < 0 ) ?
2998                                             (nWishRight+nLeftOffset) :
2999                                             Max( 0L, nWishRight ) );
3000                     }
3001 				}
3002 				break;
3003             case text::HoriOrientation::RIGHT:
3004 				{
3005                     // right indent:
3006                     nRightSpacing = nRightLine + nRightOffset;
3007                     // OD 06.03.2003 #i9040# - correct calculation of left indent:
3008                     // - Consider left indent given by left line attributes.
3009                     // - Consider negative left indent.
3010                     // wished left indent determined by wished table width and
3011                     // right offset given by surrounding fyl frames on the right:
3012                     const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset;
3013                     if ( nLeftOffset > 0 )
3014                     {
3015                         // surrounding fly frames on the left
3016                         // -> right indent is maximun of given left offset
3017                         //    and wished left offset.
3018                         nLeftSpacing = nLeftLine + Max( nLeftOffset, nWishLeft );
3019                     }
3020                     else
3021                     {
3022                         // no surrounding fly frames on the left
3023                         // If intrinsic left indent (intrinsic = not considering
3024                         // determined right indent) is negative,
3025                         //      then hold this intrinsic indent,
3026                         //      otherwise non negative wished left indent is hold.
3027                         nLeftSpacing = nLeftLine +
3028                                        ( ( (nWishLeft+nRightOffset) < 0 ) ?
3029                                            (nWishLeft+nRightOffset) :
3030                                            Max( 0L, nWishLeft ) );
3031                     }
3032 				}
3033 				break;
3034             case text::HoriOrientation::CENTER:
3035 				{
3036                     // OD 07.03.2003 #i9040# - consider left/right line attribute.
3037                     // OD 10.03.2003 #i9040# -
3038                     const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2;
3039                     nLeftSpacing = nLeftLine +
3040                                    ( (nLeftOffset > 0) ?
3041                                      Max( nCenterSpacing, nLeftOffset ) :
3042                                      nCenterSpacing );
3043                     nRightSpacing = nRightLine +
3044                                     ( (nRightOffset > 0) ?
3045                                       Max( nCenterSpacing, nRightOffset ) :
3046                                       nCenterSpacing );
3047 				}
3048 				break;
3049             case text::HoriOrientation::FULL:
3050 					//Das Teil dehnt sich ueber die gesamte Breite aus.
3051 					//Nur die fuer die Umrandung benoetigten Freiraeume
3052 					//werden beruecksichtigt.
3053 					//Die Attributwerte von LRSpace werden bewusst missachtet!
3054 					bCheckBrowseWidth = sal_True;
3055                     nLeftSpacing  = nLeftLine + nLeftOffset;
3056                     nRightSpacing = nRightLine + nRightOffset;
3057 				break;
3058             case text::HoriOrientation::NONE:
3059 				{
3060 					//Die Raender werden vom Randattribut bestimmt.
3061                     nLeftSpacing = pAttrs->CalcLeft( this );
3062 					if( nLeftOffset )
3063 					{
3064                         // OD 07.03.2003 #i9040# - surround fly frames only, if
3065                         // they overlap with the table.
3066                         // Thus, take maximun of left spacing and left offset.
3067                         // OD 10.03.2003 #i9040# - consider left line attribute.
3068                         nLeftSpacing = Max( nLeftSpacing, ( nLeftOffset + nLeftLine ) );
3069 					}
3070                     // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
3071                     nRightSpacing = pAttrs->CalcRight( this );
3072 					if( nRightOffset )
3073 					{
3074                         // OD 07.03.2003 #i9040# - surround fly frames only, if
3075                         // they overlap with the table.
3076                         // Thus, take maximun of right spacing and right offset.
3077                         // OD 10.03.2003 #i9040# - consider right line attribute.
3078                         nRightSpacing = Max( nRightSpacing, ( nRightOffset + nRightLine ) );
3079 					}
3080                     // OD 10.03.2003 #i9040# - do not hold wished table width.
3081                     /*
3082                     if ( !pAttrs->GetLRSpace().GetRight() )
3083 						nRight = Max( nRight, nMax - (nWish + nLeft + nRight));
3084                     */
3085 				}
3086 				break;
3087             case text::HoriOrientation::LEFT_AND_WIDTH:
3088                 {
3089 					//Linker Rand und die Breite zaehlen (Word-Spezialitaet)
3090                     // OD 10.03.2003 #i9040# - no width alignment in online mode.
3091                     //bCheckBrowseWidth = sal_True;
3092                     nLeftSpacing = pAttrs->CalcLeft( this );
3093 					if( nLeftOffset )
3094 					{
3095                         // OD 10.03.2003 #i9040# - surround fly frames only, if
3096                         // they overlap with the table.
3097                         // Thus, take maximun of right spacing and right offset.
3098                         // OD 10.03.2003 #i9040# - consider left line attribute.
3099                         nLeftSpacing = Max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) );
3100 					}
3101                     // OD 10.03.2003 #i9040# - consider right and left line attribute.
3102                     const SwTwips nWishRight =
3103                             nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth;
3104                     nRightSpacing = nRightLine +
3105                                     ( (nRightOffset > 0) ?
3106                                       Max( nWishRight, nRightOffset ) :
3107                                       nWishRight );
3108                 }
3109 				break;
3110 			default:
3111 				ASSERT( sal_False, "Ungueltige orientation fuer Table." );
3112 		}
3113 
3114         // --> OD 2004-07-15 #i26250# - extend bottom printing area, if table
3115         // is last content inside a table cell.
3116         if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) &&
3117              GetUpper()->IsInTab() && !GetIndNext() )
3118         {
3119             nLower += pAttrs->GetULSpace().GetLower();
3120         }
3121         // <--
3122         (this->*fnRect->fnSetYMargins)( nUpper, nLower );
3123         if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) )
3124             (this->*fnRect->fnSetXMargins)( 0, 0 );
3125 		else
3126             (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing );
3127 
3128         ViewShell *pSh = getRootFrm()->GetCurrShell();
3129         if ( bCheckBrowseWidth &&
3130              pSh && pSh->GetViewOptions()->getBrowseMode() &&
3131 			 GetUpper()->IsPageBodyFrm() &&  // nur PageBodyFrms, nicht etwa ColBodyFrms
3132 			 pSh->VisArea().Width() )
3133 		{
3134 			//Nicht ueber die Kante des sichbaren Bereiches hinausragen.
3135 			//Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
3136 			//geben kann (RootFrm::ImplCalcBrowseWidth())
3137 			long nWidth = pSh->GetBrowseWidth();
3138 			nWidth -= Prt().Left();
3139 			nWidth -= pAttrs->CalcRightLine();
3140 			Prt().Width( Min( nWidth, Prt().Width() ) );
3141 		}
3142 
3143         if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() )
3144 			bValidSize = sal_False;
3145 	}
3146 
3147 	if ( !bValidSize )
3148 	{
3149 		bValidSize = sal_True;
3150 
3151 		//Die Groesse wird durch den Inhalt plus den Raendern bestimmt.
3152 		SwTwips nRemaining = 0, nDiff;
3153 		SwFrm *pFrm = pLower;
3154 		while ( pFrm )
3155         {
3156             nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
3157             pFrm = pFrm->GetNext();
3158 		}
3159 		//Jetzt noch die Raender addieren
3160 		nRemaining += nUpper + nLower;
3161 
3162         nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
3163         if ( nDiff > 0 )
3164             Shrink( nDiff );
3165 		else if ( nDiff < 0 )
3166             Grow( -nDiff );
3167 	}
3168 }
3169 /*************************************************************************
3170 |*
3171 |*	SwTabFrm::GrowFrm()
3172 |*
3173 |*	Ersterstellung		MA 12. Mar. 93
3174 |*	Letzte Aenderung	MA 23. Sep. 96
3175 |*
3176 |*************************************************************************/
3177 SwTwips SwTabFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
3178 {
3179     SWRECTFN( this )
3180     SwTwips nHeight =(Frm().*fnRect->fnGetHeight)();
3181     if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) )
3182         nDist = LONG_MAX - nHeight;
3183 
3184     if ( bTst && !IsRestrictTableGrowth() )
3185         return nDist;
3186 
3187     if ( GetUpper() )
3188     {
3189         SwRect aOldFrm( Frm() );
3190 
3191         //Der Upper wird nur soweit wie notwendig gegrowed. In nReal wird erstmal
3192         //die bereits zur Verfuegung stehende Strecke bereitgestellt.
3193         SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
3194         SwFrm *pFrm = GetUpper()->Lower();
3195         while ( pFrm && GetFollow() != pFrm )
3196         {
3197             nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
3198             pFrm = pFrm->GetNext();
3199         }
3200 
3201         long nTmp = 0;
3202         if ( nReal < nDist )
3203         {
3204             nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo );
3205 
3206             if ( IsRestrictTableGrowth() )
3207             {
3208                 nTmp = Min( nDist, nReal + nTmp );
3209                 nDist = nTmp < 0 ? 0 : nTmp;
3210             }
3211         }
3212 
3213         if ( !bTst )
3214         {
3215             (Frm().*fnRect->fnAddBottom)( nDist );
3216 
3217             SwRootFrm *pRootFrm = getRootFrm();
3218             if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
3219                 pRootFrm->GetCurrShell() )
3220             {
3221                 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
3222             }
3223         }
3224     }
3225 
3226     if ( !bTst && ( nDist || IsRestrictTableGrowth() ) )
3227     {
3228         SwPageFrm *pPage = FindPageFrm();
3229         if ( GetNext() )
3230         {
3231             GetNext()->_InvalidatePos();
3232             if ( GetNext()->IsCntntFrm() )
3233                 GetNext()->InvalidatePage( pPage );
3234         }
3235         // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
3236         // frame on the next page/column can flow backward (e.g. it was moved
3237         // forward due to the positioning of its objects ). Thus, invalivate this
3238         // next frame, if document compatibility option 'Consider wrapping style
3239         // influence on object positioning' is ON.
3240         else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
3241         {
3242             InvalidateNextPos();
3243         }
3244         // <--
3245         _InvalidateAll();
3246         InvalidatePage( pPage );
3247         SetComplete();
3248 
3249         const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
3250         if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
3251             SetCompletePaint();
3252     }
3253 
3254     return nDist;
3255 }
3256 /*************************************************************************
3257 |*
3258 |*	  SwTabFrm::Modify()
3259 |*
3260 |*	  Ersterstellung	MA 14. Mar. 93
3261 |*	  Letzte Aenderung	MA 06. Dec. 96
3262 |*
3263 |*************************************************************************/
3264 void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
3265 {
3266 	sal_uInt8 nInvFlags = 0;
3267 	sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
3268 
3269 	if( bAttrSetChg )
3270 	{
3271 		SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
3272 		SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
3273 		SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
3274 		SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
3275 		while( sal_True )
3276 		{
3277 			_UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
3278 						 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
3279 						 &aOldSet, &aNewSet );
3280 			if( aNIter.IsAtEnd() )
3281 				break;
3282 			aNIter.NextItem();
3283 			aOIter.NextItem();
3284 		}
3285 		if ( aOldSet.Count() || aNewSet.Count() )
3286 			SwLayoutFrm::Modify( &aOldSet, &aNewSet );
3287 	}
3288 	else
3289 		_UpdateAttr( pOld, pNew, nInvFlags );
3290 
3291 	if ( nInvFlags != 0 )
3292 	{
3293 		SwPageFrm *pPage = FindPageFrm();
3294 		InvalidatePage( pPage );
3295 //		if ( nInvFlags & 0x01 )
3296 //			SetCompletePaint();
3297 		if ( nInvFlags & 0x02 )
3298 			_InvalidatePrt();
3299 		if ( nInvFlags & 0x40 )
3300 			_InvalidatePos();
3301 		SwFrm *pTmp;
3302 		if ( 0 != (pTmp = GetIndNext()) )
3303 		{
3304 			if ( nInvFlags & 0x04 )
3305 			{
3306 				pTmp->_InvalidatePrt();
3307 				if ( pTmp->IsCntntFrm() )
3308 					pTmp->InvalidatePage( pPage );
3309 			}
3310 			if ( nInvFlags & 0x10 )
3311 				pTmp->SetCompletePaint();
3312 		}
3313 		if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) )
3314 		{
3315 			pTmp->_InvalidatePrt();
3316 			if ( pTmp->IsCntntFrm() )
3317 				pTmp->InvalidatePage( pPage );
3318 		}
3319 		if ( nInvFlags & 0x20  )
3320 		{
3321 			if ( pPage && pPage->GetUpper() && !IsFollow() )
3322 				((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3323 		}
3324 		if ( nInvFlags & 0x80 )
3325 			InvalidateNextPos();
3326 	}
3327 }
3328 
3329 void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
3330 							sal_uInt8 &rInvFlags,
3331 							SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
3332 {
3333 	sal_Bool bClear = sal_True;
3334 	const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
3335 	switch( nWhich )
3336 	{
3337 		case RES_TBLHEADLINECHG:
3338 			if ( IsFollow() )
3339 			{
3340                 // Delete remaining headlines:
3341                 SwRowFrm* pLowerRow = 0;
3342                 while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() )
3343                 {
3344                     pLowerRow->Cut();
3345                     delete pLowerRow;
3346                 }
3347 
3348                 // insert new headlines
3349                 const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat();
3350                 for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx )
3351                 {
3352                     bDontCreateObjects = sal_True;          //frmtool
3353                     SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this );
3354                     pHeadline->SetRepeatedHeadline( true );
3355                     bDontCreateObjects = sal_False;
3356                     pHeadline->Paste( this, pLowerRow );
3357                 }
3358             }
3359             rInvFlags |= 0x02;
3360 			break;
3361 
3362 		case RES_FRM_SIZE:
3363 		case RES_HORI_ORIENT:
3364 			rInvFlags |= 0x22;
3365 			break;
3366 
3367 		case RES_PAGEDESC:						//Attributaenderung (an/aus)
3368 			if ( IsInDocBody() )
3369 			{
3370 				rInvFlags |= 0x40;
3371 				SwPageFrm *pPage = FindPageFrm();
3372 				if ( !GetPrev() )
3373 					CheckPageDescs( pPage );
3374 				if ( pPage && GetFmt()->GetPageDesc().GetNumOffset() )
3375 					((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
3376 				SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
3377 				GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
3378 			}
3379 			break;
3380 
3381 		case RES_BREAK:
3382 			rInvFlags |= 0xC0;
3383 			break;
3384 
3385 		case RES_LAYOUT_SPLIT:
3386 			if ( !IsFollow() )
3387 				rInvFlags |= 0x40;
3388 			break;
3389         case RES_FRAMEDIR :
3390             SetDerivedR2L( sal_False );
3391             CheckDirChange();
3392             break;
3393         case RES_COLLAPSING_BORDERS :
3394     		rInvFlags |= 0x02;
3395             lcl_InvalidateAllLowersPrt( this );
3396             break;
3397 		case RES_UL_SPACE:
3398 			rInvFlags |= 0x1C;
3399 			/* kein Break hier */
3400 
3401 		default:
3402 			bClear = sal_False;
3403 	}
3404 	if ( bClear )
3405 	{
3406 		if ( pOldSet || pNewSet )
3407 		{
3408 			if ( pOldSet )
3409 				pOldSet->ClearItem( nWhich );
3410 			if ( pNewSet )
3411 				pNewSet->ClearItem( nWhich );
3412 		}
3413 		else
3414 			SwLayoutFrm::Modify( pOld, pNew );
3415 	}
3416 }
3417 
3418 /*************************************************************************
3419 |*
3420 |*	  SwTabFrm::GetInfo()
3421 |*
3422 |*	  Ersterstellung	MA 06. Dec. 96
3423 |*	  Letzte Aenderung	MA 26. Jun. 98
3424 |*
3425 |*************************************************************************/
3426 sal_Bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const
3427 {
3428 	if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() )
3429 	{
3430 		SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
3431 		const SwPageFrm *pPage = FindPageFrm();
3432 		if ( pPage  )
3433 		{
3434 			if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
3435 			{
3436 				//Das sollte er sein (kann allenfalls temporaer anders sein,
3437 				//					  sollte uns das beunruhigen?)
3438 				rInfo.SetInfo( pPage, this );
3439 				return sal_False;
3440 			}
3441 			if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
3442 				 (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
3443 			{
3444 				//Das koennte er sein.
3445 				rInfo.SetInfo( pPage, this );
3446 			}
3447 		}
3448 	}
3449 	return sal_True;
3450 }
3451 
3452 /*************************************************************************
3453 |*
3454 |*	  SwTabFrm::FindLastCntnt()
3455 |*
3456 |*	  Ersterstellung	MA 13. Apr. 93
3457 |*	  Letzte Aenderung	MA 15. May. 98
3458 |*
3459 |*************************************************************************/
3460 SwCntntFrm *SwTabFrm::FindLastCntnt()
3461 {
3462 	SwFrm *pRet = pLower;
3463 
3464 	while ( pRet && !pRet->IsCntntFrm() )
3465 	{
3466 		SwFrm *pOld = pRet;
3467 
3468         SwFrm *pTmp = pRet;             // To skip empty section frames
3469 		while ( pRet->GetNext() )
3470         {
3471 			pRet = pRet->GetNext();
3472             if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() )
3473                 pTmp = pRet;
3474         }
3475         pRet = pTmp;
3476 
3477 		if ( pRet->GetLower() )
3478 			pRet = pRet->GetLower();
3479 		if ( pRet == pOld )
3480         {
3481             // Wenn am Ende der letzten Zelle ein spaltiger Bereich steht,
3482 			// der eine leere letzte Spalte hat, muessen wir noch die anderen
3483 			// Spalten abklappern, dies erledigt SwSectionFrm::FindLastCntnt
3484 			if( pRet->IsColBodyFrm() )
3485 			{
3486 #ifdef DBG_UTIL
3487 				SwSectionFrm* pSect = pRet->FindSctFrm();
3488 				ASSERT( pSect, "Wo kommt denn die Spalte her?")
3489 				ASSERT( IsAnLower( pSect ), "Gespaltene Zelle?" );
3490 #endif
3491 				return pRet->FindSctFrm()->FindLastCntnt();
3492 			}
3493 
3494             //
3495             // pRet may be a cell frame without a lower (cell has been split).
3496             // We have to find the last content the hard way:
3497             //
3498             ASSERT( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" )
3499             const SwFrm* pRow = pRet->GetUpper();
3500             while ( pRow && !pRow->GetUpper()->IsTabFrm() )
3501                 pRow = pRow->GetUpper();
3502             SwCntntFrm* pCntntFrm = ((SwLayoutFrm*)pRow)->ContainsCntnt();
3503             pRet = 0;
3504 
3505             while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) )
3506             {
3507                 pRet = pCntntFrm;
3508                 pCntntFrm = pCntntFrm->GetNextCntntFrm();
3509             }
3510         }
3511     }
3512 
3513     // #112929# There actually is a situation, which results in pRet = 0:
3514     // Insert frame, insert table via text <-> table. This gives you a frame
3515     // containing a table without any other content frames. Split the table
3516     // and undo the splitting. This operation gives us a table frame without
3517     // a lower.
3518     if ( pRet )
3519     {
3520         while ( pRet->GetNext() )
3521 			pRet = pRet->GetNext();
3522 
3523         if( pRet->IsSctFrm() )
3524 		    pRet = ((SwSectionFrm*)pRet)->FindLastCntnt();
3525     }
3526 
3527     return (SwCntntFrm*)pRet;
3528 }
3529 
3530 /*************************************************************************
3531 |*
3532 |*	SwTabFrm::GetLeaf()
3533 |*
3534 |*	Ersterstellung		MA 19. Mar. 93
3535 |*	Letzte Aenderung	MA 25. Apr. 95
3536 |*
3537 |*************************************************************************/
3538 SwLayoutFrm *SwTabFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
3539 {
3540 	SwLayoutFrm *pRet;
3541 	if ( bFwd )
3542 	{
3543 		pRet = GetNextLeaf( eMakePage );
3544 		while ( IsAnLower( pRet ) )
3545 			pRet = pRet->GetNextLeaf( eMakePage );
3546 	}
3547 	else
3548 		pRet = GetPrevLeaf();
3549 	if ( pRet )
3550 		pRet->Calc();
3551 	return pRet;
3552 }
3553 
3554 /*************************************************************************
3555 |*
3556 |*	SwTabFrm::ShouldBwdMoved()
3557 |*
3558 |* 	Beschreibung		Returnwert sagt ob der Frm verschoben werden sollte
3559 |*	Ersterstellung		MA 10. Jul. 95
3560 |*	Letzte Aenderung	MA 04. Mar. 97
3561 |*
3562 |*************************************************************************/
3563 sal_Bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool &rReformat )
3564 {
3565 	rReformat = sal_False;
3566 	if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) )
3567 	{
3568 		//Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
3569 		//Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
3570 		//moechte die FixSize die gleiche ist, die der Frm selbst hat.
3571 		//In diesem Fall kann einfach geprueft werden, ob der Frm genug
3572 		//Platz fuer seine VarSize findet, ist dies nicht der Fall kann
3573 		//gleich auf das Verschieben verzichtet werden.
3574 		//Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
3575 		//durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
3576 		//aufspalten kann.
3577 		//Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
3578 		//(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
3579 		//der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
3580 		//etwas Platz zur Verfuegung steht).
3581 
3582 		//Die FixSize der Umgebungen in denen Tabellen herumlungern ist immer
3583 		//Die Breite.
3584 
3585 		SwPageFrm *pOldPage = FindPageFrm(),
3586 				  *pNewPage = pNewUpper->FindPageFrm();
3587 		sal_Bool bMoveAnyway = sal_False;
3588 		SwTwips nSpace = 0;
3589 
3590         SWRECTFN( this )
3591         if ( !SwFlowFrm::IsMoveBwdJump() )
3592         {
3593 
3594             long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
3595             SWRECTFNX( pNewUpper );
3596             long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)();
3597             if( Abs( nNewWidth - nOldWidth ) < 2 )
3598             {
3599                 if( sal_False ==
3600                     ( bMoveAnyway = BwdMoveNecessary( pOldPage, Frm() ) > 1 ) )
3601                 {
3602                     SwRect aRect( pNewUpper->Prt() );
3603                     aRect.Pos() += pNewUpper->Frm().Pos();
3604                     const SwFrm *pPrevFrm = pNewUpper->Lower();
3605                     while ( pPrevFrm && pPrevFrm != this )
3606                     {
3607                         (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX->
3608                                                     fnGetBottom)() );
3609                         pPrevFrm = pPrevFrm->GetNext();
3610                     }
3611                     bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1;
3612 
3613                     // --> FME 2006-01-20 #i54861# Due to changes made in PrepareMake,
3614                     // the tabfrm may not have a correct position. Therefore
3615                     // it is possible that pNewUpper->Prt().Height == 0. In this
3616                     // case the above calculation of nSpace might give wrong
3617                     // results and we really do not want to MoveBackwrd into a
3618                     // 0 height frame. If nTmpSpace is already <= 0, we take this
3619                     // value:
3620                     const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)();
3621                     if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 )
3622                         nSpace = nTmpSpace;
3623                     // <--
3624 
3625                     const ViewShell *pSh = getRootFrm()->GetCurrShell();
3626                     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
3627                         nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
3628                 }
3629             }
3630             else if( !bLockBackMove )
3631                 bMoveAnyway = sal_True;
3632 		}
3633         else if( !bLockBackMove )
3634 			bMoveAnyway = sal_True;
3635 
3636 		if ( bMoveAnyway )
3637 			return rReformat = sal_True;
3638 		else if ( !bLockBackMove && nSpace > 0 )
3639 		{
3640             // --> OD 2004-10-05 #i26945# - check, if follow flow line
3641             // contains frame, which are moved forward due to its object
3642             // positioning.
3643             SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
3644             if ( pFirstRow && pFirstRow->IsInFollowFlowRow() &&
3645                  SwLayouter::DoesRowContainMovedFwdFrm(
3646                                             *(pFirstRow->GetFmt()->GetDoc()),
3647                                             *(pFirstRow) ) )
3648             {
3649                 return sal_False;
3650             }
3651             // <--
3652             SwTwips nTmpHeight = CalcHeightOfFirstContentLine();
3653 
3654             // --> FME 2005-01-17 #118840#
3655             // For some mysterious reason, I changed the good old
3656             // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'.
3657             // This obviously results in problems with table frames in
3658             // sections. Remember: Every twip is sacred.
3659             return nTmpHeight <= nSpace;
3660             // <--
3661         }
3662 	}
3663 	return sal_False;
3664 }
3665 
3666 /*************************************************************************
3667 |*
3668 |*	SwTabFrm::Cut()
3669 |*
3670 |*	Ersterstellung		MA 23. Feb. 94
3671 |*	Letzte Aenderung	MA 09. Sep. 98
3672 |*
3673 |*************************************************************************/
3674 void SwTabFrm::Cut()
3675 {
3676 	ASSERT( GetUpper(), "Cut ohne Upper()." );
3677 
3678 	SwPageFrm *pPage = FindPageFrm();
3679 	InvalidatePage( pPage );
3680 	SwFrm *pFrm = GetNext();
3681 	if( pFrm )
3682 	{	//Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
3683 		//berechnet der ist jetzt wo er der erste wird obsolete
3684 		pFrm->_InvalidatePrt();
3685 		pFrm->_InvalidatePos();
3686 		if ( pFrm->IsCntntFrm() )
3687 			pFrm->InvalidatePage( pPage );
3688 		if( IsInSct() && !GetPrev() )
3689 		{
3690 			SwSectionFrm* pSct = FindSctFrm();
3691 			if( !pSct->IsFollow() )
3692 			{
3693 				pSct->_InvalidatePrt();
3694 				pSct->InvalidatePage( pPage );
3695 			}
3696 		}
3697 	}
3698 	else
3699 	{
3700 		InvalidateNextPos();
3701 		//Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
3702 		if ( 0 != (pFrm = GetPrev()) )
3703 		{	pFrm->SetRetouche();
3704 			pFrm->Prepare( PREP_WIDOWS_ORPHANS );
3705 			pFrm->_InvalidatePos();
3706 			if ( pFrm->IsCntntFrm() )
3707 				pFrm->InvalidatePage( pPage );
3708 		}
3709 		//Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
3710 		//er die Retouche uebernehmen.
3711 		//Ausserdem kann eine Leerseite entstanden sein.
3712 		else
3713 		{	SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
3714 			pRoot->SetSuperfluous();
3715 			GetUpper()->SetCompletePaint();
3716 			if( IsInSct() )
3717 			{
3718 				SwSectionFrm* pSct = FindSctFrm();
3719 				if( !pSct->IsFollow() )
3720 				{
3721 					pSct->_InvalidatePrt();
3722 					pSct->InvalidatePage( pPage );
3723 				}
3724 			}
3725 		}
3726 	}
3727 
3728 	//Erst removen, dann Upper Shrinken.
3729 	SwLayoutFrm *pUp = GetUpper();
3730     SWRECTFN( this )
3731 	Remove();
3732 	if ( pUp )
3733 	{
3734 		ASSERT( !pUp->IsFtnFrm(), "Tabelle in Fussnote." );
3735 		SwSectionFrm *pSct = 0;
3736         // --> OD 2006-01-04 #126020# - adjust check for empty section
3737         // --> OD 2006-02-01 #130797# - correct fix #126020#
3738         if ( !pUp->Lower() && pUp->IsInSct() &&
3739              !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
3740              !pSct->ContainsAny( true ) )
3741         // <--
3742 		{
3743 			if ( pUp->GetUpper() )
3744 			{
3745 				pSct->DelEmpty( sal_False );
3746 				pSct->_InvalidateSize();
3747 			}
3748 		}
3749         else if( (Frm().*fnRect->fnGetHeight)() )
3750         {
3751             // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section -
3752             // undo changes of fix for #104992#
3753             pUp->Shrink( Frm().Height() );
3754         }
3755 	}
3756 
3757 	if ( pPage && !IsFollow() && pPage->GetUpper() )
3758 		((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3759 }
3760 
3761 /*************************************************************************
3762 |*
3763 |*	SwTabFrm::Paste()
3764 |*
3765 |*	Ersterstellung		MA 23. Feb. 94
3766 |*	Letzte Aenderung	MA 09. Sep. 98
3767 |*
3768 |*************************************************************************/
3769 void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
3770 {
3771 	ASSERT( pParent, "Kein Parent fuer Paste." );
3772 	ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
3773 	ASSERT( pParent != this, "Bin selbst der Parent." );
3774 	ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
3775 	ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
3776 			"Bin noch irgendwo angemeldet." );
3777 
3778 	//In den Baum einhaengen.
3779 	InsertBefore( (SwLayoutFrm*)pParent, pSibling );
3780 
3781 	_InvalidateAll();
3782 	SwPageFrm *pPage = FindPageFrm();
3783 	InvalidatePage( pPage );
3784 
3785 	if ( GetNext() )
3786 	{
3787 		GetNext()->_InvalidatePos();
3788 		GetNext()->_InvalidatePrt();
3789 		if ( GetNext()->IsCntntFrm() )
3790 			GetNext()->InvalidatePage( pPage );
3791 	}
3792 
3793     SWRECTFN( this )
3794     if( (Frm().*fnRect->fnGetHeight)() )
3795         pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
3796 
3797     if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() )
3798 		Prepare( PREP_FIXSIZE_CHG );
3799 	if ( GetPrev() )
3800 	{
3801 		if ( !IsFollow() )
3802 		{
3803 			GetPrev()->InvalidateSize();
3804 			if ( GetPrev()->IsCntntFrm() )
3805 				GetPrev()->InvalidatePage( pPage );
3806 		}
3807 	}
3808 	else if ( GetNext() )
3809 		//Bei CntntFrm's gilt es den Abstand zum Vorgaenger/Nachfolger
3810 		//zu beachten. Faelle (beide treten immer gleichzeitig auf):
3811 		//a) Der Cntnt wird der erste einer Kette
3812 		//b) Der neue Nachfolger war vorher der erste einer Kette
3813 		GetNext()->_InvalidatePrt();
3814 
3815 	if ( pPage && !IsFollow() )
3816 	{
3817 		if ( pPage->GetUpper() )
3818 			((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3819 
3820 		if ( !GetPrev() )//Mindestens fuer HTML mit Tabelle am Anfang notwendig.
3821 		{
3822 			const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc();
3823 			if ( (pDesc && pDesc != pPage->GetPageDesc()) ||
3824 				 (!pDesc && pPage->GetPageDesc() !=
3825                   &(const_cast<const SwDoc *>(GetFmt()->GetDoc())
3826                     ->GetPageDesc(0))) )
3827 				CheckPageDescs( pPage, sal_True );
3828 		}
3829 	}
3830 }
3831 
3832 /*************************************************************************
3833 |*
3834 |*  SwTabFrm::Prepare()
3835 |*
3836 |*  Created        AMA 01/10/02
3837 |*  Last Change    AMA 01/10/02
3838 |*
3839 |*************************************************************************/
3840 void SwTabFrm::Prepare( const PrepareHint eHint, const void *, sal_Bool )
3841 {
3842     if( PREP_BOSS_CHGD == eHint )
3843         CheckDirChange();
3844 }
3845 
3846 /*************************************************************************
3847 |*
3848 |*	SwRowFrm::SwRowFrm(), ~SwRowFrm()
3849 |*
3850 |*	Ersterstellung		MA 09. Mar. 93
3851 |*	Letzte Aenderung	MA 30. May. 96
3852 |*
3853 |*************************************************************************/
3854 SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ):
3855 	SwLayoutFrm( rLine.GetFrmFmt(), pSib ),
3856     pTabLine( &rLine ),
3857     pFollowRow( 0 ),
3858     // --> collapsing borders FME 2005-05-27 #i29550#
3859     mnTopMarginForLowers( 0 ),
3860     mnBottomMarginForLowers( 0 ),
3861     mnBottomLineSize( 0 ),
3862     // <-- collapsing
3863     // --> split table rows
3864     bIsFollowFlowRow( false ),
3865     // <-- split table rows
3866     bIsRepeatedHeadline( false ),
3867     mbIsRowSpanLine( false )
3868 {
3869     nType = FRMC_ROW;
3870 
3871 	//Gleich die Boxen erzeugen und einfuegen.
3872    	const SwTableBoxes &rBoxes = rLine.GetTabBoxes();
3873     SwFrm *pTmpPrev = 0;
3874   	for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
3875    	{
3876         SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent );
3877         pNew->InsertBehind( this, pTmpPrev );
3878         pTmpPrev = pNew;
3879     }
3880 }
3881 
3882 SwRowFrm::~SwRowFrm()
3883 {
3884 	SwModify* pMod = GetFmt();
3885 	if( pMod )
3886 	{
3887 		pMod->Remove( this );			// austragen,
3888 		if( !pMod->GetDepends() )
3889 			delete pMod;				// und loeschen
3890 	}
3891 }
3892 
3893 /*************************************************************************
3894 |*
3895 |*	SwRowFrm::RegistFlys()
3896 |*
3897 |*	Ersterstellung		MA 08. Jul. 93
3898 |*	Letzte Aenderung	MA 08. Jul. 93
3899 |*
3900 |*************************************************************************/
3901 void SwRowFrm::RegistFlys( SwPageFrm *pPage )
3902 {
3903 	::RegistFlys( pPage ? pPage : FindPageFrm(), this );
3904 }
3905 
3906 /*************************************************************************
3907 |*
3908 |*	  SwRowFrm::Modify()
3909 |*
3910 |*	  Ersterstellung	MA 12. Nov. 97
3911 |*	  Letzte Aenderung	MA 12. Nov. 97
3912 |*
3913 |*************************************************************************/
3914 void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
3915 {
3916 	sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
3917 	const SfxPoolItem *pItem = 0;
3918 
3919 	if( bAttrSetChg )
3920     {
3921         const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet();
3922 		pChgSet->GetItemState( RES_FRM_SIZE, sal_False, &pItem);
3923         if ( !pItem )
3924             pChgSet->GetItemState( RES_ROW_SPLIT, sal_False, &pItem);
3925     }
3926     else if ( RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which() )
3927 		pItem = pNew;
3928 
3929 	if ( pItem )
3930 	{
3931 		SwTabFrm *pTab = FindTabFrm();
3932         if ( pTab )
3933         {
3934             const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
3935                                                 this == pTab->GetFirstNonHeadlineRow();
3936             // --> FME 2004-10-27 #i35063#
3937             // Invalidation required is pRow is last row
3938             if ( bInFirstNonHeadlineRow || !GetNext() )
3939             // <--
3940             {
3941                 if ( bInFirstNonHeadlineRow )
3942                     pTab = pTab->FindMaster();
3943                 pTab->InvalidatePos();
3944             }
3945         }
3946 	}
3947 
3948 	SwLayoutFrm::Modify( pOld, pNew );
3949 }
3950 
3951 
3952 
3953 /*************************************************************************
3954 |*
3955 |*	SwRowFrm::MakeAll()
3956 |*
3957 |*	Ersterstellung		MA 01. Mar. 94
3958 |*	Letzte Aenderung	MA 01. Mar. 94
3959 |*
3960 |*************************************************************************/
3961 void SwRowFrm::MakeAll()
3962 {
3963 	if ( !GetNext() )
3964 		bValidSize = sal_False;
3965 	SwLayoutFrm::MakeAll();
3966 }
3967 
3968 /*************************************************************************
3969 |*
3970 |*	SwRowFrm::Format()
3971 |*
3972 |*	Ersterstellung		MA 13. Mar. 93
3973 |*	Letzte Aenderung	MA 20. Jun. 96
3974 |*
3975 |*************************************************************************/
3976 long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm )
3977 {
3978     SWRECTFN( pFrm )
3979 	long nHeight = 0;
3980 	const SwFrm* pTmp = pFrm->IsSctFrm() ?
3981 			((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm;
3982 	while( pTmp )
3983 	{
3984         // --> OD 2004-10-08 #i26945# - consider follow text frames
3985         const SwSortedObjs* pObjs( 0L );
3986         bool bIsFollow( false );
3987         if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() )
3988         {
3989             const SwFrm* pMaster;
3990             // --> FME 2005-04-01 #i46450# Master does not necessarily have
3991             // to exist if this function is called from JoinFrm() ->
3992             // Cut() -> Shrink()
3993             const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp);
3994             if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() &&
3995                  static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() &&
3996                  static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp )
3997                  pMaster = 0;
3998             else
3999                  pMaster = pTmpFrm->FindMaster();
4000 
4001             if ( pMaster )
4002             {
4003                  pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs();
4004                 bIsFollow = true;
4005             }
4006         }
4007         else
4008         {
4009             pObjs = pTmp->GetDrawObjs();
4010         }
4011         if ( pObjs )
4012         // <--
4013 		{
4014             for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
4015 			{
4016                 const SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
4017                 // --> OD 2004-10-08 #i26945# - if <pTmp> is follow, the
4018                 // anchor character frame has to be <pTmp>.
4019                 if ( bIsFollow &&
4020                      const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp )
4021                 {
4022                     continue;
4023                 }
4024                 // <--
4025                 // --> OD 2004-10-04 #i26945# - consider also drawing objects
4026 				{
4027                     // OD 30.09.2003 #i18732# - only objects, which follow
4028                     // the text flow have to be considered.
4029                     const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt();
4030                     const bool bConsiderObj =
4031                         (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) &&
4032                             pAnchoredObj->GetObjRect().Top() != WEIT_WECH &&
4033                             rFrmFmt.GetFollowTextFlow().GetValue() &&
4034                             pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm();
4035                     if ( bConsiderObj )
4036 					{
4037                         const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize();
4038 						if( !rSz.GetHeightPercent() )
4039                         {
4040                             const SwTwips nDistOfFlyBottomToAnchorTop =
4041                                 (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() +
4042                                     ( bVert ?
4043                                       pAnchoredObj->GetCurrRelPos().X() :
4044                                       pAnchoredObj->GetCurrRelPos().Y() );
4045 
4046                             const SwTwips nFrmDiff =
4047                                 (*fnRect->fnYDiff)(
4048                                     (pTmp->Frm().*fnRect->fnGetTop)(),
4049                                     (pFrm->Frm().*fnRect->fnGetTop)() );
4050 
4051                             nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff -
4052                                             (pFrm->Frm().*fnRect->fnGetHeight)() );
4053 
4054                             // --> FME 2006-01-24 #i56115# The first height calculation
4055                             // gives wrong results if pFrm->Prt().Y() > 0. We do
4056                             // a second calculation based on the actual rectangles of
4057                             // pFrm and pAnchoredObj, and use the maximum of the results.
4058                             // I do not want to remove the first calculation because
4059                             // if clipping has been applied, using the GetCurrRelPos
4060                             // might be the better option to calculate nHeight.
4061                             const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)(
4062                                                                             (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(),
4063                                                                             (pFrm->Frm().*fnRect->fnGetBottom)() );
4064 
4065                             nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop2 );
4066                             // <--
4067                         }
4068 					}
4069 				}
4070                 // <--
4071 			}
4072 		}
4073 		if( !pFrm->IsSctFrm() )
4074 			break;
4075 		pTmp = pTmp->FindNextCnt();
4076 		if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) )
4077 			break;
4078 	}
4079 	return nHeight;
4080 }
4081 
4082 SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs )
4083 {
4084     const SwTabFrm* pTab = rCell.FindTabFrm();
4085     SwTwips nTopSpace = 0;
4086     SwTwips nBottomSpace = 0;
4087 
4088     // --> collapsing borders FME 2005-05-27 #i29550#
4089     if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() )
4090     {
4091         nTopSpace    = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers();
4092         nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers();
4093     }
4094     // <-- collapsing
4095     else
4096     {
4097         if ( pTab->IsVertical() != rCell.IsVertical() )
4098         {
4099             nTopSpace    = rAttrs.CalcLeft( &rCell );
4100             nBottomSpace = rAttrs.CalcRight( &rCell );
4101         }
4102         else
4103         {
4104             nTopSpace    = rAttrs.CalcTop();
4105             nBottomSpace = rAttrs.CalcBottom();
4106         }
4107     }
4108 
4109     return nTopSpace + nBottomSpace;
4110 }
4111 
4112 
4113 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
4114 // control, if floating screen objects have to be considered for the minimal
4115 // cell height.
4116 SwTwips MA_FASTCALL lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell,
4117                                            const sal_Bool _bConsiderObjs,
4118                                            const SwBorderAttrs *pAttrs = 0 )
4119 {
4120     SWRECTFN( _pCell )
4121 	SwTwips nHeight = 0;
4122     const SwFrm* pLow = _pCell->Lower();
4123 	if ( pLow )
4124 	{
4125 		long nFlyAdd = 0;
4126 		while ( pLow )
4127 		{
4128             // OD 2004-02-18 #106629# - change condition and switch then-body
4129             // and else-body
4130             if ( pLow->IsRowFrm() )
4131             {
4132                 // --> OD 2004-10-04 #i26945#
4133                 nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow),
4134                                                    _bConsiderObjs );
4135                 // <--
4136             }
4137             else
4138             {
4139                 long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)();
4140                 nHeight += nLowHeight;
4141                 // --> OD 2004-10-04 #i26945#
4142                 if ( _bConsiderObjs )
4143                 {
4144                     nFlyAdd = Max( 0L, nFlyAdd - nLowHeight );
4145                     nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
4146                 }
4147                 // <--
4148 			}
4149 
4150 			pLow = pLow->GetNext();
4151 		}
4152 		if ( nFlyAdd )
4153 			nHeight += nFlyAdd;
4154 	}
4155 	//Der Border will natuerlich auch mitspielen, er kann leider nicht
4156 	//aus PrtArea und Frm errechnet werden, da diese in beliebiger
4157 	//Kombination ungueltig sein koennen.
4158     if ( _pCell->Lower() )
4159     {
4160         if ( pAttrs )
4161             nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs );
4162         else
4163         {
4164             SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell );
4165             const SwBorderAttrs &rAttrs = *aAccess.Get();
4166             nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs );
4167         }
4168     }
4169     return nHeight;
4170 }
4171 
4172 // OD 2004-02-18 #106629# - correct type of 1st parameter
4173 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to control,
4174 // if floating screen objects have to be considered for the minimal cell height
4175 SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm* _pRow,
4176                                           const sal_Bool _bConsiderObjs )
4177 {
4178     SWRECTFN( _pRow )
4179 
4180     const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize();
4181 
4182     if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() )
4183     {
4184         ASSERT( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" )
4185         return rSz.GetHeight();
4186     }
4187 
4188 	SwTwips nHeight = 0;
4189     const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower());
4190 	while ( pLow )
4191 	{
4192         SwTwips nTmp = 0;
4193         const long nRowSpan = pLow->GetLayoutRowSpan();
4194         // --> NEW TABLES
4195         // Consider height of
4196         // 1. current cell if RowSpan == 1
4197         // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1
4198         // 3. master cell if RowSpan == -1
4199         if ( 1 == nRowSpan )
4200         {
4201             nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs );
4202         }
4203         else if ( -1 == nRowSpan )
4204         {
4205             // Height of the last cell of a row span is height of master cell
4206             // minus the height of the other rows which are covered by the master
4207             // cell:
4208             const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true );
4209             nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs );
4210             const SwFrm* pMasterRow = rMaster.GetUpper();
4211             while ( pMasterRow && pMasterRow != _pRow )
4212             {
4213                 nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)();
4214                 pMasterRow = pMasterRow->GetNext();
4215             }
4216         }
4217         // <-- NEW TABLES
4218 
4219         // Do not consider rotated cells:
4220         if ( ( 0 != pLow->IsVertical() ) == ( 0 != bVert ) && nTmp > nHeight )
4221             nHeight = nTmp;
4222 
4223         pLow = static_cast<const SwCellFrm*>(pLow->GetNext());
4224 	}
4225     if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() )
4226 		nHeight = Max( nHeight, rSz.GetHeight() );
4227 	return nHeight;
4228 }
4229 
4230 // --> collapsing borders FME 2005-05-27 #i29550#
4231 
4232 // Calculate the maximum of (TopLineSize + TopLineDist) over all lowers:
4233 sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow )
4234 {
4235     sal_uInt16 nTopSpace = 0;
4236     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4237           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4238     {
4239         sal_uInt16 nTmpTopSpace = 0;
4240         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4241             nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() );
4242         else
4243         {
4244             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4245             const SvxBoxItem& rBoxItem = rSet.GetBox();
4246             nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, sal_True );
4247         }
4248         nTopSpace  = Max( nTopSpace, nTmpTopSpace );
4249     }
4250     return nTopSpace;
4251 }
4252 
4253 // Calculate the maximum of TopLineDist over all lowers:
4254 sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow )
4255 {
4256     sal_uInt16 nTopLineDist = 0;
4257     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4258           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4259     {
4260         sal_uInt16 nTmpTopLineDist = 0;
4261         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4262             nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() );
4263         else
4264         {
4265             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4266             const SvxBoxItem& rBoxItem = rSet.GetBox();
4267             nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP );
4268         }
4269         nTopLineDist = Max( nTopLineDist, nTmpTopLineDist );
4270     }
4271     return nTopLineDist;
4272 }
4273 
4274 // Calculate the maximum of BottomLineSize over all lowers:
4275 sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow )
4276 {
4277     sal_uInt16 nBottomLineSize = 0;
4278     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4279           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4280     {
4281         sal_uInt16 nTmpBottomLineSize = 0;
4282         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4283         {
4284             const SwFrm* pRow = pCurrLower->GetLastLower();
4285             nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow );
4286         }
4287         else
4288         {
4289             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4290             const SvxBoxItem& rBoxItem = rSet.GetBox();
4291             nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, sal_True ) -
4292                                  rBoxItem.GetDistance( BOX_LINE_BOTTOM );
4293         }
4294         nBottomLineSize = Max( nBottomLineSize, nTmpBottomLineSize );
4295     }
4296     return nBottomLineSize;
4297 }
4298 
4299 // Calculate the maximum of BottomLineDist over all lowers:
4300 sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow )
4301 {
4302     sal_uInt16 nBottomLineDist = 0;
4303     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4304           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4305     {
4306         sal_uInt16 nTmpBottomLineDist = 0;
4307         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4308         {
4309             const SwFrm* pRow = pCurrLower->GetLastLower();
4310             nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow );
4311         }
4312         else
4313         {
4314             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4315             const SvxBoxItem& rBoxItem = rSet.GetBox();
4316             nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
4317         }
4318         nBottomLineDist = Max( nBottomLineDist, nTmpBottomLineDist );
4319     }
4320     return nBottomLineDist;
4321 }
4322 
4323 // <-- collapsing
4324 
4325 void SwRowFrm::Format( const SwBorderAttrs *pAttrs )
4326 {
4327     SWRECTFN( this )
4328 	ASSERT( pAttrs, "SwRowFrm::Format ohne Attrs." );
4329 
4330     const sal_Bool bFix = bFixSize;
4331 
4332 	if ( !bValidPrtArea )
4333 	{
4334 		//RowFrms haben keine Umrandung usw. also entspricht die PrtArea immer
4335 		//dem Frm.
4336 		bValidPrtArea = sal_True;
4337 		aPrt.Left( 0 );
4338 		aPrt.Top( 0 );
4339 		aPrt.Width ( aFrm.Width() );
4340 		aPrt.Height( aFrm.Height() );
4341 
4342         // --> collapsing borders FME 2005-05-27 #i29550#
4343         // Here we calculate the top-printing area for the lower cell frames
4344         SwTabFrm* pTabFrm = FindTabFrm();
4345         if ( pTabFrm->IsCollapsingBorders() )
4346         {
4347             const sal_uInt16 nTopSpace        = lcl_GetTopSpace(       *this );
4348             const sal_uInt16 nTopLineDist     = lcl_GetTopLineDist(    *this );
4349             const sal_uInt16 nBottomLineSize  = lcl_GetBottomLineSize( *this );
4350             const sal_uInt16 nBottomLineDist  = lcl_GetBottomLineDist( *this );
4351 
4352 
4353             const SwRowFrm* pPreviousRow = 0;
4354 
4355             // --> FME 2004-09-14 #i32456#
4356             // In order to calculate the top printing area for the lower cell
4357             // frames, we have to find the 'previous' row frame and compare
4358             // the bottom values of the 'previous' row with the 'top' values
4359             // of this row. The best way to find the 'previous' row is to
4360             // use the table structure:
4361             const SwTable* pTable = pTabFrm->GetTable();
4362             const SwTableLine* pPrevTabLine = 0;
4363             const SwRowFrm* pTmpRow = this;
4364 
4365             while ( pTmpRow && !pPrevTabLine )
4366             {
4367                 sal_uInt16 nIdx = 0;
4368                 const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ?
4369                                              pTmpRow->GetTabLine()->GetUpper()->GetTabLines() :
4370                                              pTable->GetTabLines();
4371 
4372                 while ( rLines[ nIdx ] != pTmpRow->GetTabLine() )
4373                     ++nIdx;
4374 
4375                 if ( nIdx > 0 )
4376                 {
4377                     // pTmpRow has a 'previous' row in the table structure:
4378                     pPrevTabLine = rLines[ nIdx - 1 ];
4379                 }
4380                 else
4381                 {
4382                     // pTmpRow is a first row in the table structue.
4383                     // We go up in the table structure:
4384                     pTmpRow = pTmpRow->GetUpper()->GetUpper() &&
4385                               pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ?
4386                               static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) :
4387                               0;
4388                 }
4389             }
4390 
4391             // If we found a 'previous' row, we look for the appropriate row frame:
4392             if ( pPrevTabLine )
4393             {
4394                 SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() );
4395                 for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
4396                 {
4397                     // --> OD 2004-11-23 #115759# - do *not* take repeated
4398                     // headlines, because during split of table it can be
4399                     // invalid and thus can't provide correct border values.
4400                     if ( pRow->GetTabLine() == pPrevTabLine &&
4401                          !pRow->IsRepeatedHeadline() )
4402                     // <--
4403                     {
4404                         pPreviousRow = pRow;
4405                         break;
4406                     }
4407                 }
4408             }
4409             // <--
4410 
4411             sal_uInt16 nTopPrtMargin = nTopSpace;
4412             if ( pPreviousRow )
4413             {
4414                 const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist;
4415                 if ( nTmpPrtMargin > nTopPrtMargin )
4416                     nTopPrtMargin = nTmpPrtMargin;
4417             }
4418 
4419             // table has to be notified if it has to change its lower
4420             // margin due to changes of nBottomLineSize:
4421             if ( !GetNext() && nBottomLineSize != GetBottomLineSize() )
4422                  pTabFrm->_InvalidatePrt();
4423 
4424             // If there are rows nested inside this row, the nested rows
4425             // may not have been calculated yet. Therefore the
4426             // ::lcl_CalcMinRowHeight( this ) operation later in this
4427             // function cannot consider the correct border values. We
4428             // have to trigger the invalidation of the outer row frame
4429             // manually:
4430             // Note: If any further invalidations should be necessary, we
4431             // should consider moving the invalidation stuff to the
4432             // appropriate SwNotify object.
4433             if ( GetUpper()->GetUpper()->IsRowFrm() &&
4434                  ( nBottomLineDist != GetBottomMarginForLowers() ||
4435                    nTopPrtMargin   != GetTopMarginForLowers() ) )
4436                 GetUpper()->GetUpper()->_InvalidateSize();
4437 
4438             SetBottomMarginForLowers( nBottomLineDist );    //  3.
4439             SetBottomLineSize( nBottomLineSize );           //  4.
4440             SetTopMarginForLowers( nTopPrtMargin );         //  5.
4441 
4442         }
4443 // <-- collapsing
4444 	}
4445 
4446 	while ( !bValidSize )
4447 	{
4448 		bValidSize = sal_True;
4449 
4450 #ifdef DBG_UTIL
4451         if ( HasFixSize() )
4452 		{
4453 			const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize();
4454 			ASSERT( rFrmSize.GetSize().Height() > 0, "Hat ihn" );
4455 		}
4456 #endif
4457         const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() -
4458                               ( HasFixSize() && !IsRowSpanLine()
4459                                 ? pAttrs->GetSize().Height()
4460                                 // --> OD 2004-10-04 #i26945#
4461                                 : ::lcl_CalcMinRowHeight( this,
4462                                     FindTabFrm()->IsConsiderObjsForMinCellHeight() ) );
4463                                 // <--
4464         if ( nDiff )
4465 		{
4466             bFixSize = sal_False;
4467 			if ( nDiff > 0 )
4468                 Shrink( nDiff, sal_False, sal_True );
4469 			else if ( nDiff < 0 )
4470                 Grow( -nDiff );
4471             bFixSize = bFix;
4472 		}
4473 	}
4474 
4475     // last row will fill the space in its upper.
4476     if ( !GetNext() )
4477 	{
4478 		//Der letzte fuellt den verbleibenden Raum im Upper aus.
4479         SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)();
4480 		SwFrm *pSibling = GetUpper()->Lower();
4481 		do
4482         {   nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)();
4483 			pSibling = pSibling->GetNext();
4484 		} while ( pSibling );
4485 		if ( nDiff > 0 )
4486 		{
4487             bFixSize = sal_False;
4488             Grow( nDiff );
4489             bFixSize = bFix;
4490 			bValidSize = sal_True;
4491 		}
4492 	}
4493 }
4494 
4495 /*************************************************************************
4496 |*
4497 |*	SwRowFrm::AdjustCells()
4498 |*
4499 |*	Ersterstellung		MA 10. Aug. 93
4500 |*	Letzte Aenderung	MA 16. Dec. 96
4501 |*
4502 |*************************************************************************/
4503 void SwRowFrm::AdjustCells( const SwTwips nHeight, const sal_Bool bHeight )
4504 {
4505 	SwFrm *pFrm = Lower();
4506 	if ( bHeight )
4507 	{
4508 		SwRootFrm *pRootFrm = getRootFrm();
4509         SWRECTFN( this )
4510         SwRect aOldFrm;
4511 
4512         while ( pFrm )
4513         {
4514             SwFrm* pNotify = 0;
4515 
4516             SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm);
4517 
4518             // NEW TABLES
4519             // Which cells need to be adjusted if the current row changes
4520             // its height?
4521 
4522             // Current frame is a covered frame:
4523             // Set new height for covered cell and adjust master cell:
4524             if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
4525             {
4526                 // Set height of current (covered) cell to new line height.
4527                 const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
4528                 if ( nDiff )
4529                 {
4530                     (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
4531                     pCellFrm->_InvalidatePrt();
4532                 }
4533             }
4534 
4535             SwCellFrm* pToAdjust = 0;
4536             SwFrm* pToAdjustRow = 0;
4537 
4538             // If current frame is covered frame, we still want to adjust the
4539             // height of the cell starting the row span
4540             if ( pCellFrm->GetLayoutRowSpan() < 1 )
4541             {
4542                 pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true ));
4543                 pToAdjustRow = pToAdjust->GetUpper();
4544             }
4545             else
4546             {
4547                 pToAdjust = pCellFrm;
4548                 pToAdjustRow = this;
4549             }
4550 
4551             // Set height of master cell to height of all lines spanned by this line.
4552             long nRowSpan = pToAdjust->GetLayoutRowSpan();
4553             SwTwips nSumRowHeight = 0;
4554             while ( pToAdjustRow )
4555             {
4556                 // Use new height for the current row:
4557                 nSumRowHeight += pToAdjustRow == this ?
4558                                  nHeight :
4559                                  (pToAdjustRow->Frm().*fnRect->fnGetHeight)();
4560 
4561                 if ( nRowSpan-- == 1 )
4562                     break;
4563 
4564                 pToAdjustRow = pToAdjustRow->GetNext();
4565             }
4566 
4567             if ( pToAdjustRow && pToAdjustRow != this )
4568                 pToAdjustRow->_InvalidateSize();
4569 
4570             const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)();
4571             if ( nDiff )
4572             {
4573                 aOldFrm = pToAdjust->Frm();
4574                 (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff );
4575                 pNotify = pToAdjust;
4576             }
4577 
4578             if ( pNotify )
4579             {
4580                 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() )
4581                     pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm );
4582 
4583                 pNotify->_InvalidatePrt();
4584             }
4585 
4586 			pFrm = pFrm->GetNext();
4587 		}
4588 	}
4589 	else
4590 	{	while ( pFrm )
4591 		{
4592 			pFrm->_InvalidateAll();
4593 			pFrm = pFrm->GetNext();
4594 		}
4595 	}
4596 	InvalidatePage();
4597 }
4598 
4599 /*************************************************************************
4600 |*
4601 |*	SwRowFrm::Cut()
4602 |*
4603 |*	Ersterstellung		MA 12. Nov. 97
4604 |*	Letzte Aenderung	MA 12. Nov. 97
4605 |*
4606 |*************************************************************************/
4607 void SwRowFrm::Cut()
4608 {
4609 	SwTabFrm *pTab = FindTabFrm();
4610     if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() )
4611     {
4612 		pTab->FindMaster()->InvalidatePos();
4613 	}
4614 
4615     // --> OD 2010-02-17 #i103961#
4616     // notification for accessibility
4617     {
4618         SwRootFrm *pRootFrm = getRootFrm();
4619         if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
4620         {
4621             ViewShell* pVSh = pRootFrm->GetCurrShell();
4622             if ( pVSh && pVSh->Imp() )
4623             {
4624                 SwFrm* pCellFrm( GetLower() );
4625                 while ( pCellFrm )
4626                 {
4627                     ASSERT( pCellFrm->IsCellFrm(),
4628                             "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." );
4629                     pVSh->Imp()->DisposeAccessibleFrm( pCellFrm );
4630 
4631                     pCellFrm = pCellFrm->GetNext();
4632                 }
4633             }
4634         }
4635     }
4636     // <--
4637 
4638 	SwLayoutFrm::Cut();
4639 }
4640 
4641 /*************************************************************************
4642 |*
4643 |*	SwRowFrm::GrowFrm()
4644 |*
4645 |*	Ersterstellung		MA 15. Mar. 93
4646 |*	Letzte Aenderung	MA 05. May. 94
4647 |*
4648 |*************************************************************************/
4649 
4650 
4651 SwTwips SwRowFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
4652 {
4653     SwTwips nReal = 0;
4654 
4655     SwTabFrm* pTab = FindTabFrm();
4656     SWRECTFN( pTab )
4657 
4658     bool bRestrictTableGrowth;
4659     bool bHasFollowFlowLine = pTab->HasFollowFlowLine();
4660 
4661     if ( GetUpper()->IsTabFrm() )
4662     {
4663         const SwRowFrm* pFollowFlowRow = IsInSplitTableRow();
4664         bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine();
4665     }
4666     else
4667     {
4668         ASSERT( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" )
4669         bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine;
4670         ASSERT( !bRestrictTableGrowth || !GetNext(),
4671                 "GetFollowRow for row frame that has a Next" )
4672 
4673         //
4674         // There may still be some space left in my direct upper:
4675         //
4676         const SwTwips nAdditionalSpace =
4677                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() );
4678         if ( bRestrictTableGrowth && nAdditionalSpace > 0 )
4679         {
4680             nReal = Min( nAdditionalSpace, nDist );
4681             nDist -= nReal;
4682             if ( !bTst )
4683                 (Frm().*fnRect->fnAddBottom)( nReal );
4684         }
4685     }
4686 
4687     if ( bRestrictTableGrowth )
4688         pTab->SetRestrictTableGrowth( sal_True );
4689     else
4690     {
4691         // Ok, this looks like a hack, indeed, it is a hack.
4692         // If the current row frame is inside another cell frame,
4693         // and the current row frame has no follow, it should not
4694         // be allowed to grow. In fact, setting bRestrictTableGrowth
4695         // to 'false' does not work, because the surrounding RowFrm
4696         // would set this to 'true'.
4697         pTab->SetFollowFlowLine( sal_False );
4698     }
4699 
4700     nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo);
4701 
4702     pTab->SetRestrictTableGrowth( sal_False );
4703     pTab->SetFollowFlowLine( bHasFollowFlowLine );
4704 
4705 	//Hoehe der Zellen auf den neuesten Stand bringen.
4706 	if ( !bTst )
4707 	{
4708         SWRECTFNX( this )
4709         AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, sal_True );
4710 		if ( nReal )
4711 			SetCompletePaint();
4712 	}
4713 
4714     return nReal;
4715 }
4716 
4717 /*************************************************************************
4718 |*
4719 |*	SwRowFrm::ShrinkFrm()
4720 |*
4721 |*	Ersterstellung		MA 15. Mar. 93
4722 |*	Letzte Aenderung	MA 20. Jun. 96
4723 |*
4724 |*************************************************************************/
4725 SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
4726 {
4727     SWRECTFN( this )
4728     if( HasFixSize() )
4729 	{
4730         AdjustCells( (Prt().*fnRect->fnGetHeight)(), sal_True );
4731 		return 0L;
4732 	}
4733 
4734 	//bInfo wird ggf. vom SwRowFrm::Format auf sal_True gesetzt, hier muss dann
4735 	//entsprechend reagiert werden
4736 	const sal_Bool bShrinkAnyway = bInfo;
4737 
4738 	//Nur soweit Shrinken, wie es der Inhalt der groessten Zelle zulaesst.
4739 	SwTwips nRealDist = nDist;
4740 	{
4741 		const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
4742         SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
4743                              rSz.GetHeight() :
4744                              0;
4745 
4746         // Only necessary to calculate minimal row height if height
4747         // of pRow is at least nMinHeight. Otherwise nMinHeight is the
4748         // minimum height.
4749         if( nMinHeight < (Frm().*fnRect->fnGetHeight)() )
4750 		{
4751             // --> OD 2004-10-04 #i26945#
4752             ASSERT( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." );
4753             const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() );
4754             // <--
4755             nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs );
4756         }
4757 
4758         if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight )
4759             nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight;
4760 	}
4761 	if ( nRealDist < 0 )
4762 		nRealDist = 0;
4763 
4764 	SwTwips nReal = nRealDist;
4765 	if ( nReal )
4766 	{
4767 		if ( !bTst )
4768         {
4769             SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
4770             (Frm().*fnRect->fnSetHeight)( nHeight - nReal );
4771             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
4772             if( IsVertical() && !IsVertLR() && !bRev )
4773                 Frm().Pos().X() += nReal;
4774         }
4775 
4776         SwTwips nTmp = GetUpper()->Shrink( nReal, bTst );
4777 		if ( !bShrinkAnyway && !GetNext() && nTmp != nReal )
4778 		{
4779 			//Der letzte bekommt den Rest im Upper und nimmt deshalb
4780 			//ggf. Ruecksichten (sonst: Endlosschleife)
4781 			if ( !bTst )
4782             {
4783                 nReal -= nTmp;
4784                 SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
4785                 (Frm().*fnRect->fnSetHeight)( nHeight + nReal );
4786                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
4787                 if( IsVertical() && !IsVertLR() && !bRev )
4788                     Frm().Pos().X() -= nReal;
4789             }
4790 			nReal = nTmp;
4791 		}
4792 	}
4793 
4794 	//Geeignet invalidieren und die Hoehe der Zellen auf den neuesten
4795 	//Stand bringen.
4796 	if ( !bTst )
4797 	{
4798 		if ( nReal )
4799 		{
4800 			if ( GetNext() )
4801 				GetNext()->_InvalidatePos();
4802 			_InvalidateAll();
4803 			SetCompletePaint();
4804 
4805 			SwTabFrm *pTab = FindTabFrm();
4806             if ( !pTab->IsRebuildLastLine() && pTab->IsFollow() &&
4807                  this == pTab->GetFirstNonHeadlineRow() )
4808             {
4809                 SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() );
4810                 pMasterTab->InvalidatePos();
4811             }
4812         }
4813         AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, sal_True );
4814 	}
4815 	return nReal;
4816 }
4817 
4818 /*************************************************************************
4819 |*
4820 |*  SwRowFrm::IsRowSplitAllowed()
4821 |*
4822 |*************************************************************************/
4823 bool SwRowFrm::IsRowSplitAllowed() const
4824 {
4825     // Fixed size rows are never allowed to split:
4826     if ( HasFixSize() )
4827     {
4828         ASSERT( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" )
4829         return false;
4830     }
4831 
4832     // Repeated headlines are never allowed to split:
4833     const SwTabFrm* pTabFrm = FindTabFrm();
4834     if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
4835          pTabFrm->IsInHeadline( *this ) )
4836         return false;
4837 
4838     const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt();
4839     const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit();
4840     return 0 != rLP.GetValue();
4841 }
4842 
4843 /*************************************************************************
4844 |*
4845 |*  SwRowFrm::ShouldRowKeepWithNext()
4846 |*
4847 |*************************************************************************/
4848 bool SwRowFrm::ShouldRowKeepWithNext() const
4849 {
4850     bool bRet = false;
4851 
4852     const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower());
4853     const SwFrm* pTxt = pCell->Lower();
4854 
4855     if ( pTxt && pTxt->IsTxtFrm() )
4856     {
4857         bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
4858     }
4859     return bRet;
4860 }
4861 
4862 /*************************************************************************
4863 |*
4864 |*	SwCellFrm::SwCellFrm(), ~SwCellFrm()
4865 |*
4866 |*	Ersterstellung		MA 09. Mar. 93
4867 |*	Letzte Aenderung	MA 30. May. 96
4868 |*
4869 |*************************************************************************/
4870 SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) :
4871 	SwLayoutFrm( rBox.GetFrmFmt(), pSib ),
4872     pTabBox( &rBox )
4873 {
4874     nType = FRMC_CELL;
4875 
4876     if ( !bInsertContent )
4877         return;
4878 
4879 	//Wenn ein StartIdx vorhanden ist, so werden CntntFrms in der Zelle
4880 	//angelegt, andernfalls muessen Rows vorhanden sein und diese werden
4881 	//angelegt.
4882 	if ( rBox.GetSttIdx() )
4883 	{
4884         sal_uLong nIndex = rBox.GetSttIdx();
4885         ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex );
4886 	}
4887 	else
4888 	{
4889 	    const SwTableLines &rLines = rBox.GetTabLines();
4890         SwFrm *pTmpPrev = 0;
4891 		for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
4892 		{
4893 			SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent );
4894             pNew->InsertBehind( this, pTmpPrev );
4895             pTmpPrev = pNew;
4896 		}
4897 	}
4898 }
4899 
4900 SwCellFrm::~SwCellFrm()
4901 {
4902 	SwModify* pMod = GetFmt();
4903 	if( pMod )
4904 	{
4905 		// At this stage the lower frames aren't destroyed already,
4906 		// therfor we have to do a recursive dispose.
4907 		SwRootFrm *pRootFrm = getRootFrm();
4908 		if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
4909 			pRootFrm->GetCurrShell() )
4910 		{
4911 			pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, sal_True );
4912 		}
4913 
4914         pMod->Remove( this );           // austragen,
4915 		if( !pMod->GetDepends() )
4916 			delete pMod;				// und loeschen
4917 	}
4918 }
4919 
4920 /*************************************************************************
4921 |*
4922 |*	SwCellFrm::Format()
4923 |*
4924 |*	Ersterstellung		MA 09. Mar. 93
4925 |*	Letzte Aenderung	MA 29. Jan. 98
4926 |*
4927 |*************************************************************************/
4928 sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva )
4929 {
4930 	sal_Bool bRet = sal_False;
4931 	SwFrm *pFrm = pLay->Lower();
4932     SWRECTFN( pLay )
4933 	while ( pFrm )
4934 	{
4935         long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)();
4936         if( nFrmTop != lYStart )
4937 		{
4938 			bRet = sal_True;
4939             const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop );
4940             const long lDiffX = lYStart - nFrmTop;
4941             (pFrm->Frm().*fnRect->fnSubTop)( -lDiff );
4942             (pFrm->Frm().*fnRect->fnAddBottom)( lDiff );
4943 			pFrm->SetCompletePaint();
4944 			if ( !pFrm->GetNext() )
4945 				pFrm->SetRetouche();
4946 			if( bInva )
4947 				pFrm->Prepare( PREP_POS_CHGD );
4948 			if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() )
4949 				lcl_ArrangeLowers( (SwLayoutFrm*)pFrm,
4950                     (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)()
4951                     + lDiffX, bInva );
4952 			if ( pFrm->GetDrawObjs() )
4953 			{
4954 				for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
4955 				{
4956                     SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
4957                     // --> OD 2004-10-08 #i26945# - check, if anchored object
4958                     // is lower of layout frame by checking, if the anchor
4959                     // frame, which contains the anchor position, is a lower
4960                     // of the layout frame.
4961                     if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) )
4962                     {
4963                         continue;
4964                     }
4965                     // <--
4966                     // --> OD 2005-08-08 #i52904# - distinguish between anchored
4967                     // objects, whose vertical position depends on its anchor
4968                     // frame and whose vertical position is independent
4969                     // from its anchor frame.
4970                     bool bVertPosDepOnAnchor( true );
4971                     {
4972                         SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() );
4973                         switch ( aVert.GetRelationOrient() )
4974                         {
4975                             case text::RelOrientation::PAGE_FRAME:
4976                             case text::RelOrientation::PAGE_PRINT_AREA:
4977                                 bVertPosDepOnAnchor = false;
4978                                 break;
4979                             default: break;
4980                         }
4981                     }
4982                     if ( pAnchoredObj->ISA(SwFlyFrm) )
4983 					{
4984                         SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
4985 
4986                         // OD 2004-05-18 #i28701# - no direct move of objects,
4987                         // which are anchored to-paragraph/to-character, if
4988                         // the wrapping style influence has to be considered
4989                         // on the object positioning.
4990                         // --> OD 2005-08-08 #i52904# - no direct move of objects,
4991                         // whose vertical position doesn't depend on anchor frame.
4992                         const bool bDirectMove =
4993                                 WEIT_WECH != pFly->Frm().Top() &&
4994                                 bVertPosDepOnAnchor &&
4995                                 !pFly->ConsiderObjWrapInfluenceOnObjPos();
4996                         // <--
4997                         if ( bDirectMove )
4998                         {
4999                             (pFly->Frm().*fnRect->fnSubTop)( -lDiff );
5000                             (pFly->Frm().*fnRect->fnAddBottom)( lDiff );
5001                             pFly->GetVirtDrawObj()->SetRectsDirty();
5002                             // --> OD 2004-08-17 - also notify view of <SdrObject>
5003                             // instance, which represents the Writer fly frame in
5004                             // the drawing layer
5005                             pFly->GetVirtDrawObj()->SetChanged();
5006                             // <--
5007                             // --> OD 2006-10-13 #i58280#
5008                             pFly->InvalidateObjRectWithSpaces();
5009                             // <--
5010                         }
5011 
5012                         if ( pFly->IsFlyInCntFrm() )
5013                         {
5014                             static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff );
5015                             // --> OD 2004-12-02 #115759# - reset current relative
5016                             // position to get re-positioned, if not directly moved.
5017                             if ( !bDirectMove )
5018                             {
5019                                 pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
5020                             }
5021                             // <--
5022                         }
5023                         else if( pFly->IsAutoPos() )
5024                         {
5025                             pFly->AddLastCharY( lDiff );
5026                             // OD 2004-05-18 #i28701# - follow-up of #i22341#
5027                             // <mnLastTopOfLine> has also been adjusted.
5028                             pFly->AddLastTopOfLineY( lDiff );
5029                         }
5030                         // --> OD 2004-11-05 #i26945# - re-registration at
5031                         // page frame of anchor frame, if table frame isn't
5032                         // a follow table and table frame isn't in its
5033                         // rebuild of last line.
5034                         const SwTabFrm* pTabFrm = pLay->FindTabFrm();
5035                         // --> OD 2004-11-23 #115759#
5036                         // - save: check, if table frame is found.
5037                         if ( pTabFrm &&
5038                              !( pTabFrm->IsFollow() &&
5039                                 pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
5040                              pFly->IsFlyFreeFrm() )
5041                         // <--
5042                         {
5043                             SwPageFrm* pPageFrm = pFly->GetPageFrm();
5044                             SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
5045                             if ( pPageFrm != pPageOfAnchor )
5046                             {
5047                                 pFly->InvalidatePos();
5048                                 if ( pPageFrm )
5049                                     pPageFrm->MoveFly( pFly, pPageOfAnchor );
5050                                 else
5051                                     pPageOfAnchor->AppendFlyToPage( pFly );
5052                             }
5053                         }
5054                         // <--
5055                         // OD 2004-05-11 #i28701# - Because of the introduction
5056                         // of new positionings and alignments (e.g. aligned at
5057                         // page area, but anchored at-character), the position
5058                         // of the Writer fly frame has to be invalidated.
5059                         pFly->InvalidatePos();
5060 
5061                         // --> OD 2004-11-04 #i26945# - follow-up of #i3317#
5062                         // No arrangement of lowers, if Writer fly frame isn't
5063                         // moved
5064                         if ( bDirectMove &&
5065                              ::lcl_ArrangeLowers( pFly,
5066                                                   (pFly->*fnRect->fnGetPrtTop)(),
5067                                                   bInva ) )
5068                         // <--
5069                         {
5070 							pFly->SetCompletePaint();
5071                         }
5072 					}
5073                     else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
5074                     {
5075                         // --> OD 2004-11-05 #i26945#
5076                         const SwTabFrm* pTabFrm = pLay->FindTabFrm();
5077                         if ( pTabFrm &&
5078                              !( pTabFrm->IsFollow() &&
5079                                 pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
5080                              !pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
5081                                                             == FLY_AS_CHAR )
5082                         {
5083                             SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm();
5084                             SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
5085                             if ( pPageFrm != pPageOfAnchor )
5086                             {
5087                                 pAnchoredObj->InvalidateObjPos();
5088                                 if ( pPageFrm )
5089                                 {
5090                                     pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj );
5091                                 }
5092                                 pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj );
5093                             }
5094                         }
5095                         // --> OD 2004-07-01 #i28701# - adjust last character
5096                         // rectangle and last top of line.
5097                         pAnchoredObj->AddLastCharY( lDiff );
5098                         pAnchoredObj->AddLastTopOfLineY( lDiff );
5099                         // --> OD 2005-08-08 #i52904# - re-introduce direct move
5100                         // of drawing objects
5101                         const bool bDirectMove =
5102                                 static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() &&
5103                                 bVertPosDepOnAnchor &&
5104                                 !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos();
5105                         if ( bDirectMove )
5106                         {
5107                             SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
5108                             if ( bVert )
5109                             {
5110                                 pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) );
5111                             }
5112                             else
5113                             {
5114                                 pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) );
5115                             }
5116                             // --> OD 2006-10-13 #i58280#
5117                             pAnchoredObj->InvalidateObjRectWithSpaces();
5118                             // <--
5119                         }
5120                         // <--
5121                         pAnchoredObj->InvalidateObjPos();
5122                     }
5123                     else
5124                     {
5125                         ASSERT( false,
5126                                 "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" );
5127                     }
5128 				}
5129 			}
5130 		}
5131         // Columns and cells are ordered horizontal, not vertical
5132         if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() )
5133             lYStart = (*fnRect->fnYInc)( lYStart,
5134                                         (pFrm->Frm().*fnRect->fnGetHeight)() );
5135 
5136         // Nowadays, the content inside a cell can flow into the follow table.
5137         // Thus, the cell may only grow up to the end of the environment.
5138         // So the content may have grown, but the cell could not grow.
5139         // Therefore we have to trigger a formatting for the frames, which do
5140         // not fit into the cell anymore:
5141         SwTwips nDistanceToUpperPrtBottom =
5142             (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)());
5143         // --> OD 2006-01-19 #i56146# - Revise fix of issue #i26945#
5144         // do *not* consider content inside fly frames, if it's an undersized paragraph.
5145         // --> OD 2004-10-08 #i26945# - consider content inside fly frames
5146         if ( nDistanceToUpperPrtBottom < 0 &&
5147              ( ( pFrm->IsInFly() &&
5148                  ( !pFrm->IsTxtFrm() ||
5149                    !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) ||
5150                pFrm->IsInSplitTableRow() ) )
5151         // <--
5152         {
5153             pFrm->InvalidatePos();
5154         }
5155 
5156 		pFrm = pFrm->GetNext();
5157 	}
5158 	return bRet;
5159 }
5160 
5161 void SwCellFrm::Format( const SwBorderAttrs *pAttrs )
5162 {
5163     ASSERT( pAttrs, "CellFrm::Format, pAttrs ist 0." );
5164     const SwTabFrm* pTab = FindTabFrm();
5165     SWRECTFN( pTab )
5166 
5167     if ( !bValidPrtArea )
5168 	{
5169 		bValidPrtArea = sal_True;
5170 
5171         //Position einstellen.
5172         if ( Lower() )
5173         {
5174             SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace;
5175             // --> collapsing borders FME 2005-05-27 #i29550#
5176             if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm()  )
5177             {
5178                 const SvxBoxItem& rBoxItem = pAttrs->GetBox();
5179                 nLeftSpace   = rBoxItem.GetDistance( BOX_LINE_LEFT );
5180                 nRightSpace  = rBoxItem.GetDistance( BOX_LINE_RIGHT );
5181                 nTopSpace    =  ((SwRowFrm*)GetUpper())->GetTopMarginForLowers();
5182                 nBottomSpace =  ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers();
5183             }
5184             else
5185             {
5186             // <-- collapsing
5187                 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
5188                 nLeftSpace   = pAttrs->CalcLeft( this );
5189                 nRightSpace  = pAttrs->CalcRight( this );
5190                 nTopSpace    = pAttrs->CalcTop();
5191                 nBottomSpace = pAttrs->CalcBottom();
5192             }
5193             (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace );
5194             (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace );
5195         }
5196     }
5197     // --> OD 2004-10-04 #i26945#
5198     long nRemaining = GetTabBox()->getRowSpan() >= 1 ?
5199                       ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) :
5200                       0;
5201     // <--
5202 	if ( !bValidSize )
5203 	{
5204 		bValidSize = sal_True;
5205 
5206 		//Die VarSize der CellFrms ist immer die Breite.
5207 		//Tatsaechlich ist die Breite jedoch nicht Variabel, sie wird durch das
5208 		//Format vorgegeben. Dieser Vorgegebene Wert muss aber nun wiederum
5209 		//nicht der tatsaechlichen Breite entsprechen. Die Breite wird auf
5210 		//Basis des Attributes errechnet, der Wert im Attribut passt zu dem
5211 		//gewuenschten Wert des TabFrms. Anpassungen die dort vorgenommen
5212 		//wurden werden hier Proportional beruecksichtigt.
5213 		//Wenn die Celle keinen Nachbarn mehr hat beruecksichtigt sie nicht
5214 		//die Attribute, sonder greift sich einfach den Rest des
5215         //Uppers
5216 		SwTwips nWidth;
5217         if ( GetNext() )
5218 		{
5219             const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth();
5220 			nWidth = pAttrs->GetSize().Width();
5221 
5222 			ASSERT( nWish, "Tabelle ohne Breite?" );
5223 			ASSERT( nWidth <= nWish, "Zelle breiter als Tabelle." );
5224 			ASSERT( nWidth > 0, "Box without width" );
5225 
5226             const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
5227             if ( nWish != nPrtWidth )
5228 			{
5229                 // Avoid rounding problems, at least for the new table model
5230                 if ( pTab->GetTable()->IsNewModel() )
5231                 {
5232                     // 1. sum of widths of cells up to this cell (in model)
5233                     const SwTableLine* pTabLine = GetTabBox()->GetUpper();
5234                     const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
5235                     const SwTableBox* pTmpBox = 0;
5236 
5237                     SwTwips nSumWidth = 0;
5238                     sal_uInt16 i = 0;
5239                     do
5240                     {
5241                         pTmpBox = rBoxes[ i++ ];
5242                         nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
5243                     }
5244                     while ( pTmpBox != GetTabBox() );
5245 
5246                     // 2. calculate actual width of cells up to this one
5247                     double nTmpWidth = nSumWidth;
5248                     nTmpWidth *= nPrtWidth;
5249                     nTmpWidth /= nWish;
5250                     nWidth = (SwTwips)nTmpWidth;
5251 
5252                     // 3. calculate frame widths of cells up to this one:
5253                     const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower();
5254                     SwTwips nSumFrameWidths = 0;
5255                     while ( pTmpCell != this )
5256                     {
5257                         nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)();
5258                         pTmpCell = pTmpCell->GetNext();
5259                     }
5260 
5261                     nWidth = nWidth - nSumFrameWidths;
5262                 }
5263                 else
5264                 {
5265                     // #i12092# use double instead of long,
5266                     // otherwise this could lead to overflows
5267                     double nTmpWidth = nWidth;
5268                     nTmpWidth *= nPrtWidth;
5269                     nTmpWidth /= nWish;
5270                     nWidth = (SwTwips)nTmpWidth;
5271                 }
5272             }
5273 		}
5274 		else
5275 		{
5276 			ASSERT( pAttrs->GetSize().Width() > 0, "Box without width" );
5277             nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
5278 			SwFrm *pPre = GetUpper()->Lower();
5279 			while ( pPre != this )
5280             {
5281                 nWidth -= (pPre->Frm().*fnRect->fnGetWidth)();
5282 				pPre = pPre->GetNext();
5283 			}
5284 		}
5285         const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)();
5286         if( IsNeighbourFrm() && IsRightToLeft() )
5287             (Frm().*fnRect->fnSubLeft)( nDiff );
5288         else
5289             (Frm().*fnRect->fnAddRight)( nDiff );
5290         (Prt().*fnRect->fnAddRight)( nDiff );
5291 
5292 		//Jetzt die Hoehe einstellen, sie wird vom Inhalt und den Raendern
5293 		//bestimmt.
5294         const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)();
5295 		if ( nDiffHeight )
5296 		{
5297 			if ( nDiffHeight > 0 )
5298 			{
5299 				//Wieder validieren wenn kein Wachstum stattgefunden hat.
5300 				//Invalidiert wird durch AdjustCells von der Row.
5301                 if ( !Grow( nDiffHeight ) )
5302 					bValidSize = bValidPrtArea = sal_True;
5303 			}
5304 			else
5305 			{
5306 				//Nur dann invalidiert lassen, wenn tatsaechlich
5307 				//geshrinkt wurde; das kann abgelehnt werden, weil alle
5308 				//nebeneinanderliegenden Zellen gleichgross sein muessen.
5309                 if ( !Shrink( -nDiffHeight ) )
5310 					bValidSize = bValidPrtArea = sal_True;
5311 			}
5312 		}
5313 	}
5314 	const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient();
5315 
5316     if ( !Lower() )
5317         return;
5318 
5319     // From now on, all operations are related to the table cell.
5320     SWREFRESHFN( this )
5321 
5322     SwPageFrm* pPg = 0;
5323     if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() &&
5324     // --> OD 2008-07-16 #158225# no vertical alignment of covered cells
5325          !IsCoveredCell() &&
5326     // <--
5327     // --> FME 2004-06-29 #116532# Do not consider vertical alignment in grid mode
5328          !(pPg = FindPageFrm())->HasGrid() )
5329     // <--
5330 	{
5331         if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() )
5332 		{
5333 			//ASSERT fuer HTML-Import!
5334 			ASSERT( !this, "VAlign an Zelle ohne Inhalt" );
5335 			return;
5336 		}
5337 		sal_Bool bVertDir = sal_True;
5338         // --> OD 2005-03-30 #i43913# - no vertical alignment, if wrapping
5339         // style influence is considered on object positioning and
5340         // an object is anchored inside the cell.
5341         const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) );
5342         // <--
5343         //Keine Ausrichtung wenn Rahmen mit Umlauf in die Zelle ragen.
5344 		if ( pPg->GetSortedObjs() )
5345 		{
5346 			SwRect aRect( Prt() ); aRect += Frm().Pos();
5347 			for ( sal_uInt16 i = 0; i < pPg->GetSortedObjs()->Count(); ++i )
5348 			{
5349                 const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i];
5350                 SwRect aTmp( pAnchoredObj->GetObjRect() );
5351 				if ( aTmp.IsOver( aRect ) )
5352 				{
5353                     const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt();
5354                     const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround();
5355 
5356                     if ( SURROUND_THROUGHT != rSur.GetSurround() )
5357 					{
5358                         // frames, which the cell is a lower of, aren't relevant
5359                         if ( pAnchoredObj->ISA(SwFlyFrm) )
5360 						{
5361                             const SwFlyFrm *pFly =
5362                                     static_cast<const SwFlyFrm*>(pAnchoredObj);
5363 							if ( pFly->IsAnLower( this ) )
5364 								continue;
5365 						}
5366 
5367                         const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm();
5368                         // --> OD 2005-03-30 #i43913#
5369                         // --> OD 2005-08-08 #i52904# - no vertical alignment,
5370                         // if object, anchored inside cell, has temporarly
5371                         // consider its wrapping style on object positioning.
5372                         // --> FME 2006-02-01 #i58806# - no vertical alignment
5373                         // if object does not follow the text flow.
5374                         if ( bConsiderWrapOnObjPos ||
5375                              !IsAnLower( pAnch ) ||
5376                              pAnchoredObj->IsTmpConsiderWrapInfluence() ||
5377                              !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() )
5378                         // <--
5379 						{
5380 							bVertDir = sal_False;
5381 							break;
5382 						}
5383 					}
5384 				}
5385 			}
5386 		}
5387 
5388         long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
5389         if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) ||
5390             (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() )
5391 		{
5392 			long lTopOfst = 0,
5393                     nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining;
5394             if ( nDiff >= 0 )
5395 			{
5396 				if ( bVertDir )
5397 				{
5398 					switch ( rOri.GetVertOrient() )
5399 					{
5400                         case text::VertOrientation::CENTER:   lTopOfst = nDiff / 2; break;
5401                         case text::VertOrientation::BOTTOM:   lTopOfst = nDiff;     break;
5402                         default: break;
5403 					};
5404 				}
5405                 long nTmp = (*fnRect->fnYInc)(
5406                                     (this->*fnRect->fnGetPrtTop)(), lTopOfst );
5407                 if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) )
5408 					SetCompletePaint();
5409 			}
5410 		}
5411 	}
5412 	else
5413 	{
5414 		//Ist noch eine alte Ausrichtung beruecksichtigt worden?
5415 		if ( Lower()->IsCntntFrm() )
5416 		{
5417             const long lYStart = (this->*fnRect->fnGetPrtTop)();
5418 			lcl_ArrangeLowers( this, lYStart, sal_True );
5419 		}
5420 	}
5421 }
5422 
5423 /*************************************************************************
5424 |*
5425 |*	  SwCellFrm::Modify()
5426 |*
5427 |*	  Ersterstellung	MA 20. Dec. 96
5428 |*	  Letzte Aenderung	MA 20. Dec. 96
5429 |*
5430 |*************************************************************************/
5431 
5432 void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
5433 {
5434 	sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
5435 	const SfxPoolItem *pItem = 0;
5436 
5437 	if( bAttrSetChg )
5438 		((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, sal_False, &pItem);
5439 	else if ( RES_VERT_ORIENT == pNew->Which() )
5440 		pItem = pNew;
5441 
5442 	if ( pItem )
5443 	{
5444 		sal_Bool bInva = sal_True;
5445         if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() &&
5446              // OD 04.11.2003 #112910#
5447              Lower() && Lower()->IsCntntFrm() )
5448 		{
5449             SWRECTFN( this )
5450             const long lYStart = (this->*fnRect->fnGetPrtTop)();
5451 			bInva = lcl_ArrangeLowers( this, lYStart, sal_False );
5452 		}
5453 		if ( bInva )
5454 		{
5455 			SetCompletePaint();
5456 			InvalidatePrt();
5457 		}
5458 	}
5459 
5460 	if ( ( bAttrSetChg &&
5461 	       SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, sal_False ) ) ||
5462 		 RES_PROTECT == pNew->Which() )
5463 	{
5464 		ViewShell *pSh = getRootFrm()->GetCurrShell();
5465 		if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
5466 			pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
5467 	}
5468 
5469 	if ( bAttrSetChg &&
5470 	     SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, sal_False, &pItem ) )
5471 	{
5472         SetDerivedVert( sal_False );
5473         CheckDirChange();
5474     }
5475 
5476     // --> collapsing borders FME 2005-05-27 #i29550#
5477     if ( bAttrSetChg &&
5478          SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, sal_False, &pItem ) )
5479 	{
5480         SwFrm* pTmpUpper = GetUpper();
5481         while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() )
5482             pTmpUpper = pTmpUpper->GetUpper();
5483 
5484         SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper();
5485         if ( pTabFrm->IsCollapsingBorders() )
5486         {
5487             // Invalidate lowers of this and next row:
5488             lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
5489             pTmpUpper = pTmpUpper->GetNext();
5490             if ( pTmpUpper )
5491                 lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
5492             else
5493                 pTabFrm->InvalidatePrt();
5494         }
5495     }
5496     // <-- collapsing
5497 
5498 	SwLayoutFrm::Modify( pOld, pNew );
5499 }
5500 
5501 /*************************************************************************
5502 |*  SwCellFrm::GetLayoutRowSpan() const
5503 |*************************************************************************/
5504 
5505 long SwCellFrm::GetLayoutRowSpan() const
5506 {
5507     long nRet = GetTabBox()->getRowSpan();
5508     if ( nRet < 1 )
5509     {
5510         const SwFrm* pRow = GetUpper();
5511         const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper());
5512 
5513         if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() )
5514             nRet = -nRet;
5515     }
5516     return  nRet;
5517 }
5518 
5519 // --> OD 2010-02-17 #i103961#
5520 void SwCellFrm::Cut()
5521 {
5522     // notification for accessibility
5523     {
5524         SwRootFrm *pRootFrm = getRootFrm();
5525         if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
5526         {
5527             ViewShell* pVSh = pRootFrm->GetCurrShell();
5528             if ( pVSh && pVSh->Imp() )
5529             {
5530                 pVSh->Imp()->DisposeAccessibleFrm( this );
5531             }
5532         }
5533     }
5534 
5535     SwLayoutFrm::Cut();
5536 }
5537 // <--
5538 
5539 //
5540 // Helper functions for repeated headlines:
5541 //
5542 
5543 /*
5544  * SwTabFrm::IsInHeadline( const SwFrm& rFrm )
5545  */
5546 bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const
5547 {
5548     ASSERT( IsAnLower( &rFrm ) && rFrm.IsInTab(),
5549              "SwTabFrm::IsInHeadline called for frame not lower of table" )
5550 
5551     const SwFrm* pTmp = &rFrm;
5552     while ( !pTmp->GetUpper()->IsTabFrm() )
5553         pTmp = pTmp->GetUpper();
5554 
5555     return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() );
5556 }
5557 
5558 /*
5559  * SwTabFrm::GetFirstNonHeadlineRow()
5560  *
5561  * If this is a master table, we can may assume, that there are at least
5562  * nRepeat lines in the table.
5563  * If this is a follow table, there are intermediate states for the table
5564  * layout, e.g., during deletion of rows, which makes it necessary to find
5565  * the first non-headline row by evaluating the headline flag at the row frame.
5566  */
5567 SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const
5568 {
5569     SwRowFrm* pRet = (SwRowFrm*)Lower();
5570     if ( pRet )
5571     {
5572         if ( IsFollow() )
5573         {
5574             while ( pRet && pRet->IsRepeatedHeadline() )
5575                 pRet = (SwRowFrm*)pRet->GetNext();
5576         }
5577         else
5578         {
5579             sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
5580             while ( pRet && nRepeat > 0 )
5581             {
5582                 pRet = (SwRowFrm*)pRet->GetNext();
5583                 --nRepeat;
5584             }
5585         }
5586     }
5587 
5588     return (SwRowFrm*)pRet;
5589 }
5590 
5591 /*
5592  * SwTable::IsHeadline()
5593  */
5594 bool SwTable::IsHeadline( const SwTableLine& rLine ) const
5595 {
5596     for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i )
5597         if ( GetTabLines()[ i ] == &rLine )
5598             return true;
5599 
5600     return false;
5601 }
5602 
5603 bool SwTabFrm::IsLayoutSplitAllowed() const
5604 {
5605     return GetFmt()->GetLayoutSplit().GetValue();
5606 }
5607 
5608 // --> collapsing borders FME 2005-05-27 #i29550#
5609 
5610 sal_uInt16 SwTabFrm::GetBottomLineSize() const
5611 {
5612     ASSERT( IsCollapsingBorders(),
5613             "BottomLineSize only required for collapsing borders" )
5614 
5615     ASSERT( Lower(), "Warning! Trying to prevent a crash, please inform FME" )
5616 
5617     const SwFrm* pTmp = GetLastLower();
5618 
5619     // --> FME 2005-12-07 #124755# Try to make code robust:
5620     if ( !pTmp ) return 0;
5621     // <--
5622 
5623     return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize();
5624 }
5625 
5626 bool SwTabFrm::IsCollapsingBorders() const
5627 {
5628     return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue();
5629 }
5630 
5631 // <-- collapsing
5632 
5633 
5634 //
5635 // Local helper function to calculate height of first text row
5636 //
5637 SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine )
5638 {
5639     // Find corresponding split line in master table
5640     const SwTabFrm* pTab = rSourceLine.FindTabFrm();
5641     SWRECTFN( pTab )
5642     const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
5643 
5644     //
5645     // 1. Case: rSourceLine is a follow flow line.
5646     // In this case we have to return the minimum of the heights
5647     // of the first lines in rSourceLine.
5648     //
5649     // 2. Case: rSourceLine is not a follow flow line.
5650     // In this case we have to return the maximum of the heights
5651     // of the first lines in rSourceLine.
5652     //
5653     bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow();
5654     SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0;
5655 
5656     while ( pCurrSourceCell )
5657     {
5658         // NEW TABLES
5659         // Skip cells which are not responsible for the height of
5660         // the follow flow line:
5661         if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 )
5662         {
5663             pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
5664             continue;
5665         }
5666 
5667         const SwFrm *pTmp = pCurrSourceCell->Lower();
5668         if ( pTmp )
5669         {
5670             SwTwips nTmpHeight = USHRT_MAX;
5671             // --> FME 2004-09-14 #i32456# Consider lower row frames
5672             if ( pTmp->IsRowFrm() )
5673             {
5674                 const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
5675                 nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow );
5676             }
5677             // <--
5678             if ( pTmp->IsTabFrm() )
5679             {
5680                 nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine();
5681             }
5682             else if ( pTmp->IsTxtFrm() )
5683             {
5684                 SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp;
5685                 pTxtFrm->GetFormatted();
5686                 nTmpHeight = pTxtFrm->FirstLineHeight();
5687             }
5688 
5689             if ( USHRT_MAX != nTmpHeight )
5690             {
5691                 const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell();
5692                 if ( pPrevCell )
5693                 {
5694                     // If we are in a split row, there may be some space
5695                     // left in the cell frame of the master row.
5696                     // We look for the minimum of all first line heights;
5697                     SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)();
5698                     const SwFrm* pFrm = pPrevCell->Lower();
5699                     const SwFrm* pLast = pFrm;
5700                     while ( pFrm )
5701                     {
5702                         nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
5703                         pLast = pFrm;
5704                         pFrm = pFrm->GetNext();
5705                     }
5706 
5707                     // --> FME, OD 2004-07-15 #i26831#, #i26520#
5708                     // The additional lower space of the current last.
5709                     // --> OD 2004-11-25 #115759# - do *not* consider the
5710                     // additional lower space for 'master' text frames
5711                     if ( pLast && pLast->IsFlowFrm() &&
5712                          ( !pLast->IsTxtFrm() ||
5713                            !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) )
5714                     // <--
5715                     {
5716                         nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell();
5717                     }
5718                     // Don't forget the upper space and lower space,
5719                     // --> OD 2004-11-25 #115759# - do *not* consider the upper
5720                     // and the lower space for follow text frames.
5721                     if ( pTmp->IsFlowFrm() &&
5722                          ( !pTmp->IsTxtFrm() ||
5723                            !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) )
5724                     {
5725                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast);
5726                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
5727                     }
5728                     // <--
5729                     // --> OD 2004-11-25 #115759# - consider additional lower
5730                     // space of <pTmp>, if contains only one line.
5731                     // In this case it would be the new last text frame, which
5732                     // would have no follow and thus would add this space.
5733                     if ( pTmp->IsTxtFrm() &&
5734                          const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp))
5735                                             ->GetLineCount( STRING_LEN ) == 1 )
5736                     {
5737                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)
5738                                         ->CalcAddLowerSpaceAsLastInTableCell();
5739                     }
5740                     // <--
5741                     if ( nReal > 0 )
5742                         nTmpHeight -= nReal;
5743                 }
5744                 else
5745                 {
5746                     // pFirstRow is not a FollowFlowRow. In this case,
5747                     // we look for the maximum of all first line heights:
5748                     SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell );
5749                     const SwBorderAttrs &rAttrs = *aAccess.Get();
5750                     nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
5751                     // --> OD 2004-07-16 #i26250#
5752                     // Don't forget the upper space and lower space,
5753                     if ( pTmp->IsFlowFrm() )
5754                     {
5755                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace();
5756                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
5757                     }
5758                     // <--
5759                 }
5760             }
5761 
5762             if ( bIsInFollowFlowLine )
5763             {
5764                 // minimum
5765                 if ( nTmpHeight < nHeight )
5766                     nHeight = nTmpHeight;
5767             }
5768             else
5769             {
5770                 // maximum
5771                 if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight )
5772                     nHeight = nTmpHeight;
5773             }
5774         }
5775 
5776         pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
5777     }
5778 
5779     return ( LONG_MAX == nHeight ) ? 0 : nHeight;
5780 }
5781 
5782 //
5783 // Function to calculate height of first text row
5784 //
5785 SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const
5786 {
5787     SWRECTFN( this )
5788 
5789     const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue();
5790 
5791     if ( bDontSplit )
5792     {
5793         // Table is not allowed to split: Take the whole height, that's all
5794         return (Frm().*fnRect->fnGetHeight)();
5795     }
5796 
5797     SwRowFrm* pFirstRow = 0;
5798     SwTwips nTmpHeight = 0;
5799 
5800     pFirstRow = GetFirstNonHeadlineRow();
5801     ASSERT( !IsFollow() || pFirstRow, "FollowTable without Lower" )
5802 
5803     // NEW TABLES
5804     if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() )
5805         pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
5806 
5807     // Calculate the height of the headlines:
5808     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
5809     SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0;
5810 
5811     // Calculate the height of the keeping lines
5812     // (headlines + following keeping lines):
5813     SwTwips nKeepHeight = nRepeatHeight;
5814     if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
5815     {
5816         sal_uInt16 nKeepRows = nRepeat;
5817 
5818         // Check how many rows want to keep together
5819         while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() )
5820         {
5821             ++nKeepRows;
5822             pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
5823         }
5824 
5825         if ( nKeepRows > nRepeat )
5826             nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows );
5827     }
5828 
5829     // For master tables, the height of the headlines + the heigth of the
5830     // keeping lines (if any) has to be considered. For follow tables, we
5831     // only consider the height of the keeping rows without the repeated lines:
5832     if ( !IsFollow() )
5833     {
5834         nTmpHeight = nKeepHeight;
5835     }
5836     else
5837     {
5838         nTmpHeight = nKeepHeight - nRepeatHeight;
5839     }
5840 
5841     // pFirstRow row is the first non-heading row.
5842     // nTmpHeight is the height of the heading row if we are a follow.
5843     if ( pFirstRow )
5844     {
5845         const bool bSplittable = pFirstRow->IsRowSplitAllowed();
5846         const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)();
5847 
5848         if ( !bSplittable )
5849         {
5850             // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow
5851             // actually is determined by a lower cell with rowspan = -1. In this case we should not
5852             // just return the height of the first line. Basically we need to get the height of the
5853             // line as it would be on the last page. Since this is quite complicated to calculate,
5854             // we olny calculate the height of the first line.
5855             if ( pFirstRow->GetPrev() &&
5856                  static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() )
5857             {
5858                 // Calculate maximum height of all cells with rowspan = 1:
5859                 SwTwips nMaxHeight = 0;
5860                 const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower());
5861                 while ( pLower2 )
5862                 {
5863                     if ( 1 == pLower2->GetTabBox()->getRowSpan() )
5864                     {
5865                         const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, sal_True );
5866                         nMaxHeight = Max( nCellHeight, nMaxHeight );
5867                     }
5868                     pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext());
5869                 }
5870                 nTmpHeight += nMaxHeight;
5871             }
5872             else
5873             {
5874                 nTmpHeight += nFirstLineHeight;
5875             }
5876         }
5877 
5878         // --> FME 2004-11-18 #118411#
5879         // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger
5880         // a formatting of the row frame (via the GetFormatted()). We don't
5881         // want this formatting if the row does not have a height.
5882         else if ( 0 != nFirstLineHeight )
5883         // <--
5884         {
5885             const bool bOldJoinLock = IsJoinLocked();
5886             ((SwTabFrm*)this)->LockJoin();
5887             const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow );
5888 
5889             // Consider minimum row height:
5890             const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize();
5891             const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
5892                                           rSz.GetHeight() : 0;
5893 
5894             nTmpHeight += Max( nHeightOfFirstContentLine, nMinRowHeight );
5895 
5896             if ( !bOldJoinLock )
5897                 ((SwTabFrm*)this)->UnlockJoin();
5898         }
5899     }
5900 
5901     return nTmpHeight;
5902 }
5903 
5904 //
5905 // Some more functions for covered/covering cells. This way inclusion of
5906 // SwCellFrm can be avoided
5907 //
5908 
5909 bool SwFrm::IsLeaveUpperAllowed() const
5910 {
5911     const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
5912     return pThisCell && pThisCell->GetLayoutRowSpan() > 1;
5913 }
5914 
5915 bool SwFrm::IsCoveredCell() const
5916 {
5917     const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
5918     return pThisCell && pThisCell->GetLayoutRowSpan() < 1;
5919 }
5920 
5921 bool SwFrm::IsInCoveredCell() const
5922 {
5923     bool bRet = false;
5924 
5925     const SwFrm* pThis = this;
5926     while ( pThis && !pThis->IsCellFrm() )
5927         pThis = pThis->GetUpper();
5928 
5929     if ( pThis )
5930         bRet = pThis->IsCoveredCell();
5931 
5932     return bRet;
5933 }
5934 
5935