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