xref: /trunk/main/sw/source/core/layout/frmtool.cxx (revision 6e8337c1)
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 
27 #include <hintids.hxx>
28 #include <tools/bigint.hxx>
29 #include <svx/svdmodel.hxx>
30 #include <svx/svdpage.hxx>
31 #include <editeng/brshitem.hxx>
32 #include <editeng/keepitem.hxx>
33 #include <editeng/shaditem.hxx>
34 #include <editeng/ulspitem.hxx>
35 #include <editeng/lrspitem.hxx>
36 #include <editeng/boxitem.hxx>
37 #include <sfx2/printer.hxx>
38 #include <editeng/lspcitem.hxx>
39 #include <fmtornt.hxx>
40 #include <fmtanchr.hxx>
41 #include <fmthdft.hxx>
42 #include <fmtcntnt.hxx>
43 #include <fmtfsize.hxx>
44 #include <fmtsrnd.hxx>
45 #include <docary.hxx>
46 #include <lineinfo.hxx>
47 #include <swmodule.hxx>
48 #include "pagefrm.hxx"
49 #include "colfrm.hxx"
50 #include "doc.hxx"
51 #include "fesh.hxx"
52 #include "viewimp.hxx"
53 #include "viewopt.hxx"
54 #include "pam.hxx"
55 #include "dflyobj.hxx"
56 #include "dcontact.hxx"
57 #include "frmtool.hxx"
58 #include "docsh.hxx"
59 #include "tabfrm.hxx"
60 #include "rowfrm.hxx"
61 #include "ftnfrm.hxx"
62 #include "txtfrm.hxx"
63 #include "notxtfrm.hxx"
64 #include "flyfrms.hxx"
65 #include "layact.hxx"
66 #include "pagedesc.hxx"
67 #include "section.hxx"
68 #include "sectfrm.hxx"
69 #include "node2lay.hxx"
70 #include "ndole.hxx"
71 #include "ndtxt.hxx"
72 #include "swtable.hxx"
73 #include "hints.hxx"
74 #include <layhelp.hxx>
75 #include <laycache.hxx>
76 #include <rootfrm.hxx>
77 #include "mdiexp.hxx"
78 #include "statstr.hrc"
79 #include <paratr.hxx>
80 #include <sortedobjs.hxx>
81 #include <objectformatter.hxx>
82 #include <switerator.hxx>
83 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
84 #include <drawdoc.hxx>
85 
86 // ftnfrm.cxx:
87 void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
88 
89 using namespace ::com::sun::star;
90 
91 
92 sal_Bool bObjsDirect = sal_True;
93 sal_Bool bDontCreateObjects = sal_False;
94 sal_Bool bSetCompletePaintOnInvalidate = sal_False;
95 
96 sal_uInt8 StackHack::nCnt = 0;
97 sal_Bool StackHack::bLocked = sal_False;
98 
99 
100 
101 /*************************************************************************/
102 
SwFrmNotify(SwFrm * pF)103 SwFrmNotify::SwFrmNotify( SwFrm *pF ) :
104 	pFrm( pF ),
105 	aFrm( pF->Frm() ),
106 	aPrt( pF->Prt() ),
107     bInvaKeep( sal_False ),
108     bValidSize( pF->GetValidSizeFlag() ),
109     mbFrmDeleted( false ) // #i49383#
110 {
111     if ( pF->IsTxtFrm() )
112     {
113         mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_True );
114         mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_False );
115     }
116     else
117     {
118         mnFlyAnchorOfst = 0;
119         mnFlyAnchorOfstNoWrap = 0;
120     }
121 
122 	bHadFollow = pF->IsCntntFrm() ?
123 					(((SwCntntFrm*)pF)->GetFollow() ? sal_True : sal_False) :
124 					sal_False;
125 }
126 
127 /*************************************************************************/
128 
~SwFrmNotify()129 SwFrmNotify::~SwFrmNotify()
130 {
131     // #i49383#
132     if ( mbFrmDeleted )
133     {
134         return;
135     }
136 
137     SWRECTFN( pFrm )
138     const sal_Bool bAbsP = POS_DIFF( aFrm, pFrm->Frm() );
139     const sal_Bool bChgWidth =
140             (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)();
141     const sal_Bool bChgHeight =
142             (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)();
143     const sal_Bool bChgFlyBasePos = pFrm->IsTxtFrm() &&
144        ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_True ) ) ||
145          ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_False ) ) );
146 
147 	if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() )
148 	{
149 		SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm );
150 
151 		if ( !pFlow->IsFollow() )
152 		{
153 			if ( !pFrm->GetIndPrev() )
154 			{
155 				if ( bInvaKeep )
156 				{
157                     SwFrm *pPre = pFrm->FindPrev();
158                     if ( pPre && pPre->IsFlowFrm() )
159                     {
160                         // 1. pPre wants to keep with me:
161                         bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev();
162 
163                         // 2. pPre is a table and the last row wants to keep with me:
164                         if ( !bInvalidPrePos && pPre->IsTabFrm() )
165                         {
166                             SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre);
167                             if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
168                             {
169                                 SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower());
170                                 if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
171                                     bInvalidPrePos = true;
172                             }
173                         }
174 
175                         if ( bInvalidPrePos )
176                             pPre->InvalidatePos();
177                     }
178 				}
179 			}
180             else if ( !pFlow->HasFollow() )
181             {
182                 long nOldHeight = (aFrm.*fnRect->fnGetHeight)();
183                 long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
184                 if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
185                     pFlow->CheckKeep();
186             }
187 		}
188 	}
189 
190 	if ( bAbsP )
191 	{
192 		pFrm->SetCompletePaint();
193 
194 		SwFrm* pNxt = pFrm->GetIndNext();
195         // #121888# - skip empty section frames
196         while ( pNxt &&
197                 pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
198         {
199             pNxt = pNxt->GetIndNext();
200         }
201 
202 		if ( pNxt )
203 			pNxt->InvalidatePos();
204 		else
205 		{
206             // #104100# - correct condition for setting retouche
207             // flag for vertical layout.
208             if( pFrm->IsRetoucheFrm() &&
209                 (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 )
210             {
211 				pFrm->SetRetouche();
212             }
213 
214             // A fresh follow frame does not have to be invalidated, because
215             // it is already formatted:
216             if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() )
217             {
218                 if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() )
219                     pFrm->InvalidateNextPos();
220             }
221         }
222 	}
223 
224 	//Fuer Hintergrundgrafiken muss bei Groessenaenderungen ein Repaint her.
225     const sal_Bool bPrtWidth =
226             (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)();
227     const sal_Bool bPrtHeight =
228             (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)();
229     if ( bPrtWidth || bPrtHeight )
230     {
231         //UUUU
232         drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(pFrm->getSdrAllFillAttributesHelper());
233 
234         if(aFillAttributes.get() && aFillAttributes->isUsed())
235         {
236             //UUUU use SetCompletePaint if needed
237             if(aFillAttributes->needCompleteRepaint())
238             {
239                 pFrm->SetCompletePaint();
240             }
241         }
242         else
243         {
244             const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos();
245             if(GPOS_NONE != ePos && GPOS_TILED != ePos)
246                 pFrm->SetCompletePaint();
247         }
248     }
249     else
250     {
251         // #97597# - consider case that *only* margins between
252         // frame and printing area has changed. Then, frame has to be repainted,
253         // in order to force paint of the margin areas.
254         if ( !bAbsP && (bChgWidth || bChgHeight) )
255         {
256             pFrm->SetCompletePaint();
257         }
258     }
259 
260 	const sal_Bool bPrtP = POS_DIFF( aPrt, pFrm->Prt() );
261     if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
262          bPrtWidth || bPrtHeight || bChgFlyBasePos )
263 	{
264 		if( pFrm->IsAccessibleFrm() )
265 		{
266 			SwRootFrm *pRootFrm = pFrm->getRootFrm();
267 			if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
268 				pRootFrm->GetCurrShell() )
269 			{
270 				pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
271 			}
272 		}
273 
274         // Notification of anchored objects
275         if ( pFrm->GetDrawObjs() )
276         {
277             const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
278             SwPageFrm* pPageFrm = 0;
279             for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
280             {
281                 // OD 2004-03-31 #i26791# - no general distinction between
282                 // Writer fly frames and drawing objects
283                 bool bNotify = false;
284                 bool bNotifySize = false;
285                 SwAnchoredObject* pObj = rObjs[i];
286                 SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
287                 // --> OD 2004-12-08 #115759#
288                 const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
289                 if ( !bAnchoredAsChar )
290                 // <--
291                 {
292                     // Notify object, which aren't anchored as-character:
293 
294                     // always notify objects, if frame position has changed
295                     // or if the object is to-page|to-fly anchored.
296                     if ( bAbsP ||
297                          pContact->ObjAnchoredAtPage() ||
298                          pContact->ObjAnchoredAtFly() )
299                     {
300                         bNotify = true;
301 
302                         // assure that to-fly anchored Writer fly frames are
303                         // registered at the correct page frame, if frame
304                         // position has changed.
305                         if ( bAbsP && pContact->ObjAnchoredAtFly() &&
306                              pObj->ISA(SwFlyFrm) )
307                         {
308                             // determine to-fly anchored Writer fly frame
309                             SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
310                             // determine page frame of to-fly anchored
311                             // Writer fly frame
312                             SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm();
313                             // determine page frame, if needed.
314                             if ( !pPageFrm )
315                             {
316                                 pPageFrm = pFrm->FindPageFrm();
317                             }
318                             if ( pPageFrm != pFlyPageFrm )
319                             {
320                                 ASSERT( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" );
321                                 if( pFlyPageFrm )
322                                     pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm );
323                                 else
324                                     pPageFrm->AppendFlyToPage( pFlyFrm );
325                             }
326                         }
327                     }
328                     // otherwise the objects are notified in dependence to
329                     // its positioning and alignment
330                     else
331                     {
332                         const SwFmtVertOrient& rVert =
333                                         pContact->GetFmt()->GetVertOrient();
334                         if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
335                                rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
336                                rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
337                              ( bChgHeight || bPrtHeight ) )
338                         {
339                             bNotify = true;
340                         }
341                         if ( !bNotify )
342                         {
343                             const SwFmtHoriOrient& rHori =
344                                         pContact->GetFmt()->GetHoriOrient();
345                             if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
346                                    rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
347                                    rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
348                                  ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
349                             {
350                                 bNotify = true;
351                             }
352                         }
353                     }
354                 }
355                 else if ( bPrtWidth )
356                 {
357                     // Notify as-character anchored objects, if printing area
358                     // width has changed.
359                     bNotify = true;
360                     bNotifySize = true;
361                 }
362 
363                 // perform notification via the corresponding invalidations
364                 if ( bNotify )
365                 {
366                     if ( pObj->ISA(SwFlyFrm) )
367                     {
368                         SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
369                         if ( bNotifySize )
370                             pFlyFrm->_InvalidateSize();
371                         // --> OD 2004-12-08 #115759# - no invalidation of
372                         // position for as-character anchored objects.
373                         if ( !bAnchoredAsChar )
374                         {
375                             pFlyFrm->_InvalidatePos();
376                         }
377                         // <--
378                         pFlyFrm->_Invalidate();
379                     }
380                     else if ( pObj->ISA(SwAnchoredDrawObject) )
381                     {
382                         // --> OD 2004-12-08 #115759# - no invalidation of
383                         // position for as-character anchored objects.
384                         if ( !bAnchoredAsChar )
385                         {
386                             pObj->InvalidateObjPos();
387                         }
388                         // <--
389                     }
390                     else
391                     {
392                         ASSERT( false,
393                                 "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." );
394                     }
395                 }
396             }
397         }
398 	}
399 	else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() )
400 	{
401 		SwRootFrm *pRootFrm = pFrm->getRootFrm();
402 		if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
403 			pRootFrm->GetCurrShell() )
404 		{
405 			pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm );
406 		}
407 	}
408 
409     // #i9046# Automatic frame width
410     SwFlyFrm* pFly = 0;
411     // --> FME 2004-10-21 #i35879# Do not trust the inf flags. pFrm does not
412     // necessarily have to have an upper!
413     if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) )
414     // <--
415     {
416         // --> OD 2006-05-08 #i61999#
417         // no invalidation of columned Writer fly frames, because automatic
418         // width doesn't make sense for such Writer fly frames.
419         if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() )
420         {
421             const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize();
422 
423             // This could be optimized. Basically the fly frame only has to
424             // be invalidated, if the first line of pFrm (if pFrm is a content
425             // frame, for other frame types its the print area) has changed its
426             // size and pFrm was responsible for the current width of pFly. On
427             // the other hand, this is only rarely used and re-calculation of
428             // the fly frame does not cause too much trouble. So we keep it this
429             // way:
430             if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() )
431             {
432                 // --> OD 2005-07-29 #i50668#, #i50998# - invalidation of position
433                 // of as-character anchored fly frames not needed and can cause
434                 // layout loops
435                 if ( !pFly->ISA(SwFlyInCntFrm) )
436                 {
437                     pFly->InvalidatePos();
438                 }
439                 // <--
440                 pFly->InvalidateSize();
441             }
442         }
443         // <--
444     }
445 }
446 
447 /*************************************************************************/
448 
SwLayNotify(SwLayoutFrm * pLayFrm)449 SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) :
450 	SwFrmNotify( pLayFrm ),
451     bLowersComplete( sal_False )
452 {
453 }
454 
455 /*************************************************************************/
456 
457 // OD 2004-05-11 #i28701# - local method to invalidate the position of all
458 // frames inclusive its floating screen objects, which are lowers of the given
459 // layout frame
lcl_InvalidatePosOfLowers(SwLayoutFrm & _rLayoutFrm)460 void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm )
461 {
462     if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() )
463     {
464         _rLayoutFrm.InvalidateObjs( true, false );
465     }
466 
467     SwFrm* pLowerFrm = _rLayoutFrm.Lower();
468     while ( pLowerFrm )
469     {
470         pLowerFrm->InvalidatePos();
471         if ( pLowerFrm->IsTxtFrm() )
472         {
473             static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD );
474         }
475         else if ( pLowerFrm->IsTabFrm() )
476         {
477             pLowerFrm->InvalidatePrt();
478         }
479 
480         pLowerFrm->InvalidateObjs( true, false );
481 
482         pLowerFrm = pLowerFrm->GetNext();
483     };
484 }
485 
~SwLayNotify()486 SwLayNotify::~SwLayNotify()
487 {
488     // --> OD 2005-07-29 #i49383#
489     if ( mbFrmDeleted )
490     {
491         return;
492     }
493     // <--
494 
495 	SwLayoutFrm *pLay = GetLay();
496     SWRECTFN( pLay )
497 	sal_Bool bNotify = sal_False;
498 	if ( pLay->Prt().SSize() != aPrt.SSize() )
499 	{
500 		if ( !IsLowersComplete() )
501 		{
502 			sal_Bool bInvaPercent;
503 
504 			if ( pLay->IsRowFrm() )
505 			{
506 				bInvaPercent = sal_True;
507                 long nNew = (pLay->Prt().*fnRect->fnGetHeight)();
508                 if( nNew != (aPrt.*fnRect->fnGetHeight)() )
509                      ((SwRowFrm*)pLay)->AdjustCells( nNew, sal_True);
510                 if( (pLay->Prt().*fnRect->fnGetWidth)()
511                     != (aPrt.*fnRect->fnGetWidth)() )
512 					 ((SwRowFrm*)pLay)->AdjustCells( 0, sal_False );
513 			}
514 			else
515 			{
516 				//Proportionale Anpassung der innenliegenden.
517 				//1. Wenn der Formatierte kein Fly ist
518 				//2. Wenn er keine Spalten enthaelt
519 				//3. Wenn der Fly eine feste Hoehe hat und die Spalten in der
520 				//	 Hoehe danebenliegen.
521 				//4. niemals bei SectionFrms.
522 				sal_Bool bLow;
523 				if( pLay->IsFlyFrm() )
524 				{
525 					if ( pLay->Lower() )
526 					{
527 						bLow = !pLay->Lower()->IsColumnFrm() ||
528                             (pLay->Lower()->Frm().*fnRect->fnGetHeight)()
529                              != (pLay->Prt().*fnRect->fnGetHeight)();
530 					}
531 					else
532 						bLow = sal_False;
533 				}
534 				else if( pLay->IsSctFrm() )
535 				{
536 					if ( pLay->Lower() )
537 					{
538 						if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() )
539 							bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height();
540 						else
541 							bLow = pLay->Prt().Width() != aPrt.Width();
542 					}
543 					else
544 						bLow = sal_False;
545 				}
546                 else if( pLay->IsFooterFrm() && !pLay->HasFixSize() )
547                     bLow = pLay->Prt().Width() != aPrt.Width();
548                 else
549 					bLow = sal_True;
550 				bInvaPercent = bLow;
551 				if ( bLow )
552 				{
553                     pLay->ChgLowersProp( aPrt.SSize() );
554                 }
555 				//Wenn die PrtArea gewachsen ist, so ist es moeglich, dass die
556 				//Kette der Untergeordneten einen weiteren Frm aufnehmen kann,
557 				//mithin muss also der 'moeglicherweise passende' Invalidiert werden.
558 				//Das invalidieren lohnt nur, wenn es sich beim mir bzw. meinen
559 				//Uppers um eine Moveable-Section handelt.
560 				//Die PrtArea ist gewachsen, wenn die Breite oder die Hoehe groesser
561 				//geworden ist.
562 				if ( (pLay->Prt().Height() > aPrt.Height() ||
563 					  pLay->Prt().Width()  > aPrt.Width()) &&
564 					 (pLay->IsMoveable() || pLay->IsFlyFrm()) )
565 				{
566                     SwFrm *pTmpFrm = pLay->Lower();
567                     if ( pTmpFrm && pTmpFrm->IsFlowFrm() )
568 					{
569                         while ( pTmpFrm->GetNext() )
570                             pTmpFrm = pTmpFrm->GetNext();
571                         pTmpFrm->InvalidateNextPos();
572 					}
573 				}
574 			}
575 			bNotify = sal_True;
576 			//TEUER!! aber wie macht man es geschickter?
577 			if( bInvaPercent )
578                 pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() );
579 		}
580 		if ( pLay->IsTabFrm() )
581 			//Damit _nur_ der Schatten bei Groessenaenderungen gemalt wird.
582 			((SwTabFrm*)pLay)->SetComplete();
583         else
584         {
585             const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
586             if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
587 				  !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) )
588 			//Damit die untergeordneten sauber retouchiert werden.
589 			//Problembsp: Flys an den Henkeln packen und verkleinern.
590 			//Nicht fuer Body und Page, sonst flackerts beim HTML-Laden.
591 			pLay->SetCompletePaint();
592         }
593 	}
594 	//Lower benachrichtigen wenn sich die Position veraendert hat.
595     const sal_Bool bPrtPos = POS_DIFF( aPrt, pLay->Prt() );
596     const sal_Bool bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() );
597 	const sal_Bool bSize = pLay->Frm().SSize() != aFrm.SSize();
598 
599 	if ( bPos && pLay->Lower() && !IsLowersComplete() )
600 		pLay->Lower()->InvalidatePos();
601 
602     if ( bPrtPos )
603 		pLay->SetCompletePaint();
604 
605 	//Nachfolger benachrichtigen wenn sich die SSize geaendert hat.
606 	if ( bSize )
607 	{
608 		if( pLay->GetNext() )
609 		{
610 			if ( pLay->GetNext()->IsLayoutFrm() )
611 				pLay->GetNext()->_InvalidatePos();
612 			else
613 				pLay->GetNext()->InvalidatePos();
614 		}
615 		else if( pLay->IsSctFrm() )
616 			pLay->InvalidateNextPos();
617 	}
618 	if ( !IsLowersComplete() &&
619 		 !(pLay->GetType()&(FRM_FLY|FRM_SECTION) &&
620 			pLay->Lower() && pLay->Lower()->IsColumnFrm()) &&
621 		 (bPos || bNotify) && !(pLay->GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
622 	{
623         // --> OD 2005-03-11 #i44016# - force unlock of position of lower objects.
624         // --> OD 2005-03-30 #i43913# - no unlock of position of objects,
625         // if <pLay> is a cell frame, and its table frame resp. its parent table
626         // frame is locked.
627         // --> OD 2005-04-15 #i47458# - force unlock of position of lower objects,
628         // only if position of layout frame has changed.
629         bool bUnlockPosOfObjs( bPos );
630         if ( bUnlockPosOfObjs && pLay->IsCellFrm() )
631         {
632             SwTabFrm* pTabFrm( pLay->FindTabFrm() );
633             if ( pTabFrm &&
634                  ( pTabFrm->IsJoinLocked() ||
635                    ( pTabFrm->IsFollow() &&
636                      pTabFrm->FindMaster()->IsJoinLocked() ) ) )
637             {
638                 bUnlockPosOfObjs = false;
639             }
640         }
641         // --> OD 2005-05-18 #i49383# - check for footnote frame, if unlock
642         // of position of lower objects is allowed.
643         else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() )
644         {
645             bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs();
646         }
647         // <--
648         // --> OD 2005-07-29 #i51303# - no unlock of object positions for sections
649         else if ( bUnlockPosOfObjs && pLay->IsSctFrm() )
650         {
651             bUnlockPosOfObjs = false;
652         }
653         // <--
654         pLay->NotifyLowerObjs( bUnlockPosOfObjs );
655         // <--
656 	}
657 	if ( bPos && pLay->IsFtnFrm() && pLay->Lower() )
658 	{
659         // OD 2004-05-11 #i28701#
660         ::lcl_InvalidatePosOfLowers( *pLay );
661 	}
662     if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm()
663           && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() )
664         ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize();
665 }
666 
667 /*************************************************************************/
668 
SwFlyNotify(SwFlyFrm * pFlyFrm)669 SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) :
670 	SwLayNotify( pFlyFrm ),
671     // --> OD 2004-11-24 #115759# - keep correct page frame - the page frame
672     // the Writer fly frame is currently registered at.
673     pOldPage( pFlyFrm->GetPageFrm() ),
674     // <--
675     aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() )
676 {
677 }
678 
679 /*************************************************************************/
680 
~SwFlyNotify()681 SwFlyNotify::~SwFlyNotify()
682 {
683     // --> OD 2005-07-29 #i49383#
684     if ( mbFrmDeleted )
685     {
686         return;
687     }
688     // <--
689 
690 	SwFlyFrm *pFly = GetFly();
691 	if ( pFly->IsNotifyBack() )
692 	{
693 		ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
694 		SwViewImp *pImp = pSh ? pSh->Imp() : 0;
695 		if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
696 		{
697 			//Wenn in der LayAction das IsAgain gesetzt ist kann es sein,
698 			//dass die alte Seite inzwischen vernichtet wurde!
699             ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt );
700             // --> OD 2004-10-20 #i35640# - additional notify anchor text frame,
701             // if Writer fly frame has changed its page
702             if ( pFly->GetAnchorFrm()->IsTxtFrm() &&
703                  pFly->GetPageFrm() != pOldPage )
704             {
705                 pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
706             }
707             // <--
708 		}
709 		pFly->ResetNotifyBack();
710 	}
711 
712 	//Haben sich Groesse oder Position geaendert, so sollte die View
713 	//das wissen.
714     SWRECTFN( pFly )
715     const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() );
716     const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize();
717     const bool bPrtChgd = aPrt != pFly->Prt();
718     if ( bPosChgd || bFrmChgd || bPrtChgd )
719 	{
720 		pFly->NotifyDrawObj();
721 	}
722 	if ( bPosChgd && aFrm.Pos().X() != WEIT_WECH )
723 	{
724         // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
725         // reason: New positioning and alignment (e.g. to-paragraph anchored,
726         // but aligned at page) are introduced.
727         // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
728         // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>.
729 
730 		if ( pFly->IsFlyAtCntFrm() )
731 		{
732             SwFrm *pNxt = pFly->AnchorFrm()->FindNext();
733 			if ( pNxt )
734             {
735 				pNxt->InvalidatePos();
736             }
737 		}
738 
739         // --> OD 2004-11-05 #i26945# - notify anchor.
740         // Needed for negative positioned Writer fly frames
741         if ( pFly->GetAnchorFrm()->IsTxtFrm() )
742         {
743             pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
744         }
745         // <--
746 	}
747 
748     // OD 2004-05-13 #i28701#
749     // --> OD 2005-03-21 #i45180# - no adjustment of layout process flags and
750     // further notifications/invalidations, if format is called by grow/shrink
751     if ( pFly->ConsiderObjWrapInfluenceOnObjPos() &&
752          ( !pFly->ISA(SwFlyFreeFrm) ||
753            !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) )
754     // <--
755     {
756         // --> OD 2005-09-05 #i54138# - suppress restart of the layout process
757         // on changed frame height.
758         // Note: It doesn't seem to be necessary and can cause layout loops.
759         if ( bPosChgd )
760         // <--
761         {
762             // indicate a restart of the layout process
763             pFly->SetRestartLayoutProcess( true );
764         }
765         else
766         {
767             // lock position
768             pFly->LockPosition();
769 
770             if ( !pFly->ConsiderForTextWrap() )
771             {
772                 // indicate that object has to be considered for text wrap
773                 pFly->SetConsiderForTextWrap( true );
774                 // invalidate 'background' in order to allow its 'background'
775                 // to wrap around it.
776                 pFly->NotifyBackground( pFly->GetPageFrm(),
777                                         pFly->GetObjRectWithSpaces(),
778                                         PREP_FLY_ARRIVE );
779                 // invalidate position of anchor frame in order to force
780                 // a re-format of the anchor frame, which also causes a
781                 // re-format of the invalid previous frames of the anchor frame.
782                 pFly->AnchorFrm()->InvalidatePos();
783             }
784         }
785     }
786 }
787 
788 /*************************************************************************/
789 
SwCntntNotify(SwCntntFrm * pCntntFrm)790 SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) :
791     SwFrmNotify( pCntntFrm ),
792     // OD 08.01.2004 #i11859#
793     mbChkHeightOfLastLine( false ),
794     mnHeightOfLastLine( 0L ),
795     // OD 2004-02-26 #i25029#
796     mbInvalidatePrevPrtArea( false ),
797     mbBordersJoinedWithPrev( false )
798 {
799     // OD 08.01.2004 #i11859#
800     if ( pCntntFrm->IsTxtFrm() )
801     {
802         SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm);
803         if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
804         {
805             const SwAttrSet* pSet = pTxtFrm->GetAttrSet();
806             const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
807             if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
808             {
809                 mbChkHeightOfLastLine = true;
810                 mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine();
811             }
812         }
813     }
814 }
815 
816 /*************************************************************************/
817 
~SwCntntNotify()818 SwCntntNotify::~SwCntntNotify()
819 {
820     // --> OD 2005-07-29 #i49383#
821     if ( mbFrmDeleted )
822     {
823         return;
824     }
825     // <--
826 
827 	SwCntntFrm *pCnt = GetCnt();
828 	if ( bSetCompletePaintOnInvalidate )
829 		pCnt->SetCompletePaint();
830 
831     SWRECTFN( pCnt )
832     if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) ||
833 							 pCnt->Frm().SSize() != aFrm.SSize()))
834 	{
835 		SwLayoutFrm* pCell = pCnt->GetUpper();
836 		while( !pCell->IsCellFrm() && pCell->GetUpper() )
837 			pCell = pCell->GetUpper();
838 		ASSERT( pCell->IsCellFrm(), "Where's my cell?" );
839         if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() )
840 			pCell->InvalidatePrt();	// for vertical alignment
841 	}
842 
843     // OD 2004-02-26 #i25029#
844     if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
845          pCnt->IsTxtFrm() &&
846          !pCnt->IsFollow() && !pCnt->GetIndPrev() )
847     {
848         // determine previous frame
849         SwFrm* pPrevFrm = pCnt->FindPrev();
850         // skip empty section frames and hidden text frames
851         {
852             while ( pPrevFrm &&
853                     ( ( pPrevFrm->IsSctFrm() &&
854                         !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) ||
855                       ( pPrevFrm->IsTxtFrm() &&
856                         static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) )
857             {
858                 pPrevFrm = pPrevFrm->FindPrev();
859             }
860         }
861 
862         // Invalidate printing area of found previous frame
863         if ( pPrevFrm )
864         {
865             if ( pPrevFrm->IsSctFrm() )
866             {
867                 if ( pCnt->IsInSct() )
868                 {
869                     // Note: found previous frame is a section frame and
870                     //       <pCnt> is also inside a section.
871                     //       Thus due to <mbBordersJoinedWithPrev>,
872                     //       <pCnt> had joined its borders/shadow with the
873                     //       last content of the found section.
874                     // Invalidate printing area of last content in found section.
875                     SwFrm* pLstCntntOfSctFrm =
876                             static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
877                     if ( pLstCntntOfSctFrm )
878                     {
879                         pLstCntntOfSctFrm->InvalidatePrt();
880                     }
881                 }
882             }
883             else
884             {
885                 pPrevFrm->InvalidatePrt();
886             }
887         }
888     }
889 
890     const bool bFirst = (aFrm.*fnRect->fnGetWidth)() == 0;
891 
892 	if ( pCnt->IsNoTxtFrm() )
893 	{
894 		//Aktive PlugIn's oder OLE-Objekte sollten etwas von der Veraenderung
895 		//mitbekommen, damit sie Ihr Window entsprechend verschieben.
896 		ViewShell *pSh = pCnt->getRootFrm()->GetCurrShell();
897 		if ( pSh )
898 		{
899             SwOLENode *pNd;
900 			if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) &&
901 				 (pNd->GetOLEObj().IsOleRef() ||
902 				  pNd->IsOLESizeInvalid()) )
903 			{
904                 // --> OD #i117189#
905                 const bool bNoTxtFrmPrtAreaChanged =
906                         ( aPrt.SSize().Width() != 0 &&
907                           aPrt.SSize().Height() != 0 ) &&
908                         aPrt.SSize() != pCnt->Prt().SSize();
909                 // <--
910 				ASSERT( pCnt->IsInFly(), "OLE not in FlyFrm" );
911 				SwFlyFrm *pFly = pCnt->FindFlyFrm();
912                 svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
913 				SwFEShell *pFESh = 0;
914 				ViewShell *pTmp = pSh;
915 				do
916 				{	if ( pTmp->ISA( SwCrsrShell ) )
917 					{
918 						pFESh = (SwFEShell*)pTmp;
919                         // #108369#: Here used to be the condition if (!bFirst).
920                         // I think this should mean "do not call CalcAndSetScale"
921                         // if the frame is formatted for the first time.
922                         // Unfortunately this is not valid anymore since the
923                         // SwNoTxtFrm already gets a width during CalcLowerPreps.
924                         // Nevertheless, the intention of !bFirst seemed to be
925                         // to assure that the OLE objects have already been notified
926                         // if necessary before calling CalcAndSetScale.
927                         // So I replaced !bFirst by !IsOLESizeInvalid. There is
928                         // one additional problem specific to the word import:
929                         // The layout is calculated _before_ calling PrtOLENotify,
930                         // and the OLE objects are not invalidated during import.
931                         // Therefore I added the condition !IsUpdateExpFld,
932                         // have a look at the occurrence of CalcLayout in
933                         // uiview/view.cxx.
934                         if ( !pNd->IsOLESizeInvalid() &&
935                              !pSh->GetDoc()->IsUpdateExpFld() )
936                             pFESh->CalcAndSetScale( xObj,
937                                                     &pFly->Prt(), &pFly->Frm(),
938                                                     bNoTxtFrmPrtAreaChanged );
939 					}
940 					pTmp = (ViewShell*)pTmp->GetNext();
941 				} while ( pTmp != pSh );
942 
943 				if ( pFESh && pNd->IsOLESizeInvalid() )
944 				{
945 					pNd->SetOLESizeInvalid( sal_False );
946                     //TODO/LATER: needs OnDocumentPrinterChanged
947                     //xObj->OnDocumentPrinterChanged( pNd->GetDoc()->getPrinter( false ) );
948 					pFESh->CalcAndSetScale( xObj );//Client erzeugen lassen.
949 				}
950             }
951 			//dito Animierte Grafiken
952 			if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() )
953 			{
954 				((SwNoTxtFrm*)pCnt)->StopAnimation();
955 				pSh->InvalidateWindows( Frm() );
956 			}
957 		}
958 	}
959 
960 	if ( bFirst )
961 	{
962 		pCnt->SetRetouche();	//fix(13870)
963 
964 		SwDoc *pDoc = pCnt->GetNode()->GetDoc();
965 		if ( pDoc->GetSpzFrmFmts()->Count() &&
966 			 pDoc->DoesContainAtPageObjWithContentAnchor() && !pDoc->IsNewDoc() )
967 		{
968             // If certain import filters for foreign file format import
969             // AT_PAGE anchored objects, the corresponding page number is
970             // typically not known. In this case the content position is
971             // stored at which the anchored object is found in the
972             // imported document.
973             // When this content is formatted it is the time at which
974             // the page is known. Thus, this data can be corrected now.
975 
976             const SwPageFrm* pPage = 0;
977             SwNodeIndex *pIdx = 0;
978             SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
979             for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
980             {
981                 SwFrmFmt *pFmt = (*pTbl)[i];
982                 const SwFmtAnchor &rAnch = pFmt->GetAnchor();
983                 if ( FLY_AT_PAGE != rAnch.GetAnchorId() ||
984                      rAnch.GetCntntAnchor() == 0 )
985                 {
986                     continue;
987                 }
988 
989                 if ( !pIdx )
990                 {
991                     pIdx = new SwNodeIndex( *pCnt->GetNode() );
992                 }
993                 if ( rAnch.GetCntntAnchor()->nNode == *pIdx )
994                 {
995                     ASSERT( false, "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." );
996                     if ( !pPage )
997                     {
998                         pPage = pCnt->FindPageFrm();
999                     }
1000                     SwFmtAnchor aAnch( rAnch );
1001                     aAnch.SetAnchor( 0 );
1002                     aAnch.SetPageNum( pPage->GetPhyPageNum() );
1003                     pFmt->SetFmtAttr( aAnch );
1004                     if ( RES_DRAWFRMFMT != pFmt->Which() )
1005                     {
1006                         pFmt->MakeFrms();
1007                     }
1008                 }
1009             }
1010             delete pIdx;
1011         }
1012     }
1013 
1014     // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
1015     //  if height of last line has changed.
1016     if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine )
1017     {
1018         if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() )
1019         {
1020             pCnt->InvalidateNextPrtArea();
1021         }
1022     }
1023 
1024     // --> OD 2005-03-07 #i44049#
1025     if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) )
1026     {
1027         pCnt->InvalidateObjs( true );
1028     }
1029     // <--
1030 
1031     // --> OD 2005-04-12 #i43255# - move code to invalidate at-character
1032     // anchored objects due to a change of its anchor character from
1033     // method <SwTxtFrm::Format(..)>.
1034     if ( pCnt->IsTxtFrm() )
1035     {
1036         SwTxtFrm* pMasterFrm = pCnt->IsFollow()
1037                                ? static_cast<SwTxtFrm*>(pCnt)->FindMaster()
1038                                : static_cast<SwTxtFrm*>(pCnt);
1039         if ( pMasterFrm && !pMasterFrm->IsFlyLock() &&
1040              pMasterFrm->GetDrawObjs() )
1041         {
1042             SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs();
1043             for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
1044             {
1045                 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1046                 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
1047                         == FLY_AT_CHAR )
1048                 {
1049                     pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() );
1050                 }
1051             }
1052         }
1053     }
1054     // <--
1055 }
1056 
1057 /*************************************************************************/
1058 
AppendObjs(const SwSpzFrmFmts * pTbl,sal_uLong nIndex,SwFrm * pFrm,SwPageFrm * pPage)1059 void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex,
1060 						SwFrm *pFrm, SwPageFrm *pPage )
1061 {
1062 	for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
1063 	{
1064 		SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i];
1065 		const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1066 		if ( rAnch.GetCntntAnchor() &&
1067 			 (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) )
1068 		{
1069             const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL
1070             //Wird ein Rahmen oder ein SdrObject beschrieben?
1071             const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
1072             // OD 23.06.2003 #108784# - append also drawing objects anchored
1073             // as character.
1074             const bool bDrawObjInCntnt = bSdrObj &&
1075                                          (rAnch.GetAnchorId() == FLY_AS_CHAR);
1076 
1077             if( bFlyAtFly ||
1078                 (rAnch.GetAnchorId() == FLY_AT_PARA) ||
1079                 (rAnch.GetAnchorId() == FLY_AT_CHAR) ||
1080                 bDrawObjInCntnt )
1081 			{
1082                 SdrObject* pSdrObj = 0;
1083                 if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
1084 				{
1085 					ASSERT( !bSdrObj, "DrawObject not found." );
1086 					pFmt->GetDoc()->DelFrmFmt( pFmt );
1087 					--i;
1088 					continue;
1089 				}
1090 				if ( pSdrObj )
1091 				{
1092 					if ( !pSdrObj->GetPage() )
1093                     {
1094                         pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1095 								InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
1096                     }
1097 
1098                     SwDrawContact* pNew =
1099                         static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
1100                     if ( !pNew->GetAnchorFrm() )
1101                     {
1102                         pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) );
1103                     }
1104                     // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1105                     // if necessary. But control objects have to be excluded.
1106                     else if ( !::CheckControlLayer( pSdrObj ) &&
1107                               pNew->GetAnchorFrm() != pFrm &&
1108                               !pNew->GetDrawObjectByAnchorFrm( *pFrm ) )
1109                     {
1110                         SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
1111                         pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );
1112 
1113 						// for repaint, use new ActionChanged()
1114                         // pDrawVirtObj->SendRepaintBroadcast();
1115                         pDrawVirtObj->ActionChanged();
1116                     }
1117 
1118 				}
1119 				else
1120 				{
1121 					SwFlyFrm *pFly;
1122 					if( bFlyAtFly )
1123 						pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
1124 					else
1125 						pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
1126 					pFly->Lock();
1127 					pFrm->AppendFly( pFly );
1128 					pFly->Unlock();
1129 					if ( pPage )
1130 						::RegistFlys( pPage, pFly );
1131 				}
1132 			}
1133 		}
1134 	}
1135 }
1136 
lcl_ObjConnected(SwFrmFmt * pFmt,const SwFrm * pSib)1137 bool lcl_ObjConnected( SwFrmFmt *pFmt, const SwFrm* pSib )
1138 {
1139 	SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
1140 	if ( RES_FLYFRMFMT == pFmt->Which() )
1141     {
1142         const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0;
1143         const SwFlyFrm* pTmpFrm;
1144 		for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
1145         {
1146             if(! pRoot || pRoot == pTmpFrm->getRootFrm() )
1147                 return true;
1148         }
1149     }
1150 	else
1151 	{
1152 		SwDrawContact *pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
1153 		if ( pContact )
1154             return pContact->GetAnchorFrm() != 0;
1155 	}
1156 	return false;
1157 }
1158 
1159 /** helper method to determine, if a <SwFrmFmt>, which has an object connected,
1160     is located in header or footer.
1161 
1162     OD 23.06.2003 #108784#
1163 
1164     @author OD
1165 */
lcl_InHeaderOrFooter(SwFrmFmt & _rFmt)1166 bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt )
1167 {
1168     bool bRetVal = false;
1169 
1170     const SwFmtAnchor& rAnch = _rFmt.GetAnchor();
1171 
1172     if (rAnch.GetAnchorId() != FLY_AT_PAGE)
1173     {
1174         bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode );
1175     }
1176 
1177     return bRetVal;
1178 }
1179 
AppendAllObjs(const SwSpzFrmFmts * pTbl,const SwFrm * pSib)1180 void AppendAllObjs( const SwSpzFrmFmts *pTbl, const SwFrm* pSib )
1181 {
1182 	//Verbinden aller Objekte, die in der SpzTbl beschrieben sind mit dem
1183 	//Layout.
1184 	//Wenn sich nichts mehr tut hoeren wir auf. Dann koennen noch Formate
1185 	//uebrigbleiben, weil wir weder zeichengebundene Rahmen verbinden noch
1186 	//Objekte die in zeichengebundenen verankert sind.
1187 
1188 	SwSpzFrmFmts aCpy( 255, 255 );
1189 	aCpy.Insert( pTbl, 0 );
1190 
1191 	sal_uInt16 nOldCnt = USHRT_MAX;
1192 
1193 	while ( aCpy.Count() && aCpy.Count() != nOldCnt )
1194 	{
1195 		nOldCnt = aCpy.Count();
1196 		for ( int i = 0; i < int(aCpy.Count()); ++i )
1197 		{
1198 			SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ sal_uInt16(i) ];
1199 			const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1200 			sal_Bool bRemove = sal_False;
1201             if ((rAnch.GetAnchorId() == FLY_AT_PAGE) ||
1202                 (rAnch.GetAnchorId() == FLY_AS_CHAR))
1203             {
1204 				//Seitengebunde sind bereits verankert, zeichengebundene
1205 				//will ich hier nicht.
1206 				bRemove = sal_True;
1207             }
1208             else if ( sal_False == (bRemove = ::lcl_ObjConnected( pFmt, pSib )) ||
1209                       ::lcl_InHeaderOrFooter( *pFmt ) )
1210 			{
1211             // OD 23.06.2003 #108784# - correction: for objects in header
1212             // or footer create frames, in spite of the fact that an connected
1213             // objects already exists.
1214 				//Fuer Flys und DrawObjs nur dann ein MakeFrms rufen wenn noch
1215 				//keine abhaengigen Existieren, andernfalls, oder wenn das
1216 				//MakeFrms keine abhaengigen erzeugt, entfernen.
1217 				pFmt->MakeFrms();
1218 				bRemove = ::lcl_ObjConnected( pFmt, pSib );
1219 			}
1220 			if ( bRemove )
1221 			{
1222 				aCpy.Remove( sal_uInt16(i) );
1223 				--i;
1224 			}
1225 		}
1226 	}
1227 	aCpy.Remove( 0, aCpy.Count() );
1228 }
1229 
1230 /** local method to set 'working' position for newly inserted frames
1231 
1232     OD 12.08.2003 #i17969#
1233 
1234     @author OD
1235 */
lcl_SetPos(SwFrm & _rNewFrm,const SwLayoutFrm & _rLayFrm)1236 void lcl_SetPos( SwFrm&             _rNewFrm,
1237                  const SwLayoutFrm& _rLayFrm )
1238 {
1239     SWRECTFN( (&_rLayFrm) )
1240     (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() );
1241     // move position by one SwTwip in text flow direction in order to get
1242     // notifications for a new calculated position after its formatting.
1243     if ( bVert )
1244         _rNewFrm.Frm().Pos().X() -= 1;
1245     else
1246         _rNewFrm.Frm().Pos().Y() += 1;
1247 }
1248 
_InsertCnt(SwLayoutFrm * pLay,SwDoc * pDoc,sal_uLong nIndex,sal_Bool bPages,sal_uLong nEndIndex,SwFrm * pPrv)1249 void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc,
1250 							 sal_uLong nIndex, sal_Bool bPages, sal_uLong nEndIndex,
1251 							 SwFrm *pPrv )
1252 {
1253 	pDoc->BlockIdling();
1254 	SwRootFrm* pLayout = pLay->getRootFrm();
1255     const sal_Bool bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False;
1256 	if( bOldCallbackActionEnabled )
1257         pLayout->SetCallbackActionEnabled( sal_False );
1258 
1259 	//Bei der Erzeugung des Layouts wird bPages mit sal_True uebergeben. Dann
1260 	//werden schon mal alle x Absaetze neue Seiten angelegt. Bei umbruechen
1261 	//und/oder Pagedescriptorwechseln werden gleich die entsprechenden Seiten
1262 	//angelegt.
1263 	//Vorteil ist, das einerseits schon eine annaehernd realistische Zahl von
1264 	//Seiten angelegt wird, vor allem aber gibt es nicht mehr eine schier
1265 	//lange Kette von Absaetzen teuer verschoben werden muss, bis sie sich auf
1266 	//ertraegliches mass reduziert hat.
1267 	//Wir gehen mal davon aus, da? 20 Absaetze auf eine Seite passen
1268 	//Damit es in extremen Faellen nicht gar so heftig rechnen wir je nach
1269 	//Node noch etwas drauf.
1270 	//Wenn in der DocStatistik eine brauchbare Seitenzahl angegeben ist
1271 	//(wird beim Schreiben gepflegt), so wird von dieser Seitenanzahl
1272 	//ausgegengen.
1273 	const sal_Bool bStartPercent = bPages && !nEndIndex;
1274 
1275 	SwPageFrm *pPage = pLay->FindPageFrm();
1276 	const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1277 	SwFrm		*pFrm = 0;
1278 	sal_Bool   bBreakAfter	 = sal_False;
1279 
1280     SwActualSection *pActualSection = 0;
1281     SwLayHelper *pPageMaker;
1282 
1283     //Wenn das Layout erzeugt wird (bPages == sal_True) steuern wir den Progress
1284 	//an. Flys und DrawObjekte werden dann nicht gleich verbunden, dies
1285 	//passiert erst am Ende der Funktion.
1286     if ( bPages )
1287     {
1288         // Attention: the SwLayHelper class uses references to the content-,
1289         // page-, layout-frame etc. and may change them!
1290         pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay,
1291                 pActualSection, bBreakAfter, nIndex, 0 == nEndIndex );
1292         if( bStartPercent )
1293         {
1294             const sal_uLong nPageCount = pPageMaker->CalcPageCount();
1295             if( nPageCount )
1296                 bObjsDirect = sal_False;
1297         }
1298 	}
1299     else
1300         pPageMaker = NULL;
1301 
1302     if( pLay->IsInSct() &&
1303 		( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hierdurch werden Frischlinge
1304 			// abgefangen, deren Flags noch nicht ermittelt werden koennen,
1305 			// so z.B. beim Einfuegen einer Tabelle
1306 	{
1307 		SwSectionFrm* pSct = pLay->FindSctFrm();
1308 		// Wenn Inhalt in eine Fussnote eingefuegt wird, die in einem spaltigen
1309 		// Bereich liegt, so darf der spaltige Bereich nicht aufgebrochen werden.
1310 		// Nur wenn im Innern der Fussnote ein Bereich liegt, ist dies ein
1311 		// Kandidat fuer pActualSection.
1312 		// Gleiches gilt fuer Bereiche in Tabellen, wenn innerhalb einer Tabelle
1313 		// eingefuegt wird, duerfen nur Bereiche, die ebenfalls im Innern liegen,
1314 		// aufgebrochen werden.
1315 		if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) &&
1316 			( !pLay->IsInTab() || pSct->IsInTab() ) )
1317 		{
1318 			pActualSection = new SwActualSection( 0, pSct, 0 );
1319 			ASSERT( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(),
1320 				"_InsertCnt: Wrong Call" );
1321 		}
1322 	}
1323 
1324     //If a section is "open", the pActualSection points to an SwActualSection.
1325     //If the page breaks, for "open" sections a follow will created.
1326     //For nested sections (which have, however, not a nested layout),
1327     //the SwActualSection class has a member, which points to an upper(section).
1328     //When the "inner" section finishs, the upper will used instead.
1329 
1330 	while( sal_True )
1331 	{
1332 		SwNode *pNd = pDoc->GetNodes()[nIndex];
1333 		if ( pNd->IsCntntNode() )
1334 		{
1335 			SwCntntNode* pNode = (SwCntntNode*)pNd;
1336 			pFrm = pNode->IsTxtNode() ? new SwTxtFrm( (SwTxtNode*)pNode, pLay ) :
1337 										pNode->MakeFrm( pLay );
1338             if( pPageMaker )
1339                 pPageMaker->CheckInsert( nIndex );
1340 
1341             pFrm->InsertBehind( pLay, pPrv );
1342             // --> OD 2005-12-01 #i27138#
1343             // notify accessibility paragraphs objects about changed
1344             // CONTENT_FLOWS_FROM/_TO relation.
1345             // Relation CONTENT_FLOWS_FROM for next paragraph will change
1346             // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1347             if ( pFrm->IsTxtFrm() )
1348             {
1349                 ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1350                 // no notification, if <ViewShell> is in construction
1351                 if ( pViewShell && !pViewShell->IsInConstructor() &&
1352                      pViewShell->GetLayout() &&
1353                      pViewShell->GetLayout()->IsAnyShellAccessible() )
1354                 {
1355                     pViewShell->InvalidateAccessibleParaFlowRelation(
1356                         dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1357                         dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1358                     // --> OD 2006-08-28 #i68958#
1359                     // The information flags of the text frame are validated
1360                     // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1361                     // The information flags have to be invalidated, because
1362                     // it is possible, that the one of its upper frames
1363                     // isn't inserted into the layout.
1364                     pFrm->InvalidateInfFlags();
1365                     // <--
1366                 }
1367             }
1368             // <--
1369             // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1370             // for setting position at newly inserted frame
1371             lcl_SetPos( *pFrm, *pLay );
1372 			pPrv = pFrm;
1373 
1374 			if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
1375 				AppendObjs( pTbl, nIndex, pFrm, pPage );
1376 		}
1377 		else if ( pNd->IsTableNode() )
1378 		{	//Sollten wir auf eine Tabelle gestossen sein?
1379 			SwTableNode *pTblNode = (SwTableNode*)pNd;
1380 
1381             // #108116# loading may produce table structures that GCLines
1382             // needs to clean up. To keep table formulas correct, change
1383             // all table formulas to internal (BOXPTR) representation.
1384             SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() );
1385             aMsgHnt.eFlags = TBL_BOXPTR;
1386             pDoc->UpdateTblFlds( &aMsgHnt );
1387             pTblNode->GetTable().GCLines();
1388 
1389 			pFrm = pTblNode->MakeFrm( pLay );
1390 
1391             if( pPageMaker )
1392                 pPageMaker->CheckInsert( nIndex );
1393 
1394 			pFrm->InsertBehind( pLay, pPrv );
1395             // --> OD 2005-12-01 #i27138#
1396             // notify accessibility paragraphs objects about changed
1397             // CONTENT_FLOWS_FROM/_TO relation.
1398             // Relation CONTENT_FLOWS_FROM for next paragraph will change
1399             // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1400             {
1401                 ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1402                 // no notification, if <ViewShell> is in construction
1403                 if ( pViewShell && !pViewShell->IsInConstructor() &&
1404                      pViewShell->GetLayout() &&
1405                      pViewShell->GetLayout()->IsAnyShellAccessible() )
1406                 {
1407                     pViewShell->InvalidateAccessibleParaFlowRelation(
1408                             dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1409                             dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1410                 }
1411             }
1412             // <--
1413             if ( bObjsDirect && pTbl->Count() )
1414 				((SwTabFrm*)pFrm)->RegistFlys();
1415             // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1416             // for setting position at newly inserted frame
1417             lcl_SetPos( *pFrm, *pLay );
1418 
1419             pPrv = pFrm;
1420 			//Index auf den Endnode der Tabellensection setzen.
1421 			nIndex = pTblNode->EndOfSectionIndex();
1422 
1423             SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm;
1424             while ( pTmpFrm )
1425             {
1426                 pTmpFrm->CheckDirChange();
1427                 pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL;
1428             }
1429 
1430 		}
1431 		else if ( pNd->IsSectionNode() )
1432 		{
1433 			SwSectionNode *pNode = (SwSectionNode*)pNd;
1434 			if( pNode->GetSection().CalcHiddenFlag() )
1435 				// ist versteckt, ueberspringe den Bereich
1436 				nIndex = pNode->EndOfSectionIndex();
1437 			else
1438 			{
1439                 pFrm = pNode->MakeFrm( pLay );
1440 				pActualSection = new SwActualSection( pActualSection,
1441 												(SwSectionFrm*)pFrm, pNode );
1442 				if ( pActualSection->GetUpper() )
1443 				{
1444 					//Hinter den Upper einsetzen, beim EndNode wird der "Follow"
1445 					//des Uppers erzeugt.
1446 					SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm();
1447 					pFrm->InsertBehind( pTmp->GetUpper(), pTmp );
1448                     // OD 25.03.2003 #108339# - direct initialization of section
1449                     // after insertion in the layout
1450                     static_cast<SwSectionFrm*>(pFrm)->Init();
1451 				}
1452 				else
1453 				{
1454 					pFrm->InsertBehind( pLay, pPrv );
1455                     // OD 25.03.2003 #108339# - direct initialization of section
1456                     // after insertion in the layout
1457                     static_cast<SwSectionFrm*>(pFrm)->Init();
1458 
1459                     // --> FME 2004-09-08 #i33963#
1460                     // Do not trust the IsInFtn flag. If we are currently
1461                     // building up a table, the upper of pPrv may be a cell
1462                     // frame, but the cell frame does not have an upper yet.
1463                     if( pPrv && 0 != pPrv->ImplFindFtnFrm() )
1464                     // <--
1465                     {
1466 						if( pPrv->IsSctFrm() )
1467 							pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt();
1468 						if( pPrv && pPrv->IsTxtFrm() )
1469 							((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, sal_False );
1470 					}
1471 				}
1472                 // --> OD 2005-12-01 #i27138#
1473                 // notify accessibility paragraphs objects about changed
1474                 // CONTENT_FLOWS_FROM/_TO relation.
1475                 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1476                 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1477                 {
1478                     ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1479                     // no notification, if <ViewShell> is in construction
1480                     if ( pViewShell && !pViewShell->IsInConstructor() &&
1481                          pViewShell->GetLayout() &&
1482                          pViewShell->GetLayout()->IsAnyShellAccessible() )
1483                     {
1484                         pViewShell->InvalidateAccessibleParaFlowRelation(
1485                             dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1486                             dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1487                     }
1488                 }
1489                 // <--
1490                 pFrm->CheckDirChange();
1491 
1492                 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1493                 // for setting position at newly inserted frame
1494                 lcl_SetPos( *pFrm, *pLay );
1495 
1496                 // OD 20.11.2002 #105405# - no page, no invalidate.
1497                 if ( pPage )
1498                 {
1499                     // OD 18.09.2002 #100522#
1500                     // invalidate page in order to force format and paint of
1501                     // inserted section frame
1502                     pFrm->InvalidatePage( pPage );
1503 
1504                     // FME 10.11.2003 #112243#
1505                     // Invalidate fly content flag:
1506                     if ( pFrm->IsInFly() )
1507                         pPage->InvalidateFlyCntnt();
1508 
1509                     // OD 14.11.2002 #104684# - invalidate page content in order to
1510                     // force format and paint of section content.
1511                     pPage->InvalidateCntnt();
1512                 }
1513 
1514 				pLay = (SwLayoutFrm*)pFrm;
1515 				if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1516 					pLay = pLay->GetNextLayoutLeaf();
1517 				pPrv = 0;
1518 			}
1519 		}
1520         else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
1521 		{
1522 			ASSERT( pActualSection, "Sectionende ohne Anfang?" );
1523             ASSERT( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(),
1524 							"Sectionende mit falschen Start Node?" );
1525 
1526 			//Section schliessen, ggf. die umgebende Section wieder
1527 			//aktivieren.
1528 			SwActualSection *pTmp = pActualSection->GetUpper();
1529 			delete pActualSection;
1530 			pLay = pLay->FindSctFrm();
1531 			if ( 0 != (pActualSection = pTmp) )
1532 			{
1533 				//Koennte noch sein, das der letzte SectionFrm leer geblieben
1534 				//ist. Dann ist es jetzt an der Zeit ihn zu entfernen.
1535 				if ( !pLay->ContainsCntnt() )
1536 				{
1537                     SwFrm *pTmpFrm = pLay;
1538                     pLay = pTmpFrm->GetUpper();
1539                     pPrv = pTmpFrm->GetPrev();
1540                     pTmpFrm->Remove();
1541                     delete pTmpFrm;
1542 				}
1543 				else
1544 				{
1545 					pPrv = pLay;
1546 					pLay = pLay->GetUpper();
1547 				}
1548 
1549                 // new section frame
1550                 pFrm = pActualSection->GetSectionNode()->MakeFrm( pLay );
1551                 pFrm->InsertBehind( pLay, pPrv );
1552                 static_cast<SwSectionFrm*>(pFrm)->Init();
1553 
1554                 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1555                 // for setting position at newly inserted frame
1556                 lcl_SetPos( *pFrm, *pLay );
1557 
1558                 SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm();
1559 
1560                 // a follow has to be appended to the new section frame
1561                 SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow();
1562                 if ( pFollow )
1563                 {
1564                     pOuterSectionFrm->SetFollow( NULL );
1565                     pOuterSectionFrm->InvalidateSize();
1566                     ((SwSectionFrm*)pFrm)->SetFollow( pFollow );
1567                 }
1568 
1569 				// Wir wollen keine leeren Teile zuruecklassen
1570                 if( ! pOuterSectionFrm->IsColLocked() &&
1571                     ! pOuterSectionFrm->ContainsCntnt() )
1572 				{
1573                     pOuterSectionFrm->DelEmpty( sal_True );
1574                     delete pOuterSectionFrm;
1575 				}
1576 				pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm );
1577 
1578 				pLay = (SwLayoutFrm*)pFrm;
1579 				if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1580 					pLay = pLay->GetNextLayoutLeaf();
1581 				pPrv = 0;
1582 			}
1583 			else
1584 			{
1585 				//Nix mehr mit Sections, es geht direkt hinter dem SectionFrame
1586 				//weiter.
1587 				pPrv = pLay;
1588 				pLay = pLay->GetUpper();
1589 			}
1590 		}
1591 		else if( pNd->IsStartNode() &&
1592 				 SwFlyStartNode	== ((SwStartNode*)pNd)->GetStartNodeType() )
1593 		{
1594 			if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
1595 			{
1596 				SwFlyFrm* pFly = pLay->FindFlyFrm();
1597 				if( pFly )
1598 					AppendObjs( pTbl, nIndex, pFly, pPage );
1599 			}
1600 		}
1601 		else
1602 			// Weder Cntnt noch Tabelle noch Section,
1603 			// also muessen wir fertig sein.
1604 			break;
1605 
1606 		++nIndex;
1607 		// Der Endnode wird nicht mehr mitgenommen, es muss vom
1608 		// Aufrufenden (Section/MakeFrms()) sichergestellt sein, dass das Ende
1609 		// des Bereichs vor dem EndIndex liegt!
1610 		if ( nEndIndex && nIndex >= nEndIndex )
1611 			break;
1612 	}
1613 
1614 	if ( pActualSection )
1615 	{
1616 		//Kann passieren, dass noch eine leere (Follow-)Section uebrig geblieben ist.
1617 		if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() )
1618 		{
1619 			pLay->Remove();
1620 			delete pLay;
1621 		}
1622 		delete pActualSection;
1623 	}
1624 
1625 	if ( bPages )		//Jetzt noch die Flys verbinden lassen.
1626 	{
1627 		if ( !bDontCreateObjects )
1628 			AppendAllObjs( pTbl, pLayout );
1629 		bObjsDirect = sal_True;
1630 	}
1631 
1632     if( pPageMaker )
1633     {
1634         pPageMaker->CheckFlyCache( pPage );
1635         delete pPageMaker;
1636         if( pDoc->GetLayoutCache() )
1637         {
1638 #ifdef DBG_UTIL
1639 #if OSL_DEBUG_LEVEL > 1
1640             pDoc->GetLayoutCache()->CompareLayout( *pDoc );
1641 #endif
1642 #endif
1643             pDoc->GetLayoutCache()->ClearImpl();
1644         }
1645     }
1646 
1647     pDoc->UnblockIdling();
1648 	if( bOldCallbackActionEnabled )
1649         pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
1650 }
1651 
1652 
MakeFrms(SwDoc * pDoc,const SwNodeIndex & rSttIdx,const SwNodeIndex & rEndIdx)1653 void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
1654 			   const SwNodeIndex &rEndIdx )
1655 {
1656     bObjsDirect = sal_False;
1657 
1658 	SwNodeIndex aTmp( rSttIdx );
1659 	sal_uLong nEndIdx = rEndIdx.GetIndex();
1660     SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp,
1661 											pDoc->GetNodes()[ nEndIdx-1 ]);
1662 	if ( pNd )
1663 	{
1664 		sal_Bool bApres = aTmp < rSttIdx;
1665 		SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
1666 		SwFrm* pFrm;
1667 		while( 0 != (pFrm = aNode2Layout.NextFrm()) )
1668 		{
1669 			SwLayoutFrm *pUpper = pFrm->GetUpper();
1670 			SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm();
1671 			sal_Bool bOldLock, bOldFtn;
1672 			if( pFtnFrm )
1673 			{
1674 				bOldFtn = pFtnFrm->IsColLocked();
1675 				pFtnFrm->ColLock();
1676 			}
1677 			else
1678 				bOldFtn = sal_True;
1679 			SwSectionFrm* pSct = pUpper->FindSctFrm();
1680 			// Es sind innerhalb von Fussnoten nur die Bereiche interessant,
1681 			// die in den Fussnoten liegen, nicht etwa die (spaltigen) Bereiche,
1682 			// in denen die Fussnoten(Container) liegen.
1683             // #109767# Table frame is in section, insert section in cell frame.
1684 			if( pSct && ((pFtnFrm && !pSct->IsInFtn()) || pUpper->IsCellFrm()) )
1685 				pSct = NULL;
1686 			if( pSct )
1687 			{   // damit der SectionFrm nicht zerstoert wird durch pTmp->MoveFwd()
1688 				bOldLock = pSct->IsColLocked();
1689 				pSct->ColLock();
1690 			}
1691 			else
1692 				bOldLock = sal_True;
1693 
1694             // Wenn pFrm sich nicht bewegen kann, koennen wir auch niemanden
1695 			// auf die naechste Seite schieben. Innerhalb eines Rahmens auch
1696 			// nicht ( in der 1. Spalte eines Rahmens waere pFrm Moveable()! )
1697 			// Auch in spaltigen Bereichen in Tabellen waere pFrm Moveable.
1698             sal_Bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
1699             sal_Bool bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() &&
1700                  (!pFrm->IsInTab() || pFrm->IsTabFrm() );
1701             if ( bMoveNext && bAllowMove )
1702 			{
1703 				SwFrm *pMove = pFrm;
1704 				SwFrm *pPrev = pFrm->GetPrev();
1705 				SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove );
1706 				ASSERT( pTmp, "Missing FlowFrm" );
1707 
1708 				if ( bApres )
1709 				{
1710 					// Wir wollen, dass der Rest der Seite leer ist, d.h.
1711 					// der naechste muss auf die naechste Seite wandern.
1712 					// Dieser kann auch in der naechsten Spalte stehen!
1713 					ASSERT( !pTmp->HasFollow(), "Follows forbidden" );
1714 					pPrev = pFrm;
1715 					// Wenn unser umgebender SectionFrm einen Next besitzt,
1716 					// so soll dieser ebenfalls gemoved werden!
1717 					pMove = pFrm->GetIndNext();
1718 					SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm();
1719 					if( pCol )
1720 						pCol = (SwColumnFrm*)pCol->GetNext();
1721 					do
1722 					{
1723 						if( pCol && !pMove )
1724 						{   // Bisher haben wir keinen Nachfolger gefunden
1725 							// jetzt gucken wir in die naechste Spalte
1726 							pMove = pCol->ContainsAny();
1727 							if( pCol->GetNext() )
1728 								pCol = (SwColumnFrm*)pCol->GetNext();
1729 							else if( pCol->IsInSct() )
1730 							{   // Wenn es keine naechste Spalte gibt, wir aber
1731 								// innerhalb eines spaltigen Bereichs sind,
1732 								// koennte es noch ausserhalb des Bereich
1733 								// (Seiten-)Spalten geben
1734 								pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm();
1735 								if( pCol )
1736 									pCol = (SwColumnFrm*)pCol->GetNext();
1737 							}
1738 							else
1739 								pCol = NULL;
1740 						}
1741 						// Falls hier verschrottete SectionFrms herumgammeln,
1742 						// muessen diese uebersprungen werden.
1743 						while( pMove && pMove->IsSctFrm() &&
1744 							   !((SwSectionFrm*)pMove)->GetSection() )
1745 							pMove = pMove->GetNext();
1746 					} while( !pMove && pCol );
1747 
1748 					if( pMove )
1749 					{
1750 						if ( pMove->IsCntntFrm() )
1751 							pTmp = (SwCntntFrm*)pMove;
1752 						else if ( pMove->IsTabFrm() )
1753 							pTmp = (SwTabFrm*)pMove;
1754 						else if ( pMove->IsSctFrm() )
1755 						{
1756 							pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1757 							if( pMove )
1758 								pTmp = SwFlowFrm::CastFlowFrm( pMove );
1759 							else
1760 								pTmp = NULL;
1761 						}
1762 					}
1763 					else
1764 						pTmp = 0;
1765 				}
1766 				else
1767 				{
1768 					ASSERT( !pTmp->IsFollow(), "Follows really forbidden" );
1769 					// Bei Bereichen muss natuerlich der Inhalt auf die Reise
1770 					// geschickt werden.
1771 					if( pMove->IsSctFrm() )
1772 					{
1773 						while( pMove && pMove->IsSctFrm() &&
1774 							   !((SwSectionFrm*)pMove)->GetSection() )
1775 							pMove = pMove->GetNext();
1776 						if( pMove && pMove->IsSctFrm() )
1777 							pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1778 						if( pMove )
1779 							pTmp = SwFlowFrm::CastFlowFrm( pMove );
1780 						else
1781 							pTmp = NULL;
1782 					}
1783 				}
1784 
1785 				if( pTmp )
1786 				{
1787 					SwFrm* pOldUp = pTmp->GetFrm()->GetUpper();
1788 					// MoveFwd==sal_True bedeutet, dass wir auf der gleichen
1789 					// Seite geblieben sind, wir wollen aber die Seite wechseln,
1790 					// sofern dies moeglich ist
1791                     sal_Bool bTmpOldLock = pTmp->IsJoinLocked();
1792 					pTmp->LockJoin();
1793 					while( pTmp->MoveFwd( sal_True, sal_False, sal_True ) )
1794 					{
1795 						if( pOldUp == pTmp->GetFrm()->GetUpper() )
1796 							break;
1797 						pOldUp = pTmp->GetFrm()->GetUpper();
1798 					}
1799                     if( !bTmpOldLock )
1800 						pTmp->UnlockJoin();
1801 				}
1802 				::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(),
1803 							  pFrm->IsInDocBody(), nEndIdx, pPrev );
1804 			}
1805 			else
1806 			{
1807 				sal_Bool bSplit;
1808 				SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev();
1809 				// Wenn in einen SectionFrm ein anderer eingefuegt wird,
1810 				// muss dieser aufgebrochen werden
1811 				if( pSct && rSttIdx.GetNode().IsSectionNode() )
1812 				{
1813 					bSplit = pSct->SplitSect( pFrm, bApres );
1814 					// Wenn pSct nicht aufgespalten werden konnte
1815 					if( !bSplit && !bApres )
1816 					{
1817 						pUpper = pSct->GetUpper();
1818 						pPrv = pSct->GetPrev();
1819 					}
1820 				}
1821 				else
1822 					bSplit = sal_False;
1823                 ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), sal_False,
1824                               nEndIdx, pPrv );
1825                 // OD 23.06.2003 #108784# - correction: append objects doesn't
1826                 // depend on value of <bAllowMove>
1827                 if( !bDontCreateObjects )
1828                 {
1829                     const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1830                     if( pTbl->Count() )
1831                         AppendAllObjs( pTbl, pUpper );
1832                 }
1833 
1834 				// Wenn nichts eingefuegt wurde, z.B. ein ausgeblendeter Bereich,
1835 				// muss das Splitten rueckgaengig gemacht werden
1836 				if( bSplit && pSct && pSct->GetNext()
1837 					&& pSct->GetNext()->IsSctFrm() )
1838 					pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() );
1839 				if( pFrm->IsInFly() )
1840 					pFrm->FindFlyFrm()->_Invalidate();
1841 				if( pFrm->IsInTab() )
1842 					pFrm->InvalidateSize();
1843 			}
1844 
1845 			SwPageFrm *pPage = pUpper->FindPageFrm();
1846 			SwFrm::CheckPageDescs( pPage, sal_False );
1847 			if( !bOldFtn )
1848 				pFtnFrm->ColUnlock();
1849 			if( !bOldLock )
1850 			{
1851 				pSct->ColUnlock();
1852 				// Zum Beispiel beim Einfuegen von gelinkten Bereichen,
1853 				// die wiederum Bereiche enthalten, kann pSct jetzt leer sein
1854 				// und damit ruhig zerstoert werden.
1855 				if( !pSct->ContainsCntnt() )
1856 				{
1857 					pSct->DelEmpty( sal_True );
1858 					pUpper->getRootFrm()->RemoveFromList( pSct );
1859 					delete pSct;
1860 				}
1861 			}
1862 		}
1863 	}
1864 
1865     bObjsDirect = sal_True;
1866 }
1867 
1868 
1869 /*************************************************************************/
1870 
SwBorderAttrs(const SwModify * pMod,const SwFrm * pConstructor)1871 SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) :
1872 	SwCacheObj( pMod ),
1873 	rAttrSet( pConstructor->IsCntntFrm()
1874 					? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet()
1875 					: ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ),
1876 	rUL 	( rAttrSet.GetULSpace() ),
1877     // --> OD 2008-12-04 #i96772#
1878     // LRSpaceItem is copied due to the possibility that it is adjusted - see below
1879     rLR     ( rAttrSet.GetLRSpace() ),
1880     // <--
1881 	rBox	( rAttrSet.GetBox() 	),
1882 	rShadow ( rAttrSet.GetShadow()	),
1883 	aFrmSize( rAttrSet.GetFrmSize().GetSize() )
1884 {
1885     // --> OD 2008-12-02 #i96772#
1886     const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor);
1887     if ( pTxtFrm )
1888     {
1889         pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR );
1890     }
1891 
1892 	//Achtung: Die USHORTs fuer die gecache'ten Werte werden absichtlich
1893 	//nicht initialisiert!
1894 
1895 	//Muessen alle einmal berechnet werden:
1896 	bTopLine = bBottomLine = bLeftLine = bRightLine =
1897     bTop     = bBottom     = bLine   = sal_True;
1898 
1899 	bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = sal_False;
1900     // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev>
1901     // and <bJoinedWithNext>, which aren't initialized by default.
1902     bCachedJoinedWithPrev = sal_False;
1903     bCachedJoinedWithNext = sal_False;
1904 
1905 	bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL));
1906 }
1907 
~SwBorderAttrs()1908 SwBorderAttrs::~SwBorderAttrs()
1909 {
1910 	((SwModify*)pOwner)->SetInCache( sal_False );
1911 }
1912 
1913 /*************************************************************************
1914 |*
1915 |*	SwBorderAttrs::CalcTop(), CalcBottom(), CalcLeft(), CalcRight()
1916 |*
1917 |*	Beschreibung		Die Calc-Methoden errechnen zusaetzlich zu den
1918 |*		von den Attributen vorgegebenen Groessen einen Sicherheitsabstand.
1919 |*		der Sicherheitsabstand wird nur einkalkuliert, wenn Umrandung und/oder
1920 |*		Schatten im Spiel sind; er soll vermeiden, dass aufgrund der
1921 |*		groben physikalischen Gegebenheiten Raender usw. uebermalt werden.
1922 |*
1923 |*************************************************************************/
1924 
_CalcTop()1925 void SwBorderAttrs::_CalcTop()
1926 {
1927 	nTop = CalcTopLine() + rUL.GetUpper();
1928 	bTop = sal_False;
1929 }
1930 
_CalcBottom()1931 void SwBorderAttrs::_CalcBottom()
1932 {
1933 	nBottom = CalcBottomLine() + rUL.GetLower();
1934 	bBottom = sal_False;
1935 }
1936 
CalcRight(const SwFrm * pCaller) const1937 long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const
1938 {
1939     long nRight;
1940 
1941     // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
1942     // and right border are painted on the right respectively left.
1943     if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
1944         nRight = CalcLeftLine();
1945     else
1946         nRight = CalcRightLine();
1947 
1948     // for paragraphs, "left" is "before text" and "right" is "after text"
1949     if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1950         nRight += rLR.GetLeft();
1951     else
1952         nRight += rLR.GetRight();
1953 
1954     // --> OD 2008-01-21 #newlistlevelattrs#
1955     // correction: retrieve left margin for numbering in R2L-layout
1956     if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1957     {
1958         nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
1959     }
1960     // <--
1961 
1962     return nRight;
1963 }
1964 
CalcLeft(const SwFrm * pCaller) const1965 long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const
1966 {
1967     long nLeft;
1968 
1969     // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
1970     // and right border are painted on the right respectively left.
1971     if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
1972         nLeft = CalcRightLine();
1973     else
1974         nLeft = CalcLeftLine();
1975 
1976     // for paragraphs, "left" is "before text" and "right" is "after text"
1977     if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1978         nLeft += rLR.GetRight();
1979     else
1980         nLeft += rLR.GetLeft();
1981 
1982     // --> OD 2008-01-21 #newlistlevelattrs#
1983     // correction: do not retrieve left margin for numbering in R2L-layout
1984 //    if ( pCaller->IsTxtFrm() )
1985     if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() )
1986     // <--
1987     {
1988         nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
1989     }
1990 
1991     return nLeft;
1992 }
1993 
1994 /*************************************************************************
1995 |*
1996 |*	SwBorderAttrs::CalcTopLine(), CalcBottomLine(),
1997 |*				   CalcLeftLine(), CalcRightLine()
1998 |*
1999 |*	Beschreibung		Berechnung der Groessen fuer Umrandung und Schatten.
2000 |* 						Es kann auch ohne Linien ein Abstand erwuenscht sein,
2001 |* 						dieser wird dann nicht vom Attribut sondern hier
2002 |* 						beruecksichtigt (bBorderDist, z.B. fuer Zellen).
2003 |*
2004 |*************************************************************************/
2005 
_CalcTopLine()2006 void SwBorderAttrs::_CalcTopLine()
2007 {
2008 	nTopLine = (bBorderDist && !rBox.GetTop())
2009 							? rBox.GetDistance  (BOX_LINE_TOP)
2010 							: rBox.CalcLineSpace(BOX_LINE_TOP);
2011 	nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP);
2012 	bTopLine = sal_False;
2013 }
2014 
_CalcBottomLine()2015 void SwBorderAttrs::_CalcBottomLine()
2016 {
2017 	nBottomLine = (bBorderDist && !rBox.GetBottom())
2018 							? rBox.GetDistance  (BOX_LINE_BOTTOM)
2019 							: rBox.CalcLineSpace(BOX_LINE_BOTTOM);
2020 	nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM);
2021 	bBottomLine = sal_False;
2022 }
2023 
_CalcLeftLine()2024 void SwBorderAttrs::_CalcLeftLine()
2025 {
2026 	nLeftLine = (bBorderDist && !rBox.GetLeft())
2027 							? rBox.GetDistance  (BOX_LINE_LEFT)
2028 							: rBox.CalcLineSpace(BOX_LINE_LEFT);
2029 	nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT);
2030 	bLeftLine = sal_False;
2031 }
2032 
_CalcRightLine()2033 void SwBorderAttrs::_CalcRightLine()
2034 {
2035 	nRightLine = (bBorderDist && !rBox.GetRight())
2036 							? rBox.GetDistance  (BOX_LINE_RIGHT)
2037 							: rBox.CalcLineSpace(BOX_LINE_RIGHT);
2038 	nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT);
2039 	bRightLine = sal_False;
2040 }
2041 
2042 /*************************************************************************/
2043 
_IsLine()2044 void SwBorderAttrs::_IsLine()
2045 {
2046 	bIsLine = rBox.GetTop() || rBox.GetBottom() ||
2047 			  rBox.GetLeft()|| rBox.GetRight();
2048 	bLine = sal_False;
2049 }
2050 
2051 /*************************************************************************
2052 |*
2053 |*	SwBorderAttrs::CmpLeftRightLine(), IsTopLine(), IsBottomLine()
2054 |*
2055 |*		Die Umrandungen benachbarter Absaetze werden nach folgendem
2056 |*		Algorithmus zusammengefasst:
2057 |*
2058 |*		1. Die Umrandung oben faellt weg, wenn der Vorgaenger dieselbe
2059 |*		   Umrandung oben aufweist und 3. Zutrifft.
2060 |*		   Zusaetzlich muss der Absatz mindestens rechts oder links oder
2061 |*		   unten eine Umrandung haben.
2062 |*		2. Die Umrandung unten faellt weg, wenn der Nachfolger dieselbe
2063 |*		   Umrandung unten aufweist und 3. zutrifft.
2064 |*		   Zusaetzlich muss der Absatz mindestens rechts oder links oder
2065 |*		   oben eine Umrandung haben.
2066 |*		3. Die Umrandungen links und rechts vor Vorgaenger bzw. Nachfolger
2067 |*		   sind identisch.
2068 |*
2069 |*************************************************************************/
CmpLines(const SvxBorderLine * pL1,const SvxBorderLine * pL2)2070 inline int CmpLines( const SvxBorderLine *pL1, const SvxBorderLine *pL2 )
2071 {
2072 	return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
2073 }
2074 
2075 // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
2076 // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
2077 //          instead of only the right LR-spacing, because R2L-layout has to be
2078 //          considered.
CmpLeftRight(const SwBorderAttrs & rCmpAttrs,const SwFrm * pCaller,const SwFrm * pCmp) const2079 sal_Bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
2080 								  const SwFrm *pCaller,
2081 								  const SwFrm *pCmp ) const
2082 {
2083     return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft()  ) &&
2084              CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
2085              CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
2086              // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
2087              CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
2088 }
2089 
_JoinWithCmp(const SwFrm & _rCallerFrm,const SwFrm & _rCmpFrm) const2090 sal_Bool SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm,
2091                                   const SwFrm& _rCmpFrm ) const
2092 {
2093     sal_Bool bReturnVal = sal_False;
2094 
2095     SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm );
2096     const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
2097     if ( rShadow == rCmpAttrs.GetShadow() &&
2098          CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
2099          CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
2100          CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm )
2101        )
2102     {
2103         bReturnVal = sal_True;
2104     }
2105 
2106     return bReturnVal;
2107 }
2108 
2109 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2110 // previous frame. Calculated value saved in cached value <bJoinedWithPrev>
2111 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>
_CalcJoinedWithPrev(const SwFrm & _rFrm,const SwFrm * _pPrevFrm)2112 void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm,
2113                                          const SwFrm* _pPrevFrm )
2114 {
2115     // set default
2116     bJoinedWithPrev = sal_False;
2117 
2118     if ( _rFrm.IsTxtFrm() )
2119     {
2120         // text frame can potentially join with previous text frame, if
2121         // corresponding attribute set is set at previous text frame.
2122         // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this
2123         // one as previous frame.
2124         const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev();
2125         // OD 2004-02-13 #i25029# - skip hidden text frames.
2126         while ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2127                 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
2128         {
2129             pPrevFrm = pPrevFrm->GetPrev();
2130         }
2131         if ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2132              pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue()
2133            )
2134         {
2135             bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) );
2136         }
2137     }
2138 
2139     // valid cache status, if demanded
2140     // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm>
2141     // is set.
2142     bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm;
2143 }
2144 
2145 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2146 // next frame. Calculated value saved in cached value <bJoinedWithNext>
_CalcJoinedWithNext(const SwFrm & _rFrm)2147 void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm )
2148 {
2149     // set default
2150     bJoinedWithNext = sal_False;
2151 
2152     if ( _rFrm.IsTxtFrm() )
2153     {
2154         // text frame can potentially join with next text frame, if
2155         // corresponding attribute set is set at current text frame.
2156         // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2157         const SwFrm* pNextFrm = _rFrm.GetNext();
2158         while ( pNextFrm && pNextFrm->IsTxtFrm() &&
2159                 static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() )
2160         {
2161             pNextFrm = pNextFrm->GetNext();
2162         }
2163         if ( pNextFrm && pNextFrm->IsTxtFrm() &&
2164              _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue()
2165            )
2166         {
2167             bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) );
2168         }
2169     }
2170 
2171     // valid cache status, if demanded
2172     bCachedJoinedWithNext = bCacheGetLine;
2173 }
2174 
2175 // OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev>
2176 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to
2177 // method <_CalcJoindWithPrev(..)>.
JoinedWithPrev(const SwFrm & _rFrm,const SwFrm * _pPrevFrm) const2178 sal_Bool SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm,
2179                                     const SwFrm* _pPrevFrm ) const
2180 {
2181     if ( !bCachedJoinedWithPrev || _pPrevFrm )
2182     {
2183         // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter
2184         const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm );
2185     }
2186 
2187     return bJoinedWithPrev;
2188 }
2189 
JoinedWithNext(const SwFrm & _rFrm) const2190 sal_Bool SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const
2191 {
2192     if ( !bCachedJoinedWithNext )
2193     {
2194         const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm );
2195     }
2196 
2197     return bJoinedWithNext;
2198 }
2199 
2200 // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to
2201 // method <JoinedWithPrev>
_GetTopLine(const SwFrm & _rFrm,const SwFrm * _pPrevFrm)2202 void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm,
2203                                  const SwFrm* _pPrevFrm )
2204 {
2205     sal_uInt16 nRet = CalcTopLine();
2206 
2207     // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2208     // OD 2004-02-26 #i25029# - add 2nd parameter
2209     if ( JoinedWithPrev( _rFrm, _pPrevFrm ) )
2210     {
2211         nRet = 0;
2212     }
2213 
2214     bCachedGetTopLine = bCacheGetLine;
2215 
2216 	nGetTopLine = nRet;
2217 }
2218 
_GetBottomLine(const SwFrm & _rFrm)2219 void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm )
2220 {
2221 	sal_uInt16 nRet = CalcBottomLine();
2222 
2223     // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2224     if ( JoinedWithNext( _rFrm ) )
2225     {
2226         nRet = 0;
2227     }
2228 
2229     bCachedGetBottomLine = bCacheGetLine;
2230 
2231 	nGetBottomLine = nRet;
2232 }
2233 
2234 /*************************************************************************/
2235 
SwBorderAttrAccess(SwCache & rCach,const SwFrm * pFrm)2236 SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) :
2237     SwCacheAccess( rCach, (pFrm->IsCntntFrm() ?
2238 								(void*)((SwCntntFrm*)pFrm)->GetNode() :
2239 								(void*)((SwLayoutFrm*)pFrm)->GetFmt()),
2240 						   (sal_Bool)(pFrm->IsCntntFrm() ?
2241 				((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() :
2242 				((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ),
2243 	pConstructor( pFrm )
2244 {
2245 }
2246 
2247 /*************************************************************************/
2248 
NewObj()2249 SwCacheObj *SwBorderAttrAccess::NewObj()
2250 {
2251 	((SwModify*)pOwner)->SetInCache( sal_True );
2252 	return new SwBorderAttrs( (SwModify*)pOwner, pConstructor );
2253 }
2254 
Get()2255 SwBorderAttrs *SwBorderAttrAccess::Get()
2256 {
2257 	return (SwBorderAttrs*)SwCacheAccess::Get();
2258 }
2259 
2260 /*************************************************************************/
2261 
SwOrderIter(const SwPageFrm * pPg,sal_Bool bFlys)2262 SwOrderIter::SwOrderIter( const SwPageFrm *pPg, sal_Bool bFlys ) :
2263 	pPage( pPg ),
2264 	pCurrent( 0 ),
2265 	bFlysOnly( bFlys )
2266 {
2267 }
2268 
2269 /*************************************************************************/
2270 
Top()2271 const SdrObject *SwOrderIter::Top()
2272 {
2273 	pCurrent = 0;
2274 	if ( pPage->GetSortedObjs() )
2275 	{
2276 		sal_uInt32 nTopOrd = 0;
2277 		const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2278 		if ( pObjs->Count() )
2279 		{
2280 			(*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2281 			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2282 			{
2283 				const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2284 				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2285 					continue;
2286 				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2287 				if ( nTmp >= nTopOrd )
2288 				{
2289 					nTopOrd = nTmp;
2290 					pCurrent = pObj;
2291 				}
2292 			}
2293 		}
2294 	}
2295 	return pCurrent;
2296 }
2297 
2298 /*************************************************************************/
2299 
Bottom()2300 const SdrObject *SwOrderIter::Bottom()
2301 {
2302 	pCurrent = 0;
2303 	if ( pPage->GetSortedObjs() )
2304 	{
2305 		sal_uInt32 nBotOrd = USHRT_MAX;
2306 		const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2307 		if ( pObjs->Count() )
2308 		{
2309 			(*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2310 			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2311 			{
2312 				const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2313 				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2314 					continue;
2315 				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2316 				if ( nTmp < nBotOrd )
2317 				{
2318 					nBotOrd = nTmp;
2319 					pCurrent = pObj;
2320 				}
2321 			}
2322 		}
2323 	}
2324 	return pCurrent;
2325 }
2326 
2327 /*************************************************************************/
2328 
Next()2329 const SdrObject *SwOrderIter::Next()
2330 {
2331 	const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2332 	pCurrent = 0;
2333 	if ( pPage->GetSortedObjs() )
2334 	{
2335 		sal_uInt32 nOrd = USHRT_MAX;
2336         const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2337 		if ( pObjs->Count() )
2338 		{
2339             (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2340 			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2341 			{
2342                 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2343 				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2344 					continue;
2345 				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2346 				if ( nTmp > nCurOrd && nTmp < nOrd )
2347 				{
2348 					nOrd = nTmp;
2349 					pCurrent = pObj;
2350 				}
2351 			}
2352 		}
2353 	}
2354 	return pCurrent;
2355 }
2356 
2357 /*************************************************************************/
2358 
Prev()2359 const SdrObject *SwOrderIter::Prev()
2360 {
2361 	const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2362 	pCurrent = 0;
2363 	if ( pPage->GetSortedObjs() )
2364 	{
2365 		sal_uInt32 nOrd = 0;
2366         const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2367 		if ( pObjs->Count() )
2368 		{
2369             (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2370 			for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2371 			{
2372                 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2373 				if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2374 					continue;
2375 				sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2376 				if ( nTmp < nCurOrd && nTmp >= nOrd )
2377 				{
2378 					nOrd = nTmp;
2379 					pCurrent = pObj;
2380 				}
2381 			}
2382 		}
2383 	}
2384 	return pCurrent;
2385 }
2386 
2387 /*************************************************************************/
2388 
2389 //Unterstruktur eines LayoutFrms fuer eine Aktion aufheben und wieder
2390 //restaurieren.
2391 //Neuer Algorithmus: Es ist unuetz jeden Nachbarn einzeln zu betrachten und
2392 //die Pointer sauber zu setzen (Upper, Nachbarn, usw.)
2393 //Es reicht vollkommen jeweils eine Einzelkette zu loesen, und mit dem
2394 //Letzen der Einzelkette nachzuschauen ob noch eine weitere Kette
2395 //angeheangt werden muss. Es brauchen nur die Pointer korrigiert werden,
2396 //die zur Verkettung notwendig sind. So koennen Beipspielsweise die Pointer
2397 //auf die Upper auf den alten Uppern stehenbleiben. Korrigiert werden die
2398 //Pointer dann im RestoreCntnt. Zwischenzeitlich ist sowieso jeder Zugriff
2399 //verboten.
2400 //Unterwegs werden die Flys bei der Seite abgemeldet.
2401 
2402 // --> OD 2004-11-29 #115759# - 'remove' also drawing object from page and
2403 // at-fly anchored objects from page
lcl_RemoveObjsFromPage(SwFrm * _pFrm)2404 void MA_FASTCALL lcl_RemoveObjsFromPage( SwFrm* _pFrm )
2405 {
2406     ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_RemoveFlysFromPage." );
2407     SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2408 	for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2409 	{
2410         SwAnchoredObject* pObj = rObjs[i];
2411         // --> OD 2004-11-29 #115759# - reset member, at which the anchored
2412         // object orients its vertical position
2413         pObj->ClearVertPosOrientFrm();
2414         // <--
2415         // --> OD 2005-03-03 #i43913#
2416         pObj->ResetLayoutProcessBools();
2417         // <--
2418         // --> OD 2004-11-29 #115759# - remove also lower objects of as-character
2419         // anchored Writer fly frames from page
2420         if ( pObj->ISA(SwFlyFrm) )
2421         {
2422             SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2423 
2424             // --> OD 2004-11-29 #115759# - remove also direct lowers of Writer
2425             // fly frame from page
2426             if ( pFlyFrm->GetDrawObjs() )
2427             {
2428                 ::lcl_RemoveObjsFromPage( pFlyFrm );
2429             }
2430             // <--
2431 
2432             SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt();
2433             while ( pCnt )
2434             {
2435                 if ( pCnt->GetDrawObjs() )
2436                     ::lcl_RemoveObjsFromPage( pCnt );
2437                 pCnt = pCnt->GetNextCntntFrm();
2438             }
2439             if ( pFlyFrm->IsFlyFreeFrm() )
2440             {
2441                 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
2442                 pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm );
2443             }
2444         }
2445         // <--
2446         // --> OD 2004-11-29 #115759# - remove also drawing objects from page
2447         else if ( pObj->ISA(SwAnchoredDrawObject) )
2448         {
2449             if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
2450             {
2451                 pObj->GetPageFrm()->RemoveDrawObjFromPage(
2452                                 *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2453             }
2454         }
2455         // <--
2456 	}
2457 }
2458 
SaveCntnt(SwLayoutFrm * pLay,SwFrm * pStart)2459 SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart )
2460 {
2461 	if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
2462 		lcl_RemoveFtns( (SwColumnFrm*)pLay->Lower(), sal_True, sal_True );
2463 
2464 	SwFrm *pSav;
2465 	if ( 0 == (pSav = pLay->ContainsAny()) )
2466 		return 0;
2467 
2468 	if( pSav->IsInFtn() && !pLay->IsInFtn() )
2469 	{
2470 		do
2471 			pSav = pSav->FindNext();
2472 		while( pSav && pSav->IsInFtn() );
2473 		if( !pSav || !pLay->IsAnLower( pSav ) )
2474 			return NULL;
2475 	}
2476 
2477     // Tables should be saved as a whole, exception:
2478     // The contents of a section or a cell inside a table should be saved
2479     if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) )
2480         while ( !pSav->IsTabFrm() )
2481             pSav = pSav->GetUpper();
2482 
2483 	if( pSav->IsInSct() )
2484 	{ // Jetzt wird der oberste Bereich gesucht, der innerhalb von pLay ist.
2485 		SwFrm* pSect = pLay->FindSctFrm();
2486 		SwFrm *pTmp = pSav;
2487 		do
2488 		{
2489 			pSav = pTmp;
2490 			pTmp = pSav->GetUpper() ? pSav->GetUpper()->FindSctFrm() : NULL;
2491 		} while ( pTmp != pSect );
2492 	}
2493 
2494 	SwFrm *pFloat = pSav;
2495 	if( !pStart )
2496 		pStart = pSav;
2497 	sal_Bool bGo = pStart == pSav;
2498 	do
2499 	{
2500 		if( bGo )
2501 			pFloat->GetUpper()->pLower = 0; 	//Die Teilkette ausklinken.
2502 
2503 		//Das Ende der Teilkette suchen, unterwegs die Flys abmelden.
2504 		do
2505 		{
2506 			if( bGo )
2507 			{
2508 				if ( pFloat->IsCntntFrm() )
2509 				{
2510 					if ( pFloat->GetDrawObjs() )
2511                         ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat );
2512 				}
2513 				else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() )
2514 				{
2515 					SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt();
2516 					if( pCnt )
2517 					{
2518 						do
2519 						{	if ( pCnt->GetDrawObjs() )
2520                                 ::lcl_RemoveObjsFromPage( pCnt );
2521 							pCnt = pCnt->GetNextCntntFrm();
2522 						} while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) );
2523 					}
2524 				}
2525 				else {
2526 					ASSERT( !pFloat, "Neuer Float-Frame?" );
2527                 }
2528 			}
2529 			if ( pFloat->GetNext()	)
2530 			{
2531 				if( bGo )
2532 					pFloat->pUpper = NULL;
2533 				pFloat = pFloat->GetNext();
2534 				if( !bGo && pFloat == pStart )
2535 				{
2536 					bGo = sal_True;
2537 					pFloat->pPrev->pNext = NULL;
2538 					pFloat->pPrev = NULL;
2539 				}
2540 			}
2541 			else
2542 				break;
2543 
2544 		} while ( pFloat );
2545 
2546 		//Die naechste Teilkette suchen und die Ketten miteinander verbinden.
2547 		SwFrm *pTmp = pFloat->FindNext();
2548 		if( bGo )
2549 			pFloat->pUpper = NULL;
2550 
2551 		if( !pLay->IsInFtn() )
2552 			while( pTmp && pTmp->IsInFtn() )
2553 				pTmp = pTmp->FindNext();
2554 
2555 		if ( !pLay->IsAnLower( pTmp ) )
2556 			pTmp = 0;
2557 
2558 		if ( pTmp && bGo )
2559 		{
2560 			pFloat->pNext = pTmp;			//Die beiden Ketten verbinden.
2561 			pFloat->pNext->pPrev = pFloat;
2562 		}
2563 		pFloat = pTmp;
2564 		bGo = bGo || ( pStart == pFloat );
2565 	}  while ( pFloat );
2566 
2567 	return bGo ? pStart : NULL;
2568 }
2569 
2570 // --> OD 2004-11-29 #115759# - add also drawing objects to page and at-fly
2571 // anchored objects to page
lcl_AddObjsToPage(SwFrm * _pFrm,SwPageFrm * _pPage)2572 void MA_FASTCALL lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage )
2573 {
2574     ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_AddFlysToPage." );
2575     SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2576 	for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2577 	{
2578         SwAnchoredObject* pObj = rObjs[i];
2579 
2580         // --> OD 2004-11-29 #115759# - unlock position of anchored object
2581         // in order to get the object's position calculated.
2582         pObj->UnlockPosition();
2583         // <--
2584         // --> OD 2004-11-29 #115759# - add also lower objects of as-character
2585         // anchored Writer fly frames from page
2586         if ( pObj->ISA(SwFlyFrm) )
2587         {
2588             SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2589             if ( pObj->ISA(SwFlyFreeFrm) )
2590             {
2591                 _pPage->AppendFlyToPage( pFlyFrm );
2592             }
2593             pFlyFrm->_InvalidatePos();
2594             pFlyFrm->_InvalidateSize();
2595             pFlyFrm->InvalidatePage( _pPage );
2596 
2597             // --> OD 2004-11-29 #115759# - add also at-fly anchored objects
2598             // to page
2599             if ( pFlyFrm->GetDrawObjs() )
2600             {
2601                 ::lcl_AddObjsToPage( pFlyFrm, _pPage );
2602             }
2603             // <--
2604 
2605             SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt();
2606             while ( pCnt )
2607             {
2608                 if ( pCnt->GetDrawObjs() )
2609                     ::lcl_AddObjsToPage( pCnt, _pPage );
2610                 pCnt = pCnt->GetNextCntntFrm();
2611             }
2612         }
2613         // <--
2614         // --> OD 2004-11-29 #115759# - remove also drawing objects from page
2615         else if ( pObj->ISA(SwAnchoredDrawObject) )
2616         {
2617             if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
2618             {
2619                 pObj->InvalidateObjPos();
2620                 _pPage->AppendDrawObjToPage(
2621                                 *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2622             }
2623         }
2624         // <--
2625 	}
2626 }
2627 
RestoreCntnt(SwFrm * pSav,SwLayoutFrm * pParent,SwFrm * pSibling,bool bGrow)2628 void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow )
2629 {
2630 	ASSERT( pSav && pParent, "Kein Save oder Parent fuer Restore." );
2631     SWRECTFN( pParent )
2632 
2633 	//Wenn es bereits FlowFrms unterhalb des neuen Parent gibt, so wird die
2634 	//Kette, beginnend mit pSav, hinter dem letzten angehaengt.
2635 	//Die Teile werden kurzerhand insertet und geeignet invalidiert.
2636 	//Unterwegs werden die Flys der CntntFrms bei der Seite angemeldet.
2637 
2638 	SwPageFrm *pPage = pParent->FindPageFrm();
2639 
2640 	if ( pPage )
2641 		pPage->InvalidatePage( pPage ); //Invalides Layout anmelden.
2642 
2643 	//Vorgaenger feststellen und die Verbindung herstellen bzw. initialisieren.
2644 	pSav->pPrev = pSibling;
2645 	SwFrm* pNxt;
2646 	if ( pSibling )
2647 	{
2648 		pNxt = pSibling->pNext;
2649 		pSibling->pNext = pSav;
2650 		pSibling->_InvalidatePrt();
2651 		((SwCntntFrm*)pSibling)->InvalidatePage( pPage );//Invaliden Cntnt anmelden.
2652 		if ( ((SwCntntFrm*)pSibling)->GetFollow() )
2653 			pSibling->Prepare( PREP_CLEAR, 0, sal_False );
2654 	}
2655 	else
2656 	{	pNxt = pParent->pLower;
2657 		pParent->pLower = pSav;
2658 		pSav->pUpper = pParent;		//Schon mal setzen, sonst ist fuer das
2659 									//invalidate der Parent (z.B. ein Fly) nicht klar.
2660 		//Invaliden Cntnt anmelden.
2661 		if ( pSav->IsCntntFrm() )
2662 			((SwCntntFrm*)pSav)->InvalidatePage( pPage );
2663 		else
2664 		{   // pSav koennte auch ein leerer SectFrm sein
2665 			SwCntntFrm* pCnt = pParent->ContainsCntnt();
2666 			if( pCnt )
2667 				pCnt->InvalidatePage( pPage );
2668 		}
2669 	}
2670 
2671 	//Der Parent muss entsprechend gegrow'ed werden.
2672 	SwTwips nGrowVal = 0;
2673 	SwFrm* pLast;
2674 	do
2675 	{	pSav->pUpper = pParent;
2676 		nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)();
2677 		pSav->_InvalidateAll();
2678 
2679         //Jetzt die Flys anmelden, fuer TxtFrms gleich geeignet invalidieren.
2680 		if ( pSav->IsCntntFrm() )
2681 		{
2682 			if ( pSav->IsTxtFrm() &&
2683 				 ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX )
2684 				((SwTxtFrm*)pSav)->Init();	//Ich bin sein Freund.
2685 
2686 			if ( pPage && pSav->GetDrawObjs() )
2687                 ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage );
2688 		}
2689 		else
2690 		{	SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt();
2691 			if( pBlub )
2692 			{
2693 				do
2694 				{	if ( pPage && pBlub->GetDrawObjs() )
2695                         ::lcl_AddObjsToPage( pBlub, pPage );
2696 					if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() &&
2697 				 		((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX )
2698 						((SwTxtFrm*)pBlub)->Init();	//Ich bin sein Freund.
2699 					pBlub = pBlub->GetNextCntntFrm();
2700 				} while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub ));
2701 			}
2702 		}
2703 		pLast = pSav;
2704 		pSav = pSav->GetNext();
2705 
2706 	} while ( pSav );
2707 
2708 	if( pNxt )
2709 	{
2710 		pLast->pNext = pNxt;
2711 		pNxt->pPrev = pLast;
2712 	}
2713 
2714 	if ( bGrow )
2715 		pParent->Grow( nGrowVal );
2716 }
2717 
2718 /*************************************************************************
2719 |*
2720 |*	SqRt()				Berechnung der Quadratwurzel, damit die math.lib
2721 |*		nicht auch noch dazugelinkt werden muss.
2722 |*
2723 |*************************************************************************/
2724 
SqRt(BigInt nX)2725 sal_uLong MA_FASTCALL SqRt( BigInt nX )
2726 {
2727 	BigInt nErg = 1;
2728 
2729 	if ( !nX.IsNeg() )
2730 	{
2731 		BigInt nOldErg = 1;
2732 		for ( int i = 0; i <= 5; i++ )
2733 		{
2734 			nErg = (nOldErg + (nX / nOldErg)) / BigInt(2);
2735 			nOldErg = nErg;
2736 		}
2737 	}
2738 	return nErg >= BigInt(SAL_MAX_UINT32) ? ULONG_MAX : (sal_uLong)nErg;
2739 }
2740 
2741 /*************************************************************************/
2742 
InsertNewPage(SwPageDesc & rDesc,SwFrm * pUpper,sal_Bool bOdd,sal_Bool bInsertEmpty,sal_Bool bFtn,SwFrm * pSibling)2743 SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
2744 						  sal_Bool bOdd, sal_Bool bInsertEmpty, sal_Bool bFtn,
2745 						  SwFrm *pSibling )
2746 {
2747 	SwPageFrm *pRet;
2748 	SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc();
2749 	SwFrmFmt *pFmt = bOdd ? rDesc.GetRightFmt() : rDesc.GetLeftFmt();
2750 	//Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben
2751 	//eine Leerseite einfuegen.
2752 	if ( !pFmt )
2753 	{
2754 		pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt();
2755 		ASSERT( pFmt, "Descriptor without any format?!" );
2756 		bInsertEmpty = !bInsertEmpty;
2757 	}
2758 	if( bInsertEmpty )
2759 	{
2760 		SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
2761 				((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc;
2762 		pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pUpper, pTmpDesc );
2763 		pRet->Paste( pUpper, pSibling );
2764 		pRet->PreparePage( bFtn );
2765 	}
2766 	pRet = new SwPageFrm( pFmt, pUpper, &rDesc );
2767 	pRet->Paste( pUpper, pSibling );
2768 	pRet->PreparePage( bFtn );
2769 	if ( pRet->GetNext() )
2770 		((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet );
2771 	return pRet;
2772 }
2773 
2774 
2775 /*************************************************************************
2776 |*
2777 |*	RegistFlys(), Regist()	Die beiden folgenden Methoden durchsuchen rekursiv
2778 |*		eine Layoutstruktur und melden alle FlyFrms, die einen beliebigen Frm
2779 |*		innerhalb der Struktur als Anker haben bei der Seite an.
2780 |*
2781 |*************************************************************************/
2782 
lcl_Regist(SwPageFrm * pPage,const SwFrm * pAnch)2783 void MA_FASTCALL lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch )
2784 {
2785     SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs();
2786 	for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2787 	{
2788         SwAnchoredObject* pObj = (*pObjs)[i];
2789         if ( pObj->ISA(SwFlyFrm) )
2790 		{
2791             SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
2792 			//Ggf. ummelden, nicht anmelden wenn bereits bekannt.
2793             // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
2794             SwPageFrm *pPg = pFly->IsFlyFreeFrm()
2795                              ? pFly->GetPageFrm() : pFly->FindPageFrm();
2796 			if ( pPg != pPage )
2797 			{
2798 				if ( pPg )
2799                     pPg->RemoveFlyFromPage( pFly );
2800                 pPage->AppendFlyToPage( pFly );
2801 			}
2802 			::RegistFlys( pPage, pFly );
2803 		}
2804 		else
2805 		{
2806             // --> OD 2008-04-22 #i87493#
2807             if ( pPage != pObj->GetPageFrm() )
2808             {
2809                 // --> OD 2004-07-02 #i28701#
2810                 if ( pObj->GetPageFrm() )
2811                     pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj );
2812                 pPage->AppendDrawObjToPage( *pObj );
2813                 // <--
2814             }
2815             // <--
2816 		}
2817 
2818         const SwFlyFrm* pFly = pAnch->FindFlyFrm();
2819         if ( pFly &&
2820              pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
2821              pObj->GetDrawObj()->GetPage() )
2822         {
2823             //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
2824             pObj->DrawObj()->GetPage()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(),
2825                                                          pObj->GetDrawObj()->GetOrdNumDirect() );
2826         }
2827 	}
2828 }
2829 
RegistFlys(SwPageFrm * pPage,const SwLayoutFrm * pLay)2830 void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay )
2831 {
2832 	if ( pLay->GetDrawObjs() )
2833 		::lcl_Regist( pPage, pLay );
2834 	const SwFrm *pFrm = pLay->Lower();
2835 	while ( pFrm )
2836 	{
2837 		if ( pFrm->IsLayoutFrm() )
2838 			::RegistFlys( pPage, (const SwLayoutFrm*)pFrm );
2839 		else if ( pFrm->GetDrawObjs() )
2840 			::lcl_Regist( pPage, pFrm );
2841 		pFrm = pFrm->GetNext();
2842 	}
2843 }
2844 
2845 /*************************************************************************
2846 |*
2847 |*	void Notify()
2848 |*
2849 |*	Beschreibung		Benachrichtigt den Hintergrund je nach der
2850 |*		Veraenderung zwischen altem und neuem Rechteck.
2851 |*
2852 |*************************************************************************/
2853 
Notify(SwFlyFrm * pFly,SwPageFrm * pOld,const SwRect & rOld,const SwRect * pOldPrt)2854 void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
2855              const SwRect* pOldPrt )
2856 {
2857     const SwRect aFrm( pFly->GetObjRectWithSpaces() );
2858 	if ( rOld.Pos() != aFrm.Pos() )
2859 	{	//Positionsaenderung, alten und neuen Bereich invalidieren
2860 		if ( rOld.HasArea() &&
2861 			 rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < WEIT_WECH )
2862 		{
2863 			pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE );
2864 		}
2865 		pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
2866 	}
2867 	else if ( rOld.SSize() != aFrm.SSize() )
2868 	{	//Groessenaenderung, den Bereich der Verlassen wurde bzw. jetzt
2869 		//ueberdeckt wird invalidieren.
2870 		//Der Einfachheit halber wird hier bewusst jeweils ein Twip
2871 		//unnoetig invalidiert.
2872 
2873 		ViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
2874 		if( pSh && rOld.HasArea() )
2875 			pSh->InvalidateWindows( rOld );
2876 
2877         // --> OD 2005-08-19 #i51941# - consider case that fly frame isn't
2878         // registered at the old page <pOld>
2879         SwPageFrm* pPageFrm = pFly->FindPageFrm();
2880         if ( pOld != pPageFrm )
2881         {
2882             pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE );
2883         }
2884         // <--
2885 
2886 		if ( rOld.Left() != aFrm.Left() )
2887         {
2888             SwRect aTmp( rOld );
2889 			aTmp.Union( aFrm );
2890 			aTmp.Left(	Min(aFrm.Left(), rOld.Left()) );
2891 			aTmp.Right( Max(aFrm.Left(), rOld.Left()) );
2892 			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2893 		}
2894 		SwTwips nOld = rOld.Right();
2895 		SwTwips nNew = aFrm.Right();
2896 		if ( nOld != nNew )
2897         {
2898             SwRect aTmp( rOld );
2899 			aTmp.Union( aFrm );
2900 			aTmp.Left(	Min(nNew, nOld) );
2901 			aTmp.Right( Max(nNew, nOld) );
2902 			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2903 		}
2904 		if ( rOld.Top() != aFrm.Top() )
2905         {
2906             SwRect aTmp( rOld );
2907 			aTmp.Union( aFrm );
2908 			aTmp.Top(	 Min(aFrm.Top(), rOld.Top()) );
2909 			aTmp.Bottom( Max(aFrm.Top(), rOld.Top()) );
2910 			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2911 		}
2912 		nOld = rOld.Bottom();
2913 		nNew = aFrm.Bottom();
2914 		if ( nOld != nNew )
2915         {
2916             SwRect aTmp( rOld );
2917 			aTmp.Union( aFrm );
2918 			aTmp.Top(	 Min(nNew, nOld) );
2919 			aTmp.Bottom( Max(nNew, nOld) );
2920 			pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2921 		}
2922 	}
2923     else if ( pOldPrt && *pOldPrt != pFly->Prt() &&
2924               pFly->GetFmt()->GetSurround().IsContour() )
2925     {
2926         // #i24097#
2927         pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
2928     }
2929 }
2930 
2931 /*************************************************************************/
2932 
lcl_CheckFlowBack(SwFrm * pFrm,const SwRect & rRect)2933 void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect )
2934 {
2935     SwTwips nBottom = rRect.Bottom();
2936     while( pFrm )
2937     {
2938         if( pFrm->IsLayoutFrm() )
2939         {
2940             if( rRect.IsOver( pFrm->Frm() ) )
2941                 lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect );
2942         }
2943         else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() )
2944         {
2945             if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() )
2946                 pFrm->InvalidateSize();
2947             else
2948                 pFrm->InvalidateNextPos();
2949         }
2950         pFrm = pFrm->GetNext();
2951     }
2952 }
2953 
lcl_NotifyCntnt(const SdrObject * pThis,SwCntntFrm * pCnt,const SwRect & rRect,const PrepareHint eHint)2954 void MA_FASTCALL lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt,
2955 	const SwRect &rRect, const PrepareHint eHint )
2956 {
2957 	if ( pCnt->IsTxtFrm() )
2958 	{
2959 		SwRect aCntPrt( pCnt->Prt() );
2960 		aCntPrt.Pos() += pCnt->Frm().Pos();
2961 		if ( eHint == PREP_FLY_ATTR_CHG )
2962 		{
2963             // --> OD 2004-10-20 #i35640# - use given rectangle <rRect> instead
2964             // of current bound rectangle
2965             if ( aCntPrt.IsOver( rRect ) )
2966             // <--
2967 				pCnt->Prepare( PREP_FLY_ATTR_CHG );
2968 		}
2969         // --> OD 2004-11-01 #i23129# - only invalidate, if the text frame
2970         // printing area overlaps with the given rectangle.
2971         else if ( aCntPrt.IsOver( rRect ) )
2972         // <--
2973 			pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) );
2974 		if ( pCnt->GetDrawObjs() )
2975 		{
2976             const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
2977 			for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2978 			{
2979                 SwAnchoredObject* pObj = rObjs[i];
2980                 if ( pObj->ISA(SwFlyFrm) )
2981 				{
2982                     SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
2983 					if ( pFly->IsFlyInCntFrm() )
2984 					{
2985 						SwCntntFrm *pCntnt = pFly->ContainsCntnt();
2986 						while ( pCntnt )
2987 						{
2988 							::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint );
2989 							pCntnt = pCntnt->GetNextCntntFrm();
2990 						}
2991 					}
2992 				}
2993 			}
2994 		}
2995 	}
2996 }
2997 
Notify_Background(const SdrObject * pObj,SwPageFrm * pPage,const SwRect & rRect,const PrepareHint eHint,const sal_Bool bInva)2998 void Notify_Background( const SdrObject* pObj,
2999                         SwPageFrm* pPage,
3000                         const SwRect& rRect,
3001                         const PrepareHint eHint,
3002                         const sal_Bool bInva )
3003 {
3004 
3005 	//Wenn der Frm gerade erstmalig sinnvoll positioniert wurde, braucht der
3006 	//alte Bereich nicht benachrichtigt werden.
3007 	if ( eHint == PREP_FLY_LEAVE && rRect.Top() == WEIT_WECH )
3008 		 return;
3009 
3010     SwLayoutFrm* pArea;
3011 	SwFlyFrm *pFlyFrm = 0;
3012 	SwFrm* pAnchor;
3013 	if( pObj->ISA(SwVirtFlyDrawObj) )
3014 	{
3015 		pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
3016         pAnchor = pFlyFrm->AnchorFrm();
3017 	}
3018 	else
3019 	{
3020 		pFlyFrm = NULL;
3021         pAnchor = const_cast<SwFrm*>(
3022                     GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() );
3023 	}
3024 	if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() )
3025 		pArea = pAnchor->FindFlyFrm();
3026 	else
3027         pArea = pPage;
3028 	SwCntntFrm *pCnt = 0;
3029 	if ( pArea )
3030 	{
3031         if( PREP_FLY_ARRIVE != eHint )
3032             lcl_CheckFlowBack( pArea, rRect );
3033 
3034 		//Es reagieren sowieso nur die auf den Anker folgenden auf den Fly, also
3035 		//brauchen diese nicht abgeklappert werden.
3036 		//Ausnahme sind ist natuerlich das LEAVE, denn der Fly koennte ja von
3037 		//"oben" kommen.
3038 		// Wenn der Anker auf der vorhergehenden Seite liegt, muss ebenfalls
3039 		// die gesamte Seite abgearbeitet werden. (47722)
3040         // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
3041         // on the object positioning, the complete area has to be processed,
3042         // because content frames before the anchor frame also have to consider
3043         // the object for the text wrapping.
3044         // --> OD 2004-08-25 #i3317# - The complete area has always been
3045         // processed.
3046         {
3047 			pCnt = pArea->ContainsCntnt();
3048         }
3049         // <--
3050 	}
3051 	SwFrm *pLastTab = 0;
3052 
3053     while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
3054 	{
3055 		::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
3056 		if ( pCnt->IsInTab() )
3057 		{
3058 			SwLayoutFrm* pCell = pCnt->GetUpper();
3059             // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
3060             // instead of <GetCurrentBoundRect()>, because a recalculation
3061             // of the bounding rectangle isn't intended here.
3062             if ( pCell->IsCellFrm() &&
3063                  ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) ||
3064                    pCell->Frm().IsOver( rRect ) ) )
3065             // <--
3066 			{
3067 				const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient();
3068                 if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
3069 					pCell->InvalidatePrt();
3070 			}
3071 			SwTabFrm *pTab = pCnt->FindTabFrm();
3072 			if ( pTab != pLastTab )
3073 			{
3074 				pLastTab = pTab;
3075                 // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
3076                 // instead of <GetCurrentBoundRect()>, because a recalculation
3077                 // of the bounding rectangle isn't intended here.
3078                 if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) ||
3079                      pTab->Frm().IsOver( rRect ) )
3080                 // <--
3081 				{
3082                     if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) )
3083 						pTab->InvalidatePrt();
3084 				}
3085 			}
3086 		}
3087 		pCnt = pCnt->GetNextCntntFrm();
3088 	}
3089 // #108745# Sorry, but this causes nothing but trouble. I remove these lines
3090 // taking the risk that the footer frame will have a wrong height
3091 //  if( pPage->Lower() )
3092 //  {
3093 //      SwFrm* pFrm = pPage->Lower();
3094 //      while( pFrm->GetNext() )
3095 //          pFrm = pFrm->GetNext();
3096 //      if( pFrm->IsFooterFrm() &&
3097 //          ( ( pFrm->Frm().IsOver( pObj->GetBoundRect() ) ||
3098 //              pFrm->Frm().IsOver( rRect ) ) ) )
3099 //           pFrm->InvalidateSize();
3100 //  }
3101     // --> OD 2007-07-24 #128702# - make code robust
3102     if ( pPage && pPage->GetSortedObjs() )
3103     // <--
3104 	{
3105 		pObj->GetOrdNum();
3106         const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
3107 		for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
3108 		{
3109             SwAnchoredObject* pAnchoredObj = rObjs[i];
3110             if ( pAnchoredObj->ISA(SwFlyFrm) )
3111 			{
3112                 if( pAnchoredObj->GetDrawObj() == pObj )
3113 					continue;
3114                 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3115 				if ( pFly->Frm().Top() == WEIT_WECH )
3116 					continue;
3117 
3118 				if ( !pFlyFrm ||
3119                         (!pFly->IsLowerOf( pFlyFrm ) &&
3120 						pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
3121 				{
3122 					pCnt = pFly->ContainsCntnt();
3123 					while ( pCnt )
3124 					{
3125 						::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
3126 						pCnt = pCnt->GetNextCntntFrm();
3127 					}
3128 				}
3129 				if( pFly->IsFlyLayFrm() )
3130 				{
3131 					if( pFly->Lower() && pFly->Lower()->IsColumnFrm() &&
3132 						pFly->Frm().Bottom() >= rRect.Top() &&
3133 						pFly->Frm().Top() <= rRect.Bottom() &&
3134 						pFly->Frm().Right() >= rRect.Left() &&
3135 						pFly->Frm().Left() <= rRect.Right() )
3136 					 {
3137                         pFly->InvalidateSize();
3138 					 }
3139 				}
3140 				//Flys, die ueber mir liegen muessen/mussten evtl.
3141 				//ausweichen, wenn sie eine automatische Ausrichtung haben.
3142 				//das ist unabhaengig von meinem Attribut, weil dies sich
3143 				//gerade geaendert haben kann und eben deshalb
3144 				//umformatiert wurde.
3145 				else if ( pFly->IsFlyAtCntFrm() &&
3146 						pObj->GetOrdNumDirect() <
3147 						pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
3148                         pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) )
3149 				{
3150 					const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
3151                     if ( text::HoriOrientation::NONE != rH.GetHoriOrient() &&
3152                             text::HoriOrientation::CENTER != rH.GetHoriOrient() &&
3153                             ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
3154 							(pFly->Frm().Bottom() >= rRect.Top() &&
3155 							pFly->Frm().Top() <= rRect.Bottom()) )
3156 						pFly->InvalidatePos();
3157 				}
3158 			}
3159 		}
3160 	}
3161 	if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
3162 		pAnchor->GetUpper()->InvalidateSize();
3163 
3164     // --> OD 2008-01-30 #i82258# - make code robust
3165     ViewShell* pSh = 0;
3166     if ( bInva && pPage &&
3167         0 != (pSh = pPage->getRootFrm()->GetCurrShell()) )
3168     {
3169         pSh->InvalidateWindows( rRect );
3170     }
3171     // <--
3172 }
3173 
3174 /*************************************************************************
3175 |*
3176 |*	GetVirtualUpper() liefert bei absatzgebundenen Objekten den Upper
3177 |*  des Ankers. Falls es sich dabei um verkettete Rahmen oder
3178 |*	Fussnoten handelt, wird ggf. der "virtuelle" Upper ermittelt.
3179 |*
3180 |*************************************************************************/
3181 
GetVirtualUpper(const SwFrm * pFrm,const Point & rPos)3182 const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos )
3183 {
3184 	if( pFrm->IsTxtFrm() )
3185 	{
3186 		pFrm = pFrm->GetUpper();
3187 		if( !pFrm->Frm().IsInside( rPos ) )
3188 		{
3189 			if( pFrm->IsFtnFrm() )
3190 			{
3191 				const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow();
3192 				while( pTmp )
3193 				{
3194 					if( pTmp->Frm().IsInside( rPos ) )
3195 						return pTmp;
3196 					pTmp = pTmp->GetFollow();
3197 				}
3198 			}
3199 			else
3200 			{
3201 				SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm();
3202 				while( pTmp )
3203 				{
3204 					if( pTmp->Frm().IsInside( rPos ) )
3205 						return pTmp;
3206 					pTmp = pTmp->GetNextLink();
3207 				}
3208 			}
3209 		}
3210 	}
3211 	return pFrm;
3212 }
3213 
3214 /*************************************************************************/
3215 
Is_Lower_Of(const SwFrm * pCurrFrm,const SdrObject * pObj)3216 sal_Bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj )
3217 {
3218 	Point aPos;
3219 	const SwFrm* pFrm;
3220 	if( pObj->ISA(SwVirtFlyDrawObj) )
3221 	{
3222 		const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm();
3223         pFrm = pFly->GetAnchorFrm();
3224 		aPos = pFly->Frm().Pos();
3225 	}
3226 	else
3227 	{
3228         pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm(pObj);
3229 		aPos = pObj->GetCurrentBoundRect().TopLeft();
3230 	}
3231 	ASSERT( pFrm, "8-( Fly is lost in Space." );
3232 	pFrm = GetVirtualUpper( pFrm, aPos );
3233 	do
3234 	{	if ( pFrm == pCurrFrm )
3235 			return sal_True;
3236 		if( pFrm->IsFlyFrm() )
3237 		{
3238 			aPos = pFrm->Frm().Pos();
3239             pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3240 		}
3241 		else
3242 			pFrm = pFrm->GetUpper();
3243 	} while ( pFrm );
3244 	return sal_False;
3245 }
3246 
FindKontext(const SwFrm * pFrm,sal_uInt16 nAdditionalKontextTyp)3247 const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp )
3248 {
3249 	//Liefert die Umgebung des Frm in die kein Fly aus einer anderen
3250 	//Umgebung hineinragen kann.
3251 	const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER   | FRM_FOOTER | FRM_FTNCONT  |
3252 						FRM_FTN  | FRM_FLY      |
3253 						FRM_TAB  | FRM_ROW		| FRM_CELL |
3254 						nAdditionalKontextTyp;
3255 	do
3256 	{	if ( pFrm->GetType() & nTyp )
3257 			break;
3258 		pFrm = pFrm->GetUpper();
3259 	} while( pFrm );
3260 	return pFrm;
3261 }
3262 
IsFrmInSameKontext(const SwFrm * pInnerFrm,const SwFrm * pFrm)3263 sal_Bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm )
3264 {
3265 	const SwFrm *pKontext = FindKontext( pInnerFrm, 0 );
3266 
3267 	const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER   | FRM_FOOTER | FRM_FTNCONT  |
3268 						FRM_FTN  | FRM_FLY      |
3269 						FRM_TAB  | FRM_ROW 		| FRM_CELL;
3270 	do
3271 	{	if ( pFrm->GetType() & nTyp )
3272 		{
3273 			if( pFrm == pKontext )
3274 				return sal_True;
3275 			if( pFrm->IsCellFrm() )
3276 				return sal_False;
3277 		}
3278 		if( pFrm->IsFlyFrm() )
3279 		{
3280 			Point aPos( pFrm->Frm().Pos() );
3281             pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3282 		}
3283 		else
3284 			pFrm = pFrm->GetUpper();
3285 	} while( pFrm );
3286 
3287 	return sal_False;
3288 }
3289 
3290 
3291 //---------------------------------
3292 
lcl_CalcCellRstHeight(SwLayoutFrm * pCell)3293 SwTwips MA_FASTCALL lcl_CalcCellRstHeight( SwLayoutFrm *pCell )
3294 {
3295 	if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() )
3296 	{
3297 		SwFrm *pLow = pCell->Lower();
3298 		long nHeight = 0, nFlyAdd = 0;
3299 		do
3300 		{
3301 			long nLow = pLow->Frm().Height();
3302 			if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() )
3303 				nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height();
3304 			else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() )
3305 				nLow += ((SwSectionFrm*)pLow)->Undersize();
3306 			nFlyAdd = Max( 0L, nFlyAdd - nLow );
3307 			nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
3308 			nHeight += nLow;
3309 			pLow = pLow->GetNext();
3310 		} while ( pLow );
3311 		if ( nFlyAdd )
3312 			nHeight += nFlyAdd;
3313 
3314 		//Der Border will natuerlich auch mitspielen, er kann leider nicht
3315 		//aus PrtArea und Frm errechnet werden, da diese in beliebiger
3316 		//Kombination ungueltig sein koennen.
3317 		SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
3318 		const SwBorderAttrs &rAttrs = *aAccess.Get();
3319 		nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
3320 
3321 		return pCell->Frm().Height() - nHeight;
3322 	}
3323 	else
3324 	{
3325 		long nRstHeight = 0;
3326 		SwFrm *pLow = pCell->Lower();
3327 		do
3328 		{	nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow );
3329 			pLow = pLow->GetNext();
3330 
3331 		} while ( pLow );
3332 
3333 		return nRstHeight;
3334 	}
3335 }
3336 
CalcRowRstHeight(SwLayoutFrm * pRow)3337 SwTwips MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow )
3338 {
3339 	SwTwips nRstHeight = LONG_MAX;
3340 	SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower();
3341 	while ( pLow )
3342 	{
3343 		nRstHeight = Min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) );
3344 		pLow = (SwLayoutFrm*)pLow->GetNext();
3345 	}
3346 	return nRstHeight;
3347 }
3348 
FindPage(const SwRect & rRect,const SwFrm * pPage)3349 const SwFrm* MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage )
3350 {
3351 	if ( !rRect.IsOver( pPage->Frm() ) )
3352 	{
3353         const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper());
3354         const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0;
3355         if ( pTmpPage )
3356             pPage = pTmpPage;
3357     }
3358 
3359     return pPage;
3360 }
3361 
3362 #include <svl/smplhint.hxx>
3363 class SwFrmHolder : private SfxListener
3364 {
3365     SwFrm* pFrm;
3366     bool bSet;
3367     virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
3368 public:
SwFrmHolder()3369     SwFrmHolder() : pFrm(0), bSet(false) {}
3370     void SetFrm( SwFrm* pHold );
GetFrm()3371     SwFrm* GetFrm() { return pFrm; }
3372     void Reset();
IsSet()3373     bool IsSet() { return bSet; }
3374 };
3375 
SetFrm(SwFrm * pHold)3376 void SwFrmHolder::SetFrm( SwFrm* pHold )
3377 {
3378     bSet = true;
3379     pFrm = pHold;
3380     StartListening(*pHold);
3381 }
3382 
Reset()3383 void SwFrmHolder::Reset()
3384 {
3385     if (pFrm)
3386         EndListening(*pFrm);
3387     bSet = false;
3388     pFrm = 0;
3389 }
3390 
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)3391 void SwFrmHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
3392 {
3393     if ( rHint.IsA(TYPE(SfxSimpleHint)) )
3394     {
3395         if ( ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DYING && &rBC == pFrm )
3396             pFrm = 0;
3397     }
3398 }
3399 
GetFrmOfModify(const SwRootFrm * pLayout,SwModify const & rMod,sal_uInt16 const nFrmType,const Point * pPoint,const SwPosition * pPos,const sal_Bool bCalcFrm)3400 SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const& rMod, sal_uInt16 const nFrmType,
3401         const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm )
3402 {
3403 	SwFrm *pMinFrm = 0, *pTmpFrm;
3404     SwFrmHolder aHolder;
3405 	SwRect aCalcRect;
3406     bool bClientIterChanged = false;
3407 
3408 	SwIterator<SwFrm,SwModify> aIter( rMod );
3409 	do {
3410 		pMinFrm = 0;
3411         aHolder.Reset();
3412         sal_uInt64 nMinDist = 0;
3413         bClientIterChanged = false;
3414 
3415 		for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
3416         {
3417 			if( pTmpFrm->GetType() & nFrmType &&
3418                 ( !pLayout || pLayout == pTmpFrm->getRootFrm() ) &&
3419 				(!pTmpFrm->IsFlowFrm() ||
3420 				 !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() ))
3421 			{
3422 				if( pPoint )
3423 				{
3424                     // watch for Frm being deleted
3425                     if ( pMinFrm )
3426                         aHolder.SetFrm( pMinFrm );
3427                     else
3428                         aHolder.Reset();
3429 
3430 					if( bCalcFrm )
3431                     {
3432                         // --> OD 2005-03-04 #b6234250# - format parent Writer
3433                         // fly frame, if it isn't been formatted yet.
3434                         // Note: The Writer fly frame could be the frame itself.
3435                         SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() );
3436                         if ( pFlyFrm &&
3437                              pFlyFrm->Frm().Pos().X() == WEIT_WECH &&
3438                              pFlyFrm->Frm().Pos().Y() == WEIT_WECH )
3439                         {
3440                             SwObjectFormatter::FormatObj( *pFlyFrm );
3441                         }
3442                         // <--
3443                         pTmpFrm->Calc();
3444                     }
3445 
3446                     // #127369#
3447                     // aIter.IsChanged checks if the current pTmpFrm has been deleted while
3448                     // it is the current iterator
3449                     // FrmHolder watches for deletion of the current pMinFrm
3450                     if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrm() ) )
3451                     {
3452                         // restart iteration
3453                         bClientIterChanged = true;
3454                         break;
3455                     }
3456 
3457 					// bei Flys ggfs. ueber den Parent gehen wenn sie selbst
3458 					// nocht nicht "formatiert" sind
3459 					if( !bCalcFrm && nFrmType & FRM_FLY &&
3460                         ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() &&
3461 						WEIT_WECH == pTmpFrm->Frm().Pos().X() &&
3462 						WEIT_WECH == pTmpFrm->Frm().Pos().Y() )
3463                         aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm();
3464 					else
3465 						aCalcRect = pTmpFrm->Frm();
3466 
3467                     if ( aCalcRect.IsInside( *pPoint ) )
3468                     {
3469 					    pMinFrm = pTmpFrm;
3470 						break;
3471                     }
3472 
3473                     // Point not in rectangle. Compare distances:
3474                     const Point aCalcRectCenter = aCalcRect.Center();
3475                     const Point aDiff = aCalcRectCenter - *pPoint;
3476                     const sal_uInt64 nCurrentDist = aDiff.X() * aDiff.X() + aDiff.Y() * aDiff.Y(); // opt: no sqrt
3477                     if ( !pMinFrm || nCurrentDist < nMinDist )
3478                     {
3479         				pMinFrm = pTmpFrm;
3480 	        			nMinDist = nCurrentDist;
3481                     }
3482 				}
3483 				else
3484 				{
3485 					// Wenn kein pPoint angegeben ist, dann reichen
3486 					// wir irgendeinen raus: den ersten!
3487 					pMinFrm = pTmpFrm;
3488 					break;
3489 				}
3490 			}
3491         }
3492 	} while( bClientIterChanged );
3493 
3494 	if( pPos && pMinFrm && pMinFrm->IsTxtFrm() )
3495 		return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos );
3496 
3497 	return pMinFrm;
3498 }
3499 
IsExtraData(const SwDoc * pDoc)3500 sal_Bool IsExtraData( const SwDoc *pDoc )
3501 {
3502 	const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
3503 	return rInf.IsPaintLineNumbers() ||
3504 		   rInf.IsCountInFlys() ||
3505            ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE &&
3506 			pDoc->GetRedlineTbl().Count());
3507 }
3508 
3509 // OD 22.09.2003 #110978#
PrtWithoutHeaderAndFooter() const3510 const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const
3511 {
3512     SwRect aPrtWithoutHeaderFooter( Prt() );
3513     aPrtWithoutHeaderFooter.Pos() += Frm().Pos();
3514 
3515     const SwFrm* pLowerFrm = Lower();
3516     while ( pLowerFrm )
3517     {
3518         // Note: independent on text direction page header and page footer are
3519         //       always at top respectively at bottom of the page frame.
3520         if ( pLowerFrm->IsHeaderFrm() )
3521         {
3522             aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() +
3523                                          pLowerFrm->Frm().Height() );
3524         }
3525         if ( pLowerFrm->IsFooterFrm() )
3526         {
3527             aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() -
3528                                             pLowerFrm->Frm().Height() );
3529         }
3530 
3531         pLowerFrm = pLowerFrm->GetNext();
3532     }
3533 
3534     return aPrtWithoutHeaderFooter;
3535 }
3536 
3537 /** method to determine the spacing values of a frame
3538 
3539     OD 2004-03-10 #i28701#
3540     OD 2009-08-28 #i102458#
3541     Add output parameter <obIsLineSpacingProportional>
3542 
3543     @author OD
3544 */
GetSpacingValuesOfFrm(const SwFrm & rFrm,SwTwips & onLowerSpacing,SwTwips & onLineSpacing,bool & obIsLineSpacingProportional)3545 void GetSpacingValuesOfFrm( const SwFrm& rFrm,
3546                             SwTwips& onLowerSpacing,
3547                             SwTwips& onLineSpacing,
3548                             bool& obIsLineSpacingProportional )
3549 {
3550     if ( !rFrm.IsFlowFrm() )
3551     {
3552         onLowerSpacing = 0;
3553         onLineSpacing = 0;
3554     }
3555     else
3556     {
3557         const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace();
3558         onLowerSpacing = rULSpace.GetLower();
3559 
3560         onLineSpacing = 0;
3561         obIsLineSpacingProportional = false;
3562         if ( rFrm.IsTxtFrm() )
3563         {
3564             onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace();
3565             obIsLineSpacingProportional =
3566                 onLineSpacing != 0 &&
3567                 static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0;
3568         }
3569 
3570         ASSERT( onLowerSpacing >= 0 && onLineSpacing >= 0,
3571                 "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" );
3572     }
3573 }
3574 
3575 /** method to get the content of the table cell, skipping content from nested tables
3576 */
GetCellCntnt(const SwLayoutFrm & rCell)3577 const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell )
3578 {
3579     const SwCntntFrm* pCntnt = rCell.ContainsCntnt();
3580     const SwTabFrm* pTab = rCell.FindTabFrm();
3581 
3582     while ( pCntnt && rCell.IsAnLower( pCntnt ) )
3583     {
3584         const SwTabFrm* pTmpTab = pCntnt->FindTabFrm();
3585         if ( pTmpTab != pTab )
3586         {
3587             pCntnt = pTmpTab->FindLastCntnt();
3588             if ( pCntnt )
3589 
3590                 pCntnt = pCntnt->FindNextCnt();
3591 
3592 		}
3593 		else
3594 			break;
3595 	}
3596 	return pCntnt;
3597 }
3598 
3599 /** Can be used to check if a frame has been deleted
3600  */
HasBeenDeleted()3601 bool SwDeletionChecker::HasBeenDeleted()
3602 {
3603 	if ( !mpFrm || !mpRegIn )
3604 		return false;
3605 
3606 	SwIterator<SwFrm,SwModify> aIter(*mpRegIn);
3607 	SwFrm* pLast = aIter.First();
3608 	while ( pLast )
3609 	{
3610 		if ( pLast == mpFrm )
3611 			return false;
3612 		pLast = aIter.Next();
3613 	}
3614 
3615 	return true;
3616 }
3617 
3618