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