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