xref: /trunk/main/sw/source/core/layout/tabfrm.cxx (revision 9d3f73ea)
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 namespace {
1879     bool AreAllRowsKeepWithNext( const SwRowFrm* pFirstRowFrm )
1880     {
1881         bool bRet = pFirstRowFrm != 0 &&
1882                     pFirstRowFrm->ShouldRowKeepWithNext();
1883 
1884         while ( bRet && pFirstRowFrm->GetNext() != 0 )
1885         {
1886             pFirstRowFrm = dynamic_cast<const SwRowFrm*>(pFirstRowFrm->GetNext());
1887             bRet = pFirstRowFrm != 0 &&
1888                    pFirstRowFrm->ShouldRowKeepWithNext();
1889         }
1890 
1891         return bRet;
1892     }
1893 }
1894 void SwTabFrm::MakeAll()
1895 {
1896 	if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 )
1897 		return;
1898 
1899     if ( HasFollow() )
1900     {
1901         SwTabFrm* pFollowFrm = (SwTabFrm*)GetFollow();
1902         ASSERT( !pFollowFrm->IsJoinLocked() || !pFollowFrm->IsRebuildLastLine(),
1903                 "SwTabFrm::MakeAll for master while follow is in RebuildLastLine()" )
1904         if ( pFollowFrm->IsJoinLocked() && pFollowFrm->IsRebuildLastLine() )
1905             return;
1906     }
1907 
1908     PROTOCOL_ENTER( this, PROT_MAKEALL, 0, 0 )
1909 
1910     LockJoin(); //Ich lass mich nicht unterwegs vernichten.
1911 	SwLayNotify aNotify( this );	//uebernimmt im DTor die Benachrichtigung
1912     // If pos is invalid, we have to call a SetInvaKeep at aNotify.
1913     // Otherwise the keep atribute would not work in front of a table.
1914     const sal_Bool bOldValidPos = GetValidPosFlag();
1915 
1916 	//Wenn mein direkter Nachbar gleichzeitig mein Follow ist
1917 	//verleibe ich mir das Teil ein.
1918     // OD 09.04.2003 #108698# - join all follows, which are placed on the
1919     // same page/column.
1920     // OD 29.04.2003 #109213# - join follow, only if join for the follow
1921     // is not locked. Otherwise, join will not be performed and this loop
1922     // will be endless.
1923     while ( GetNext() && GetNext() == GetFollow() &&
1924             !GetFollow()->IsJoinLocked()
1925           )
1926     {
1927         if ( HasFollowFlowLine() )
1928             RemoveFollowFlowLine();
1929         Join();
1930     }
1931 
1932     // The bRemoveFollowFlowLinePending is set if the split attribute of the
1933     // last line is set:
1934     if ( IsRemoveFollowFlowLinePending() && HasFollowFlowLine() )
1935     {
1936         if ( RemoveFollowFlowLine() )
1937             Join();
1938         SetRemoveFollowFlowLinePending( sal_False );
1939     }
1940 
1941 	if ( bResizeHTMLTable )	//Optimiertes Zusammenspiel mit Grow/Shrink des Inhaltes
1942 	{
1943 		bResizeHTMLTable = sal_False;
1944 		SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
1945 		if ( pLayout )
1946 			bCalcLowers = pLayout->Resize(
1947 							pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
1948 	}
1949 
1950 
1951 	sal_Bool bMakePage	= sal_True;		//solange sal_True kann eine neue Seite
1952 								//angelegt werden (genau einmal)
1953 	sal_Bool bMovedBwd	= sal_False;	//Wird sal_True wenn der Frame zurueckfliesst
1954 	sal_Bool bMovedFwd	= sal_False;	//solange sal_False kann der Frm zurueck-
1955 								//fliessen (solange, bis er einmal
1956 								//vorwaerts ge'moved wurde).
1957 	sal_Bool bSplit		= sal_False;	//Wird sal_True wenn der Frm gesplittet wurde.
1958     const sal_Bool bFtnsInDoc = 0 != GetFmt()->GetDoc()->GetFtnIdxs().Count();
1959 	sal_Bool bMoveable;
1960 	const sal_Bool bFly		= IsInFly();
1961 
1962 	SwBorderAttrAccess  *pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
1963 	const SwBorderAttrs *pAttrs = pAccess->Get();
1964 
1965     // The beloved keep attribute
1966     const bool bKeep = IsKeep( pAttrs->GetAttrSet() );
1967 
1968     // All rows should keep together
1969     // OD 2004-05-25 #i21478# - don't split table, if it has to keep with next
1970     const bool bDontSplit = !IsFollow() &&
1971                             ( !GetFmt()->GetLayoutSplit().GetValue() || bKeep );
1972 
1973     // The number of repeated headlines
1974     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
1975 
1976     // This flag indicates that we are allowed to try to split the
1977     // table rows.
1978     bool bTryToSplit = true;
1979 
1980     // --> FME 2006-02-16 #131283#
1981     // Indicates that two individual rows may keep together, based on the keep
1982     // attribute set at the first paragraph in the first cell.
1983     const bool bTableRowKeep = !bDontSplit && GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP);
1984 
1985     // The Magic Move: Used for the table row keep feature.
1986     // If only the last row of the table wants to keep (implicitely by setting
1987     // keep for the first paragraph in the first cell), and this table does
1988     // not have a next, the last line will be cut. Loop prevention: Only
1989     // one try.
1990     bool bLastRowHasToMoveToFollow = false;
1991     bool bLastRowMoveNoMoreTries = false;
1992 
1993     // Join follow table, if this table is not allowed to split:
1994 	if ( bDontSplit )
1995     {
1996 		while ( GetFollow() && !GetFollow()->IsJoinLocked() )
1997         {
1998             if ( HasFollowFlowLine() )
1999                 RemoveFollowFlowLine();
2000             Join();
2001         }
2002     }
2003 
2004     // Join follow table, if this does not have enough (repeated) lines:
2005     if ( nRepeat )
2006     {
2007         if( GetFollow() && !GetFollow()->IsJoinLocked() &&
2008             0 == GetFirstNonHeadlineRow() )
2009         {
2010             if ( HasFollowFlowLine() )
2011                 RemoveFollowFlowLine();
2012             Join();
2013         }
2014     }
2015 
2016     // Join follow table, if last row of this table should keep:
2017     if ( bTableRowKeep && GetFollow() && !GetFollow()->IsJoinLocked() )
2018     {
2019         const SwRowFrm* pTmpRow = static_cast<const SwRowFrm*>(GetLastLower());
2020         if ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
2021         {
2022             if ( HasFollowFlowLine() )
2023                 RemoveFollowFlowLine();
2024             Join();
2025         }
2026     }
2027 
2028     //Einen Frischling moven wir gleich schon einmal vorwaerts...
2029 	if ( !Frm().Top() && IsFollow() )
2030 	{
2031 		SwFrm *pPre = GetPrev();
2032 		if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
2033 		{
2034 			if ( !MoveFwd( bMakePage, sal_False ) )
2035 				bMakePage = sal_False;
2036 			bMovedFwd = sal_True;
2037 		}
2038 	}
2039 
2040 	int nUnSplitted = 5; // Just another loop control :-(
2041     SWRECTFN( this )
2042 	while ( !bValidPos || !bValidSize || !bValidPrtArea )
2043 	{
2044 		if ( sal_True == (bMoveable = IsMoveable()) )
2045 			if ( CheckMoveFwd( bMakePage, bKeep && KEEPTAB, bMovedBwd ) )
2046 			{
2047 				bMovedFwd = sal_True;
2048 				bCalcLowers = sal_True;
2049                 // --> OD 2009-08-12 #i99267#
2050                 // reset <bSplit> after forward move to assure that follows
2051                 // can be joined, if further space is available.
2052                 bSplit = sal_False;
2053                 // <--
2054 			}
2055 
2056         Point aOldPos( (Frm().*fnRect->fnGetPos)() );
2057 		MakePos();
2058 
2059         if ( aOldPos != (Frm().*fnRect->fnGetPos)() )
2060 		{
2061             if ( aOldPos.Y() != (Frm().*fnRect->fnGetTop)() )
2062 			{
2063 				SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
2064 				if( pLayout )
2065 				{
2066 					delete pAccess;
2067 					bCalcLowers |= pLayout->Resize(
2068 						pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
2069                     pAccess = new SwBorderAttrAccess( SwFrm::GetCache(), this );
2070 					pAttrs = pAccess->Get();
2071 				}
2072 
2073 				bValidPrtArea = sal_False;
2074 				aNotify.SetLowersComplete( sal_False );
2075 			}
2076 			SwFrm *pPre;
2077 			if ( bKeep || (0 != (pPre = FindPrev()) &&
2078 						   pPre->GetAttrSet()->GetKeep().GetValue()) )
2079 			{
2080 				bCalcLowers = sal_True;
2081 			}
2082 		}
2083 
2084 		//Wir muessen die Hoehe der ersten Zeile kennen, denn nur wenn diese
2085 		//kleiner wird muss ggf. der Master angestossen werden um noetigenfalls
2086 		//die Zeile aufzunehmen.
2087 		long n1StLineHeight = 0;
2088 		if ( IsFollow() )
2089 		{
2090             SwFrm* pFrm = GetFirstNonHeadlineRow();
2091             if ( pFrm )
2092                 n1StLineHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
2093 		}
2094 
2095 		if ( !bValidSize || !bValidPrtArea )
2096 		{
2097             const long nOldPrtWidth = (Prt().*fnRect->fnGetWidth)();
2098             const long nOldFrmWidth = (Frm().*fnRect->fnGetWidth)();
2099             const Point aOldPrtPos  = (Prt().*fnRect->fnGetPos)();
2100 			Format( pAttrs );
2101 
2102 			SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout();
2103 			if ( pLayout &&
2104                  ((Prt().*fnRect->fnGetWidth)() != nOldPrtWidth ||
2105                   (Frm().*fnRect->fnGetWidth)() != nOldFrmWidth) )
2106             {
2107 				delete pAccess;
2108 				bCalcLowers |= pLayout->Resize(
2109 						pLayout->GetBrowseWidthByTabFrm( *this ), sal_False );
2110 //					GetFmt()->GetDoc()->GetDocShell()->IsReadOnly() ? sal_False : sal_True );
2111 				pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2112 				pAttrs = pAccess->Get();
2113 			}
2114             if ( aOldPrtPos != (Prt().*fnRect->fnGetPos)() )
2115 				aNotify.SetLowersComplete( sal_False );
2116 		}
2117 
2118 		//Wenn ich der erste einer Kette bin koennte ich mal sehen ob
2119 		//ich zurueckfliessen kann (wenn ich mich ueberhaupt bewegen soll).
2120 		//Damit es keine Oszillation gibt, darf ich nicht gerade vorwaerts
2121 		//geflosssen sein.
2122         if ( !bMovedFwd && (bMoveable || bFly) && lcl_NoPrev( *this ) )
2123 		{
2124 			//Bei Follows muss der Master benachrichtigt
2125 			//werden. Der Follow muss nur dann Moven, wenn er leere Blaetter
2126 			//ueberspringen muss.
2127 			if ( IsFollow() )
2128 			{
2129 				//Nur wenn die Hoehe der ersten Zeile kleiner geworder ist.
2130                 SwFrm *pFrm = GetFirstNonHeadlineRow();
2131                 if( pFrm && n1StLineHeight >(pFrm->Frm().*fnRect->fnGetHeight )() )
2132 				{
2133 					SwTabFrm *pMaster = (SwTabFrm*)FindMaster();
2134 					sal_Bool bDummy;
2135 					if ( ShouldBwdMoved( pMaster->GetUpper(), sal_False, bDummy ) )
2136 						pMaster->InvalidatePos();
2137 				}
2138 			}
2139 			SwFtnBossFrm *pOldBoss = bFtnsInDoc ? FindFtnBossFrm( sal_True ) : 0;
2140 			sal_Bool bReformat;
2141 			if ( MoveBwd( bReformat ) )
2142 			{
2143                 SWREFRESHFN( this )
2144 				bMovedBwd = sal_True;
2145 				aNotify.SetLowersComplete( sal_False );
2146 				if ( bFtnsInDoc )
2147 					MoveLowerFtns( 0, pOldBoss, 0, sal_True );
2148 				if ( bReformat || bKeep )
2149 				{
2150                     long nOldTop = (Frm().*fnRect->fnGetTop)();
2151                     MakePos();
2152                     if( nOldTop != (Frm().*fnRect->fnGetTop)() )
2153 					{
2154                         SwHTMLTableLayout *pHTMLLayout =
2155 							GetTable()->GetHTMLTableLayout();
2156                         if( pHTMLLayout )
2157 						{
2158 							delete pAccess;
2159                             bCalcLowers |= pHTMLLayout->Resize(
2160                                 pHTMLLayout->GetBrowseWidthByTabFrm( *this ),
2161 								sal_False );
2162 
2163                             pAccess= new SwBorderAttrAccess(
2164 										SwFrm::GetCache(), this );
2165 							pAttrs = pAccess->Get();
2166 						}
2167 
2168 						bValidPrtArea = sal_False;
2169 						Format( pAttrs );
2170 					}
2171                     lcl_RecalcTable( *this, 0, aNotify );
2172 					bLowersFormatted = sal_True;
2173 					if ( bKeep && KEEPTAB )
2174 					{
2175                         // --> OD 2005-09-28 #b6329202#
2176                         // Consider case that table is inside another table,
2177                         // because it has to be avoided, that superior table
2178                         // is formatted.
2179                         // Thus, find next content, table or section
2180                         // and, if a section is found, get its first
2181                         // content.
2182 //                        SwFrm *pNxt = FindNextCnt();
2183 //                        if( pNxt && pNxt->IsInTab() )
2184 //                            pNxt = pNxt->FindTabFrm();
2185 //                        if ( pNxt )
2186 //                        {
2187 //                            pNxt->Calc();
2188 //                            if ( !GetNext() )
2189 //                                bValidPos = sal_False;
2190 //                        }
2191                         if ( 0 != lcl_FormatNextCntntForKeep( this ) && !GetNext() )
2192                         {
2193                             bValidPos = sal_False;
2194                         }
2195                         // <--
2196 					}
2197 				}
2198 			}
2199 		}
2200 
2201 		//Wieder ein Wert ungueltig? - dann nochmal das ganze...
2202 		if ( !bValidPos || !bValidSize || !bValidPrtArea )
2203 			continue;
2204 
2205         // check, if calculation of table frame is ready.
2206 
2207         /// OD 23.10.2002 #103517# - Local variable <nDistanceToUpperPrtBottom>
2208         ///     Introduce local variable and init it with the distance from the
2209         ///     table frame bottom to the bottom of the upper printing area.
2210         /// Note: negative values denotes the situation that table frame doesn't
2211         ///     fit in its upper.
2212 
2213         SwTwips nDistanceToUpperPrtBottom =
2214                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
2215 
2216         /// OD 23.10.2002 #103517# - In online layout try to grow upper of table
2217         /// frame, if table frame doesn't fit in its upper.
2218         const ViewShell *pSh = getRootFrm()->GetCurrShell();
2219         const bool bBrowseMode = pSh && pSh->GetViewOptions()->getBrowseMode();
2220         if ( nDistanceToUpperPrtBottom < 0 && bBrowseMode )
2221         {
2222             if ( GetUpper()->Grow( -nDistanceToUpperPrtBottom ) )
2223             {
2224                 // upper is grown --> recalculate <nDistanceToUpperPrtBottom>
2225                 nDistanceToUpperPrtBottom =
2226                     (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
2227             }
2228         }
2229 
2230         // If there is still some space left in the upper, we check if we
2231         // can join some rows of the follow.
2232         // Setting bLastRowHasToMoveToFollow to true means we want to force
2233         // the table to be split! Only skip this if condition once.
2234         if( nDistanceToUpperPrtBottom >= 0 && !bLastRowHasToMoveToFollow )
2235         {
2236             // OD 23.10.2002 - translate german commentary
2237             // If there is space left in the upper printing area, join as for trial
2238             // at least one further row of an existing follow.
2239 			if ( !bSplit && GetFollow() )
2240 			{
2241 				sal_Bool bDummy;
2242 				if ( GetFollow()->ShouldBwdMoved( GetUpper(), sal_False, bDummy ) )
2243 				{
2244                     SwFrm *pTmp = GetUpper();
2245                     SwTwips nDeadLine = (pTmp->*fnRect->fnGetPrtBottom)();
2246                     if ( bBrowseMode )
2247                         nDeadLine += pTmp->Grow( LONG_MAX, sal_True );
2248                     if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 )
2249 					{
2250                         //
2251                         // First, we remove an existing follow flow line.
2252                         //
2253                         if ( HasFollowFlowLine() )
2254                         {
2255                             SwFrm* pLastLine = const_cast<SwFrm*>(GetLastLower());
2256                             RemoveFollowFlowLine();
2257                             // invalidate and rebuild last row
2258                             if ( pLastLine )
2259                             {
2260                                 ::SwInvalidateAll( pLastLine, LONG_MAX );
2261                                 SetRebuildLastLine( sal_True );
2262                                 lcl_RecalcRow( static_cast<SwRowFrm&>(*pLastLine), LONG_MAX );
2263                                 SetRebuildLastLine( sal_False );
2264                             }
2265 
2266                             SwFrm* pRow = GetFollow()->GetFirstNonHeadlineRow();
2267 
2268                             if ( !pRow || !pRow->GetNext() )
2269     							//Der Follow wird leer und damit ueberfluessig.
2270                                 Join();
2271 
2272                             continue;
2273                         }
2274 
2275                         //
2276                         // If there is no follow flow line, we move the first
2277                         // row in the follow table to the master table.
2278                         //
2279                         SwRowFrm *pRow = GetFollow()->GetFirstNonHeadlineRow();
2280 
2281   						//Der Follow wird leer und damit ueberfluessig.
2282            				if ( !pRow )
2283                         {
2284                             Join();
2285                             continue;
2286                         }
2287 
2288                         const SwTwips nOld = (Frm().*fnRect->fnGetHeight)();
2289                         long nRowsToMove = lcl_GetMaximumLayoutRowSpan( *pRow );
2290                         SwFrm* pRowToMove = pRow;
2291 
2292                         while ( pRowToMove && nRowsToMove-- > 0 )
2293                         {
2294 						    const sal_Bool bMoveFtns = bFtnsInDoc && !GetFollow()->IsJoinLocked();
2295 
2296                             SwFtnBossFrm *pOldBoss = 0;
2297 					    	if ( bMoveFtns )
2298 				    			pOldBoss = pRowToMove->FindFtnBossFrm( sal_True );
2299 
2300                             SwFrm* pNextRow = pRowToMove->GetNext();
2301 
2302 		    				if ( !pNextRow )
2303 	    						//Der Follow wird leer und damit ueberfluessig.
2304                                 Join();
2305                             else
2306 						    {
2307 							    pRowToMove->Cut();
2308 							    pRowToMove->Paste( this );
2309                             }
2310 
2311 						    //Die Fussnoten verschieben!
2312 						    if ( bMoveFtns )
2313 							    if ( ((SwLayoutFrm*)pRowToMove)->MoveLowerFtns(
2314 							    	 0, pOldBoss, FindFtnBossFrm( sal_True ), sal_True ) )
2315 						    		GetUpper()->Calc();
2316 
2317                             pRowToMove = pNextRow;
2318                         }
2319 
2320                         if ( nOld != (Frm().*fnRect->fnGetHeight)() )
2321                             lcl_RecalcTable( *this, (SwLayoutFrm*)pRow, aNotify );
2322 
2323                         continue;
2324 					}
2325 				}
2326 			}
2327 			else if ( KEEPTAB )
2328 			{
2329                 bool bFormat = false;
2330                 if ( bKeep )
2331                     bFormat = true;
2332                 else if ( bTableRowKeep && !bLastRowMoveNoMoreTries )
2333                 {
2334                     // We only want to give the last row one chance to move
2335                     // to the follow table. Set the flag as early as possible:
2336                     bLastRowMoveNoMoreTries = true;
2337 
2338                     // The last line of the table has to be cut off if:
2339                     // 1. The table does not want to keep with its next
2340                     // 2. The compatibility option is set and the table is allowed to split
2341                     // 3. We did not already cut off the last row
2342                     // 4. There is not break after attribute set at the table
2343                     // 5. There is no break before attribute set behind the table
2344                     // 6. There is no section change behind the table (see IsKeep)
2345                     // 7. The last table row wants to keep with its next.
2346                     const SwRowFrm* pLastRow = static_cast<const SwRowFrm*>(GetLastLower());
2347                     if ( pLastRow && IsKeep( pAttrs->GetAttrSet(), true ) &&
2348                          pLastRow->ShouldRowKeepWithNext() )
2349                         bFormat = true;
2350                 }
2351 
2352                 if ( bFormat )
2353                 {
2354                     delete pAccess;
2355 
2356                     // --> OD 2005-09-28 #b6329202#
2357                     // Consider case that table is inside another table, because
2358                     // it has to be avoided, that superior table is formatted.
2359                     // Thus, find next content, table or section and, if a section
2360                     // is found, get its first content.
2361                     const SwFrm* pTmpNxt = lcl_FormatNextCntntForKeep( this );
2362                     // <--
2363 
2364                     pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2365                     pAttrs = pAccess->Get();
2366 
2367                     // The last row wants to keep with the frame behind the table.
2368                     // Check if the next frame is on a different page and valid.
2369                     // In this case we do a magic trick:
2370                     if ( !bKeep && !GetNext() && pTmpNxt && pTmpNxt->IsValid() )
2371                     {
2372                         bValidPos = sal_False;
2373                         bLastRowHasToMoveToFollow = true;
2374                     }
2375                 }
2376 			}
2377 
2378 			if ( IsValid() )
2379 			{
2380 				if ( bCalcLowers )
2381 				{
2382                     lcl_RecalcTable( *this, 0, aNotify );
2383 					bLowersFormatted = sal_True;
2384 					bCalcLowers = sal_False;
2385 				}
2386 				else if ( bONECalcLowers )
2387 				{
2388                     lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2389 					bONECalcLowers = sal_False;
2390 				}
2391 			}
2392 			continue;
2393 		}
2394 
2395         //Ich passe nicht mehr in meinen Uebergeordneten, also ist es jetzt
2396 		//an der Zeit moeglichst konstruktive Veranderungen vorzunehmen
2397 
2398 		//Wenn ich den uebergeordneten Frm nicht verlassen darf, habe
2399 		//ich ein Problem; Frei nach Artur Dent tun wir das einzige das man
2400 		//mit einen nicht loesbaren Problem tun kann: wir ignorieren es - und
2401 		//zwar mit aller Kraft.
2402 		if ( !bMoveable )
2403 		{
2404 			if ( bCalcLowers && IsValid() )
2405 			{
2406                 lcl_RecalcTable( *this, 0, aNotify );
2407 				bLowersFormatted = sal_True;
2408 				bCalcLowers = sal_False;
2409 			}
2410 			else if ( bONECalcLowers )
2411 			{
2412                 lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2413 				bONECalcLowers = sal_False;
2414 			}
2415 
2416             // It does not make sense to cut off the last line if we are
2417             // not moveable:
2418             bLastRowHasToMoveToFollow = false;
2419 
2420 			continue;
2421 		}
2422 
2423         if ( bCalcLowers && IsValid() )
2424 		{
2425             lcl_RecalcTable( *this, 0, aNotify );
2426 			bLowersFormatted = sal_True;
2427 			bCalcLowers = sal_False;
2428             if( !IsValid() )
2429                 continue;
2430 		}
2431 
2432         //
2433         // First try to split the table. Condition:
2434         // 1. We have at least one non headline row
2435         // 2. If this row wants to keep, we need an additional row
2436         // 3. The table is allowed to split or we do not have an pIndPrev:
2437         //
2438         SwFrm* pIndPrev = GetIndPrev();
2439         const SwRowFrm* pFirstNonHeadlineRow = GetFirstNonHeadlineRow();
2440         // #120016# if this row wants to keep, allow split in case that all rows want to keep with next,
2441         // the table can not move forward as it is the first one and a split is in general allowed.
2442         const bool bAllowSplitOfRow = ( bTableRowKeep &&
2443                                         AreAllRowsKeepWithNext( pFirstNonHeadlineRow ) ) &&
2444                                       !pIndPrev &&
2445                                       !bDontSplit;
2446 
2447         if ( pFirstNonHeadlineRow && nUnSplitted > 0 &&
2448              ( !bTableRowKeep || pFirstNonHeadlineRow->GetNext() || !pFirstNonHeadlineRow->ShouldRowKeepWithNext() || bAllowSplitOfRow ) &&
2449              ( !bDontSplit || !pIndPrev ) )
2450         {
2451             // --> FME 2004-06-03 #i29438#
2452             // Special DoNotSplit case:
2453             // We better avoid splitting of a row frame if we are inside a columned
2454             // section which has a height of 0, because this is not growable and thus
2455             // all kinds of unexpected things could happen.
2456             const SwSectionFrm* pTmpSct = 0;
2457             if ( IsInSct() &&
2458                 (pTmpSct = FindSctFrm())->Lower()->IsColumnFrm() &&
2459                 0 == (GetUpper()->Frm().*fnRect->fnGetHeight)()  )
2460             {
2461                 bTryToSplit = false;
2462             }
2463             // <--
2464 
2465             // 1. Try: bTryToSplit = true  => Try to split the row.
2466             // 2. Try: bTryToSplit = false => Split the table between the rows.
2467             if ( pFirstNonHeadlineRow->GetNext() || bTryToSplit )
2468             {
2469                 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)();
2470                 if( IsInSct() || GetUpper()->IsInTab() ) // TABLE IN TABLE)
2471                     nDeadLine = (*fnRect->fnYInc)( nDeadLine,
2472                                         GetUpper()->Grow( LONG_MAX, sal_True ) );
2473 
2474                 ::lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), nDeadLine );
2475                 bLowersFormatted = sal_True;
2476                 aNotify.SetLowersComplete( sal_True );
2477 
2478                 // One more check if its really necessary to split the table.
2479                 // 1. The table either has to exceed the deadline or
2480                 // 2. We explicitly want to cut off the last row.
2481                 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) > 0 && !bLastRowHasToMoveToFollow )
2482                 {
2483                     continue;
2484                 }
2485 
2486                 // Set to false again as early as possible.
2487                 bLastRowHasToMoveToFollow = false;
2488 
2489                 // --> FME 2005-08-03 #i52781#
2490                 // YaSC - Yet another special case:
2491                 // If our upper is inside a table cell which is not allowed
2492                 // to split, we do not try to split:
2493                 if ( GetUpper()->IsInTab() )
2494                 {
2495                     const SwFrm* pTmpRow = GetUpper();
2496                     while ( pTmpRow && !pTmpRow->IsRowFrm() )
2497                        pTmpRow = pTmpRow->GetUpper();
2498                     if ( pTmpRow && !static_cast<const SwRowFrm*>(pTmpRow)->IsRowSplitAllowed() )
2499                         continue;
2500                 }
2501                 // <--
2502 
2503                 sal_uInt16 nMinNumOfLines = nRepeat;
2504 
2505                 if ( bTableRowKeep )
2506                 {
2507                     const SwRowFrm* pTmpRow = pFirstNonHeadlineRow;
2508                     while ( pTmpRow && pTmpRow->ShouldRowKeepWithNext() )
2509                     {
2510                         ++nMinNumOfLines;
2511                         pTmpRow = static_cast<const SwRowFrm*>(pTmpRow->GetNext());
2512                     }
2513                     // Check if all lines want to keep together and we
2514                     // have a pIndPrev. In this case we set nDeadLine
2515                     // to 0, forcing the table to move forward.
2516                     if ( !pTmpRow && pIndPrev )
2517                         nDeadLine = 0;
2518                 }
2519 
2520                 if ( !bTryToSplit )
2521                     ++nMinNumOfLines;
2522 
2523                 const SwTwips nBreakLine = (*fnRect->fnYInc)(
2524                         (Frm().*fnRect->fnGetTop)(),
2525                         (this->*fnRect->fnGetTopMargin)() +
2526                          lcl_GetHeightOfRows( GetLower(), nMinNumOfLines ) );
2527 
2528                 // Some more checks if we want to call the split algorithm or not:
2529                 // The repeating lines / keeping lines still fit into the upper or
2530                 // if we do not have an (in)direkt Prev, we split anyway.
2531                 if( (*fnRect->fnYDiff)(nDeadLine, nBreakLine) >=0 || !pIndPrev )
2532                 {
2533                     aNotify.SetLowersComplete( sal_False );
2534                     bSplit = sal_True;
2535 
2536                     //
2537                     // An existing follow flow line has to be removed.
2538                     //
2539                     if ( HasFollowFlowLine() )
2540                     {
2541                         RemoveFollowFlowLine();
2542                     }
2543 
2544                     const bool bSplitError = !Split( nDeadLine, bTryToSplit, ( bTableRowKeep && !bAllowSplitOfRow ) );
2545                     if( !bTryToSplit && !bSplitError && nUnSplitted > 0 )
2546                     {
2547                         --nUnSplitted;
2548                     }
2549 
2550                     // --> FME 2004-06-09 #i29771# Two tries to split the table:
2551                     // If an error occured during splitting. We start a second
2552                     // try, this time without splitting of table rows.
2553                     if ( bSplitError )
2554                     {
2555                         if ( HasFollowFlowLine() )
2556                             RemoveFollowFlowLine();
2557                     }
2558 
2559                     // --> FME 2005-02-10 #119477#
2560                     // If splitting the table was successfull or not,
2561                     // we do not want to have 'empty' follow tables.
2562                     if ( GetFollow() && !GetFollow()->GetFirstNonHeadlineRow() )
2563                         Join();
2564                     // <--
2565 
2566 
2567                     // We want to restore the situation before the failed
2568                     // split operation as good as possible. Therefore we
2569                     // do some more calculations. Note: Restricting this
2570                     // to nDeadLine may not be enough.
2571                     if ( bSplitError && bTryToSplit ) // no restart if we did not try to split: i72847, i79426
2572                     {
2573                         lcl_RecalcRow( static_cast<SwRowFrm&>(*Lower()), LONG_MAX );
2574                         bValidPos = sal_False;
2575                         bTryToSplit = false;
2576                         continue;
2577                     }
2578                     // <--
2579 
2580                     bTryToSplit = !bSplitError;
2581 
2582                     //Damit es nicht zu Oszillationen kommt, muss der
2583                     //Follow gleich gueltig gemacht werden.
2584                     if ( GetFollow() )
2585                     {
2586                         // --> OD 2007-11-30 #i80924#
2587                         // After a successful split assure that the first row
2588                         // is invalid. When graphics are present, this isn't hold.
2589                         // Note: defect i80924 could also be fixed, if it is
2590                         // assured, that <SwLayNotify::bLowersComplete> is only
2591                         // set, if all lower are valid *and* are correct laid out.
2592                         if ( !bSplitError && GetFollow()->GetLower() )
2593                         {
2594                             GetFollow()->GetLower()->InvalidatePos();
2595                         }
2596                         // <--
2597                         SWRECTFNX( GetFollow() )
2598 
2599                         static sal_uInt8 nStack = 0;
2600                         if ( !StackHack::IsLocked() && nStack < 4 )
2601                         {
2602                             ++nStack;
2603                             StackHack aHack;
2604                             delete pAccess;
2605 
2606                             GetFollow()->MakeAll();
2607 
2608                             pAccess= new SwBorderAttrAccess( SwFrm::GetCache(), this );
2609                             pAttrs = pAccess->Get();
2610 
2611                             ((SwTabFrm*)GetFollow())->SetLowersFormatted(sal_False);
2612                             // --> OD 2005-03-30 #i43913# - lock follow table
2613                             // to avoid its formatting during the format of
2614                             // its content.
2615                             const bool bOldJoinLock =  GetFollow()->IsJoinLocked();
2616                             GetFollow()->LockJoin();
2617                             // <--
2618                             ::lcl_RecalcRow( static_cast<SwRowFrm&>(*GetFollow()->Lower()),
2619                                              (GetFollow()->GetUpper()->Frm().*fnRectX->fnGetBottom)() );
2620                             // --> OD 2005-03-30 #i43913#
2621                             // --> FME 2006-04-05 #i63632# Do not unlock the
2622                             // follow if it wasn't locked before.
2623                             if ( !bOldJoinLock )
2624                                 GetFollow()->UnlockJoin();
2625                             // <--
2626 
2627                             if ( !GetFollow()->GetFollow() )
2628                             {
2629                                 SwFrm* pNxt = ((SwFrm*)GetFollow())->FindNext();
2630                                 if ( pNxt )
2631                                 {
2632                                     // OD 26.08.2003 #i18103# - no formatting
2633                                     // of found next frame, if its a follow
2634                                     // section of the 'ColLocked' section,
2635                                     // the follow table is in.
2636                                     bool bCalcNxt = true;
2637                                     if ( GetFollow()->IsInSct() && pNxt->IsSctFrm() )
2638                                     {
2639                                         SwSectionFrm* pSct = GetFollow()->FindSctFrm();
2640                                         if ( pSct->IsColLocked() &&
2641                                              pSct->GetFollow() == pNxt )
2642                                         {
2643                                             bCalcNxt = false;
2644                                         }
2645                                     }
2646                                     if ( bCalcNxt )
2647                                     {
2648                                         pNxt->Calc();
2649                                     }
2650                                 }
2651                             }
2652                             --nStack;
2653                         }
2654                         else if ( GetFollow() == GetNext() )
2655                             ((SwTabFrm*)GetFollow())->MoveFwd( sal_True, sal_False );
2656                     }
2657                     continue;
2658                 }
2659             }
2660         }
2661 
2662         // Set to false again as early as possible.
2663         bLastRowHasToMoveToFollow = false;
2664 
2665         if( IsInSct() && bMovedFwd && bMakePage && GetUpper()->IsColBodyFrm() &&
2666             GetUpper()->GetUpper()->GetUpper()->IsSctFrm() &&
2667             ( GetUpper()->GetUpper()->GetPrev() || GetIndPrev() ) &&
2668             ((SwSectionFrm*)GetUpper()->GetUpper()->GetUpper())->MoveAllowed(this) )
2669         {
2670             bMovedFwd = sal_False;
2671         }
2672 
2673         // --> FME 2004-06-09 #i29771# Reset bTryToSplit flag on change of upper
2674         const SwFrm* pOldUpper = GetUpper();
2675         // <--
2676 
2677         //Mal sehen ob ich irgenwo Platz finde...
2678         if ( !bMovedFwd && !MoveFwd( bMakePage, sal_False ) )
2679             bMakePage = sal_False;
2680 
2681         // --> FME 2004-06-09 #i29771# Reset bSplitError flag on change of upper
2682         if ( GetUpper() != pOldUpper )
2683 		{
2684             bTryToSplit = true;
2685 			nUnSplitted = 5;
2686 		}
2687         // <--
2688 
2689         SWREFRESHFN( this )
2690         bMovedFwd = bCalcLowers = sal_True;
2691         aNotify.SetLowersComplete( sal_False );
2692 		if ( IsFollow() )
2693 		{	//Um Oszillationen zu vermeiden sollte kein ungueltiger Master
2694 			//zurueckbleiben.
2695 			SwTabFrm *pTab = FindMaster();
2696 			if ( pTab->GetUpper() )
2697 				pTab->GetUpper()->Calc();
2698 			pTab->Calc();
2699 			pTab->SetLowersFormatted( sal_False );
2700 		}
2701 
2702 		//Wenn mein direkter Nachbar jetzt gleichzeitig mein Follow ist
2703 		//verleibe ich mir das Teil ein.
2704 		if ( ( GetNext() && GetNext() == GetFollow() ) || !GetLower() )
2705         {
2706             if ( HasFollowFlowLine() )
2707                 RemoveFollowFlowLine();
2708             if ( GetFollow() )
2709                 Join();
2710         }
2711 
2712 		if ( bMovedBwd && GetUpper() )
2713 			//Beim zurueckfliessen wurde der Upper angeregt sich vollstaendig
2714 			//zu Painten, dass koennen wir uns jetzt nach dem hin und her
2715 			//fliessen sparen.
2716 			GetUpper()->ResetCompletePaint();
2717 
2718         if ( bCalcLowers && IsValid() )
2719 		{
2720             // --> OD 2005-05-11 #i44910# - format of lower frames unnecessary
2721             // and can cause layout loops, if table doesn't fit and isn't
2722             // allowed to split.
2723             SwTwips nDistToUpperPrtBottom =
2724                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->*fnRect->fnGetPrtBottom)());
2725             if ( nDistToUpperPrtBottom >= 0 || bTryToSplit )
2726             {
2727                 lcl_RecalcTable( *this, 0, aNotify );
2728                 bLowersFormatted = sal_True;
2729                 bCalcLowers = sal_False;
2730             }
2731 #if OSL_DEBUG_LEVEL > 1
2732             else
2733             {
2734                 ASSERT( false, "debug assertion: <SwTabFrm::MakeAll()> - format of table lowers suppressed by fix i44910" );
2735             }
2736 #endif
2737             // <--
2738 		}
2739 
2740 	} //while ( !bValidPos || !bValidSize || !bValidPrtArea )
2741 
2742 	//Wenn mein direkter Vorgaenger jetzt mein Master ist, so kann er mich
2743 	//bei der nachstbesten Gelegenheit vernichten.
2744 	if ( IsFollow() )
2745 	{
2746 		SwFrm *pPre = GetPrev();
2747 		if ( pPre && pPre->IsTabFrm() && ((SwTabFrm*)pPre)->GetFollow() == this)
2748 			pPre->InvalidatePos();
2749 	}
2750 
2751 	bCalcLowers = bONECalcLowers = sal_False;
2752 	delete pAccess;
2753 	UnlockJoin();
2754     if ( bMovedFwd || bMovedBwd || !bOldValidPos )
2755 		aNotify.SetInvaKeep();
2756 }
2757 
2758 /*************************************************************************
2759 |*
2760 |*	SwTabFrm::CalcFlyOffsets()
2761 |*
2762 |*	Beschreibung:		Berechnet die Offsets, die durch FlyFrames
2763 |*						entstehen.
2764 |*	Ersterstellung		MA/MIB 14. Apr. 99
2765 |*	Letzte Aenderung
2766 |*
2767 |*************************************************************************/
2768 sal_Bool SwTabFrm::CalcFlyOffsets( SwTwips& rUpper,
2769 							   long& rLeftOffset,
2770 							   long& rRightOffset ) const
2771 {
2772 	sal_Bool bInvalidatePrtArea = sal_False;
2773 	const SwPageFrm *pPage = FindPageFrm();
2774 	const SwFlyFrm* pMyFly = FindFlyFrm();
2775 
2776     // --> #108724# Page header/footer content doesn't have to wrap around
2777     //              floating screen objects
2778 
2779     const IDocumentSettingAccess* pIDSA = GetFmt()->getIDocumentSettingAccess();
2780     const bool bWrapAllowed = pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) ||
2781                                 ( !IsInFtn() && 0 == FindFooterOrHeader() );
2782     // <--
2783 
2784 	if ( pPage->GetSortedObjs() && bWrapAllowed )
2785 	{
2786         SWRECTFN( this )
2787         const bool bConsiderWrapOnObjPos = pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION);
2788         long nPrtPos = (Frm().*fnRect->fnGetTop)();
2789         nPrtPos = (*fnRect->fnYInc)( nPrtPos, rUpper );
2790 		SwRect aRect( Frm() );
2791         long nYDiff = (*fnRect->fnYDiff)( (Prt().*fnRect->fnGetTop)(), rUpper );
2792         if( nYDiff > 0 )
2793             (aRect.*fnRect->fnAddBottom)( -nYDiff );
2794 		for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
2795 		{
2796             SwAnchoredObject* pAnchoredObj = (*pPage->GetSortedObjs())[i];
2797             if ( pAnchoredObj->ISA(SwFlyFrm) )
2798 			{
2799                 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
2800                 const SwRect aFlyRect = pFly->GetObjRectWithSpaces();
2801                 // --> OD 2004-10-07 #i26945# - correction of conditions,
2802                 // if Writer fly frame has to be considered:
2803                 // - no need to check, if top of Writer fly frame differs
2804                 //   from WEIT_WECH, because its also check, if the Writer
2805                 //   fly frame rectangle overlaps with <aRect>
2806                 // - no check, if bottom of anchor frame is prior the top of
2807                 //   the table, because Writer fly frames can be negative positioned.
2808                 // - correct check, if the Writer fly frame is an lower of the
2809                 //   table, because table lines/rows can split and a at-character
2810                 //   anchored Writer fly frame could be positioned in the follow
2811                 //   flow line.
2812                 // - add condition, that an existing anchor character text frame
2813                 //   has to be on the same page as the table.
2814                 //   E.g., it could happen, that the fly frame is still registered
2815                 //   at the page frame, the table is on, but it's anchor character
2816                 //   text frame has already changed its page.
2817                 //if ( WEIT_WECH != (pFly->Frm().*fnRect->fnGetTop)() &&
2818                 //     pFly->IsFlyAtCntFrm() && aFlyRect.IsOver( aRect ) &&
2819                 //     // OD 25.02.2003 #i9040# - use '<=' instead of '<'
2820                 //     (*fnRect->fnYDiff)(
2821                 //            (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetBottom)(),
2822                 //            (Frm().*fnRect->fnGetTop)() ) <= 0 &&
2823                 //     !IsAnLower( pFly ) && !pFly->IsAnLower( this ) &&
2824                 //     ( !pMyFly || pMyFly->IsAnLower( pFly ) ) &&
2825                 //     pPage->GetPhyPageNum() >=
2826                 //     pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
2827                 //     // anchor should be in same page body/header/footer
2828                 //     ( pFly->GetAnchorFrm()->FindFooterOrHeader() ==
2829                 //       FindFooterOrHeader() ) )
2830                 const SwTxtFrm* pAnchorCharFrm = pFly->FindAnchorCharFrm();
2831                 bool bConsiderFly =
2832                     // --> OD 2005-04-06 #i46807# - do not consider invalid
2833                     // Writer fly frames.
2834                     pFly->IsValid() &&
2835                     // <--
2836                     // fly anchored at character
2837                     pFly->IsFlyAtCntFrm() &&
2838                     // fly overlaps with corresponding table rectangle
2839                     aFlyRect.IsOver( aRect ) &&
2840                     // fly isn't lower of table and
2841                     // anchor character frame of fly isn't lower of table
2842                     ( !IsAnLower( pFly ) &&
2843                       ( !pAnchorCharFrm || !IsAnLower( pAnchorCharFrm ) ) ) &&
2844                     // table isn't lower of fly
2845                     !pFly->IsAnLower( this ) &&
2846                     // fly is lower of fly, the table is in
2847                     // --> OD 2005-05-31 #123274# - correction:
2848                     // assure that fly isn't a lower of a fly, the table isn't in.
2849                     // E.g., a table in the body doesn't wrap around a graphic,
2850                     // which is inside a frame.
2851                     ( ( !pMyFly ||
2852                         pMyFly->IsAnLower( pFly ) ) &&
2853                       pMyFly == pFly->GetAnchorFrmContainingAnchPos()->FindFlyFrm() ) &&
2854                     // <--
2855                     // anchor frame not on following page
2856                     pPage->GetPhyPageNum() >=
2857                       pFly->GetAnchorFrm()->FindPageFrm()->GetPhyPageNum() &&
2858                     // anchor character text frame on same page
2859                     ( !pAnchorCharFrm ||
2860                       pAnchorCharFrm->FindPageFrm()->GetPhyPageNum() ==
2861                         pPage->GetPhyPageNum() );
2862 
2863                 if ( bConsiderFly )
2864                 {
2865                     const SwFrm* pFlyHeaderFooterFrm = pFly->GetAnchorFrm()->FindFooterOrHeader();
2866                     const SwFrm* pThisHeaderFooterFrm = FindFooterOrHeader();
2867 
2868                     if ( pFlyHeaderFooterFrm != pThisHeaderFooterFrm &&
2869                         // --> FME 2007-07-02 #148493# If bConsiderWrapOnObjPos is set,
2870                         // we want to consider the fly if it is located in the header and
2871                         // the table is located in the body:
2872                          ( !bConsiderWrapOnObjPos || 0 != pThisHeaderFooterFrm || !pFlyHeaderFooterFrm->IsHeaderFrm() ) )
2873                         bConsiderFly = false;
2874                         // <--
2875                 }
2876 
2877                 if ( bConsiderFly )
2878                 // <--
2879 				{
2880 					const SwFmtSurround   &rSur = pFly->GetFmt()->GetSurround();
2881 					const SwFmtHoriOrient &rHori= pFly->GetFmt()->GetHoriOrient();
2882 					if ( SURROUND_NONE == rSur.GetSurround() )
2883 					{
2884                         long nBottom = (aFlyRect.*fnRect->fnGetBottom)();
2885                         if( (*fnRect->fnYDiff)( nPrtPos, nBottom ) < 0 )
2886                             nPrtPos = nBottom;
2887 						bInvalidatePrtArea = sal_True;
2888 					}
2889 					if ( (SURROUND_RIGHT	== rSur.GetSurround() ||
2890 						  SURROUND_PARALLEL == rSur.GetSurround())&&
2891                          text::HoriOrientation::LEFT == rHori.GetHoriOrient() )
2892 					{
2893                         const long nWidth = (*fnRect->fnXDiff)(
2894                             (aFlyRect.*fnRect->fnGetRight)(),
2895                             (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetLeft)() );
2896 						rLeftOffset = Max( rLeftOffset, nWidth );
2897 						bInvalidatePrtArea = sal_True;
2898 					}
2899 					if ( (SURROUND_LEFT		== rSur.GetSurround() ||
2900 						  SURROUND_PARALLEL == rSur.GetSurround())&&
2901                          text::HoriOrientation::RIGHT == rHori.GetHoriOrient() )
2902 					{
2903                         const long nWidth = (*fnRect->fnXDiff)(
2904                             (pFly->GetAnchorFrm()->Frm().*fnRect->fnGetRight)(),
2905                             (aFlyRect.*fnRect->fnGetLeft)() );
2906 						rRightOffset = Max( rRightOffset, nWidth );
2907 						bInvalidatePrtArea = sal_True;
2908 					}
2909 				}
2910 			}
2911 		}
2912         rUpper = (*fnRect->fnYDiff)( nPrtPos, (Frm().*fnRect->fnGetTop)() );
2913 	}
2914 
2915 	return bInvalidatePrtArea;
2916 }
2917 
2918 /*************************************************************************
2919 |*
2920 |*	SwTabFrm::Format()
2921 |*
2922 |*	Beschreibung:		"Formatiert" den Frame; Frm und PrtArea
2923 |*						Die Fixsize wird hier nicht eingestellt.
2924 |*	Ersterstellung		MA 09. Mar. 93
2925 |*	Letzte Aenderung	MA 18. Jun. 97
2926 |*
2927 |*************************************************************************/
2928 void SwTabFrm::Format( const SwBorderAttrs *pAttrs )
2929 {
2930 	ASSERT( pAttrs, "TabFrm::Format, pAttrs ist 0." );
2931 
2932     SWRECTFN( this )
2933 	if ( !bValidSize )
2934     {
2935         long nDiff = (GetUpper()->Prt().*fnRect->fnGetWidth)() -
2936                      (Frm().*fnRect->fnGetWidth)();
2937         if( nDiff )
2938             (aFrm.*fnRect->fnAddRight)( nDiff );
2939     }
2940 
2941 	//VarSize ist immer die Hoehe.
2942 	//Fuer den oberen/unteren Rand gelten die selben Regeln wie fuer
2943 	//cntfrms (sie MakePrtArea() von diesen).
2944 
2945 	SwTwips nUpper = CalcUpperSpace( pAttrs );
2946 
2947 	//Wir wollen Rahmen ausweichen. Zwei Moeglichkeiten:
2948 	//1. Es gibt Rahmen mit SurroundNone, diesen wird vollsaendig ausgewichen
2949 	//2. Es gibt Rahmen mit Umlauf nur rechts bzw. nur links und diese sind
2950 	//   rechts bzw. links ausgerichtet, diese geben ein Minimum fuer die
2951 	//	 Raender vor.
2952 	long nTmpRight = -1000000,
2953 		 nLeftOffset  = 0;
2954 	if( CalcFlyOffsets( nUpper, nLeftOffset, nTmpRight ) )
2955 		bValidPrtArea = sal_False;
2956 	long nRightOffset = Max( 0L, nTmpRight );
2957 
2958 	SwTwips nLower = pAttrs->CalcBottomLine();
2959     // --> collapsing borders FME 2005-05-27 #i29550#
2960     if ( IsCollapsingBorders() )
2961         nLower += GetBottomLineSize();
2962     // <-- collapsing
2963 
2964     if ( !bValidPrtArea )
2965 	{	bValidPrtArea = sal_True;
2966 
2967 		//Die Breite der PrtArea wird vom FrmFmt vorgegeben, die Raender
2968 		//sind entsprechend einzustellen.
2969 		//Mindestraender werden von Umrandung und Schatten vorgegeben.
2970 		//Die Rander werden so eingestellt, dass die PrtArea nach dem
2971 		//angegebenen Adjustment im Frm ausgerichtet wird.
2972 		//Wenn das Adjustment 0 ist, so werden die Rander anhand des
2973 		//Randattributes eingestellt.
2974 
2975         const SwTwips nOldHeight = (Prt().*fnRect->fnGetHeight)();
2976         const SwTwips nMax = (aFrm.*fnRect->fnGetWidth)();
2977 
2978         // OD 14.03.2003 #i9040# - adjust variable names.
2979         const SwTwips nLeftLine  = pAttrs->CalcLeftLine();
2980         const SwTwips nRightLine = pAttrs->CalcRightLine();
2981 
2982 		//Die Breite ist evtl. eine Prozentangabe. Wenn die Tabelle irgendwo
2983 		//'drinsteckt bezieht sie sich auf die Umgebung. Ist es der Body, so
2984 		//bezieht sie sich in der BrowseView auf die Bildschirmbreite.
2985 		const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
2986         // OD 14.03.2003 #i9040# - adjust variable name.
2987         const SwTwips nWishedTableWidth = CalcRel( rSz, sal_True );
2988 
2989 		sal_Bool bCheckBrowseWidth = sal_False;
2990 
2991         // OD 14.03.2003 #i9040# - insert new variables for left/right spacing.
2992         SwTwips nLeftSpacing  = 0;
2993         SwTwips nRightSpacing = 0;
2994         switch ( GetFmt()->GetHoriOrient().GetHoriOrient() )
2995 		{
2996             case text::HoriOrientation::LEFT:
2997 				{
2998                     // left indent:
2999                     nLeftSpacing = nLeftLine + nLeftOffset;
3000                     // OD 06.03.2003 #i9040# - correct calculation of right indent:
3001                     // - Consider right indent given by right line attributes.
3002                     // - Consider negative right indent.
3003                     // wished right indent determined by wished table width and
3004                     // left offset given by surround fly frames on the left:
3005                     const SwTwips nWishRight = nMax - nWishedTableWidth - nLeftOffset;
3006                     if ( nRightOffset > 0 )
3007                     {
3008                         // surrounding fly frames on the right
3009                         // -> right indent is maximun of given right offset
3010                         //    and wished right offset.
3011                         nRightSpacing = nRightLine + Max( nRightOffset, nWishRight );
3012                     }
3013                     else
3014                     {
3015                         // no surrounding fly frames on the right
3016                         // If intrinsic right indent (intrinsic means not considering
3017                         // determined left indent) is negative,
3018                         //      then hold this intrinsic indent,
3019                         //      otherwise non negative wished right indent is hold.
3020                         nRightSpacing = nRightLine +
3021                                         ( ( (nWishRight+nLeftOffset) < 0 ) ?
3022                                             (nWishRight+nLeftOffset) :
3023                                             Max( 0L, nWishRight ) );
3024                     }
3025 				}
3026 				break;
3027             case text::HoriOrientation::RIGHT:
3028 				{
3029                     // right indent:
3030                     nRightSpacing = nRightLine + nRightOffset;
3031                     // OD 06.03.2003 #i9040# - correct calculation of left indent:
3032                     // - Consider left indent given by left line attributes.
3033                     // - Consider negative left indent.
3034                     // wished left indent determined by wished table width and
3035                     // right offset given by surrounding fyl frames on the right:
3036                     const SwTwips nWishLeft = nMax - nWishedTableWidth - nRightOffset;
3037                     if ( nLeftOffset > 0 )
3038                     {
3039                         // surrounding fly frames on the left
3040                         // -> right indent is maximun of given left offset
3041                         //    and wished left offset.
3042                         nLeftSpacing = nLeftLine + Max( nLeftOffset, nWishLeft );
3043                     }
3044                     else
3045                     {
3046                         // no surrounding fly frames on the left
3047                         // If intrinsic left indent (intrinsic = not considering
3048                         // determined right indent) is negative,
3049                         //      then hold this intrinsic indent,
3050                         //      otherwise non negative wished left indent is hold.
3051                         nLeftSpacing = nLeftLine +
3052                                        ( ( (nWishLeft+nRightOffset) < 0 ) ?
3053                                            (nWishLeft+nRightOffset) :
3054                                            Max( 0L, nWishLeft ) );
3055                     }
3056 				}
3057 				break;
3058             case text::HoriOrientation::CENTER:
3059 				{
3060                     // OD 07.03.2003 #i9040# - consider left/right line attribute.
3061                     // OD 10.03.2003 #i9040# -
3062                     const SwTwips nCenterSpacing = ( nMax - nWishedTableWidth ) / 2;
3063                     nLeftSpacing = nLeftLine +
3064                                    ( (nLeftOffset > 0) ?
3065                                      Max( nCenterSpacing, nLeftOffset ) :
3066                                      nCenterSpacing );
3067                     nRightSpacing = nRightLine +
3068                                     ( (nRightOffset > 0) ?
3069                                       Max( nCenterSpacing, nRightOffset ) :
3070                                       nCenterSpacing );
3071 				}
3072 				break;
3073             case text::HoriOrientation::FULL:
3074 					//Das Teil dehnt sich ueber die gesamte Breite aus.
3075 					//Nur die fuer die Umrandung benoetigten Freiraeume
3076 					//werden beruecksichtigt.
3077 					//Die Attributwerte von LRSpace werden bewusst missachtet!
3078 					bCheckBrowseWidth = sal_True;
3079                     nLeftSpacing  = nLeftLine + nLeftOffset;
3080                     nRightSpacing = nRightLine + nRightOffset;
3081 				break;
3082             case text::HoriOrientation::NONE:
3083 				{
3084 					//Die Raender werden vom Randattribut bestimmt.
3085                     nLeftSpacing = pAttrs->CalcLeft( this );
3086 					if( nLeftOffset )
3087 					{
3088                         // OD 07.03.2003 #i9040# - surround fly frames only, if
3089                         // they overlap with the table.
3090                         // Thus, take maximun of left spacing and left offset.
3091                         // OD 10.03.2003 #i9040# - consider left line attribute.
3092                         nLeftSpacing = Max( nLeftSpacing, ( nLeftOffset + nLeftLine ) );
3093 					}
3094                     // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
3095                     nRightSpacing = pAttrs->CalcRight( this );
3096 					if( nRightOffset )
3097 					{
3098                         // OD 07.03.2003 #i9040# - surround fly frames only, if
3099                         // they overlap with the table.
3100                         // Thus, take maximun of right spacing and right offset.
3101                         // OD 10.03.2003 #i9040# - consider right line attribute.
3102                         nRightSpacing = Max( nRightSpacing, ( nRightOffset + nRightLine ) );
3103 					}
3104                     // OD 10.03.2003 #i9040# - do not hold wished table width.
3105                     /*
3106                     if ( !pAttrs->GetLRSpace().GetRight() )
3107 						nRight = Max( nRight, nMax - (nWish + nLeft + nRight));
3108                     */
3109 				}
3110 				break;
3111             case text::HoriOrientation::LEFT_AND_WIDTH:
3112                 {
3113 					//Linker Rand und die Breite zaehlen (Word-Spezialitaet)
3114                     // OD 10.03.2003 #i9040# - no width alignment in online mode.
3115                     //bCheckBrowseWidth = sal_True;
3116                     nLeftSpacing = pAttrs->CalcLeft( this );
3117 					if( nLeftOffset )
3118 					{
3119                         // OD 10.03.2003 #i9040# - surround fly frames only, if
3120                         // they overlap with the table.
3121                         // Thus, take maximun of right spacing and right offset.
3122                         // OD 10.03.2003 #i9040# - consider left line attribute.
3123                         nLeftSpacing = Max( nLeftSpacing, ( pAttrs->CalcLeftLine() + nLeftOffset ) );
3124 					}
3125                     // OD 10.03.2003 #i9040# - consider right and left line attribute.
3126                     const SwTwips nWishRight =
3127                             nMax - (nLeftSpacing-pAttrs->CalcLeftLine()) - nWishedTableWidth;
3128                     nRightSpacing = nRightLine +
3129                                     ( (nRightOffset > 0) ?
3130                                       Max( nWishRight, nRightOffset ) :
3131                                       nWishRight );
3132                 }
3133 				break;
3134 			default:
3135 				ASSERT( sal_False, "Ungueltige orientation fuer Table." );
3136 		}
3137 
3138         // --> OD 2004-07-15 #i26250# - extend bottom printing area, if table
3139         // is last content inside a table cell.
3140         if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS) &&
3141              GetUpper()->IsInTab() && !GetIndNext() )
3142         {
3143             nLower += pAttrs->GetULSpace().GetLower();
3144         }
3145         // <--
3146         (this->*fnRect->fnSetYMargins)( nUpper, nLower );
3147         if( (nMax - MINLAY) < (nLeftSpacing + nRightSpacing) )
3148             (this->*fnRect->fnSetXMargins)( 0, 0 );
3149 		else
3150             (this->*fnRect->fnSetXMargins)( nLeftSpacing, nRightSpacing );
3151 
3152         ViewShell *pSh = getRootFrm()->GetCurrShell();
3153         if ( bCheckBrowseWidth &&
3154              pSh && pSh->GetViewOptions()->getBrowseMode() &&
3155 			 GetUpper()->IsPageBodyFrm() &&  // nur PageBodyFrms, nicht etwa ColBodyFrms
3156 			 pSh->VisArea().Width() )
3157 		{
3158 			//Nicht ueber die Kante des sichbaren Bereiches hinausragen.
3159 			//Die Seite kann breiter sein, weil es Objekte mit "ueberbreite"
3160 			//geben kann (RootFrm::ImplCalcBrowseWidth())
3161 			long nWidth = pSh->GetBrowseWidth();
3162 			nWidth -= Prt().Left();
3163 			nWidth -= pAttrs->CalcRightLine();
3164 			Prt().Width( Min( nWidth, Prt().Width() ) );
3165 		}
3166 
3167         if ( nOldHeight != (Prt().*fnRect->fnGetHeight)() )
3168 			bValidSize = sal_False;
3169 	}
3170 
3171 	if ( !bValidSize )
3172 	{
3173 		bValidSize = sal_True;
3174 
3175 		//Die Groesse wird durch den Inhalt plus den Raendern bestimmt.
3176 		SwTwips nRemaining = 0, nDiff;
3177 		SwFrm *pFrm = pLower;
3178 		while ( pFrm )
3179         {
3180             nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)();
3181             pFrm = pFrm->GetNext();
3182 		}
3183 		//Jetzt noch die Raender addieren
3184 		nRemaining += nUpper + nLower;
3185 
3186         nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining;
3187         if ( nDiff > 0 )
3188             Shrink( nDiff );
3189 		else if ( nDiff < 0 )
3190             Grow( -nDiff );
3191 	}
3192 }
3193 /*************************************************************************
3194 |*
3195 |*	SwTabFrm::GrowFrm()
3196 |*
3197 |*	Ersterstellung		MA 12. Mar. 93
3198 |*	Letzte Aenderung	MA 23. Sep. 96
3199 |*
3200 |*************************************************************************/
3201 SwTwips SwTabFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
3202 {
3203     SWRECTFN( this )
3204     SwTwips nHeight =(Frm().*fnRect->fnGetHeight)();
3205     if( nHeight > 0 && nDist > ( LONG_MAX - nHeight ) )
3206         nDist = LONG_MAX - nHeight;
3207 
3208     if ( bTst && !IsRestrictTableGrowth() )
3209         return nDist;
3210 
3211     if ( GetUpper() )
3212     {
3213         SwRect aOldFrm( Frm() );
3214 
3215         //Der Upper wird nur soweit wie notwendig gegrowed. In nReal wird erstmal
3216         //die bereits zur Verfuegung stehende Strecke bereitgestellt.
3217         SwTwips nReal = (GetUpper()->Prt().*fnRect->fnGetHeight)();
3218         SwFrm *pFrm = GetUpper()->Lower();
3219         while ( pFrm && GetFollow() != pFrm )
3220         {
3221             nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
3222             pFrm = pFrm->GetNext();
3223         }
3224 
3225         long nTmp = 0;
3226         if ( nReal < nDist )
3227         {
3228             nTmp = GetUpper()->Grow( nDist - ( nReal > 0 ? nReal : 0), bTst, bInfo );
3229 
3230             if ( IsRestrictTableGrowth() )
3231             {
3232                 nTmp = Min( nDist, nReal + nTmp );
3233                 nDist = nTmp < 0 ? 0 : nTmp;
3234             }
3235         }
3236 
3237         if ( !bTst )
3238         {
3239             (Frm().*fnRect->fnAddBottom)( nDist );
3240 
3241             SwRootFrm *pRootFrm = getRootFrm();
3242             if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
3243                 pRootFrm->GetCurrShell() )
3244             {
3245                 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( this, aOldFrm );
3246             }
3247         }
3248     }
3249 
3250     if ( !bTst && ( nDist || IsRestrictTableGrowth() ) )
3251     {
3252         SwPageFrm *pPage = FindPageFrm();
3253         if ( GetNext() )
3254         {
3255             GetNext()->_InvalidatePos();
3256             if ( GetNext()->IsCntntFrm() )
3257                 GetNext()->InvalidatePage( pPage );
3258         }
3259         // --> OD 2004-07-05 #i28701# - Due to the new object positioning the
3260         // frame on the next page/column can flow backward (e.g. it was moved
3261         // forward due to the positioning of its objects ). Thus, invalivate this
3262         // next frame, if document compatibility option 'Consider wrapping style
3263         // influence on object positioning' is ON.
3264         else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
3265         {
3266             InvalidateNextPos();
3267         }
3268         // <--
3269         _InvalidateAll();
3270         InvalidatePage( pPage );
3271         SetComplete();
3272 
3273         const SvxGraphicPosition ePos = GetFmt()->GetBackground().GetGraphicPos();
3274         if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
3275             SetCompletePaint();
3276     }
3277 
3278     return nDist;
3279 }
3280 /*************************************************************************
3281 |*
3282 |*	  SwTabFrm::Modify()
3283 |*
3284 |*	  Ersterstellung	MA 14. Mar. 93
3285 |*	  Letzte Aenderung	MA 06. Dec. 96
3286 |*
3287 |*************************************************************************/
3288 void SwTabFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
3289 {
3290 	sal_uInt8 nInvFlags = 0;
3291 	sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
3292 
3293 	if( bAttrSetChg )
3294 	{
3295 		SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() );
3296 		SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() );
3297 		SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
3298 		SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
3299 		while( sal_True )
3300 		{
3301 			_UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(),
3302 						 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags,
3303 						 &aOldSet, &aNewSet );
3304 			if( aNIter.IsAtEnd() )
3305 				break;
3306 			aNIter.NextItem();
3307 			aOIter.NextItem();
3308 		}
3309 		if ( aOldSet.Count() || aNewSet.Count() )
3310 			SwLayoutFrm::Modify( &aOldSet, &aNewSet );
3311 	}
3312 	else
3313 		_UpdateAttr( pOld, pNew, nInvFlags );
3314 
3315 	if ( nInvFlags != 0 )
3316 	{
3317 		SwPageFrm *pPage = FindPageFrm();
3318 		InvalidatePage( pPage );
3319 //		if ( nInvFlags & 0x01 )
3320 //			SetCompletePaint();
3321 		if ( nInvFlags & 0x02 )
3322 			_InvalidatePrt();
3323 		if ( nInvFlags & 0x40 )
3324 			_InvalidatePos();
3325 		SwFrm *pTmp;
3326 		if ( 0 != (pTmp = GetIndNext()) )
3327 		{
3328 			if ( nInvFlags & 0x04 )
3329 			{
3330 				pTmp->_InvalidatePrt();
3331 				if ( pTmp->IsCntntFrm() )
3332 					pTmp->InvalidatePage( pPage );
3333 			}
3334 			if ( nInvFlags & 0x10 )
3335 				pTmp->SetCompletePaint();
3336 		}
3337 		if ( nInvFlags & 0x08 && 0 != (pTmp = GetPrev()) )
3338 		{
3339 			pTmp->_InvalidatePrt();
3340 			if ( pTmp->IsCntntFrm() )
3341 				pTmp->InvalidatePage( pPage );
3342 		}
3343 		if ( nInvFlags & 0x20  )
3344 		{
3345 			if ( pPage && pPage->GetUpper() && !IsFollow() )
3346 				((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3347 		}
3348 		if ( nInvFlags & 0x80 )
3349 			InvalidateNextPos();
3350 	}
3351 }
3352 
3353 void SwTabFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
3354 							sal_uInt8 &rInvFlags,
3355 							SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
3356 {
3357 	sal_Bool bClear = sal_True;
3358 	const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
3359 	switch( nWhich )
3360 	{
3361 		case RES_TBLHEADLINECHG:
3362 			if ( IsFollow() )
3363 			{
3364                 // Delete remaining headlines:
3365                 SwRowFrm* pLowerRow = 0;
3366                 while ( 0 != ( pLowerRow = (SwRowFrm*)Lower() ) && pLowerRow->IsRepeatedHeadline() )
3367                 {
3368                     pLowerRow->Cut();
3369                     delete pLowerRow;
3370                 }
3371 
3372                 // insert new headlines
3373                 const sal_uInt16 nNewRepeat = GetTable()->GetRowsToRepeat();
3374                 for ( sal_uInt16 nIdx = 0; nIdx < nNewRepeat; ++nIdx )
3375                 {
3376                     bDontCreateObjects = sal_True;          //frmtool
3377                     SwRowFrm* pHeadline = new SwRowFrm( *GetTable()->GetTabLines()[ nIdx ], this );
3378                     pHeadline->SetRepeatedHeadline( true );
3379                     bDontCreateObjects = sal_False;
3380                     pHeadline->Paste( this, pLowerRow );
3381                 }
3382             }
3383             rInvFlags |= 0x02;
3384 			break;
3385 
3386 		case RES_FRM_SIZE:
3387 		case RES_HORI_ORIENT:
3388 			rInvFlags |= 0x22;
3389 			break;
3390 
3391 		case RES_PAGEDESC:						//Attributaenderung (an/aus)
3392 			if ( IsInDocBody() )
3393 			{
3394 				rInvFlags |= 0x40;
3395 				SwPageFrm *pPage = FindPageFrm();
3396 				if ( !GetPrev() )
3397 					CheckPageDescs( pPage );
3398 				if ( pPage && GetFmt()->GetPageDesc().GetNumOffset() )
3399 					((SwRootFrm*)pPage->GetUpper())->SetVirtPageNum( sal_True );
3400 				SwDocPosUpdate aMsgHnt( pPage->Frm().Top() );
3401 				GetFmt()->GetDoc()->UpdatePageFlds( &aMsgHnt );
3402 			}
3403 			break;
3404 
3405 		case RES_BREAK:
3406 			rInvFlags |= 0xC0;
3407 			break;
3408 
3409 		case RES_LAYOUT_SPLIT:
3410 			if ( !IsFollow() )
3411 				rInvFlags |= 0x40;
3412 			break;
3413         case RES_FRAMEDIR :
3414             SetDerivedR2L( sal_False );
3415             CheckDirChange();
3416             break;
3417         case RES_COLLAPSING_BORDERS :
3418     		rInvFlags |= 0x02;
3419             lcl_InvalidateAllLowersPrt( this );
3420             break;
3421 		case RES_UL_SPACE:
3422 			rInvFlags |= 0x1C;
3423 			/* kein Break hier */
3424 
3425 		default:
3426 			bClear = sal_False;
3427 	}
3428 	if ( bClear )
3429 	{
3430 		if ( pOldSet || pNewSet )
3431 		{
3432 			if ( pOldSet )
3433 				pOldSet->ClearItem( nWhich );
3434 			if ( pNewSet )
3435 				pNewSet->ClearItem( nWhich );
3436 		}
3437 		else
3438 			SwLayoutFrm::Modify( pOld, pNew );
3439 	}
3440 }
3441 
3442 /*************************************************************************
3443 |*
3444 |*	  SwTabFrm::GetInfo()
3445 |*
3446 |*	  Ersterstellung	MA 06. Dec. 96
3447 |*	  Letzte Aenderung	MA 26. Jun. 98
3448 |*
3449 |*************************************************************************/
3450 sal_Bool SwTabFrm::GetInfo( SfxPoolItem &rHnt ) const
3451 {
3452 	if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && !IsFollow() )
3453 	{
3454 		SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
3455 		const SwPageFrm *pPage = FindPageFrm();
3456 		if ( pPage  )
3457 		{
3458 			if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
3459 			{
3460 				//Das sollte er sein (kann allenfalls temporaer anders sein,
3461 				//					  sollte uns das beunruhigen?)
3462 				rInfo.SetInfo( pPage, this );
3463 				return sal_False;
3464 			}
3465 			if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
3466 				 (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
3467 			{
3468 				//Das koennte er sein.
3469 				rInfo.SetInfo( pPage, this );
3470 			}
3471 		}
3472 	}
3473 	return sal_True;
3474 }
3475 
3476 /*************************************************************************
3477 |*
3478 |*	  SwTabFrm::FindLastCntnt()
3479 |*
3480 |*	  Ersterstellung	MA 13. Apr. 93
3481 |*	  Letzte Aenderung	MA 15. May. 98
3482 |*
3483 |*************************************************************************/
3484 SwCntntFrm *SwTabFrm::FindLastCntnt()
3485 {
3486 	SwFrm *pRet = pLower;
3487 
3488 	while ( pRet && !pRet->IsCntntFrm() )
3489 	{
3490 		SwFrm *pOld = pRet;
3491 
3492         SwFrm *pTmp = pRet;             // To skip empty section frames
3493 		while ( pRet->GetNext() )
3494         {
3495 			pRet = pRet->GetNext();
3496             if( !pRet->IsSctFrm() || ((SwSectionFrm*)pRet)->GetSection() )
3497                 pTmp = pRet;
3498         }
3499         pRet = pTmp;
3500 
3501 		if ( pRet->GetLower() )
3502 			pRet = pRet->GetLower();
3503 		if ( pRet == pOld )
3504         {
3505             // Wenn am Ende der letzten Zelle ein spaltiger Bereich steht,
3506 			// der eine leere letzte Spalte hat, muessen wir noch die anderen
3507 			// Spalten abklappern, dies erledigt SwSectionFrm::FindLastCntnt
3508 			if( pRet->IsColBodyFrm() )
3509 			{
3510 #ifdef DBG_UTIL
3511 				SwSectionFrm* pSect = pRet->FindSctFrm();
3512 				ASSERT( pSect, "Wo kommt denn die Spalte her?")
3513 				ASSERT( IsAnLower( pSect ), "Gespaltene Zelle?" );
3514 #endif
3515 				return pRet->FindSctFrm()->FindLastCntnt();
3516 			}
3517 
3518             //
3519             // pRet may be a cell frame without a lower (cell has been split).
3520             // We have to find the last content the hard way:
3521             //
3522             ASSERT( pRet->IsCellFrm(), "SwTabFrm::FindLastCntnt failed" )
3523             const SwFrm* pRow = pRet->GetUpper();
3524             while ( pRow && !pRow->GetUpper()->IsTabFrm() )
3525                 pRow = pRow->GetUpper();
3526             SwCntntFrm* pCntntFrm = ((SwLayoutFrm*)pRow)->ContainsCntnt();
3527             pRet = 0;
3528 
3529             while ( pCntntFrm && ((SwLayoutFrm*)pRow)->IsAnLower( pCntntFrm ) )
3530             {
3531                 pRet = pCntntFrm;
3532                 pCntntFrm = pCntntFrm->GetNextCntntFrm();
3533             }
3534         }
3535     }
3536 
3537     // #112929# There actually is a situation, which results in pRet = 0:
3538     // Insert frame, insert table via text <-> table. This gives you a frame
3539     // containing a table without any other content frames. Split the table
3540     // and undo the splitting. This operation gives us a table frame without
3541     // a lower.
3542     if ( pRet )
3543     {
3544         while ( pRet->GetNext() )
3545 			pRet = pRet->GetNext();
3546 
3547         if( pRet->IsSctFrm() )
3548 		    pRet = ((SwSectionFrm*)pRet)->FindLastCntnt();
3549     }
3550 
3551     return (SwCntntFrm*)pRet;
3552 }
3553 
3554 /*************************************************************************
3555 |*
3556 |*	SwTabFrm::GetLeaf()
3557 |*
3558 |*	Ersterstellung		MA 19. Mar. 93
3559 |*	Letzte Aenderung	MA 25. Apr. 95
3560 |*
3561 |*************************************************************************/
3562 SwLayoutFrm *SwTabFrm::GetLeaf( MakePageType eMakePage, sal_Bool bFwd )
3563 {
3564 	SwLayoutFrm *pRet;
3565 	if ( bFwd )
3566 	{
3567 		pRet = GetNextLeaf( eMakePage );
3568 		while ( IsAnLower( pRet ) )
3569 			pRet = pRet->GetNextLeaf( eMakePage );
3570 	}
3571 	else
3572 		pRet = GetPrevLeaf();
3573 	if ( pRet )
3574 		pRet->Calc();
3575 	return pRet;
3576 }
3577 
3578 /*************************************************************************
3579 |*
3580 |*	SwTabFrm::ShouldBwdMoved()
3581 |*
3582 |* 	Beschreibung		Returnwert sagt ob der Frm verschoben werden sollte
3583 |*	Ersterstellung		MA 10. Jul. 95
3584 |*	Letzte Aenderung	MA 04. Mar. 97
3585 |*
3586 |*************************************************************************/
3587 sal_Bool SwTabFrm::ShouldBwdMoved( SwLayoutFrm *pNewUpper, sal_Bool, sal_Bool &rReformat )
3588 {
3589 	rReformat = sal_False;
3590 	if ( (SwFlowFrm::IsMoveBwdJump() || !IsPrevObjMove()) )
3591 	{
3592 		//Das zurueckfliessen von Frm's ist leider etwas Zeitintensiv.
3593 		//Der haufigste Fall ist der, dass dort wo der Frm hinfliessen
3594 		//moechte die FixSize die gleiche ist, die der Frm selbst hat.
3595 		//In diesem Fall kann einfach geprueft werden, ob der Frm genug
3596 		//Platz fuer seine VarSize findet, ist dies nicht der Fall kann
3597 		//gleich auf das Verschieben verzichtet werden.
3598 		//Die Pruefung, ob der Frm genug Platz findet fuehrt er selbst
3599 		//durch, dabei wird beruecksichtigt, dass er sich moeglicherweise
3600 		//aufspalten kann.
3601 		//Wenn jedoch die FixSize eine andere ist oder Flys im Spiel sind
3602 		//(an der alten oder neuen Position) hat alle Prueferei keinen Sinn
3603 		//der Frm muss dann halt Probehalber verschoben werden (Wenn ueberhaupt
3604 		//etwas Platz zur Verfuegung steht).
3605 
3606 		//Die FixSize der Umgebungen in denen Tabellen herumlungern ist immer
3607 		//Die Breite.
3608 
3609 		SwPageFrm *pOldPage = FindPageFrm(),
3610 				  *pNewPage = pNewUpper->FindPageFrm();
3611 		sal_Bool bMoveAnyway = sal_False;
3612 		SwTwips nSpace = 0;
3613 
3614         SWRECTFN( this )
3615         if ( !SwFlowFrm::IsMoveBwdJump() )
3616         {
3617 
3618             long nOldWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
3619             SWRECTFNX( pNewUpper );
3620             long nNewWidth = (pNewUpper->Prt().*fnRectX->fnGetWidth)();
3621             if( Abs( nNewWidth - nOldWidth ) < 2 )
3622             {
3623                 if( sal_False ==
3624                     ( bMoveAnyway = BwdMoveNecessary( pOldPage, Frm() ) > 1 ) )
3625                 {
3626                     SwRect aRect( pNewUpper->Prt() );
3627                     aRect.Pos() += pNewUpper->Frm().Pos();
3628                     const SwFrm *pPrevFrm = pNewUpper->Lower();
3629                     while ( pPrevFrm && pPrevFrm != this )
3630                     {
3631                         (aRect.*fnRectX->fnSetTop)( (pPrevFrm->Frm().*fnRectX->
3632                                                     fnGetBottom)() );
3633                         pPrevFrm = pPrevFrm->GetNext();
3634                     }
3635                     bMoveAnyway = BwdMoveNecessary( pNewPage, aRect) > 1;
3636 
3637                     // --> FME 2006-01-20 #i54861# Due to changes made in PrepareMake,
3638                     // the tabfrm may not have a correct position. Therefore
3639                     // it is possible that pNewUpper->Prt().Height == 0. In this
3640                     // case the above calculation of nSpace might give wrong
3641                     // results and we really do not want to MoveBackwrd into a
3642                     // 0 height frame. If nTmpSpace is already <= 0, we take this
3643                     // value:
3644                     const SwTwips nTmpSpace = (aRect.*fnRectX->fnGetHeight)();
3645                     if ( (pNewUpper->Prt().*fnRectX->fnGetHeight)() > 0 || nTmpSpace <= 0 )
3646                         nSpace = nTmpSpace;
3647                     // <--
3648 
3649                     const ViewShell *pSh = getRootFrm()->GetCurrShell();
3650                     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
3651                         nSpace += pNewUpper->Grow( LONG_MAX, sal_True );
3652                 }
3653             }
3654             else if( !bLockBackMove )
3655                 bMoveAnyway = sal_True;
3656 		}
3657         else if( !bLockBackMove )
3658 			bMoveAnyway = sal_True;
3659 
3660 		if ( bMoveAnyway )
3661 			return rReformat = sal_True;
3662 		else if ( !bLockBackMove && nSpace > 0 )
3663 		{
3664             // --> OD 2004-10-05 #i26945# - check, if follow flow line
3665             // contains frame, which are moved forward due to its object
3666             // positioning.
3667             SwRowFrm* pFirstRow = GetFirstNonHeadlineRow();
3668             if ( pFirstRow && pFirstRow->IsInFollowFlowRow() &&
3669                  SwLayouter::DoesRowContainMovedFwdFrm(
3670                                             *(pFirstRow->GetFmt()->GetDoc()),
3671                                             *(pFirstRow) ) )
3672             {
3673                 return sal_False;
3674             }
3675             // <--
3676             SwTwips nTmpHeight = CalcHeightOfFirstContentLine();
3677 
3678             // --> FME 2005-01-17 #118840#
3679             // For some mysterious reason, I changed the good old
3680             // 'return nHeight <= nSpace' to 'return nTmpHeight < nSpace'.
3681             // This obviously results in problems with table frames in
3682             // sections. Remember: Every twip is sacred.
3683             return nTmpHeight <= nSpace;
3684             // <--
3685         }
3686 	}
3687 	return sal_False;
3688 }
3689 
3690 /*************************************************************************
3691 |*
3692 |*	SwTabFrm::Cut()
3693 |*
3694 |*	Ersterstellung		MA 23. Feb. 94
3695 |*	Letzte Aenderung	MA 09. Sep. 98
3696 |*
3697 |*************************************************************************/
3698 void SwTabFrm::Cut()
3699 {
3700 	ASSERT( GetUpper(), "Cut ohne Upper()." );
3701 
3702 	SwPageFrm *pPage = FindPageFrm();
3703 	InvalidatePage( pPage );
3704 	SwFrm *pFrm = GetNext();
3705 	if( pFrm )
3706 	{	//Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger
3707 		//berechnet der ist jetzt wo er der erste wird obsolete
3708 		pFrm->_InvalidatePrt();
3709 		pFrm->_InvalidatePos();
3710 		if ( pFrm->IsCntntFrm() )
3711 			pFrm->InvalidatePage( pPage );
3712 		if( IsInSct() && !GetPrev() )
3713 		{
3714 			SwSectionFrm* pSct = FindSctFrm();
3715 			if( !pSct->IsFollow() )
3716 			{
3717 				pSct->_InvalidatePrt();
3718 				pSct->InvalidatePage( pPage );
3719 			}
3720 		}
3721 	}
3722 	else
3723 	{
3724 		InvalidateNextPos();
3725 		//Einer muss die Retusche uebernehmen: Vorgaenger oder Upper
3726 		if ( 0 != (pFrm = GetPrev()) )
3727 		{	pFrm->SetRetouche();
3728 			pFrm->Prepare( PREP_WIDOWS_ORPHANS );
3729 			pFrm->_InvalidatePos();
3730 			if ( pFrm->IsCntntFrm() )
3731 				pFrm->InvalidatePage( pPage );
3732 		}
3733 		//Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss
3734 		//er die Retouche uebernehmen.
3735 		//Ausserdem kann eine Leerseite entstanden sein.
3736 		else
3737 		{	SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper();
3738 			pRoot->SetSuperfluous();
3739 			GetUpper()->SetCompletePaint();
3740 			if( IsInSct() )
3741 			{
3742 				SwSectionFrm* pSct = FindSctFrm();
3743 				if( !pSct->IsFollow() )
3744 				{
3745 					pSct->_InvalidatePrt();
3746 					pSct->InvalidatePage( pPage );
3747 				}
3748 			}
3749 		}
3750 	}
3751 
3752 	//Erst removen, dann Upper Shrinken.
3753 	SwLayoutFrm *pUp = GetUpper();
3754     SWRECTFN( this )
3755 	Remove();
3756 	if ( pUp )
3757 	{
3758 		ASSERT( !pUp->IsFtnFrm(), "Tabelle in Fussnote." );
3759 		SwSectionFrm *pSct = 0;
3760         // --> OD 2006-01-04 #126020# - adjust check for empty section
3761         // --> OD 2006-02-01 #130797# - correct fix #126020#
3762         if ( !pUp->Lower() && pUp->IsInSct() &&
3763              !(pSct = pUp->FindSctFrm())->ContainsCntnt() &&
3764              !pSct->ContainsAny( true ) )
3765         // <--
3766 		{
3767 			if ( pUp->GetUpper() )
3768 			{
3769 				pSct->DelEmpty( sal_False );
3770 				pSct->_InvalidateSize();
3771 			}
3772 		}
3773         else if( (Frm().*fnRect->fnGetHeight)() )
3774         {
3775             // OD 26.08.2003 #i18103# - *no* 'ColUnlock' of section -
3776             // undo changes of fix for #104992#
3777             pUp->Shrink( Frm().Height() );
3778         }
3779 	}
3780 
3781 	if ( pPage && !IsFollow() && pPage->GetUpper() )
3782 		((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3783 }
3784 
3785 /*************************************************************************
3786 |*
3787 |*	SwTabFrm::Paste()
3788 |*
3789 |*	Ersterstellung		MA 23. Feb. 94
3790 |*	Letzte Aenderung	MA 09. Sep. 98
3791 |*
3792 |*************************************************************************/
3793 void SwTabFrm::Paste( SwFrm* pParent, SwFrm* pSibling )
3794 {
3795 	ASSERT( pParent, "Kein Parent fuer Paste." );
3796 	ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." );
3797 	ASSERT( pParent != this, "Bin selbst der Parent." );
3798 	ASSERT( pSibling != this, "Bin mein eigener Nachbar." );
3799 	ASSERT( !GetPrev() && !GetNext() && !GetUpper(),
3800 			"Bin noch irgendwo angemeldet." );
3801 
3802 	//In den Baum einhaengen.
3803 	InsertBefore( (SwLayoutFrm*)pParent, pSibling );
3804 
3805 	_InvalidateAll();
3806 	SwPageFrm *pPage = FindPageFrm();
3807 	InvalidatePage( pPage );
3808 
3809 	if ( GetNext() )
3810 	{
3811 		GetNext()->_InvalidatePos();
3812 		GetNext()->_InvalidatePrt();
3813 		if ( GetNext()->IsCntntFrm() )
3814 			GetNext()->InvalidatePage( pPage );
3815 	}
3816 
3817     SWRECTFN( this )
3818     if( (Frm().*fnRect->fnGetHeight)() )
3819         pParent->Grow( (Frm().*fnRect->fnGetHeight)() );
3820 
3821     if( (Frm().*fnRect->fnGetWidth)() != (pParent->Prt().*fnRect->fnGetWidth)() )
3822 		Prepare( PREP_FIXSIZE_CHG );
3823 	if ( GetPrev() )
3824 	{
3825 		if ( !IsFollow() )
3826 		{
3827 			GetPrev()->InvalidateSize();
3828 			if ( GetPrev()->IsCntntFrm() )
3829 				GetPrev()->InvalidatePage( pPage );
3830 		}
3831 	}
3832 	else if ( GetNext() )
3833 		//Bei CntntFrm's gilt es den Abstand zum Vorgaenger/Nachfolger
3834 		//zu beachten. Faelle (beide treten immer gleichzeitig auf):
3835 		//a) Der Cntnt wird der erste einer Kette
3836 		//b) Der neue Nachfolger war vorher der erste einer Kette
3837 		GetNext()->_InvalidatePrt();
3838 
3839 	if ( pPage && !IsFollow() )
3840 	{
3841 		if ( pPage->GetUpper() )
3842 			((SwRootFrm*)pPage->GetUpper())->InvalidateBrowseWidth();
3843 
3844 		if ( !GetPrev() )//Mindestens fuer HTML mit Tabelle am Anfang notwendig.
3845 		{
3846 			const SwPageDesc *pDesc = GetFmt()->GetPageDesc().GetPageDesc();
3847 			if ( (pDesc && pDesc != pPage->GetPageDesc()) ||
3848 				 (!pDesc && pPage->GetPageDesc() !=
3849                   &(const_cast<const SwDoc *>(GetFmt()->GetDoc())
3850                     ->GetPageDesc(0))) )
3851 				CheckPageDescs( pPage, sal_True );
3852 		}
3853 	}
3854 }
3855 
3856 /*************************************************************************
3857 |*
3858 |*  SwTabFrm::Prepare()
3859 |*
3860 |*  Created        AMA 01/10/02
3861 |*  Last Change    AMA 01/10/02
3862 |*
3863 |*************************************************************************/
3864 void SwTabFrm::Prepare( const PrepareHint eHint, const void *, sal_Bool )
3865 {
3866     if( PREP_BOSS_CHGD == eHint )
3867         CheckDirChange();
3868 }
3869 
3870 /*************************************************************************
3871 |*
3872 |*	SwRowFrm::SwRowFrm(), ~SwRowFrm()
3873 |*
3874 |*	Ersterstellung		MA 09. Mar. 93
3875 |*	Letzte Aenderung	MA 30. May. 96
3876 |*
3877 |*************************************************************************/
3878 SwRowFrm::SwRowFrm( const SwTableLine &rLine, SwFrm* pSib, bool bInsertContent ):
3879 	SwLayoutFrm( rLine.GetFrmFmt(), pSib ),
3880     pTabLine( &rLine ),
3881     pFollowRow( 0 ),
3882     // --> collapsing borders FME 2005-05-27 #i29550#
3883     mnTopMarginForLowers( 0 ),
3884     mnBottomMarginForLowers( 0 ),
3885     mnBottomLineSize( 0 ),
3886     // <-- collapsing
3887     // --> split table rows
3888     bIsFollowFlowRow( false ),
3889     // <-- split table rows
3890     bIsRepeatedHeadline( false ),
3891     mbIsRowSpanLine( false )
3892 {
3893     nType = FRMC_ROW;
3894 
3895 	//Gleich die Boxen erzeugen und einfuegen.
3896    	const SwTableBoxes &rBoxes = rLine.GetTabBoxes();
3897     SwFrm *pTmpPrev = 0;
3898   	for ( sal_uInt16 i = 0; i < rBoxes.Count(); ++i )
3899    	{
3900         SwCellFrm *pNew = new SwCellFrm( *rBoxes[i], this, bInsertContent );
3901         pNew->InsertBehind( this, pTmpPrev );
3902         pTmpPrev = pNew;
3903     }
3904 }
3905 
3906 SwRowFrm::~SwRowFrm()
3907 {
3908 	SwModify* pMod = GetFmt();
3909 	if( pMod )
3910 	{
3911 		pMod->Remove( this );			// austragen,
3912 		if( !pMod->GetDepends() )
3913 			delete pMod;				// und loeschen
3914 	}
3915 }
3916 
3917 /*************************************************************************
3918 |*
3919 |*	SwRowFrm::RegistFlys()
3920 |*
3921 |*	Ersterstellung		MA 08. Jul. 93
3922 |*	Letzte Aenderung	MA 08. Jul. 93
3923 |*
3924 |*************************************************************************/
3925 void SwRowFrm::RegistFlys( SwPageFrm *pPage )
3926 {
3927 	::RegistFlys( pPage ? pPage : FindPageFrm(), this );
3928 }
3929 
3930 /*************************************************************************
3931 |*
3932 |*	  SwRowFrm::Modify()
3933 |*
3934 |*	  Ersterstellung	MA 12. Nov. 97
3935 |*	  Letzte Aenderung	MA 12. Nov. 97
3936 |*
3937 |*************************************************************************/
3938 void SwRowFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
3939 {
3940 	sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
3941 	const SfxPoolItem *pItem = 0;
3942 
3943 	if( bAttrSetChg )
3944     {
3945         const SwAttrSet* pChgSet = ((SwAttrSetChg*)pNew)->GetChgSet();
3946 		pChgSet->GetItemState( RES_FRM_SIZE, sal_False, &pItem);
3947         if ( !pItem )
3948             pChgSet->GetItemState( RES_ROW_SPLIT, sal_False, &pItem);
3949     }
3950     else if ( RES_FRM_SIZE == pNew->Which() || RES_ROW_SPLIT == pNew->Which() )
3951 		pItem = pNew;
3952 
3953 	if ( pItem )
3954 	{
3955 		SwTabFrm *pTab = FindTabFrm();
3956         if ( pTab )
3957         {
3958             const bool bInFirstNonHeadlineRow = pTab->IsFollow() &&
3959                                                 this == pTab->GetFirstNonHeadlineRow();
3960             // --> FME 2004-10-27 #i35063#
3961             // Invalidation required is pRow is last row
3962             if ( bInFirstNonHeadlineRow || !GetNext() )
3963             // <--
3964             {
3965                 if ( bInFirstNonHeadlineRow )
3966                     pTab = pTab->FindMaster();
3967                 pTab->InvalidatePos();
3968             }
3969         }
3970 	}
3971 
3972 	SwLayoutFrm::Modify( pOld, pNew );
3973 }
3974 
3975 
3976 
3977 /*************************************************************************
3978 |*
3979 |*	SwRowFrm::MakeAll()
3980 |*
3981 |*	Ersterstellung		MA 01. Mar. 94
3982 |*	Letzte Aenderung	MA 01. Mar. 94
3983 |*
3984 |*************************************************************************/
3985 void SwRowFrm::MakeAll()
3986 {
3987 	if ( !GetNext() )
3988 		bValidSize = sal_False;
3989 	SwLayoutFrm::MakeAll();
3990 }
3991 
3992 /*************************************************************************
3993 |*
3994 |*	SwRowFrm::Format()
3995 |*
3996 |*	Ersterstellung		MA 13. Mar. 93
3997 |*	Letzte Aenderung	MA 20. Jun. 96
3998 |*
3999 |*************************************************************************/
4000 long MA_FASTCALL CalcHeightWidthFlys( const SwFrm *pFrm )
4001 {
4002     SWRECTFN( pFrm )
4003 	long nHeight = 0;
4004 	const SwFrm* pTmp = pFrm->IsSctFrm() ?
4005 			((SwSectionFrm*)pFrm)->ContainsCntnt() : pFrm;
4006 	while( pTmp )
4007 	{
4008         // --> OD 2004-10-08 #i26945# - consider follow text frames
4009         const SwSortedObjs* pObjs( 0L );
4010         bool bIsFollow( false );
4011         if ( pTmp->IsTxtFrm() && static_cast<const SwTxtFrm*>(pTmp)->IsFollow() )
4012         {
4013             const SwFrm* pMaster;
4014             // --> FME 2005-04-01 #i46450# Master does not necessarily have
4015             // to exist if this function is called from JoinFrm() ->
4016             // Cut() -> Shrink()
4017             const SwTxtFrm* pTmpFrm = static_cast<const SwTxtFrm*>(pTmp);
4018             if ( pTmpFrm->GetPrev() && pTmpFrm->GetPrev()->IsTxtFrm() &&
4019                  static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() &&
4020                  static_cast<const SwTxtFrm*>(pTmpFrm->GetPrev())->GetFollow() != pTmp )
4021                  pMaster = 0;
4022             else
4023                  pMaster = pTmpFrm->FindMaster();
4024 
4025             if ( pMaster )
4026             {
4027                  pObjs = static_cast<const SwTxtFrm*>(pTmp)->FindMaster()->GetDrawObjs();
4028                 bIsFollow = true;
4029             }
4030         }
4031         else
4032         {
4033             pObjs = pTmp->GetDrawObjs();
4034         }
4035         if ( pObjs )
4036         // <--
4037 		{
4038             for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
4039 			{
4040                 const SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
4041                 // --> OD 2004-10-08 #i26945# - if <pTmp> is follow, the
4042                 // anchor character frame has to be <pTmp>.
4043                 if ( bIsFollow &&
4044                      const_cast<SwAnchoredObject*>(pAnchoredObj)->FindAnchorCharFrm() != pTmp )
4045                 {
4046                     continue;
4047                 }
4048                 // <--
4049                 // --> OD 2004-10-04 #i26945# - consider also drawing objects
4050 				{
4051                     // OD 30.09.2003 #i18732# - only objects, which follow
4052                     // the text flow have to be considered.
4053                     const SwFrmFmt& rFrmFmt = pAnchoredObj->GetFrmFmt();
4054                     const bool bConsiderObj =
4055                         (rFrmFmt.GetAnchor().GetAnchorId() != FLY_AS_CHAR) &&
4056                             pAnchoredObj->GetObjRect().Top() != WEIT_WECH &&
4057                             rFrmFmt.GetFollowTextFlow().GetValue() &&
4058                             pAnchoredObj->GetPageFrm() == pTmp->FindPageFrm();
4059                     if ( bConsiderObj )
4060 					{
4061                         const SwFmtFrmSize &rSz = rFrmFmt.GetFrmSize();
4062 						if( !rSz.GetHeightPercent() )
4063                         {
4064                             const SwTwips nDistOfFlyBottomToAnchorTop =
4065                                 (pAnchoredObj->GetObjRect().*fnRect->fnGetHeight)() +
4066                                     ( bVert ?
4067                                       pAnchoredObj->GetCurrRelPos().X() :
4068                                       pAnchoredObj->GetCurrRelPos().Y() );
4069 
4070                             const SwTwips nFrmDiff =
4071                                 (*fnRect->fnYDiff)(
4072                                     (pTmp->Frm().*fnRect->fnGetTop)(),
4073                                     (pFrm->Frm().*fnRect->fnGetTop)() );
4074 
4075                             nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop + nFrmDiff -
4076                                             (pFrm->Frm().*fnRect->fnGetHeight)() );
4077 
4078                             // --> FME 2006-01-24 #i56115# The first height calculation
4079                             // gives wrong results if pFrm->Prt().Y() > 0. We do
4080                             // a second calculation based on the actual rectangles of
4081                             // pFrm and pAnchoredObj, and use the maximum of the results.
4082                             // I do not want to remove the first calculation because
4083                             // if clipping has been applied, using the GetCurrRelPos
4084                             // might be the better option to calculate nHeight.
4085                             const SwTwips nDistOfFlyBottomToAnchorTop2 = (*fnRect->fnYDiff)(
4086                                                                             (pAnchoredObj->GetObjRect().*fnRect->fnGetBottom)(),
4087                                                                             (pFrm->Frm().*fnRect->fnGetBottom)() );
4088 
4089                             nHeight = Max( nHeight, nDistOfFlyBottomToAnchorTop2 );
4090                             // <--
4091                         }
4092 					}
4093 				}
4094                 // <--
4095 			}
4096 		}
4097 		if( !pFrm->IsSctFrm() )
4098 			break;
4099 		pTmp = pTmp->FindNextCnt();
4100 		if( !((SwSectionFrm*)pFrm)->IsAnLower( pTmp ) )
4101 			break;
4102 	}
4103 	return nHeight;
4104 }
4105 
4106 SwTwips lcl_CalcTopAndBottomMargin( const SwLayoutFrm& rCell, const SwBorderAttrs& rAttrs )
4107 {
4108     const SwTabFrm* pTab = rCell.FindTabFrm();
4109     SwTwips nTopSpace = 0;
4110     SwTwips nBottomSpace = 0;
4111 
4112     // --> collapsing borders FME 2005-05-27 #i29550#
4113     if ( pTab->IsCollapsingBorders() && rCell.Lower() && !rCell.Lower()->IsRowFrm() )
4114     {
4115         nTopSpace    = ((SwRowFrm*)rCell.GetUpper())->GetTopMarginForLowers();
4116         nBottomSpace = ((SwRowFrm*)rCell.GetUpper())->GetBottomMarginForLowers();
4117     }
4118     // <-- collapsing
4119     else
4120     {
4121         if ( pTab->IsVertical() != rCell.IsVertical() )
4122         {
4123             nTopSpace    = rAttrs.CalcLeft( &rCell );
4124             nBottomSpace = rAttrs.CalcRight( &rCell );
4125         }
4126         else
4127         {
4128             nTopSpace    = rAttrs.CalcTop();
4129             nBottomSpace = rAttrs.CalcBottom();
4130         }
4131     }
4132 
4133     return nTopSpace + nBottomSpace;
4134 }
4135 
4136 
4137 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to
4138 // control, if floating screen objects have to be considered for the minimal
4139 // cell height.
4140 SwTwips MA_FASTCALL lcl_CalcMinCellHeight( const SwLayoutFrm *_pCell,
4141                                            const sal_Bool _bConsiderObjs,
4142                                            const SwBorderAttrs *pAttrs = 0 )
4143 {
4144     SWRECTFN( _pCell )
4145 	SwTwips nHeight = 0;
4146     const SwFrm* pLow = _pCell->Lower();
4147 	if ( pLow )
4148 	{
4149 		long nFlyAdd = 0;
4150 		while ( pLow )
4151 		{
4152             // OD 2004-02-18 #106629# - change condition and switch then-body
4153             // and else-body
4154             if ( pLow->IsRowFrm() )
4155             {
4156                 // --> OD 2004-10-04 #i26945#
4157                 nHeight += ::lcl_CalcMinRowHeight( static_cast<const SwRowFrm*>(pLow),
4158                                                    _bConsiderObjs );
4159                 // <--
4160             }
4161             else
4162             {
4163                 long nLowHeight = (pLow->Frm().*fnRect->fnGetHeight)();
4164                 nHeight += nLowHeight;
4165                 // --> OD 2004-10-04 #i26945#
4166                 if ( _bConsiderObjs )
4167                 {
4168                     nFlyAdd = Max( 0L, nFlyAdd - nLowHeight );
4169                     nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
4170                 }
4171                 // <--
4172 			}
4173 
4174 			pLow = pLow->GetNext();
4175 		}
4176 		if ( nFlyAdd )
4177 			nHeight += nFlyAdd;
4178 	}
4179 	//Der Border will natuerlich auch mitspielen, er kann leider nicht
4180 	//aus PrtArea und Frm errechnet werden, da diese in beliebiger
4181 	//Kombination ungueltig sein koennen.
4182     if ( _pCell->Lower() )
4183     {
4184         if ( pAttrs )
4185             nHeight += lcl_CalcTopAndBottomMargin( *_pCell, *pAttrs );
4186         else
4187         {
4188             SwBorderAttrAccess aAccess( SwFrm::GetCache(), _pCell );
4189             const SwBorderAttrs &rAttrs = *aAccess.Get();
4190             nHeight += lcl_CalcTopAndBottomMargin( *_pCell, rAttrs );
4191         }
4192     }
4193     return nHeight;
4194 }
4195 
4196 // OD 2004-02-18 #106629# - correct type of 1st parameter
4197 // --> OD 2004-10-04 #i26945# - add parameter <_bConsiderObjs> in order to control,
4198 // if floating screen objects have to be considered for the minimal cell height
4199 SwTwips MA_FASTCALL lcl_CalcMinRowHeight( const SwRowFrm* _pRow,
4200                                           const sal_Bool _bConsiderObjs )
4201 {
4202     SWRECTFN( _pRow )
4203 
4204     const SwFmtFrmSize &rSz = _pRow->GetFmt()->GetFrmSize();
4205 
4206     if ( _pRow->HasFixSize() && !_pRow->IsRowSpanLine() )
4207     {
4208         ASSERT( ATT_FIX_SIZE == rSz.GetHeightSizeType(), "pRow claims to have fixed size" )
4209         return rSz.GetHeight();
4210     }
4211 
4212 	SwTwips nHeight = 0;
4213     const SwCellFrm* pLow = static_cast<const SwCellFrm*>(_pRow->Lower());
4214 	while ( pLow )
4215 	{
4216         SwTwips nTmp = 0;
4217         const long nRowSpan = pLow->GetLayoutRowSpan();
4218         // --> NEW TABLES
4219         // Consider height of
4220         // 1. current cell if RowSpan == 1
4221         // 2. current cell if cell is "follow" cell of a cell with RowSpan == -1
4222         // 3. master cell if RowSpan == -1
4223         if ( 1 == nRowSpan )
4224         {
4225             nTmp = ::lcl_CalcMinCellHeight( pLow, _bConsiderObjs );
4226         }
4227         else if ( -1 == nRowSpan )
4228         {
4229             // Height of the last cell of a row span is height of master cell
4230             // minus the height of the other rows which are covered by the master
4231             // cell:
4232             const SwCellFrm& rMaster = pLow->FindStartEndOfRowSpanCell( true, true );
4233             nTmp = ::lcl_CalcMinCellHeight( &rMaster, _bConsiderObjs );
4234             const SwFrm* pMasterRow = rMaster.GetUpper();
4235             while ( pMasterRow && pMasterRow != _pRow )
4236             {
4237                 nTmp -= (pMasterRow->Frm().*fnRect->fnGetHeight)();
4238                 pMasterRow = pMasterRow->GetNext();
4239             }
4240         }
4241         // <-- NEW TABLES
4242 
4243         // Do not consider rotated cells:
4244         if ( ( 0 != pLow->IsVertical() ) == ( 0 != bVert ) && nTmp > nHeight )
4245             nHeight = nTmp;
4246 
4247         pLow = static_cast<const SwCellFrm*>(pLow->GetNext());
4248 	}
4249     if ( rSz.GetHeightSizeType() == ATT_MIN_SIZE && !_pRow->IsRowSpanLine() )
4250 		nHeight = Max( nHeight, rSz.GetHeight() );
4251 	return nHeight;
4252 }
4253 
4254 // --> collapsing borders FME 2005-05-27 #i29550#
4255 
4256 // Calculate the maximum of (TopLineSize + TopLineDist) over all lowers:
4257 sal_uInt16 lcl_GetTopSpace( const SwRowFrm& rRow )
4258 {
4259     sal_uInt16 nTopSpace = 0;
4260     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4261           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4262     {
4263         sal_uInt16 nTmpTopSpace = 0;
4264         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4265             nTmpTopSpace = lcl_GetTopSpace( *(SwRowFrm*)pCurrLower->Lower() );
4266         else
4267         {
4268             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4269             const SvxBoxItem& rBoxItem = rSet.GetBox();
4270             nTmpTopSpace = rBoxItem.CalcLineSpace( BOX_LINE_TOP, sal_True );
4271         }
4272         nTopSpace  = Max( nTopSpace, nTmpTopSpace );
4273     }
4274     return nTopSpace;
4275 }
4276 
4277 // Calculate the maximum of TopLineDist over all lowers:
4278 sal_uInt16 lcl_GetTopLineDist( const SwRowFrm& rRow )
4279 {
4280     sal_uInt16 nTopLineDist = 0;
4281     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4282           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4283     {
4284         sal_uInt16 nTmpTopLineDist = 0;
4285         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4286             nTmpTopLineDist = lcl_GetTopLineDist( *(SwRowFrm*)pCurrLower->Lower() );
4287         else
4288         {
4289             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4290             const SvxBoxItem& rBoxItem = rSet.GetBox();
4291             nTmpTopLineDist = rBoxItem.GetDistance( BOX_LINE_TOP );
4292         }
4293         nTopLineDist = Max( nTopLineDist, nTmpTopLineDist );
4294     }
4295     return nTopLineDist;
4296 }
4297 
4298 // Calculate the maximum of BottomLineSize over all lowers:
4299 sal_uInt16 lcl_GetBottomLineSize( const SwRowFrm& rRow )
4300 {
4301     sal_uInt16 nBottomLineSize = 0;
4302     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4303           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4304     {
4305         sal_uInt16 nTmpBottomLineSize = 0;
4306         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4307         {
4308             const SwFrm* pRow = pCurrLower->GetLastLower();
4309             nTmpBottomLineSize = lcl_GetBottomLineSize( *(SwRowFrm*)pRow );
4310         }
4311         else
4312         {
4313             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4314             const SvxBoxItem& rBoxItem = rSet.GetBox();
4315             nTmpBottomLineSize = rBoxItem.CalcLineSpace( BOX_LINE_BOTTOM, sal_True ) -
4316                                  rBoxItem.GetDistance( BOX_LINE_BOTTOM );
4317         }
4318         nBottomLineSize = Max( nBottomLineSize, nTmpBottomLineSize );
4319     }
4320     return nBottomLineSize;
4321 }
4322 
4323 // Calculate the maximum of BottomLineDist over all lowers:
4324 sal_uInt16 lcl_GetBottomLineDist( const SwRowFrm& rRow )
4325 {
4326     sal_uInt16 nBottomLineDist = 0;
4327     for ( SwCellFrm* pCurrLower = (SwCellFrm*)rRow.Lower(); pCurrLower;
4328           pCurrLower = (SwCellFrm*)pCurrLower->GetNext() )
4329     {
4330         sal_uInt16 nTmpBottomLineDist = 0;
4331         if ( pCurrLower->Lower() && pCurrLower->Lower()->IsRowFrm() )
4332         {
4333             const SwFrm* pRow = pCurrLower->GetLastLower();
4334             nTmpBottomLineDist = lcl_GetBottomLineDist( *(SwRowFrm*)pRow );
4335         }
4336         else
4337         {
4338             const SwAttrSet& rSet = ((SwCellFrm*)pCurrLower)->GetFmt()->GetAttrSet();
4339             const SvxBoxItem& rBoxItem = rSet.GetBox();
4340             nTmpBottomLineDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
4341         }
4342         nBottomLineDist = Max( nBottomLineDist, nTmpBottomLineDist );
4343     }
4344     return nBottomLineDist;
4345 }
4346 
4347 // <-- collapsing
4348 
4349 void SwRowFrm::Format( const SwBorderAttrs *pAttrs )
4350 {
4351     SWRECTFN( this )
4352 	ASSERT( pAttrs, "SwRowFrm::Format ohne Attrs." );
4353 
4354     const sal_Bool bFix = bFixSize;
4355 
4356 	if ( !bValidPrtArea )
4357 	{
4358 		//RowFrms haben keine Umrandung usw. also entspricht die PrtArea immer
4359 		//dem Frm.
4360 		bValidPrtArea = sal_True;
4361 		aPrt.Left( 0 );
4362 		aPrt.Top( 0 );
4363 		aPrt.Width ( aFrm.Width() );
4364 		aPrt.Height( aFrm.Height() );
4365 
4366         // --> collapsing borders FME 2005-05-27 #i29550#
4367         // Here we calculate the top-printing area for the lower cell frames
4368         SwTabFrm* pTabFrm = FindTabFrm();
4369         if ( pTabFrm->IsCollapsingBorders() )
4370         {
4371             const sal_uInt16 nTopSpace        = lcl_GetTopSpace(       *this );
4372             const sal_uInt16 nTopLineDist     = lcl_GetTopLineDist(    *this );
4373             const sal_uInt16 nBottomLineSize  = lcl_GetBottomLineSize( *this );
4374             const sal_uInt16 nBottomLineDist  = lcl_GetBottomLineDist( *this );
4375 
4376 
4377             const SwRowFrm* pPreviousRow = 0;
4378 
4379             // --> FME 2004-09-14 #i32456#
4380             // In order to calculate the top printing area for the lower cell
4381             // frames, we have to find the 'previous' row frame and compare
4382             // the bottom values of the 'previous' row with the 'top' values
4383             // of this row. The best way to find the 'previous' row is to
4384             // use the table structure:
4385             const SwTable* pTable = pTabFrm->GetTable();
4386             const SwTableLine* pPrevTabLine = 0;
4387             const SwRowFrm* pTmpRow = this;
4388 
4389             while ( pTmpRow && !pPrevTabLine )
4390             {
4391                 sal_uInt16 nIdx = 0;
4392                 const SwTableLines& rLines = pTmpRow->GetTabLine()->GetUpper() ?
4393                                              pTmpRow->GetTabLine()->GetUpper()->GetTabLines() :
4394                                              pTable->GetTabLines();
4395 
4396                 while ( rLines[ nIdx ] != pTmpRow->GetTabLine() )
4397                     ++nIdx;
4398 
4399                 if ( nIdx > 0 )
4400                 {
4401                     // pTmpRow has a 'previous' row in the table structure:
4402                     pPrevTabLine = rLines[ nIdx - 1 ];
4403                 }
4404                 else
4405                 {
4406                     // pTmpRow is a first row in the table structue.
4407                     // We go up in the table structure:
4408                     pTmpRow = pTmpRow->GetUpper()->GetUpper() &&
4409                               pTmpRow->GetUpper()->GetUpper()->IsRowFrm() ?
4410                               static_cast<const SwRowFrm*>( pTmpRow->GetUpper()->GetUpper() ) :
4411                               0;
4412                 }
4413             }
4414 
4415             // If we found a 'previous' row, we look for the appropriate row frame:
4416             if ( pPrevTabLine )
4417             {
4418                 SwIterator<SwRowFrm,SwFmt> aIter( *pPrevTabLine->GetFrmFmt() );
4419                 for ( SwRowFrm* pRow = aIter.First(); pRow; pRow = aIter.Next() )
4420                 {
4421                     // --> OD 2004-11-23 #115759# - do *not* take repeated
4422                     // headlines, because during split of table it can be
4423                     // invalid and thus can't provide correct border values.
4424                     if ( pRow->GetTabLine() == pPrevTabLine &&
4425                          !pRow->IsRepeatedHeadline() )
4426                     // <--
4427                     {
4428                         pPreviousRow = pRow;
4429                         break;
4430                     }
4431                 }
4432             }
4433             // <--
4434 
4435             sal_uInt16 nTopPrtMargin = nTopSpace;
4436             if ( pPreviousRow )
4437             {
4438                 const sal_uInt16 nTmpPrtMargin = pPreviousRow->GetBottomLineSize() + nTopLineDist;
4439                 if ( nTmpPrtMargin > nTopPrtMargin )
4440                     nTopPrtMargin = nTmpPrtMargin;
4441             }
4442 
4443             // table has to be notified if it has to change its lower
4444             // margin due to changes of nBottomLineSize:
4445             if ( !GetNext() && nBottomLineSize != GetBottomLineSize() )
4446                  pTabFrm->_InvalidatePrt();
4447 
4448             // If there are rows nested inside this row, the nested rows
4449             // may not have been calculated yet. Therefore the
4450             // ::lcl_CalcMinRowHeight( this ) operation later in this
4451             // function cannot consider the correct border values. We
4452             // have to trigger the invalidation of the outer row frame
4453             // manually:
4454             // Note: If any further invalidations should be necessary, we
4455             // should consider moving the invalidation stuff to the
4456             // appropriate SwNotify object.
4457             if ( GetUpper()->GetUpper()->IsRowFrm() &&
4458                  ( nBottomLineDist != GetBottomMarginForLowers() ||
4459                    nTopPrtMargin   != GetTopMarginForLowers() ) )
4460                 GetUpper()->GetUpper()->_InvalidateSize();
4461 
4462             SetBottomMarginForLowers( nBottomLineDist );    //  3.
4463             SetBottomLineSize( nBottomLineSize );           //  4.
4464             SetTopMarginForLowers( nTopPrtMargin );         //  5.
4465 
4466         }
4467 // <-- collapsing
4468 	}
4469 
4470 	while ( !bValidSize )
4471 	{
4472 		bValidSize = sal_True;
4473 
4474 #ifdef DBG_UTIL
4475         if ( HasFixSize() )
4476 		{
4477 			const SwFmtFrmSize &rFrmSize = GetFmt()->GetFrmSize();
4478 			ASSERT( rFrmSize.GetSize().Height() > 0, "Hat ihn" );
4479 		}
4480 #endif
4481         const SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() -
4482                               ( HasFixSize() && !IsRowSpanLine()
4483                                 ? pAttrs->GetSize().Height()
4484                                 // --> OD 2004-10-04 #i26945#
4485                                 : ::lcl_CalcMinRowHeight( this,
4486                                     FindTabFrm()->IsConsiderObjsForMinCellHeight() ) );
4487                                 // <--
4488         if ( nDiff )
4489 		{
4490             bFixSize = sal_False;
4491 			if ( nDiff > 0 )
4492                 Shrink( nDiff, sal_False, sal_True );
4493 			else if ( nDiff < 0 )
4494                 Grow( -nDiff );
4495             bFixSize = bFix;
4496 		}
4497 	}
4498 
4499     // last row will fill the space in its upper.
4500     if ( !GetNext() )
4501 	{
4502 		//Der letzte fuellt den verbleibenden Raum im Upper aus.
4503         SwTwips nDiff = (GetUpper()->Prt().*fnRect->fnGetHeight)();
4504 		SwFrm *pSibling = GetUpper()->Lower();
4505 		do
4506         {   nDiff -= (pSibling->Frm().*fnRect->fnGetHeight)();
4507 			pSibling = pSibling->GetNext();
4508 		} while ( pSibling );
4509 		if ( nDiff > 0 )
4510 		{
4511             bFixSize = sal_False;
4512             Grow( nDiff );
4513             bFixSize = bFix;
4514 			bValidSize = sal_True;
4515 		}
4516 	}
4517 }
4518 
4519 /*************************************************************************
4520 |*
4521 |*	SwRowFrm::AdjustCells()
4522 |*
4523 |*	Ersterstellung		MA 10. Aug. 93
4524 |*	Letzte Aenderung	MA 16. Dec. 96
4525 |*
4526 |*************************************************************************/
4527 void SwRowFrm::AdjustCells( const SwTwips nHeight, const sal_Bool bHeight )
4528 {
4529 	SwFrm *pFrm = Lower();
4530 	if ( bHeight )
4531 	{
4532 		SwRootFrm *pRootFrm = getRootFrm();
4533         SWRECTFN( this )
4534         SwRect aOldFrm;
4535 
4536         while ( pFrm )
4537         {
4538             SwFrm* pNotify = 0;
4539 
4540             SwCellFrm* pCellFrm = static_cast<SwCellFrm*>(pFrm);
4541 
4542             // NEW TABLES
4543             // Which cells need to be adjusted if the current row changes
4544             // its height?
4545 
4546             // Current frame is a covered frame:
4547             // Set new height for covered cell and adjust master cell:
4548             if ( pCellFrm->GetTabBox()->getRowSpan() < 1 )
4549             {
4550                 // Set height of current (covered) cell to new line height.
4551                 const long nDiff = nHeight - (pCellFrm->Frm().*fnRect->fnGetHeight)();
4552                 if ( nDiff )
4553                 {
4554                     (pCellFrm->Frm().*fnRect->fnAddBottom)( nDiff );
4555                     pCellFrm->_InvalidatePrt();
4556                 }
4557             }
4558 
4559             SwCellFrm* pToAdjust = 0;
4560             SwFrm* pToAdjustRow = 0;
4561 
4562             // If current frame is covered frame, we still want to adjust the
4563             // height of the cell starting the row span
4564             if ( pCellFrm->GetLayoutRowSpan() < 1 )
4565             {
4566                 pToAdjust = const_cast< SwCellFrm*>(&pCellFrm->FindStartEndOfRowSpanCell( true, true ));
4567                 pToAdjustRow = pToAdjust->GetUpper();
4568             }
4569             else
4570             {
4571                 pToAdjust = pCellFrm;
4572                 pToAdjustRow = this;
4573             }
4574 
4575             // Set height of master cell to height of all lines spanned by this line.
4576             long nRowSpan = pToAdjust->GetLayoutRowSpan();
4577             SwTwips nSumRowHeight = 0;
4578             while ( pToAdjustRow )
4579             {
4580                 // Use new height for the current row:
4581                 nSumRowHeight += pToAdjustRow == this ?
4582                                  nHeight :
4583                                  (pToAdjustRow->Frm().*fnRect->fnGetHeight)();
4584 
4585                 if ( nRowSpan-- == 1 )
4586                     break;
4587 
4588                 pToAdjustRow = pToAdjustRow->GetNext();
4589             }
4590 
4591             if ( pToAdjustRow && pToAdjustRow != this )
4592                 pToAdjustRow->_InvalidateSize();
4593 
4594             const long nDiff = nSumRowHeight - (pToAdjust->Frm().*fnRect->fnGetHeight)();
4595             if ( nDiff )
4596             {
4597                 aOldFrm = pToAdjust->Frm();
4598                 (pToAdjust->Frm().*fnRect->fnAddBottom)( nDiff );
4599                 pNotify = pToAdjust;
4600             }
4601 
4602             if ( pNotify )
4603             {
4604                 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && pRootFrm->GetCurrShell() )
4605                     pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pNotify, aOldFrm );
4606 
4607                 pNotify->_InvalidatePrt();
4608             }
4609 
4610 			pFrm = pFrm->GetNext();
4611 		}
4612 	}
4613 	else
4614 	{	while ( pFrm )
4615 		{
4616 			pFrm->_InvalidateAll();
4617 			pFrm = pFrm->GetNext();
4618 		}
4619 	}
4620 	InvalidatePage();
4621 }
4622 
4623 /*************************************************************************
4624 |*
4625 |*	SwRowFrm::Cut()
4626 |*
4627 |*	Ersterstellung		MA 12. Nov. 97
4628 |*	Letzte Aenderung	MA 12. Nov. 97
4629 |*
4630 |*************************************************************************/
4631 void SwRowFrm::Cut()
4632 {
4633 	SwTabFrm *pTab = FindTabFrm();
4634     if ( pTab && pTab->IsFollow() && this == pTab->GetFirstNonHeadlineRow() )
4635     {
4636 		pTab->FindMaster()->InvalidatePos();
4637 	}
4638 
4639     // --> OD 2010-02-17 #i103961#
4640     // notification for accessibility
4641     {
4642         SwRootFrm *pRootFrm = getRootFrm();
4643         if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
4644         {
4645             ViewShell* pVSh = pRootFrm->GetCurrShell();
4646             if ( pVSh && pVSh->Imp() )
4647             {
4648                 SwFrm* pCellFrm( GetLower() );
4649                 while ( pCellFrm )
4650                 {
4651                     ASSERT( pCellFrm->IsCellFrm(),
4652                             "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." );
4653                     pVSh->Imp()->DisposeAccessibleFrm( pCellFrm );
4654 
4655                     pCellFrm = pCellFrm->GetNext();
4656                 }
4657             }
4658         }
4659     }
4660     // <--
4661 
4662 	SwLayoutFrm::Cut();
4663 }
4664 
4665 /*************************************************************************
4666 |*
4667 |*	SwRowFrm::GrowFrm()
4668 |*
4669 |*	Ersterstellung		MA 15. Mar. 93
4670 |*	Letzte Aenderung	MA 05. May. 94
4671 |*
4672 |*************************************************************************/
4673 
4674 
4675 SwTwips SwRowFrm::GrowFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
4676 {
4677     SwTwips nReal = 0;
4678 
4679     SwTabFrm* pTab = FindTabFrm();
4680     SWRECTFN( pTab )
4681 
4682     bool bRestrictTableGrowth;
4683     bool bHasFollowFlowLine = pTab->HasFollowFlowLine();
4684 
4685     if ( GetUpper()->IsTabFrm() )
4686     {
4687         const SwRowFrm* pFollowFlowRow = IsInSplitTableRow();
4688         bRestrictTableGrowth = pFollowFlowRow && !pFollowFlowRow->IsRowSpanLine();
4689     }
4690     else
4691     {
4692         ASSERT( GetUpper()->IsCellFrm(), "RowFrm->GetUpper neither table nor cell" )
4693         bRestrictTableGrowth = GetFollowRow() && bHasFollowFlowLine;
4694         ASSERT( !bRestrictTableGrowth || !GetNext(),
4695                 "GetFollowRow for row frame that has a Next" )
4696 
4697         //
4698         // There may still be some space left in my direct upper:
4699         //
4700         const SwTwips nAdditionalSpace =
4701                 (Frm().*fnRect->fnBottomDist)( (GetUpper()->GetUpper()->*fnRect->fnGetPrtBottom)() );
4702         if ( bRestrictTableGrowth && nAdditionalSpace > 0 )
4703         {
4704             nReal = Min( nAdditionalSpace, nDist );
4705             nDist -= nReal;
4706             if ( !bTst )
4707                 (Frm().*fnRect->fnAddBottom)( nReal );
4708         }
4709     }
4710 
4711     if ( bRestrictTableGrowth )
4712         pTab->SetRestrictTableGrowth( sal_True );
4713     else
4714     {
4715         // Ok, this looks like a hack, indeed, it is a hack.
4716         // If the current row frame is inside another cell frame,
4717         // and the current row frame has no follow, it should not
4718         // be allowed to grow. In fact, setting bRestrictTableGrowth
4719         // to 'false' does not work, because the surrounding RowFrm
4720         // would set this to 'true'.
4721         pTab->SetFollowFlowLine( sal_False );
4722     }
4723 
4724     nReal += SwLayoutFrm::GrowFrm( nDist, bTst, bInfo);
4725 
4726     pTab->SetRestrictTableGrowth( sal_False );
4727     pTab->SetFollowFlowLine( bHasFollowFlowLine );
4728 
4729 	//Hoehe der Zellen auf den neuesten Stand bringen.
4730 	if ( !bTst )
4731 	{
4732         SWRECTFNX( this )
4733         AdjustCells( (Prt().*fnRectX->fnGetHeight)() + nReal, sal_True );
4734 		if ( nReal )
4735 			SetCompletePaint();
4736 	}
4737 
4738     return nReal;
4739 }
4740 
4741 /*************************************************************************
4742 |*
4743 |*	SwRowFrm::ShrinkFrm()
4744 |*
4745 |*	Ersterstellung		MA 15. Mar. 93
4746 |*	Letzte Aenderung	MA 20. Jun. 96
4747 |*
4748 |*************************************************************************/
4749 SwTwips SwRowFrm::ShrinkFrm( SwTwips nDist, sal_Bool bTst, sal_Bool bInfo )
4750 {
4751     SWRECTFN( this )
4752     if( HasFixSize() )
4753 	{
4754         AdjustCells( (Prt().*fnRect->fnGetHeight)(), sal_True );
4755 		return 0L;
4756 	}
4757 
4758 	//bInfo wird ggf. vom SwRowFrm::Format auf sal_True gesetzt, hier muss dann
4759 	//entsprechend reagiert werden
4760 	const sal_Bool bShrinkAnyway = bInfo;
4761 
4762 	//Nur soweit Shrinken, wie es der Inhalt der groessten Zelle zulaesst.
4763 	SwTwips nRealDist = nDist;
4764 	{
4765 		const SwFmtFrmSize &rSz = GetFmt()->GetFrmSize();
4766         SwTwips nMinHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
4767                              rSz.GetHeight() :
4768                              0;
4769 
4770         // Only necessary to calculate minimal row height if height
4771         // of pRow is at least nMinHeight. Otherwise nMinHeight is the
4772         // minimum height.
4773         if( nMinHeight < (Frm().*fnRect->fnGetHeight)() )
4774 		{
4775             // --> OD 2004-10-04 #i26945#
4776             ASSERT( FindTabFrm(), "<SwRowFrm::ShrinkFrm(..)> - no table frame -> crash." );
4777             const bool bConsiderObjs( FindTabFrm()->IsConsiderObjsForMinCellHeight() );
4778             // <--
4779             nMinHeight = lcl_CalcMinRowHeight( this, bConsiderObjs );
4780         }
4781 
4782         if ( ((Frm().*fnRect->fnGetHeight)() - nRealDist) < nMinHeight )
4783             nRealDist = (Frm().*fnRect->fnGetHeight)() - nMinHeight;
4784 	}
4785 	if ( nRealDist < 0 )
4786 		nRealDist = 0;
4787 
4788 	SwTwips nReal = nRealDist;
4789 	if ( nReal )
4790 	{
4791 		if ( !bTst )
4792         {
4793             SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
4794             (Frm().*fnRect->fnSetHeight)( nHeight - nReal );
4795             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
4796             if( IsVertical() && !IsVertLR() && !bRev )
4797                 Frm().Pos().X() += nReal;
4798         }
4799 
4800         SwTwips nTmp = GetUpper()->Shrink( nReal, bTst );
4801 		if ( !bShrinkAnyway && !GetNext() && nTmp != nReal )
4802 		{
4803 			//Der letzte bekommt den Rest im Upper und nimmt deshalb
4804 			//ggf. Ruecksichten (sonst: Endlosschleife)
4805 			if ( !bTst )
4806             {
4807                 nReal -= nTmp;
4808                 SwTwips nHeight = (Frm().*fnRect->fnGetHeight)();
4809                 (Frm().*fnRect->fnSetHeight)( nHeight + nReal );
4810                 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
4811                 if( IsVertical() && !IsVertLR() && !bRev )
4812                     Frm().Pos().X() -= nReal;
4813             }
4814 			nReal = nTmp;
4815 		}
4816 	}
4817 
4818 	//Geeignet invalidieren und die Hoehe der Zellen auf den neuesten
4819 	//Stand bringen.
4820 	if ( !bTst )
4821 	{
4822 		if ( nReal )
4823 		{
4824 			if ( GetNext() )
4825 				GetNext()->_InvalidatePos();
4826 			_InvalidateAll();
4827 			SetCompletePaint();
4828 
4829 			SwTabFrm *pTab = FindTabFrm();
4830             if ( !pTab->IsRebuildLastLine() && pTab->IsFollow() &&
4831                  this == pTab->GetFirstNonHeadlineRow() )
4832             {
4833                 SwTabFrm* pMasterTab = const_cast< SwTabFrm* >( pTab->FindMaster() );
4834                 pMasterTab->InvalidatePos();
4835             }
4836         }
4837         AdjustCells( (Prt().*fnRect->fnGetHeight)() - nReal, sal_True );
4838 	}
4839 	return nReal;
4840 }
4841 
4842 /*************************************************************************
4843 |*
4844 |*  SwRowFrm::IsRowSplitAllowed()
4845 |*
4846 |*************************************************************************/
4847 bool SwRowFrm::IsRowSplitAllowed() const
4848 {
4849     // Fixed size rows are never allowed to split:
4850     if ( HasFixSize() )
4851     {
4852         ASSERT( ATT_FIX_SIZE == GetFmt()->GetFrmSize().GetHeightSizeType(), "pRow claims to have fixed size" )
4853         return false;
4854     }
4855 
4856     // Repeated headlines are never allowed to split:
4857     const SwTabFrm* pTabFrm = FindTabFrm();
4858     if ( pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
4859          pTabFrm->IsInHeadline( *this ) )
4860         return false;
4861 
4862     const SwTableLineFmt* pFrmFmt = (SwTableLineFmt*)GetTabLine()->GetFrmFmt();
4863     const SwFmtRowSplit& rLP = pFrmFmt->GetRowSplit();
4864     return 0 != rLP.GetValue();
4865 }
4866 
4867 /*************************************************************************
4868 |*
4869 |*  SwRowFrm::ShouldRowKeepWithNext()
4870 |*
4871 |*************************************************************************/
4872 bool SwRowFrm::ShouldRowKeepWithNext() const
4873 {
4874     bool bRet = false;
4875 
4876     const SwCellFrm* pCell = static_cast<const SwCellFrm*>(Lower());
4877     const SwFrm* pTxt = pCell->Lower();
4878 
4879     if ( pTxt && pTxt->IsTxtFrm() )
4880     {
4881         bRet = static_cast<const SwTxtFrm*>(pTxt)->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
4882     }
4883     return bRet;
4884 }
4885 
4886 /*************************************************************************
4887 |*
4888 |*	SwCellFrm::SwCellFrm(), ~SwCellFrm()
4889 |*
4890 |*	Ersterstellung		MA 09. Mar. 93
4891 |*	Letzte Aenderung	MA 30. May. 96
4892 |*
4893 |*************************************************************************/
4894 SwCellFrm::SwCellFrm( const SwTableBox &rBox, SwFrm* pSib, bool bInsertContent ) :
4895 	SwLayoutFrm( rBox.GetFrmFmt(), pSib ),
4896     pTabBox( &rBox )
4897 {
4898     nType = FRMC_CELL;
4899 
4900     if ( !bInsertContent )
4901         return;
4902 
4903 	//Wenn ein StartIdx vorhanden ist, so werden CntntFrms in der Zelle
4904 	//angelegt, andernfalls muessen Rows vorhanden sein und diese werden
4905 	//angelegt.
4906 	if ( rBox.GetSttIdx() )
4907 	{
4908         sal_uLong nIndex = rBox.GetSttIdx();
4909         ::_InsertCnt( this, rBox.GetFrmFmt()->GetDoc(), ++nIndex );
4910 	}
4911 	else
4912 	{
4913 	    const SwTableLines &rLines = rBox.GetTabLines();
4914         SwFrm *pTmpPrev = 0;
4915 		for ( sal_uInt16 i = 0; i < rLines.Count(); ++i )
4916 		{
4917 			SwRowFrm *pNew = new SwRowFrm( *rLines[i], this, bInsertContent );
4918             pNew->InsertBehind( this, pTmpPrev );
4919             pTmpPrev = pNew;
4920 		}
4921 	}
4922 }
4923 
4924 SwCellFrm::~SwCellFrm()
4925 {
4926 	SwModify* pMod = GetFmt();
4927 	if( pMod )
4928 	{
4929 		// At this stage the lower frames aren't destroyed already,
4930 		// therfor we have to do a recursive dispose.
4931 		SwRootFrm *pRootFrm = getRootFrm();
4932 		if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
4933 			pRootFrm->GetCurrShell() )
4934 		{
4935 			pRootFrm->GetCurrShell()->Imp()->DisposeAccessibleFrm( this, sal_True );
4936 		}
4937 
4938         pMod->Remove( this );           // austragen,
4939 		if( !pMod->GetDepends() )
4940 			delete pMod;				// und loeschen
4941 	}
4942 }
4943 
4944 /*************************************************************************
4945 |*
4946 |*	SwCellFrm::Format()
4947 |*
4948 |*	Ersterstellung		MA 09. Mar. 93
4949 |*	Letzte Aenderung	MA 29. Jan. 98
4950 |*
4951 |*************************************************************************/
4952 sal_Bool lcl_ArrangeLowers( SwLayoutFrm *pLay, long lYStart, sal_Bool bInva )
4953 {
4954 	sal_Bool bRet = sal_False;
4955 	SwFrm *pFrm = pLay->Lower();
4956     SWRECTFN( pLay )
4957 	while ( pFrm )
4958 	{
4959         long nFrmTop = (pFrm->Frm().*fnRect->fnGetTop)();
4960         if( nFrmTop != lYStart )
4961 		{
4962 			bRet = sal_True;
4963             const long lDiff = (*fnRect->fnYDiff)( lYStart, nFrmTop );
4964             const long lDiffX = lYStart - nFrmTop;
4965             (pFrm->Frm().*fnRect->fnSubTop)( -lDiff );
4966             (pFrm->Frm().*fnRect->fnAddBottom)( lDiff );
4967 			pFrm->SetCompletePaint();
4968 			if ( !pFrm->GetNext() )
4969 				pFrm->SetRetouche();
4970 			if( bInva )
4971 				pFrm->Prepare( PREP_POS_CHGD );
4972 			if ( pFrm->IsLayoutFrm() && ((SwLayoutFrm*)pFrm)->Lower() )
4973 				lcl_ArrangeLowers( (SwLayoutFrm*)pFrm,
4974                     (((SwLayoutFrm*)pFrm)->Lower()->Frm().*fnRect->fnGetTop)()
4975                     + lDiffX, bInva );
4976 			if ( pFrm->GetDrawObjs() )
4977 			{
4978 				for ( sal_uInt16 i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
4979 				{
4980                     SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
4981                     // --> OD 2004-10-08 #i26945# - check, if anchored object
4982                     // is lower of layout frame by checking, if the anchor
4983                     // frame, which contains the anchor position, is a lower
4984                     // of the layout frame.
4985                     if ( !pLay->IsAnLower( pAnchoredObj->GetAnchorFrmContainingAnchPos() ) )
4986                     {
4987                         continue;
4988                     }
4989                     // <--
4990                     // --> OD 2005-08-08 #i52904# - distinguish between anchored
4991                     // objects, whose vertical position depends on its anchor
4992                     // frame and whose vertical position is independent
4993                     // from its anchor frame.
4994                     bool bVertPosDepOnAnchor( true );
4995                     {
4996                         SwFmtVertOrient aVert( pAnchoredObj->GetFrmFmt().GetVertOrient() );
4997                         switch ( aVert.GetRelationOrient() )
4998                         {
4999                             case text::RelOrientation::PAGE_FRAME:
5000                             case text::RelOrientation::PAGE_PRINT_AREA:
5001                                 bVertPosDepOnAnchor = false;
5002                                 break;
5003                             default: break;
5004                         }
5005                     }
5006                     if ( pAnchoredObj->ISA(SwFlyFrm) )
5007 					{
5008                         SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
5009 
5010                         // OD 2004-05-18 #i28701# - no direct move of objects,
5011                         // which are anchored to-paragraph/to-character, if
5012                         // the wrapping style influence has to be considered
5013                         // on the object positioning.
5014                         // --> OD 2005-08-08 #i52904# - no direct move of objects,
5015                         // whose vertical position doesn't depend on anchor frame.
5016                         const bool bDirectMove =
5017                                 WEIT_WECH != pFly->Frm().Top() &&
5018                                 bVertPosDepOnAnchor &&
5019                                 !pFly->ConsiderObjWrapInfluenceOnObjPos();
5020                         // <--
5021                         if ( bDirectMove )
5022                         {
5023                             (pFly->Frm().*fnRect->fnSubTop)( -lDiff );
5024                             (pFly->Frm().*fnRect->fnAddBottom)( lDiff );
5025                             pFly->GetVirtDrawObj()->SetRectsDirty();
5026                             // --> OD 2004-08-17 - also notify view of <SdrObject>
5027                             // instance, which represents the Writer fly frame in
5028                             // the drawing layer
5029                             pFly->GetVirtDrawObj()->SetChanged();
5030                             // <--
5031                             // --> OD 2006-10-13 #i58280#
5032                             pFly->InvalidateObjRectWithSpaces();
5033                             // <--
5034                         }
5035 
5036                         if ( pFly->IsFlyInCntFrm() )
5037                         {
5038                             static_cast<SwFlyInCntFrm*>(pFly)->AddRefOfst( lDiff );
5039                             // --> OD 2004-12-02 #115759# - reset current relative
5040                             // position to get re-positioned, if not directly moved.
5041                             if ( !bDirectMove )
5042                             {
5043                                 pAnchoredObj->SetCurrRelPos( Point( 0, 0 ) );
5044                             }
5045                             // <--
5046                         }
5047                         else if( pFly->IsAutoPos() )
5048                         {
5049                             pFly->AddLastCharY( lDiff );
5050                             // OD 2004-05-18 #i28701# - follow-up of #i22341#
5051                             // <mnLastTopOfLine> has also been adjusted.
5052                             pFly->AddLastTopOfLineY( lDiff );
5053                         }
5054                         // --> OD 2004-11-05 #i26945# - re-registration at
5055                         // page frame of anchor frame, if table frame isn't
5056                         // a follow table and table frame isn't in its
5057                         // rebuild of last line.
5058                         const SwTabFrm* pTabFrm = pLay->FindTabFrm();
5059                         // --> OD 2004-11-23 #115759#
5060                         // - save: check, if table frame is found.
5061                         if ( pTabFrm &&
5062                              !( pTabFrm->IsFollow() &&
5063                                 pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
5064                              pFly->IsFlyFreeFrm() )
5065                         // <--
5066                         {
5067                             SwPageFrm* pPageFrm = pFly->GetPageFrm();
5068                             SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
5069                             if ( pPageFrm != pPageOfAnchor )
5070                             {
5071                                 pFly->InvalidatePos();
5072                                 if ( pPageFrm )
5073                                     pPageFrm->MoveFly( pFly, pPageOfAnchor );
5074                                 else
5075                                     pPageOfAnchor->AppendFlyToPage( pFly );
5076                             }
5077                         }
5078                         // <--
5079                         // OD 2004-05-11 #i28701# - Because of the introduction
5080                         // of new positionings and alignments (e.g. aligned at
5081                         // page area, but anchored at-character), the position
5082                         // of the Writer fly frame has to be invalidated.
5083                         pFly->InvalidatePos();
5084 
5085                         // --> OD 2004-11-04 #i26945# - follow-up of #i3317#
5086                         // No arrangement of lowers, if Writer fly frame isn't
5087                         // moved
5088                         if ( bDirectMove &&
5089                              ::lcl_ArrangeLowers( pFly,
5090                                                   (pFly->*fnRect->fnGetPrtTop)(),
5091                                                   bInva ) )
5092                         // <--
5093                         {
5094 							pFly->SetCompletePaint();
5095                         }
5096 					}
5097                     else if ( pAnchoredObj->ISA(SwAnchoredDrawObject) )
5098                     {
5099                         // --> OD 2004-11-05 #i26945#
5100                         const SwTabFrm* pTabFrm = pLay->FindTabFrm();
5101                         if ( pTabFrm &&
5102                              !( pTabFrm->IsFollow() &&
5103                                 pTabFrm->FindMaster()->IsRebuildLastLine() ) &&
5104                              !pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
5105                                                             == FLY_AS_CHAR )
5106                         {
5107                             SwPageFrm* pPageFrm = pAnchoredObj->GetPageFrm();
5108                             SwPageFrm* pPageOfAnchor = pFrm->FindPageFrm();
5109                             if ( pPageFrm != pPageOfAnchor )
5110                             {
5111                                 pAnchoredObj->InvalidateObjPos();
5112                                 if ( pPageFrm )
5113                                 {
5114                                     pPageFrm->RemoveDrawObjFromPage( *pAnchoredObj );
5115                                 }
5116                                 pPageOfAnchor->AppendDrawObjToPage( *pAnchoredObj );
5117                             }
5118                         }
5119                         // --> OD 2004-07-01 #i28701# - adjust last character
5120                         // rectangle and last top of line.
5121                         pAnchoredObj->AddLastCharY( lDiff );
5122                         pAnchoredObj->AddLastTopOfLineY( lDiff );
5123                         // --> OD 2005-08-08 #i52904# - re-introduce direct move
5124                         // of drawing objects
5125                         const bool bDirectMove =
5126                                 static_cast<const SwDrawFrmFmt&>(pAnchoredObj->GetFrmFmt()).IsPosAttrSet() &&
5127                                 bVertPosDepOnAnchor &&
5128                                 !pAnchoredObj->ConsiderObjWrapInfluenceOnObjPos();
5129                         if ( bDirectMove )
5130                         {
5131                             SwObjPositioningInProgress aObjPosInProgress( *pAnchoredObj );
5132                             if ( bVert )
5133                             {
5134                                 pAnchoredObj->DrawObj()->Move( Size( lDiff, 0 ) );
5135                             }
5136                             else
5137                             {
5138                                 pAnchoredObj->DrawObj()->Move( Size( 0, lDiff ) );
5139                             }
5140                             // --> OD 2006-10-13 #i58280#
5141                             pAnchoredObj->InvalidateObjRectWithSpaces();
5142                             // <--
5143                         }
5144                         // <--
5145                         pAnchoredObj->InvalidateObjPos();
5146                     }
5147                     else
5148                     {
5149                         ASSERT( false,
5150                                 "<lcl_ArrangeLowers(..)> - unknown type of anchored object!" );
5151                     }
5152 				}
5153 			}
5154 		}
5155         // Columns and cells are ordered horizontal, not vertical
5156         if( !pFrm->IsColumnFrm() && !pFrm->IsCellFrm() )
5157             lYStart = (*fnRect->fnYInc)( lYStart,
5158                                         (pFrm->Frm().*fnRect->fnGetHeight)() );
5159 
5160         // Nowadays, the content inside a cell can flow into the follow table.
5161         // Thus, the cell may only grow up to the end of the environment.
5162         // So the content may have grown, but the cell could not grow.
5163         // Therefore we have to trigger a formatting for the frames, which do
5164         // not fit into the cell anymore:
5165         SwTwips nDistanceToUpperPrtBottom =
5166             (pFrm->Frm().*fnRect->fnBottomDist)( (pLay->*fnRect->fnGetPrtBottom)());
5167         // --> OD 2006-01-19 #i56146# - Revise fix of issue #i26945#
5168         // do *not* consider content inside fly frames, if it's an undersized paragraph.
5169         // --> OD 2004-10-08 #i26945# - consider content inside fly frames
5170         if ( nDistanceToUpperPrtBottom < 0 &&
5171              ( ( pFrm->IsInFly() &&
5172                  ( !pFrm->IsTxtFrm() ||
5173                    !static_cast<SwTxtFrm*>(pFrm)->IsUndersized() ) ) ||
5174                pFrm->IsInSplitTableRow() ) )
5175         // <--
5176         {
5177             pFrm->InvalidatePos();
5178         }
5179 
5180 		pFrm = pFrm->GetNext();
5181 	}
5182 	return bRet;
5183 }
5184 
5185 void SwCellFrm::Format( const SwBorderAttrs *pAttrs )
5186 {
5187     ASSERT( pAttrs, "CellFrm::Format, pAttrs ist 0." );
5188     const SwTabFrm* pTab = FindTabFrm();
5189     SWRECTFN( pTab )
5190 
5191     if ( !bValidPrtArea )
5192 	{
5193 		bValidPrtArea = sal_True;
5194 
5195         //Position einstellen.
5196         if ( Lower() )
5197         {
5198             SwTwips nTopSpace, nBottomSpace, nLeftSpace, nRightSpace;
5199             // --> collapsing borders FME 2005-05-27 #i29550#
5200             if ( pTab->IsCollapsingBorders() && !Lower()->IsRowFrm()  )
5201             {
5202                 const SvxBoxItem& rBoxItem = pAttrs->GetBox();
5203                 nLeftSpace   = rBoxItem.GetDistance( BOX_LINE_LEFT );
5204                 nRightSpace  = rBoxItem.GetDistance( BOX_LINE_RIGHT );
5205                 nTopSpace    =  ((SwRowFrm*)GetUpper())->GetTopMarginForLowers();
5206                 nBottomSpace =  ((SwRowFrm*)GetUpper())->GetBottomMarginForLowers();
5207             }
5208             else
5209             {
5210             // <-- collapsing
5211                 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
5212                 nLeftSpace   = pAttrs->CalcLeft( this );
5213                 nRightSpace  = pAttrs->CalcRight( this );
5214                 nTopSpace    = pAttrs->CalcTop();
5215                 nBottomSpace = pAttrs->CalcBottom();
5216             }
5217             (this->*fnRect->fnSetXMargins)( nLeftSpace, nRightSpace );
5218             (this->*fnRect->fnSetYMargins)( nTopSpace, nBottomSpace );
5219         }
5220     }
5221     // --> OD 2004-10-04 #i26945#
5222     long nRemaining = GetTabBox()->getRowSpan() >= 1 ?
5223                       ::lcl_CalcMinCellHeight( this, pTab->IsConsiderObjsForMinCellHeight(), pAttrs ) :
5224                       0;
5225     // <--
5226 	if ( !bValidSize )
5227 	{
5228 		bValidSize = sal_True;
5229 
5230 		//Die VarSize der CellFrms ist immer die Breite.
5231 		//Tatsaechlich ist die Breite jedoch nicht Variabel, sie wird durch das
5232 		//Format vorgegeben. Dieser Vorgegebene Wert muss aber nun wiederum
5233 		//nicht der tatsaechlichen Breite entsprechen. Die Breite wird auf
5234 		//Basis des Attributes errechnet, der Wert im Attribut passt zu dem
5235 		//gewuenschten Wert des TabFrms. Anpassungen die dort vorgenommen
5236 		//wurden werden hier Proportional beruecksichtigt.
5237 		//Wenn die Celle keinen Nachbarn mehr hat beruecksichtigt sie nicht
5238 		//die Attribute, sonder greift sich einfach den Rest des
5239         //Uppers
5240 		SwTwips nWidth;
5241         if ( GetNext() )
5242 		{
5243             const SwTwips nWish = pTab->GetFmt()->GetFrmSize().GetWidth();
5244 			nWidth = pAttrs->GetSize().Width();
5245 
5246 			ASSERT( nWish, "Tabelle ohne Breite?" );
5247 			ASSERT( nWidth <= nWish, "Zelle breiter als Tabelle." );
5248 			ASSERT( nWidth > 0, "Box without width" );
5249 
5250             const long nPrtWidth = (pTab->Prt().*fnRect->fnGetWidth)();
5251             if ( nWish != nPrtWidth )
5252 			{
5253                 // Avoid rounding problems, at least for the new table model
5254                 if ( pTab->GetTable()->IsNewModel() )
5255                 {
5256                     // 1. sum of widths of cells up to this cell (in model)
5257                     const SwTableLine* pTabLine = GetTabBox()->GetUpper();
5258                     const SwTableBoxes& rBoxes = pTabLine->GetTabBoxes();
5259                     const SwTableBox* pTmpBox = 0;
5260 
5261                     SwTwips nSumWidth = 0;
5262                     sal_uInt16 i = 0;
5263                     do
5264                     {
5265                         pTmpBox = rBoxes[ i++ ];
5266                         nSumWidth += pTmpBox->GetFrmFmt()->GetFrmSize().GetWidth();
5267                     }
5268                     while ( pTmpBox != GetTabBox() );
5269 
5270                     // 2. calculate actual width of cells up to this one
5271                     double nTmpWidth = nSumWidth;
5272                     nTmpWidth *= nPrtWidth;
5273                     nTmpWidth /= nWish;
5274                     nWidth = (SwTwips)nTmpWidth;
5275 
5276                     // 3. calculate frame widths of cells up to this one:
5277                     const SwFrm* pTmpCell = static_cast<const SwLayoutFrm*>(GetUpper())->Lower();
5278                     SwTwips nSumFrameWidths = 0;
5279                     while ( pTmpCell != this )
5280                     {
5281                         nSumFrameWidths += (pTmpCell->Frm().*fnRect->fnGetWidth)();
5282                         pTmpCell = pTmpCell->GetNext();
5283                     }
5284 
5285                     nWidth = nWidth - nSumFrameWidths;
5286                 }
5287                 else
5288                 {
5289                     // #i12092# use double instead of long,
5290                     // otherwise this could lead to overflows
5291                     double nTmpWidth = nWidth;
5292                     nTmpWidth *= nPrtWidth;
5293                     nTmpWidth /= nWish;
5294                     nWidth = (SwTwips)nTmpWidth;
5295                 }
5296             }
5297 		}
5298 		else
5299 		{
5300 			ASSERT( pAttrs->GetSize().Width() > 0, "Box without width" );
5301             nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)();
5302 			SwFrm *pPre = GetUpper()->Lower();
5303 			while ( pPre != this )
5304             {
5305                 nWidth -= (pPre->Frm().*fnRect->fnGetWidth)();
5306 				pPre = pPre->GetNext();
5307 			}
5308 		}
5309         const long nDiff = nWidth - (Frm().*fnRect->fnGetWidth)();
5310         if( IsNeighbourFrm() && IsRightToLeft() )
5311             (Frm().*fnRect->fnSubLeft)( nDiff );
5312         else
5313             (Frm().*fnRect->fnAddRight)( nDiff );
5314         (Prt().*fnRect->fnAddRight)( nDiff );
5315 
5316 		//Jetzt die Hoehe einstellen, sie wird vom Inhalt und den Raendern
5317 		//bestimmt.
5318         const long nDiffHeight = nRemaining - (Frm().*fnRect->fnGetHeight)();
5319 		if ( nDiffHeight )
5320 		{
5321 			if ( nDiffHeight > 0 )
5322 			{
5323 				//Wieder validieren wenn kein Wachstum stattgefunden hat.
5324 				//Invalidiert wird durch AdjustCells von der Row.
5325                 if ( !Grow( nDiffHeight ) )
5326 					bValidSize = bValidPrtArea = sal_True;
5327 			}
5328 			else
5329 			{
5330 				//Nur dann invalidiert lassen, wenn tatsaechlich
5331 				//geshrinkt wurde; das kann abgelehnt werden, weil alle
5332 				//nebeneinanderliegenden Zellen gleichgross sein muessen.
5333                 if ( !Shrink( -nDiffHeight ) )
5334 					bValidSize = bValidPrtArea = sal_True;
5335 			}
5336 		}
5337 	}
5338 	const SwFmtVertOrient &rOri = pAttrs->GetAttrSet().GetVertOrient();
5339 
5340     if ( !Lower() )
5341         return;
5342 
5343     // From now on, all operations are related to the table cell.
5344     SWREFRESHFN( this )
5345 
5346     SwPageFrm* pPg = 0;
5347     if ( !FindTabFrm()->IsRebuildLastLine() && text::VertOrientation::NONE != rOri.GetVertOrient() &&
5348     // --> OD 2008-07-16 #158225# no vertical alignment of covered cells
5349          !IsCoveredCell() &&
5350     // <--
5351     // --> FME 2004-06-29 #116532# Do not consider vertical alignment in grid mode
5352          !(pPg = FindPageFrm())->HasGrid() )
5353     // <--
5354 	{
5355         if ( !Lower()->IsCntntFrm() && !Lower()->IsSctFrm() && !Lower()->IsTabFrm() )
5356 		{
5357 			//ASSERT fuer HTML-Import!
5358 			ASSERT( !this, "VAlign an Zelle ohne Inhalt" );
5359 			return;
5360 		}
5361 		sal_Bool bVertDir = sal_True;
5362         // --> OD 2005-03-30 #i43913# - no vertical alignment, if wrapping
5363         // style influence is considered on object positioning and
5364         // an object is anchored inside the cell.
5365         const bool bConsiderWrapOnObjPos( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) );
5366         // <--
5367         //Keine Ausrichtung wenn Rahmen mit Umlauf in die Zelle ragen.
5368 		if ( pPg->GetSortedObjs() )
5369 		{
5370 			SwRect aRect( Prt() ); aRect += Frm().Pos();
5371 			for ( sal_uInt16 i = 0; i < pPg->GetSortedObjs()->Count(); ++i )
5372 			{
5373                 const SwAnchoredObject* pAnchoredObj = (*pPg->GetSortedObjs())[i];
5374                 SwRect aTmp( pAnchoredObj->GetObjRect() );
5375 				if ( aTmp.IsOver( aRect ) )
5376 				{
5377                     const SwFrmFmt& rAnchoredObjFrmFmt = pAnchoredObj->GetFrmFmt();
5378                     const SwFmtSurround &rSur = rAnchoredObjFrmFmt.GetSurround();
5379 
5380                     if ( SURROUND_THROUGHT != rSur.GetSurround() )
5381 					{
5382                         // frames, which the cell is a lower of, aren't relevant
5383                         if ( pAnchoredObj->ISA(SwFlyFrm) )
5384 						{
5385                             const SwFlyFrm *pFly =
5386                                     static_cast<const SwFlyFrm*>(pAnchoredObj);
5387 							if ( pFly->IsAnLower( this ) )
5388 								continue;
5389 						}
5390 
5391                         const SwFrm* pAnch = pAnchoredObj->GetAnchorFrm();
5392                         // --> OD 2005-03-30 #i43913#
5393                         // --> OD 2005-08-08 #i52904# - no vertical alignment,
5394                         // if object, anchored inside cell, has temporarly
5395                         // consider its wrapping style on object positioning.
5396                         // --> FME 2006-02-01 #i58806# - no vertical alignment
5397                         // if object does not follow the text flow.
5398                         if ( bConsiderWrapOnObjPos ||
5399                              !IsAnLower( pAnch ) ||
5400                              pAnchoredObj->IsTmpConsiderWrapInfluence() ||
5401                              !rAnchoredObjFrmFmt.GetFollowTextFlow().GetValue() )
5402                         // <--
5403 						{
5404 							bVertDir = sal_False;
5405 							break;
5406 						}
5407 					}
5408 				}
5409 			}
5410 		}
5411 
5412         long nPrtHeight = (Prt().*fnRect->fnGetHeight)();
5413         if( ( bVertDir && ( nRemaining -= lcl_CalcTopAndBottomMargin( *this, *pAttrs ) ) < nPrtHeight ) ||
5414             (Lower()->Frm().*fnRect->fnGetTop)() != (this->*fnRect->fnGetPrtTop)() )
5415 		{
5416 			long lTopOfst = 0,
5417                     nDiff = (Prt().*fnRect->fnGetHeight)() - nRemaining;
5418             if ( nDiff >= 0 )
5419 			{
5420 				if ( bVertDir )
5421 				{
5422 					switch ( rOri.GetVertOrient() )
5423 					{
5424                         case text::VertOrientation::CENTER:   lTopOfst = nDiff / 2; break;
5425                         case text::VertOrientation::BOTTOM:   lTopOfst = nDiff;     break;
5426                         default: break;
5427 					};
5428 				}
5429                 long nTmp = (*fnRect->fnYInc)(
5430                                     (this->*fnRect->fnGetPrtTop)(), lTopOfst );
5431                 if ( lcl_ArrangeLowers( this, nTmp, !bVertDir ) )
5432 					SetCompletePaint();
5433 			}
5434 		}
5435 	}
5436 	else
5437 	{
5438 		//Ist noch eine alte Ausrichtung beruecksichtigt worden?
5439 		if ( Lower()->IsCntntFrm() )
5440 		{
5441             const long lYStart = (this->*fnRect->fnGetPrtTop)();
5442 			lcl_ArrangeLowers( this, lYStart, sal_True );
5443 		}
5444 	}
5445 }
5446 
5447 /*************************************************************************
5448 |*
5449 |*	  SwCellFrm::Modify()
5450 |*
5451 |*	  Ersterstellung	MA 20. Dec. 96
5452 |*	  Letzte Aenderung	MA 20. Dec. 96
5453 |*
5454 |*************************************************************************/
5455 
5456 void SwCellFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
5457 {
5458 	sal_Bool bAttrSetChg = pNew && RES_ATTRSET_CHG == pNew->Which();
5459 	const SfxPoolItem *pItem = 0;
5460 
5461 	if( bAttrSetChg )
5462 		((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_VERT_ORIENT, sal_False, &pItem);
5463 	else if ( RES_VERT_ORIENT == pNew->Which() )
5464 		pItem = pNew;
5465 
5466 	if ( pItem )
5467 	{
5468 		sal_Bool bInva = sal_True;
5469         if ( text::VertOrientation::NONE == ((SwFmtVertOrient*)pItem)->GetVertOrient() &&
5470              // OD 04.11.2003 #112910#
5471              Lower() && Lower()->IsCntntFrm() )
5472 		{
5473             SWRECTFN( this )
5474             const long lYStart = (this->*fnRect->fnGetPrtTop)();
5475 			bInva = lcl_ArrangeLowers( this, lYStart, sal_False );
5476 		}
5477 		if ( bInva )
5478 		{
5479 			SetCompletePaint();
5480 			InvalidatePrt();
5481 		}
5482 	}
5483 
5484 	if ( ( bAttrSetChg &&
5485 	       SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_PROTECT, sal_False ) ) ||
5486 		 RES_PROTECT == pNew->Which() )
5487 	{
5488 		ViewShell *pSh = getRootFrm()->GetCurrShell();
5489 		if( pSh && pSh->GetLayout()->IsAnyShellAccessible() )
5490 			pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this );
5491 	}
5492 
5493 	if ( bAttrSetChg &&
5494 	     SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_FRAMEDIR, sal_False, &pItem ) )
5495 	{
5496         SetDerivedVert( sal_False );
5497         CheckDirChange();
5498     }
5499 
5500     // --> collapsing borders FME 2005-05-27 #i29550#
5501     if ( bAttrSetChg &&
5502          SFX_ITEM_SET == ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_BOX, sal_False, &pItem ) )
5503 	{
5504         SwFrm* pTmpUpper = GetUpper();
5505         while ( pTmpUpper->GetUpper() && !pTmpUpper->GetUpper()->IsTabFrm() )
5506             pTmpUpper = pTmpUpper->GetUpper();
5507 
5508         SwTabFrm* pTabFrm = (SwTabFrm*)pTmpUpper->GetUpper();
5509         if ( pTabFrm->IsCollapsingBorders() )
5510         {
5511             // Invalidate lowers of this and next row:
5512             lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
5513             pTmpUpper = pTmpUpper->GetNext();
5514             if ( pTmpUpper )
5515                 lcl_InvalidateAllLowersPrt( (SwRowFrm*)pTmpUpper );
5516             else
5517                 pTabFrm->InvalidatePrt();
5518         }
5519     }
5520     // <-- collapsing
5521 
5522 	SwLayoutFrm::Modify( pOld, pNew );
5523 }
5524 
5525 /*************************************************************************
5526 |*  SwCellFrm::GetLayoutRowSpan() const
5527 |*************************************************************************/
5528 
5529 long SwCellFrm::GetLayoutRowSpan() const
5530 {
5531     long nRet = GetTabBox()->getRowSpan();
5532     if ( nRet < 1 )
5533     {
5534         const SwFrm* pRow = GetUpper();
5535         const SwTabFrm* pTab = static_cast<const SwTabFrm*>(pRow->GetUpper());
5536 
5537         if ( pTab && pTab->IsFollow() && pRow == pTab->GetFirstNonHeadlineRow() )
5538             nRet = -nRet;
5539     }
5540     return  nRet;
5541 }
5542 
5543 // --> OD 2010-02-17 #i103961#
5544 void SwCellFrm::Cut()
5545 {
5546     // notification for accessibility
5547     {
5548         SwRootFrm *pRootFrm = getRootFrm();
5549         if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
5550         {
5551             ViewShell* pVSh = pRootFrm->GetCurrShell();
5552             if ( pVSh && pVSh->Imp() )
5553             {
5554                 pVSh->Imp()->DisposeAccessibleFrm( this );
5555             }
5556         }
5557     }
5558 
5559     SwLayoutFrm::Cut();
5560 }
5561 // <--
5562 
5563 //
5564 // Helper functions for repeated headlines:
5565 //
5566 
5567 /*
5568  * SwTabFrm::IsInHeadline( const SwFrm& rFrm )
5569  */
5570 bool SwTabFrm::IsInHeadline( const SwFrm& rFrm ) const
5571 {
5572     ASSERT( IsAnLower( &rFrm ) && rFrm.IsInTab(),
5573              "SwTabFrm::IsInHeadline called for frame not lower of table" )
5574 
5575     const SwFrm* pTmp = &rFrm;
5576     while ( !pTmp->GetUpper()->IsTabFrm() )
5577         pTmp = pTmp->GetUpper();
5578 
5579     return GetTable()->IsHeadline( *((SwRowFrm*)pTmp)->GetTabLine() );
5580 }
5581 
5582 /*
5583  * SwTabFrm::GetFirstNonHeadlineRow()
5584  *
5585  * If this is a master table, we can may assume, that there are at least
5586  * nRepeat lines in the table.
5587  * If this is a follow table, there are intermediate states for the table
5588  * layout, e.g., during deletion of rows, which makes it necessary to find
5589  * the first non-headline row by evaluating the headline flag at the row frame.
5590  */
5591 SwRowFrm* SwTabFrm::GetFirstNonHeadlineRow() const
5592 {
5593     SwRowFrm* pRet = (SwRowFrm*)Lower();
5594     if ( pRet )
5595     {
5596         if ( IsFollow() )
5597         {
5598             while ( pRet && pRet->IsRepeatedHeadline() )
5599                 pRet = (SwRowFrm*)pRet->GetNext();
5600         }
5601         else
5602         {
5603             sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
5604             while ( pRet && nRepeat > 0 )
5605             {
5606                 pRet = (SwRowFrm*)pRet->GetNext();
5607                 --nRepeat;
5608             }
5609         }
5610     }
5611 
5612     return (SwRowFrm*)pRet;
5613 }
5614 
5615 /*
5616  * SwTable::IsHeadline()
5617  */
5618 bool SwTable::IsHeadline( const SwTableLine& rLine ) const
5619 {
5620     for ( sal_uInt16 i = 0; i < GetRowsToRepeat(); ++i )
5621         if ( GetTabLines()[ i ] == &rLine )
5622             return true;
5623 
5624     return false;
5625 }
5626 
5627 bool SwTabFrm::IsLayoutSplitAllowed() const
5628 {
5629     return GetFmt()->GetLayoutSplit().GetValue();
5630 }
5631 
5632 // --> collapsing borders FME 2005-05-27 #i29550#
5633 
5634 sal_uInt16 SwTabFrm::GetBottomLineSize() const
5635 {
5636     ASSERT( IsCollapsingBorders(),
5637             "BottomLineSize only required for collapsing borders" )
5638 
5639     ASSERT( Lower(), "Warning! Trying to prevent a crash, please inform FME" )
5640 
5641     const SwFrm* pTmp = GetLastLower();
5642 
5643     // --> FME 2005-12-07 #124755# Try to make code robust:
5644     if ( !pTmp ) return 0;
5645     // <--
5646 
5647     return static_cast<const SwRowFrm*>(pTmp)->GetBottomLineSize();
5648 }
5649 
5650 bool SwTabFrm::IsCollapsingBorders() const
5651 {
5652     return ((SfxBoolItem&)GetFmt()->GetAttrSet().Get( RES_COLLAPSING_BORDERS )).GetValue();
5653 }
5654 
5655 // <-- collapsing
5656 
5657 
5658 //
5659 // Local helper function to calculate height of first text row
5660 //
5661 SwTwips lcl_CalcHeightOfFirstContentLine( const SwRowFrm& rSourceLine )
5662 {
5663     // Find corresponding split line in master table
5664     const SwTabFrm* pTab = rSourceLine.FindTabFrm();
5665     SWRECTFN( pTab )
5666     const SwCellFrm* pCurrSourceCell = (SwCellFrm*)rSourceLine.Lower();
5667 
5668     //
5669     // 1. Case: rSourceLine is a follow flow line.
5670     // In this case we have to return the minimum of the heights
5671     // of the first lines in rSourceLine.
5672     //
5673     // 2. Case: rSourceLine is not a follow flow line.
5674     // In this case we have to return the maximum of the heights
5675     // of the first lines in rSourceLine.
5676     //
5677     bool bIsInFollowFlowLine = rSourceLine.IsInFollowFlowRow();
5678     SwTwips nHeight = bIsInFollowFlowLine ? LONG_MAX : 0;
5679 
5680     while ( pCurrSourceCell )
5681     {
5682         // NEW TABLES
5683         // Skip cells which are not responsible for the height of
5684         // the follow flow line:
5685         if ( bIsInFollowFlowLine && pCurrSourceCell->GetLayoutRowSpan() > 1 )
5686         {
5687             pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
5688             continue;
5689         }
5690 
5691         const SwFrm *pTmp = pCurrSourceCell->Lower();
5692         if ( pTmp )
5693         {
5694             SwTwips nTmpHeight = USHRT_MAX;
5695             // --> FME 2004-09-14 #i32456# Consider lower row frames
5696             if ( pTmp->IsRowFrm() )
5697             {
5698                 const SwRowFrm* pTmpSourceRow = (SwRowFrm*)pCurrSourceCell->Lower();
5699                 nTmpHeight = lcl_CalcHeightOfFirstContentLine( *pTmpSourceRow );
5700             }
5701             // <--
5702             if ( pTmp->IsTabFrm() )
5703             {
5704                 nTmpHeight = ((SwTabFrm*)pTmp)->CalcHeightOfFirstContentLine();
5705             }
5706             else if ( pTmp->IsTxtFrm() )
5707             {
5708                 SwTxtFrm* pTxtFrm = (SwTxtFrm*)pTmp;
5709                 pTxtFrm->GetFormatted();
5710                 nTmpHeight = pTxtFrm->FirstLineHeight();
5711             }
5712 
5713             if ( USHRT_MAX != nTmpHeight )
5714             {
5715                 const SwCellFrm* pPrevCell = pCurrSourceCell->GetPreviousCell();
5716                 if ( pPrevCell )
5717                 {
5718                     // If we are in a split row, there may be some space
5719                     // left in the cell frame of the master row.
5720                     // We look for the minimum of all first line heights;
5721                     SwTwips nReal = (pPrevCell->Prt().*fnRect->fnGetHeight)();
5722                     const SwFrm* pFrm = pPrevCell->Lower();
5723                     const SwFrm* pLast = pFrm;
5724                     while ( pFrm )
5725                     {
5726                         nReal -= (pFrm->Frm().*fnRect->fnGetHeight)();
5727                         pLast = pFrm;
5728                         pFrm = pFrm->GetNext();
5729                     }
5730 
5731                     // --> FME, OD 2004-07-15 #i26831#, #i26520#
5732                     // The additional lower space of the current last.
5733                     // --> OD 2004-11-25 #115759# - do *not* consider the
5734                     // additional lower space for 'master' text frames
5735                     if ( pLast && pLast->IsFlowFrm() &&
5736                          ( !pLast->IsTxtFrm() ||
5737                            !static_cast<const SwTxtFrm*>(pLast)->GetFollow() ) )
5738                     // <--
5739                     {
5740                         nReal += SwFlowFrm::CastFlowFrm(pLast)->CalcAddLowerSpaceAsLastInTableCell();
5741                     }
5742                     // Don't forget the upper space and lower space,
5743                     // --> OD 2004-11-25 #115759# - do *not* consider the upper
5744                     // and the lower space for follow text frames.
5745                     if ( pTmp->IsFlowFrm() &&
5746                          ( !pTmp->IsTxtFrm() ||
5747                            !static_cast<const SwTxtFrm*>(pTmp)->IsFollow() ) )
5748                     {
5749                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace( NULL, pLast);
5750                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
5751                     }
5752                     // <--
5753                     // --> OD 2004-11-25 #115759# - consider additional lower
5754                     // space of <pTmp>, if contains only one line.
5755                     // In this case it would be the new last text frame, which
5756                     // would have no follow and thus would add this space.
5757                     if ( pTmp->IsTxtFrm() &&
5758                          const_cast<SwTxtFrm*>(static_cast<const SwTxtFrm*>(pTmp))
5759                                             ->GetLineCount( STRING_LEN ) == 1 )
5760                     {
5761                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)
5762                                         ->CalcAddLowerSpaceAsLastInTableCell();
5763                     }
5764                     // <--
5765                     if ( nReal > 0 )
5766                         nTmpHeight -= nReal;
5767                 }
5768                 else
5769                 {
5770                     // pFirstRow is not a FollowFlowRow. In this case,
5771                     // we look for the maximum of all first line heights:
5772                     SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCurrSourceCell );
5773                     const SwBorderAttrs &rAttrs = *aAccess.Get();
5774                     nTmpHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
5775                     // --> OD 2004-07-16 #i26250#
5776                     // Don't forget the upper space and lower space,
5777                     if ( pTmp->IsFlowFrm() )
5778                     {
5779                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcUpperSpace();
5780                         nTmpHeight += SwFlowFrm::CastFlowFrm(pTmp)->CalcLowerSpace();
5781                     }
5782                     // <--
5783                 }
5784             }
5785 
5786             if ( bIsInFollowFlowLine )
5787             {
5788                 // minimum
5789                 if ( nTmpHeight < nHeight )
5790                     nHeight = nTmpHeight;
5791             }
5792             else
5793             {
5794                 // maximum
5795                 if ( nTmpHeight > nHeight && USHRT_MAX != nTmpHeight )
5796                     nHeight = nTmpHeight;
5797             }
5798         }
5799 
5800         pCurrSourceCell = (SwCellFrm*)pCurrSourceCell->GetNext();
5801     }
5802 
5803     return ( LONG_MAX == nHeight ) ? 0 : nHeight;
5804 }
5805 
5806 //
5807 // Function to calculate height of first text row
5808 //
5809 SwTwips SwTabFrm::CalcHeightOfFirstContentLine() const
5810 {
5811     SWRECTFN( this )
5812 
5813     const bool bDontSplit = !IsFollow() && !GetFmt()->GetLayoutSplit().GetValue();
5814 
5815     if ( bDontSplit )
5816     {
5817         // Table is not allowed to split: Take the whole height, that's all
5818         return (Frm().*fnRect->fnGetHeight)();
5819     }
5820 
5821     SwRowFrm* pFirstRow = 0;
5822     SwTwips nTmpHeight = 0;
5823 
5824     pFirstRow = GetFirstNonHeadlineRow();
5825     ASSERT( !IsFollow() || pFirstRow, "FollowTable without Lower" )
5826 
5827     // NEW TABLES
5828     if ( pFirstRow && pFirstRow->IsRowSpanLine() && pFirstRow->GetNext() )
5829         pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
5830 
5831     // Calculate the height of the headlines:
5832     const sal_uInt16 nRepeat = GetTable()->GetRowsToRepeat();
5833     SwTwips nRepeatHeight = nRepeat ? lcl_GetHeightOfRows( GetLower(), nRepeat ) : 0;
5834 
5835     // Calculate the height of the keeping lines
5836     // (headlines + following keeping lines):
5837     SwTwips nKeepHeight = nRepeatHeight;
5838     if ( GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
5839     {
5840         sal_uInt16 nKeepRows = nRepeat;
5841 
5842         // Check how many rows want to keep together
5843         while ( pFirstRow && pFirstRow->ShouldRowKeepWithNext() )
5844         {
5845             ++nKeepRows;
5846             pFirstRow = static_cast<SwRowFrm*>(pFirstRow->GetNext());
5847         }
5848 
5849         if ( nKeepRows > nRepeat )
5850             nKeepHeight = lcl_GetHeightOfRows( GetLower(), nKeepRows );
5851     }
5852 
5853     // For master tables, the height of the headlines + the heigth of the
5854     // keeping lines (if any) has to be considered. For follow tables, we
5855     // only consider the height of the keeping rows without the repeated lines:
5856     if ( !IsFollow() )
5857     {
5858         nTmpHeight = nKeepHeight;
5859     }
5860     else
5861     {
5862         nTmpHeight = nKeepHeight - nRepeatHeight;
5863     }
5864 
5865     // pFirstRow row is the first non-heading row.
5866     // nTmpHeight is the height of the heading row if we are a follow.
5867     if ( pFirstRow )
5868     {
5869         const bool bSplittable = pFirstRow->IsRowSplitAllowed();
5870         const SwTwips nFirstLineHeight = (pFirstRow->Frm().*fnRect->fnGetHeight)();
5871 
5872         if ( !bSplittable )
5873         {
5874             // pFirstRow is not splittable, but it is still possible that the line height of pFirstRow
5875             // actually is determined by a lower cell with rowspan = -1. In this case we should not
5876             // just return the height of the first line. Basically we need to get the height of the
5877             // line as it would be on the last page. Since this is quite complicated to calculate,
5878             // we olny calculate the height of the first line.
5879             if ( pFirstRow->GetPrev() &&
5880                  static_cast<SwRowFrm*>(pFirstRow->GetPrev())->IsRowSpanLine() )
5881             {
5882                 // Calculate maximum height of all cells with rowspan = 1:
5883                 SwTwips nMaxHeight = 0;
5884                 const SwCellFrm* pLower2 = static_cast<const SwCellFrm*>(pFirstRow->Lower());
5885                 while ( pLower2 )
5886                 {
5887                     if ( 1 == pLower2->GetTabBox()->getRowSpan() )
5888                     {
5889                         const SwTwips nCellHeight = lcl_CalcMinCellHeight( pLower2, sal_True );
5890                         nMaxHeight = Max( nCellHeight, nMaxHeight );
5891                     }
5892                     pLower2 = static_cast<const SwCellFrm*>(pLower2->GetNext());
5893                 }
5894                 nTmpHeight += nMaxHeight;
5895             }
5896             else
5897             {
5898                 nTmpHeight += nFirstLineHeight;
5899             }
5900         }
5901 
5902         // --> FME 2004-11-18 #118411#
5903         // Optimization: lcl_CalcHeightOfFirstContentLine actually can trigger
5904         // a formatting of the row frame (via the GetFormatted()). We don't
5905         // want this formatting if the row does not have a height.
5906         else if ( 0 != nFirstLineHeight )
5907         // <--
5908         {
5909             const bool bOldJoinLock = IsJoinLocked();
5910             ((SwTabFrm*)this)->LockJoin();
5911             const SwTwips nHeightOfFirstContentLine = lcl_CalcHeightOfFirstContentLine( *(SwRowFrm*)pFirstRow );
5912 
5913             // Consider minimum row height:
5914             const SwFmtFrmSize &rSz = static_cast<const SwRowFrm*>(pFirstRow)->GetFmt()->GetFrmSize();
5915             const SwTwips nMinRowHeight = rSz.GetHeightSizeType() == ATT_MIN_SIZE ?
5916                                           rSz.GetHeight() : 0;
5917 
5918             nTmpHeight += Max( nHeightOfFirstContentLine, nMinRowHeight );
5919 
5920             if ( !bOldJoinLock )
5921                 ((SwTabFrm*)this)->UnlockJoin();
5922         }
5923     }
5924 
5925     return nTmpHeight;
5926 }
5927 
5928 //
5929 // Some more functions for covered/covering cells. This way inclusion of
5930 // SwCellFrm can be avoided
5931 //
5932 
5933 bool SwFrm::IsLeaveUpperAllowed() const
5934 {
5935     const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
5936     return pThisCell && pThisCell->GetLayoutRowSpan() > 1;
5937 }
5938 
5939 bool SwFrm::IsCoveredCell() const
5940 {
5941     const SwCellFrm* pThisCell = dynamic_cast<const SwCellFrm*>(this);
5942     return pThisCell && pThisCell->GetLayoutRowSpan() < 1;
5943 }
5944 
5945 bool SwFrm::IsInCoveredCell() const
5946 {
5947     bool bRet = false;
5948 
5949     const SwFrm* pThis = this;
5950     while ( pThis && !pThis->IsCellFrm() )
5951         pThis = pThis->GetUpper();
5952 
5953     if ( pThis )
5954         bRet = pThis->IsCoveredCell();
5955 
5956     return bRet;
5957 }
5958 
5959