Update ooo320-m1
[ooovba.git] / sw / source / core / layout / frmtool.cxx
blobc7bc49c3542a4b5913ba34695967e26be84bf7a9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: frmtool.cxx,v $
10 * $Revision: 1.107 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <hintids.hxx>
34 #include <tools/bigint.hxx>
35 #include <svx/svdmodel.hxx>
36 #include <svx/svdpage.hxx>
37 #include <svx/brshitem.hxx>
38 #include <svx/keepitem.hxx>
39 #include <svx/shaditem.hxx>
40 #include <svx/ulspitem.hxx>
41 #include <svx/lrspitem.hxx>
42 #include <svx/boxitem.hxx>
43 #include <sfx2/printer.hxx>
44 // OD 08.01.2004 #i11859#
45 #include <svx/lspcitem.hxx>
48 #include <fmtornt.hxx>
49 #include <fmtanchr.hxx>
50 #include <fmthdft.hxx>
51 #include <fmtcntnt.hxx>
52 #include <fmtfsize.hxx>
53 #include <fmtsrnd.hxx>
54 #include <docary.hxx>
55 #include <lineinfo.hxx>
56 #include <swmodule.hxx>
57 #include "pagefrm.hxx"
58 #include "colfrm.hxx"
59 #include "doc.hxx"
60 #include "fesh.hxx"
61 #include "viewimp.hxx"
62 #include "pam.hxx"
63 #include "dflyobj.hxx"
64 #include "dcontact.hxx"
65 #include "frmtool.hxx"
66 #include "docsh.hxx"
67 #include "tabfrm.hxx"
68 #include "rowfrm.hxx"
69 #include "ftnfrm.hxx"
70 #include "txtfrm.hxx"
71 #include "notxtfrm.hxx"
72 #include "flyfrms.hxx"
73 #include "layact.hxx"
74 #include "pagedesc.hxx"
75 #include "section.hxx"
76 #include "sectfrm.hxx"
77 #include "node2lay.hxx"
78 #include "ndole.hxx"
79 #include "ndtxt.hxx"
80 #include "swtable.hxx"
81 #include "hints.hxx"
82 #include <layhelp.hxx>
83 #include <laycache.hxx>
85 #include <rootfrm.hxx>
87 #include "mdiexp.hxx"
88 #include "statstr.hrc"
89 // OD 21.05.2003 #108789#
90 #include <paratr.hxx>
91 // OD 2004-05-24 #i28701#
92 #include <sortedobjs.hxx>
93 // --> OD 2005-03-04 #b6234250#
94 #include <objectformatter.hxx>
95 // <--
97 // ftnfrm.cxx:
98 void lcl_RemoveFtns( SwFtnBossFrm* pBoss, BOOL bPageOnly, BOOL bEndNotes );
100 using namespace ::com::sun::star;
103 BOOL bObjsDirect = TRUE;
104 BOOL bDontCreateObjects = FALSE;
105 BOOL bSetCompletePaintOnInvalidate = FALSE;
107 BYTE StackHack::nCnt = 0;
108 BOOL StackHack::bLocked = FALSE;
112 /*************************************************************************
114 |* SwFrmNotify::SwFrmNotify()
116 |* Ersterstellung MA 27. Nov. 92
117 |* Letzte Aenderung MA 09. Apr. 97
119 |*************************************************************************/
121 SwFrmNotify::SwFrmNotify( SwFrm *pF ) :
122 pFrm( pF ),
123 aFrm( pF->Frm() ),
124 aPrt( pF->Prt() ),
125 bInvaKeep( FALSE ),
126 bValidSize( pF->GetValidSizeFlag() ),
127 // --> OD 2005-07-29 #i49383#
128 mbFrmDeleted( false )
129 // <--
131 if ( pF->IsTxtFrm() )
133 mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_True );
134 mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_False );
136 else
138 mnFlyAnchorOfst = 0;
139 mnFlyAnchorOfstNoWrap = 0;
142 bHadFollow = pF->IsCntntFrm() ?
143 (((SwCntntFrm*)pF)->GetFollow() ? TRUE : FALSE) :
144 FALSE;
147 /*************************************************************************
149 |* SwFrmNotify::~SwFrmNotify()
151 |* Ersterstellung MA 27. Nov. 92
152 |* Letzte Aenderung MA 09. Apr. 97
154 |*************************************************************************/
156 SwFrmNotify::~SwFrmNotify()
158 // --> OD 2005-07-29 #i49383#
159 if ( mbFrmDeleted )
161 return;
163 // <--
165 SWRECTFN( pFrm )
166 const BOOL bAbsP = POS_DIFF( aFrm, pFrm->Frm() );
167 const BOOL bChgWidth =
168 (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)();
169 const BOOL bChgHeight =
170 (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)();
171 const BOOL bChgFlyBasePos = pFrm->IsTxtFrm() &&
172 ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_True ) ) ||
173 ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_False ) ) );
175 if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() )
177 SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm );
179 if ( !pFlow->IsFollow() )
181 if ( !pFrm->GetIndPrev() )
183 if ( bInvaKeep )
185 SwFrm *pPre = pFrm->FindPrev();
186 if ( pPre && pPre->IsFlowFrm() )
188 // 1. pPre wants to keep with me:
189 bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev();
191 // 2. pPre is a table and the last row wants to keep with me:
192 if ( !bInvalidPrePos && pPre->IsTabFrm() )
194 SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre);
195 if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
197 SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower());
198 if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
199 bInvalidPrePos = true;
203 if ( bInvalidPrePos )
204 pPre->InvalidatePos();
208 else if ( !pFlow->HasFollow() )
210 long nOldHeight = (aFrm.*fnRect->fnGetHeight)();
211 long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
212 if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
213 pFlow->CheckKeep();
218 if ( bAbsP )
220 pFrm->SetCompletePaint();
222 SwFrm* pNxt = pFrm->GetIndNext();
223 // --> OD 2005-05-20 #121888# - skip empty section frames
224 while ( pNxt &&
225 pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
227 pNxt = pNxt->GetIndNext();
229 // <--
231 if ( pNxt )
232 pNxt->InvalidatePos();
233 else
235 // OD 04.11.2002 #104100# - correct condition for setting retouche
236 // flag for vertical layout.
237 if( pFrm->IsRetoucheFrm() &&
238 (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 )
240 pFrm->SetRetouche();
243 // A fresh follow frame does not have to be invalidated, because
244 // it is already formatted:
245 if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() )
247 if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() )
248 pFrm->InvalidateNextPos();
253 //Fuer Hintergrundgrafiken muss bei Groessenaenderungen ein Repaint her.
254 const BOOL bPrtWidth =
255 (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)();
256 const BOOL bPrtHeight =
257 (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)();
258 if ( bPrtWidth || bPrtHeight )
260 const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos();
261 if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
262 pFrm->SetCompletePaint();
264 else
266 // OD 13.11.2002 #97597# - consider case that *only* margins between
267 // frame and printing area has changed. Then, frame has to be repainted,
268 // in order to force paint of the margin areas.
269 if ( !bAbsP && (bChgWidth || bChgHeight) )
271 pFrm->SetCompletePaint();
275 const BOOL bPrtP = POS_DIFF( aPrt, pFrm->Prt() );
276 if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
277 bPrtWidth || bPrtHeight || bChgFlyBasePos )
279 if( pFrm->IsAccessibleFrm() )
281 SwRootFrm *pRootFrm = pFrm->FindRootFrm();
282 if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
283 pRootFrm->GetCurrShell() )
285 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
289 // Notification of anchored objects
290 if ( pFrm->GetDrawObjs() )
292 const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
293 SwPageFrm* pPageFrm = 0;
294 for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
296 // OD 2004-03-31 #i26791# - no general distinction between
297 // Writer fly frames and drawing objects
298 bool bNotify = false;
299 bool bNotifySize = false;
300 SwAnchoredObject* pObj = rObjs[i];
301 SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
302 // --> OD 2004-12-08 #115759#
303 const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
304 if ( !bAnchoredAsChar )
305 // <--
307 // Notify object, which aren't anchored as-character:
309 // always notify objects, if frame position has changed
310 // or if the object is to-page|to-fly anchored.
311 if ( bAbsP ||
312 pContact->ObjAnchoredAtPage() ||
313 pContact->ObjAnchoredAtFly() )
315 bNotify = true;
317 // assure that to-fly anchored Writer fly frames are
318 // registered at the correct page frame, if frame
319 // position has changed.
320 if ( bAbsP && pContact->ObjAnchoredAtFly() &&
321 pObj->ISA(SwFlyFrm) )
323 // determine to-fly anchored Writer fly frame
324 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
325 // determine page frame of to-fly anchored
326 // Writer fly frame
327 SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm();
328 // determine page frame, if needed.
329 if ( !pPageFrm )
331 pPageFrm = pFrm->FindPageFrm();
333 if ( pPageFrm != pFlyPageFrm )
335 ASSERT( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" );
336 if( pFlyPageFrm )
337 pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm );
338 else
339 pPageFrm->AppendFlyToPage( pFlyFrm );
343 // otherwise the objects are notified in dependence to
344 // its positioning and alignment
345 else
347 const SwFmtVertOrient& rVert =
348 pContact->GetFmt()->GetVertOrient();
349 if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
350 rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
351 rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
352 ( bChgHeight || bPrtHeight ) )
354 bNotify = true;
356 if ( !bNotify )
358 const SwFmtHoriOrient& rHori =
359 pContact->GetFmt()->GetHoriOrient();
360 if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
361 rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
362 rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
363 ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
365 bNotify = true;
370 else if ( bPrtWidth )
372 // Notify as-character anchored objects, if printing area
373 // width has changed.
374 bNotify = true;
375 bNotifySize = true;
378 // perform notification via the corresponding invalidations
379 if ( bNotify )
381 if ( pObj->ISA(SwFlyFrm) )
383 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
384 if ( bNotifySize )
385 pFlyFrm->_InvalidateSize();
386 // --> OD 2004-12-08 #115759# - no invalidation of
387 // position for as-character anchored objects.
388 if ( !bAnchoredAsChar )
390 pFlyFrm->_InvalidatePos();
392 // <--
393 pFlyFrm->_Invalidate();
395 else if ( pObj->ISA(SwAnchoredDrawObject) )
397 // --> OD 2004-12-08 #115759# - no invalidation of
398 // position for as-character anchored objects.
399 if ( !bAnchoredAsChar )
401 pObj->InvalidateObjPos();
403 // <--
405 else
407 ASSERT( false,
408 "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." );
414 else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() )
416 SwRootFrm *pRootFrm = pFrm->FindRootFrm();
417 if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
418 pRootFrm->GetCurrShell() )
420 pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm );
424 // #i9046# Automatic frame width
425 SwFlyFrm* pFly = 0;
426 // --> FME 2004-10-21 #i35879# Do not trust the inf flags. pFrm does not
427 // necessarily have to have an upper!
428 if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) )
429 // <--
431 // --> OD 2006-05-08 #i61999#
432 // no invalidation of columned Writer fly frames, because automatic
433 // width doesn't make sense for such Writer fly frames.
434 if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() )
436 const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize();
438 // This could be optimized. Basically the fly frame only has to
439 // be invalidated, if the first line of pFrm (if pFrm is a content
440 // frame, for other frame types its the print area) has changed its
441 // size and pFrm was responsible for the current width of pFly. On
442 // the other hand, this is only rarely used and re-calculation of
443 // the fly frame does not cause too much trouble. So we keep it this
444 // way:
445 if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() )
447 // --> OD 2005-07-29 #i50668#, #i50998# - invalidation of position
448 // of as-character anchored fly frames not needed and can cause
449 // layout loops
450 if ( !pFly->ISA(SwFlyInCntFrm) )
452 pFly->InvalidatePos();
454 // <--
455 pFly->InvalidateSize();
458 // <--
462 /*************************************************************************
464 |* SwLayNotify::SwLayNotify()
466 |* Ersterstellung MA 17. Nov. 92
467 |* Letzte Aenderung MA 03. Jun. 93
469 |*************************************************************************/
472 SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) :
473 SwFrmNotify( pLayFrm ),
474 bLowersComplete( FALSE )
478 /*************************************************************************
480 |* SwLayNotify::~SwLayNotify()
482 |* Ersterstellung MA 17. Nov. 92
483 |* Letzte Aenderung MA 13. Jun. 96
485 |*************************************************************************/
487 // OD 2004-05-11 #i28701# - local method to invalidate the position of all
488 // frames inclusive its floating screen objects, which are lowers of the given
489 // layout frame
490 void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm )
492 if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() )
494 _rLayoutFrm.InvalidateObjs( true, false );
497 SwFrm* pLowerFrm = _rLayoutFrm.Lower();
498 while ( pLowerFrm )
500 pLowerFrm->InvalidatePos();
501 if ( pLowerFrm->IsTxtFrm() )
503 static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD );
505 else if ( pLowerFrm->IsTabFrm() )
507 pLowerFrm->InvalidatePrt();
510 pLowerFrm->InvalidateObjs( true, false );
512 pLowerFrm = pLowerFrm->GetNext();
516 SwLayNotify::~SwLayNotify()
518 // --> OD 2005-07-29 #i49383#
519 if ( mbFrmDeleted )
521 return;
523 // <--
525 SwLayoutFrm *pLay = GetLay();
526 SWRECTFN( pLay )
527 BOOL bNotify = FALSE;
528 if ( pLay->Prt().SSize() != aPrt.SSize() )
530 if ( !IsLowersComplete() )
532 BOOL bInvaPercent;
534 if ( pLay->IsRowFrm() )
536 bInvaPercent = TRUE;
537 long nNew = (pLay->Prt().*fnRect->fnGetHeight)();
538 if( nNew != (aPrt.*fnRect->fnGetHeight)() )
539 ((SwRowFrm*)pLay)->AdjustCells( nNew, TRUE);
540 if( (pLay->Prt().*fnRect->fnGetWidth)()
541 != (aPrt.*fnRect->fnGetWidth)() )
542 ((SwRowFrm*)pLay)->AdjustCells( 0, FALSE );
544 else
546 //Proportionale Anpassung der innenliegenden.
547 //1. Wenn der Formatierte kein Fly ist
548 //2. Wenn er keine Spalten enthaelt
549 //3. Wenn der Fly eine feste Hoehe hat und die Spalten in der
550 // Hoehe danebenliegen.
551 //4. niemals bei SectionFrms.
552 BOOL bLow;
553 if( pLay->IsFlyFrm() )
555 if ( pLay->Lower() )
557 bLow = !pLay->Lower()->IsColumnFrm() ||
558 (pLay->Lower()->Frm().*fnRect->fnGetHeight)()
559 != (pLay->Prt().*fnRect->fnGetHeight)();
561 else
562 bLow = FALSE;
564 else if( pLay->IsSctFrm() )
566 if ( pLay->Lower() )
568 if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() )
569 bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height();
570 else
571 bLow = pLay->Prt().Width() != aPrt.Width();
573 else
574 bLow = FALSE;
576 else if( pLay->IsFooterFrm() && !pLay->HasFixSize() )
577 bLow = pLay->Prt().Width() != aPrt.Width();
578 else
579 bLow = TRUE;
580 bInvaPercent = bLow;
581 if ( bLow )
583 pLay->ChgLowersProp( aPrt.SSize() );
585 //Wenn die PrtArea gewachsen ist, so ist es moeglich, dass die
586 //Kette der Untergeordneten einen weiteren Frm aufnehmen kann,
587 //mithin muss also der 'moeglicherweise passende' Invalidiert werden.
588 //Das invalidieren lohnt nur, wenn es sich beim mir bzw. meinen
589 //Uppers um eine Moveable-Section handelt.
590 //Die PrtArea ist gewachsen, wenn die Breite oder die Hoehe groesser
591 //geworden ist.
592 if ( (pLay->Prt().Height() > aPrt.Height() ||
593 pLay->Prt().Width() > aPrt.Width()) &&
594 (pLay->IsMoveable() || pLay->IsFlyFrm()) )
596 SwFrm *pTmpFrm = pLay->Lower();
597 if ( pTmpFrm && pTmpFrm->IsFlowFrm() )
599 while ( pTmpFrm->GetNext() )
600 pTmpFrm = pTmpFrm->GetNext();
601 pTmpFrm->InvalidateNextPos();
605 bNotify = TRUE;
606 //TEUER!! aber wie macht man es geschickter?
607 if( bInvaPercent )
608 pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() );
610 if ( pLay->IsTabFrm() )
611 //Damit _nur_ der Shatten bei Groessenaenderungen gemalt wird.
612 ((SwTabFrm*)pLay)->SetComplete();
613 else if ( !pLay->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) ||
614 !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) )
615 //Damit die untergeordneten sauber retouchiert werden.
616 //Problembsp: Flys an den Henkeln packen und verkleinern.
617 //Nicht fuer Body und Page, sonst flackerts beim HTML-Laden.
618 pLay->SetCompletePaint();
621 //Lower benachrichtigen wenn sich die Position veraendert hat.
622 const BOOL bPrtPos = POS_DIFF( aPrt, pLay->Prt() );
623 const BOOL bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() );
624 const BOOL bSize = pLay->Frm().SSize() != aFrm.SSize();
626 if ( bPos && pLay->Lower() && !IsLowersComplete() )
627 pLay->Lower()->InvalidatePos();
629 if ( bPrtPos )
630 pLay->SetCompletePaint();
632 //Nachfolger benachrichtigen wenn sich die SSize geaendert hat.
633 if ( bSize )
635 if( pLay->GetNext() )
637 if ( pLay->GetNext()->IsLayoutFrm() )
638 pLay->GetNext()->_InvalidatePos();
639 else
640 pLay->GetNext()->InvalidatePos();
642 else if( pLay->IsSctFrm() )
643 pLay->InvalidateNextPos();
645 if ( !IsLowersComplete() &&
646 !(pLay->GetType()&(FRM_FLY|FRM_SECTION) &&
647 pLay->Lower() && pLay->Lower()->IsColumnFrm()) &&
648 (bPos || bNotify) && !(pLay->GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
650 // --> OD 2005-03-11 #i44016# - force unlock of position of lower objects.
651 // --> OD 2005-03-30 #i43913# - no unlock of position of objects,
652 // if <pLay> is a cell frame, and its table frame resp. its parent table
653 // frame is locked.
654 // --> OD 2005-04-15 #i47458# - force unlock of position of lower objects,
655 // only if position of layout frame has changed.
656 bool bUnlockPosOfObjs( bPos );
657 if ( bUnlockPosOfObjs && pLay->IsCellFrm() )
659 SwTabFrm* pTabFrm( pLay->FindTabFrm() );
660 if ( pTabFrm &&
661 ( pTabFrm->IsJoinLocked() ||
662 ( pTabFrm->IsFollow() &&
663 pTabFrm->FindMaster()->IsJoinLocked() ) ) )
665 bUnlockPosOfObjs = false;
668 // --> OD 2005-05-18 #i49383# - check for footnote frame, if unlock
669 // of position of lower objects is allowed.
670 else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() )
672 bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs();
674 // <--
675 // --> OD 2005-07-29 #i51303# - no unlock of object positions for sections
676 else if ( bUnlockPosOfObjs && pLay->IsSctFrm() )
678 bUnlockPosOfObjs = false;
680 // <--
681 pLay->NotifyLowerObjs( bUnlockPosOfObjs );
682 // <--
684 if ( bPos && pLay->IsFtnFrm() && pLay->Lower() )
686 // OD 2004-05-11 #i28701#
687 ::lcl_InvalidatePosOfLowers( *pLay );
689 if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm()
690 && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() )
691 ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize();
694 /*************************************************************************
696 |* SwFlyNotify::SwFlyNotify()
698 |* Ersterstellung MA 17. Nov. 92
699 |* Letzte Aenderung MA 26. Aug. 93
701 |*************************************************************************/
703 SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) :
704 SwLayNotify( pFlyFrm ),
705 // --> OD 2004-11-24 #115759# - keep correct page frame - the page frame
706 // the Writer fly frame is currently registered at.
707 pOldPage( pFlyFrm->GetPageFrm() ),
708 // <--
709 aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() )
713 /*************************************************************************
715 |* SwFlyNotify::~SwFlyNotify()
717 |* Ersterstellung MA 17. Nov. 92
718 |* Letzte Aenderung MA 09. Nov. 95
720 |*************************************************************************/
722 SwFlyNotify::~SwFlyNotify()
724 // --> OD 2005-07-29 #i49383#
725 if ( mbFrmDeleted )
727 return;
729 // <--
731 SwFlyFrm *pFly = GetFly();
732 if ( pFly->IsNotifyBack() )
734 ViewShell *pSh = pFly->GetShell();
735 SwViewImp *pImp = pSh ? pSh->Imp() : 0;
736 if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
738 //Wenn in der LayAction das IsAgain gesetzt ist kann es sein,
739 //dass die alte Seite inzwischen vernichtet wurde!
740 ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt );
741 // --> OD 2004-10-20 #i35640# - additional notify anchor text frame,
742 // if Writer fly frame has changed its page
743 if ( pFly->GetAnchorFrm()->IsTxtFrm() &&
744 pFly->GetPageFrm() != pOldPage )
746 pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
748 // <--
750 pFly->ResetNotifyBack();
753 //Haben sich Groesse oder Position geaendert, so sollte die View
754 //das wissen.
755 SWRECTFN( pFly )
756 const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() );
757 const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize();
758 const bool bPrtChgd = aPrt != pFly->Prt();
759 if ( bPosChgd || bFrmChgd || bPrtChgd )
761 pFly->NotifyDrawObj();
763 if ( bPosChgd && aFrm.Pos().X() != WEIT_WECH )
765 // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
766 // reason: New positioning and alignment (e.g. to-paragraph anchored,
767 // but aligned at page) are introduced.
768 // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
769 // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>.
771 if ( pFly->IsFlyAtCntFrm() )
773 SwFrm *pNxt = pFly->AnchorFrm()->FindNext();
774 if ( pNxt )
776 pNxt->InvalidatePos();
780 // --> OD 2004-11-05 #i26945# - notify anchor.
781 // Needed for negative positioned Writer fly frames
782 if ( pFly->GetAnchorFrm()->IsTxtFrm() )
784 pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
786 // <--
789 // OD 2004-05-13 #i28701#
790 // --> OD 2005-03-21 #i45180# - no adjustment of layout process flags and
791 // further notifications/invalidations, if format is called by grow/shrink
792 if ( pFly->ConsiderObjWrapInfluenceOnObjPos() &&
793 ( !pFly->ISA(SwFlyFreeFrm) ||
794 !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) )
795 // <--
797 // --> OD 2005-09-05 #i54138# - suppress restart of the layout process
798 // on changed frame height.
799 // Note: It doesn't seem to be necessary and can cause layout loops.
800 if ( bPosChgd )
801 // <--
803 // indicate a restart of the layout process
804 pFly->SetRestartLayoutProcess( true );
806 else
808 // lock position
809 pFly->LockPosition();
811 if ( !pFly->ConsiderForTextWrap() )
813 // indicate that object has to be considered for text wrap
814 pFly->SetConsiderForTextWrap( true );
815 // invalidate 'background' in order to allow its 'background'
816 // to wrap around it.
817 pFly->NotifyBackground( pFly->GetPageFrm(),
818 pFly->GetObjRectWithSpaces(),
819 PREP_FLY_ARRIVE );
820 // invalidate position of anchor frame in order to force
821 // a re-format of the anchor frame, which also causes a
822 // re-format of the invalid previous frames of the anchor frame.
823 pFly->AnchorFrm()->InvalidatePos();
829 /*************************************************************************
831 |* SwCntntNotify::SwCntntNotify()
833 |* Ersterstellung MA 24. Nov. 92
834 |* Letzte Aenderung MA 16. May. 95
836 |*************************************************************************/
838 SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) :
839 SwFrmNotify( pCntntFrm ),
840 // OD 08.01.2004 #i11859#
841 mbChkHeightOfLastLine( false ),
842 mnHeightOfLastLine( 0L ),
843 // OD 2004-02-26 #i25029#
844 mbInvalidatePrevPrtArea( false ),
845 mbBordersJoinedWithPrev( false )
847 // OD 08.01.2004 #i11859#
848 if ( pCntntFrm->IsTxtFrm() )
850 SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm);
851 if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
853 const SwAttrSet* pSet = pTxtFrm->GetAttrSet();
854 const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
855 if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
857 mbChkHeightOfLastLine = true;
858 mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine();
864 /*************************************************************************
866 |* SwCntntNotify::~SwCntntNotify()
868 |* Ersterstellung MA 24. Nov. 92
869 |* Letzte Aenderung MA 09. Apr. 97
871 |*************************************************************************/
873 SwCntntNotify::~SwCntntNotify()
875 // --> OD 2005-07-29 #i49383#
876 if ( mbFrmDeleted )
878 return;
880 // <--
882 SwCntntFrm *pCnt = GetCnt();
883 if ( bSetCompletePaintOnInvalidate )
884 pCnt->SetCompletePaint();
886 SWRECTFN( pCnt )
887 if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) ||
888 pCnt->Frm().SSize() != aFrm.SSize()))
890 SwLayoutFrm* pCell = pCnt->GetUpper();
891 while( !pCell->IsCellFrm() && pCell->GetUpper() )
892 pCell = pCell->GetUpper();
893 ASSERT( pCell->IsCellFrm(), "Where's my cell?" );
894 if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() )
895 pCell->InvalidatePrt(); //fuer vertikale Ausrichtung.
898 // OD 2004-02-26 #i25029#
899 if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
900 pCnt->IsTxtFrm() &&
901 !pCnt->IsFollow() && !pCnt->GetIndPrev() )
903 // determine previous frame
904 SwFrm* pPrevFrm = pCnt->FindPrev();
905 // skip empty section frames and hidden text frames
907 while ( pPrevFrm &&
908 ( ( pPrevFrm->IsSctFrm() &&
909 !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) ||
910 ( pPrevFrm->IsTxtFrm() &&
911 static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) )
913 pPrevFrm = pPrevFrm->FindPrev();
917 // Invalidate printing area of found previous frame
918 if ( pPrevFrm )
920 if ( pPrevFrm->IsSctFrm() )
922 if ( pCnt->IsInSct() )
924 // Note: found previous frame is a section frame and
925 // <pCnt> is also inside a section.
926 // Thus due to <mbBordersJoinedWithPrev>,
927 // <pCnt> had joined its borders/shadow with the
928 // last content of the found section.
929 // Invalidate printing area of last content in found section.
930 SwFrm* pLstCntntOfSctFrm =
931 static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
932 if ( pLstCntntOfSctFrm )
934 pLstCntntOfSctFrm->InvalidatePrt();
938 else
940 pPrevFrm->InvalidatePrt();
945 BOOL bFirst = (aFrm.*fnRect->fnGetWidth)() == 0;
947 if ( pCnt->IsNoTxtFrm() )
949 //Aktive PlugIn's oder OLE-Objekte sollten etwas von der Veraenderung
950 //mitbekommen, damit sie Ihr Window entsprechend verschieben.
951 ViewShell *pSh = pCnt->GetShell();
952 if ( pSh )
954 SwOLENode *pNd;
955 if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) &&
956 (pNd->GetOLEObj().IsOleRef() ||
957 pNd->IsOLESizeInvalid()) )
959 ASSERT( pCnt->IsInFly(), "OLE not in FlyFrm" );
960 SwFlyFrm *pFly = pCnt->FindFlyFrm();
961 svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
962 SwFEShell *pFESh = 0;
963 ViewShell *pTmp = pSh;
965 { if ( pTmp->ISA( SwCrsrShell ) )
967 pFESh = (SwFEShell*)pTmp;
968 // #108369#: Here used to be the condition if (!bFirst).
969 // I think this should mean "do not call CalcAndSetScale"
970 // if the frame is formatted for the first time.
971 // Unfortunately this is not valid anymore since the
972 // SwNoTxtFrm already gets a width during CalcLowerPreps.
973 // Nevertheless, the indention of !bFirst seemed to be
974 // to assure that the OLE objects have already been notified
975 // if necessary before calling CalcAndSetScale.
976 // So I replaced !bFirst by !IsOLESizeInvalid. There is
977 // one additional problem specific to the word import:
978 // The layout is calculated _before_ calling PrtOLENotify,
979 // and the OLE objects are not invalidated during import.
980 // Therefore I added the condition !IsUpdateExpFld,
981 // have a look at the occurence of CalcLayout in
982 // uiview/view.cxx.
983 if ( !pNd->IsOLESizeInvalid() &&
984 !pSh->GetDoc()->IsUpdateExpFld() )
985 pFESh->CalcAndSetScale( xObj, &pFly->Prt(), &pFly->Frm());
987 pTmp = (ViewShell*)pTmp->GetNext();
988 } while ( pTmp != pSh );
990 if ( pFESh && pNd->IsOLESizeInvalid() )
992 pNd->SetOLESizeInvalid( FALSE );
993 //TODO/LATER: needs OnDocumentPrinterChanged
994 //xObj->OnDocumentPrinterChanged( pNd->GetDoc()->getPrinter( false ) );
995 pFESh->CalcAndSetScale( xObj );//Client erzeugen lassen.
998 //dito Animierte Grafiken
999 if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() )
1001 ((SwNoTxtFrm*)pCnt)->StopAnimation();
1002 pSh->InvalidateWindows( Frm() );
1007 if ( bFirst )
1009 pCnt->SetRetouche(); //fix(13870)
1011 SwDoc *pDoc = pCnt->GetNode()->GetDoc();
1012 if ( pDoc->GetSpzFrmFmts()->Count() &&
1013 !pDoc->IsLoaded() && !pDoc->IsNewDoc() )
1015 //Der Frm wurde wahrscheinlich zum ersten mal formatiert.
1016 //Wenn ein Filter Flys oder Zeichenobjekte einliest und diese
1017 //Seitengebunden sind, hat er ein Problem, weil er i.d.R. die
1018 //Seitennummer nicht kennt. Er weiss lediglich welches der Inhalt
1019 //(CntntNode) an dieser Stelle ist.
1020 //Die Filter stellen dazu das Ankerattribut der Objekte so ein, dass
1021 //sie vom Typ zwar Seitengebunden sind, aber der Index des Ankers
1022 //auf diesen CntntNode zeigt.
1023 //Hier werden diese vorlauefigen Verbindungen aufgeloest.
1025 const SwPageFrm *pPage = 0;
1026 SwNodeIndex *pIdx = 0;
1027 SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1029 for ( USHORT i = 0; i < pTbl->Count(); ++i )
1031 if ( !pPage )
1032 pPage = pCnt->FindPageFrm();
1033 SwFrmFmt *pFmt = (*pTbl)[i];
1034 const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1036 if ( FLY_PAGE != rAnch.GetAnchorId() &&
1037 FLY_AT_CNTNT != rAnch.GetAnchorId() )
1038 continue; //#60878# nicht etwa zeichengebundene.
1040 BOOL bCheckPos = FALSE;
1041 if ( rAnch.GetCntntAnchor() )
1043 if ( !pIdx )
1045 pIdx = new SwNodeIndex( *pCnt->GetNode() );
1047 if ( rAnch.GetCntntAnchor()->nNode == *pIdx )
1049 bCheckPos = TRUE;
1050 if ( FLY_PAGE == rAnch.GetAnchorId() )
1052 ASSERT( false, "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." );
1053 SwFmtAnchor aAnch( rAnch );
1054 aAnch.SetAnchor( 0 );
1055 aAnch.SetPageNum( pPage->GetPhyPageNum() );
1056 pFmt->SetFmtAttr( aAnch );
1057 if ( RES_DRAWFRMFMT != pFmt->Which() )
1058 pFmt->MakeFrms();
1063 delete pIdx;
1067 // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
1068 // if height of last line has changed.
1069 if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine )
1071 if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() )
1073 pCnt->InvalidateNextPrtArea();
1077 // --> OD 2005-03-07 #i44049#
1078 if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) )
1080 pCnt->InvalidateObjs( true );
1082 // <--
1084 // --> OD 2005-04-12 #i43255# - move code to invalidate at-character
1085 // anchored objects due to a change of its anchor character from
1086 // method <SwTxtFrm::Format(..)>.
1087 if ( pCnt->IsTxtFrm() )
1089 SwTxtFrm* pMasterFrm = pCnt->IsFollow()
1090 ? static_cast<SwTxtFrm*>(pCnt)->FindMaster()
1091 : static_cast<SwTxtFrm*>(pCnt);
1092 if ( pMasterFrm && !pMasterFrm->IsFlyLock() &&
1093 pMasterFrm->GetDrawObjs() )
1095 SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs();
1096 for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
1098 SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
1099 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
1100 == FLY_AUTO_CNTNT )
1102 pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() );
1107 // <--
1110 /*************************************************************************
1112 |* InsertCnt
1114 |* Beschreibung Hilfsfunktionen, die friend von irgendwem sind, damit
1115 |* nicht immer gleich 'ne ganze Klasse befreundet werden
1116 |* muss.
1117 |* Ersterstellung MA 13. Apr. 93
1118 |* Letzte Aenderung MA 11. May. 95
1120 |*************************************************************************/
1122 void AppendObjs( const SwSpzFrmFmts *pTbl, ULONG nIndex,
1123 SwFrm *pFrm, SwPageFrm *pPage )
1125 for ( USHORT i = 0; i < pTbl->Count(); ++i )
1127 SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i];
1128 const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1129 if ( rAnch.GetCntntAnchor() &&
1130 (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) )
1132 const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL
1133 //Wird ein Rahmen oder ein SdrObject beschrieben?
1134 const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
1135 // OD 23.06.2003 #108784# - append also drawing objects anchored
1136 // as character.
1137 const bool bDrawObjInCntnt = bSdrObj &&
1138 rAnch.GetAnchorId() == FLY_IN_CNTNT;
1140 if( bFlyAtFly ||
1141 rAnch.GetAnchorId() == FLY_AT_CNTNT ||
1142 rAnch.GetAnchorId() == FLY_AUTO_CNTNT ||
1143 bDrawObjInCntnt )
1145 SdrObject* pSdrObj = 0;
1146 if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
1148 ASSERT( !bSdrObj, "DrawObject not found." );
1149 pFmt->GetDoc()->DelFrmFmt( pFmt );
1150 --i;
1151 continue;
1153 if ( pSdrObj )
1155 if ( !pSdrObj->GetPage() )
1157 pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1158 InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
1161 SwDrawContact* pNew =
1162 static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
1163 if ( !pNew->GetAnchorFrm() )
1165 pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) );
1167 // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1168 // if necessary. But control objects have to be excluded.
1169 else if ( !::CheckControlLayer( pSdrObj ) &&
1170 pNew->GetAnchorFrm() != pFrm &&
1171 !pNew->GetDrawObjectByAnchorFrm( *pFrm ) )
1173 SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
1174 pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );
1176 // for repaint, use new ActionChanged()
1177 // pDrawVirtObj->SendRepaintBroadcast();
1178 pDrawVirtObj->ActionChanged();
1182 else
1184 SwFlyFrm *pFly;
1185 if( bFlyAtFly )
1186 pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm );
1187 else
1188 pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm );
1189 pFly->Lock();
1190 pFrm->AppendFly( pFly );
1191 pFly->Unlock();
1192 if ( pPage )
1193 ::RegistFlys( pPage, pFly );
1200 BOOL MA_FASTCALL lcl_ObjConnected( SwFrmFmt *pFmt )
1202 SwClientIter aIter( *pFmt );
1203 if ( RES_FLYFRMFMT == pFmt->Which() )
1204 return 0 != aIter.First( TYPE(SwFlyFrm) );
1205 else
1207 SwDrawContact *pContact;
1208 if ( 0 != (pContact = (SwDrawContact*)aIter.First( TYPE(SwDrawContact))))
1209 return pContact->GetAnchorFrm() != 0;
1211 return FALSE;
1214 /** helper method to determine, if a <SwFrmFmt>, which has an object connected,
1215 is located in header or footer.
1217 OD 23.06.2003 #108784#
1219 @author OD
1221 bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt )
1223 ASSERT( lcl_ObjConnected( &_rFmt ),
1224 "::lcl_InHeaderOrFooter(..) - <SwFrmFmt> has no connected object" );
1226 bool bRetVal = false;
1228 const SwFmtAnchor& rAnch = _rFmt.GetAnchor();
1230 if ( rAnch.GetAnchorId() != FLY_PAGE )
1232 bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode );
1235 return bRetVal;
1238 void AppendAllObjs( const SwSpzFrmFmts *pTbl )
1240 //Verbinden aller Objekte, die in der SpzTbl beschrieben sind mit dem
1241 //Layout.
1242 //Wenn sich nix mehr tut hoeren wir auf. Dann koennen noch Formate
1243 //uebrigbleiben, weil wir weder zeichengebunde Rahmen verbinden noch
1244 //Objecte die in zeichengebundenen verankert sind.
1246 SwSpzFrmFmts aCpy( 255, 255 );
1247 aCpy.Insert( pTbl, 0 );
1249 USHORT nOldCnt = USHRT_MAX;
1251 while ( aCpy.Count() && aCpy.Count() != nOldCnt )
1253 nOldCnt = aCpy.Count();
1254 for ( int i = 0; i < int(aCpy.Count()); ++i )
1256 SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ USHORT(i) ];
1257 const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1258 BOOL bRemove = FALSE;
1259 if ( rAnch.GetAnchorId() == FLY_PAGE || rAnch.GetAnchorId() == FLY_IN_CNTNT )
1260 //Seitengebunde sind bereits verankert, zeichengebundene
1261 //will ich hier nicht.
1262 bRemove = TRUE;
1263 else if ( FALSE == (bRemove = ::lcl_ObjConnected( pFmt )) ||
1264 ::lcl_InHeaderOrFooter( *pFmt ) )
1266 // OD 23.06.2003 #108784# - correction: for objects in header
1267 // or footer create frames, in spite of the fact that an connected
1268 // objects already exists.
1269 //Fuer Flys und DrawObjs nur dann ein MakeFrms rufen wenn noch
1270 //keine abhaengigen Existieren, andernfalls, oder wenn das
1271 //MakeFrms keine abhaengigen erzeugt, entfernen.
1272 pFmt->MakeFrms();
1273 bRemove = ::lcl_ObjConnected( pFmt );
1275 if ( bRemove )
1277 aCpy.Remove( USHORT(i) );
1278 --i;
1282 aCpy.Remove( 0, aCpy.Count() );
1285 /** local method to set 'working' position for newly inserted frames
1287 OD 12.08.2003 #i17969#
1289 @author OD
1291 void lcl_SetPos( SwFrm& _rNewFrm,
1292 const SwLayoutFrm& _rLayFrm )
1294 SWRECTFN( (&_rLayFrm) )
1295 (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() );
1296 // move position by one SwTwip in text flow direction in order to get
1297 // notifications for a new calculated position after its formatting.
1298 if ( bVert )
1299 _rNewFrm.Frm().Pos().X() -= 1;
1300 else
1301 _rNewFrm.Frm().Pos().Y() += 1;
1304 void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc,
1305 ULONG nIndex, BOOL bPages, ULONG nEndIndex,
1306 SwFrm *pPrv )
1308 pDoc->BlockIdling();
1309 SwRootFrm* pLayout = pDoc->GetRootFrm();
1310 const BOOL bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False;
1311 if(pLayout)
1312 pLayout->SetCallbackActionEnabled( FALSE );
1314 //Bei der Erzeugung des Layouts wird bPages mit TRUE uebergeben. Dann
1315 //werden schon mal alle x Absaetze neue Seiten angelegt. Bei umbruechen
1316 //und/oder Pagedescriptorwechseln werden gleich die entsprechenden Seiten
1317 //angelegt.
1318 //Vorteil ist, das einerseits schon eine annaehernd realistische Zahl von
1319 //Seiten angelegt wird, vor allem aber gibt es nicht mehr eine schier
1320 //lange Kette von Absaetzen teuer verschoben werden muss, bis sie sich auf
1321 //ertraegliches mass reduziert hat.
1322 //Wir gehen mal davon aus, da? 20 Absaetze auf eine Seite passen
1323 //Damit es in extremen Faellen nicht gar so heftig rechenen wir je nach
1324 //Node noch etwas drauf.
1325 //Wenn in der DocStatistik eine brauchebare Seitenzahl angegeben ist
1326 //(wird beim Schreiben gepflegt), so wird von dieser Seitenanzahl
1327 //ausgegengen.
1328 const BOOL bStartPercent = bPages && !nEndIndex;
1330 SwPageFrm *pPage = pLay->FindPageFrm();
1331 const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1332 SwFrm *pFrm = 0;
1333 BOOL bBreakAfter = FALSE;
1335 SwActualSection *pActualSection = 0;
1336 SwLayHelper *pPageMaker;
1338 //Wenn das Layout erzeugt wird (bPages == TRUE) steuern wir den Progress
1339 //an. Flys und DrawObjekte werden dann nicht gleich verbunden, dies
1340 //passiert erst am Ende der Funktion.
1341 if ( bPages )
1343 // Attention: the SwLayHelper class uses references to the content-,
1344 // page-, layout-frame etc. and may change them!
1345 pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay,
1346 pActualSection, bBreakAfter, nIndex, 0 == nEndIndex );
1347 if( bStartPercent )
1349 const ULONG nPageCount = pPageMaker->CalcPageCount();
1350 if( nPageCount )
1351 bObjsDirect = FALSE;
1354 else
1355 pPageMaker = NULL;
1357 if( pLay->IsInSct() &&
1358 ( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hierdurch werden Frischlinge
1359 // abgefangen, deren Flags noch nicht ermittelt werden koennen,
1360 // so z.B. beim Einfuegen einer Tabelle
1362 SwSectionFrm* pSct = pLay->FindSctFrm();
1363 // Wenn Inhalt in eine Fussnote eingefuegt wird, die in einem spaltigen
1364 // Bereich liegt, so darf der spaltige Bereich nicht aufgebrochen werden.
1365 // Nur wenn im Innern der Fussnote ein Bereich liegt, ist dies ein
1366 // Kandidat fuer pActualSection.
1367 // Gleiches gilt fuer Bereiche in Tabellen, wenn innerhalb einer Tabelle
1368 // eingefuegt wird, duerfen nur Bereiche, die ebenfalls im Innern liegen,
1369 // aufgebrochen werden.
1370 if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) &&
1371 ( !pLay->IsInTab() || pSct->IsInTab() ) )
1373 pActualSection = new SwActualSection( 0, pSct, 0 );
1374 ASSERT( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(),
1375 "_InsertCnt: Wrong Call" );
1379 //If a section is "open", the pActualSection points to an SwActualSection.
1380 //If the page breaks, for "open" sections a follow will created.
1381 //For nested sections (which have, however, not a nested layout),
1382 //the SwActualSection class has a member, which points to an upper(section).
1383 //When the "inner" section finishs, the upper will used instead.
1385 while( TRUE )
1387 SwNode *pNd = pDoc->GetNodes()[nIndex];
1388 if ( pNd->IsCntntNode() )
1390 SwCntntNode* pNode = (SwCntntNode*)pNd;
1391 pFrm = pNode->IsTxtNode() ? new SwTxtFrm( (SwTxtNode*)pNode ) :
1392 pNode->MakeFrm();
1393 if( pPageMaker )
1394 pPageMaker->CheckInsert( nIndex );
1396 pFrm->InsertBehind( pLay, pPrv );
1397 // --> OD 2005-12-01 #i27138#
1398 // notify accessibility paragraphs objects about changed
1399 // CONTENT_FLOWS_FROM/_TO relation.
1400 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1401 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1402 if ( pFrm->IsTxtFrm() )
1404 ViewShell* pViewShell( pFrm->GetShell() );
1405 // no notification, if <ViewShell> is in construction
1406 if ( pViewShell && !pViewShell->IsInConstructor() &&
1407 pViewShell->GetLayout() &&
1408 pViewShell->GetLayout()->IsAnyShellAccessible() )
1410 pViewShell->InvalidateAccessibleParaFlowRelation(
1411 dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1412 dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1413 // --> OD 2006-08-28 #i68958#
1414 // The information flags of the text frame are validated
1415 // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1416 // The information flags have to be invalidated, because
1417 // it is possible, that the one of its upper frames
1418 // isn't inserted into the layout.
1419 pFrm->InvalidateInfFlags();
1420 // <--
1423 // <--
1424 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1425 // for setting position at newly inserted frame
1426 lcl_SetPos( *pFrm, *pLay );
1427 pPrv = pFrm;
1429 if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
1430 AppendObjs( pTbl, nIndex, pFrm, pPage );
1432 else if ( pNd->IsTableNode() )
1433 { //Sollten wir auf eine Tabelle gestossen sein?
1434 SwTableNode *pTblNode = (SwTableNode*)pNd;
1436 // #108116# loading may produce table structures that GCLines
1437 // needs to clean up. To keep table formulas correct, change
1438 // all table formulas to internal (BOXPTR) representation.
1439 SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() );
1440 aMsgHnt.eFlags = TBL_BOXPTR;
1441 pDoc->UpdateTblFlds( &aMsgHnt );
1442 pTblNode->GetTable().GCLines();
1444 pFrm = pTblNode->MakeFrm();
1446 if( pPageMaker )
1447 pPageMaker->CheckInsert( nIndex );
1449 pFrm->InsertBehind( pLay, pPrv );
1450 // --> OD 2005-12-01 #i27138#
1451 // notify accessibility paragraphs objects about changed
1452 // CONTENT_FLOWS_FROM/_TO relation.
1453 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1454 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1456 ViewShell* pViewShell( pFrm->GetShell() );
1457 // no notification, if <ViewShell> is in construction
1458 if ( pViewShell && !pViewShell->IsInConstructor() &&
1459 pViewShell->GetLayout() &&
1460 pViewShell->GetLayout()->IsAnyShellAccessible() )
1462 pViewShell->InvalidateAccessibleParaFlowRelation(
1463 dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1464 dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1467 // <--
1468 if ( bObjsDirect && pTbl->Count() )
1469 ((SwTabFrm*)pFrm)->RegistFlys();
1470 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1471 // for setting position at newly inserted frame
1472 lcl_SetPos( *pFrm, *pLay );
1474 pPrv = pFrm;
1475 //Index auf den Endnode der Tabellensection setzen.
1476 nIndex = pTblNode->EndOfSectionIndex();
1478 SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm;
1479 while ( pTmpFrm )
1481 pTmpFrm->CheckDirChange();
1482 pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL;
1486 else if ( pNd->IsSectionNode() )
1488 SwSectionNode *pNode = (SwSectionNode*)pNd;
1489 if( pNode->GetSection().CalcHiddenFlag() )
1490 // ist versteckt, ueberspringe den Bereich
1491 nIndex = pNode->EndOfSectionIndex();
1492 else
1494 pFrm = pNode->MakeFrm();
1495 pActualSection = new SwActualSection( pActualSection,
1496 (SwSectionFrm*)pFrm, pNode );
1497 if ( pActualSection->GetUpper() )
1499 //Hinter den Upper einsetzen, beim EndNode wird der "Follow"
1500 //des Uppers erzeugt.
1501 SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm();
1502 pFrm->InsertBehind( pTmp->GetUpper(), pTmp );
1503 // OD 25.03.2003 #108339# - direct initialization of section
1504 // after insertion in the layout
1505 static_cast<SwSectionFrm*>(pFrm)->Init();
1507 else
1509 pFrm->InsertBehind( pLay, pPrv );
1510 // OD 25.03.2003 #108339# - direct initialization of section
1511 // after insertion in the layout
1512 static_cast<SwSectionFrm*>(pFrm)->Init();
1514 // --> FME 2004-09-08 #i33963#
1515 // Do not trust the IsInFtn flag. If we are currently
1516 // building up a table, the upper of pPrv may be a cell
1517 // frame, but the cell frame does not have an upper yet.
1518 if( pPrv && 0 != pPrv->ImplFindFtnFrm() )
1519 // <--
1521 if( pPrv->IsSctFrm() )
1522 pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt();
1523 if( pPrv && pPrv->IsTxtFrm() )
1524 ((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, FALSE );
1527 // --> OD 2005-12-01 #i27138#
1528 // notify accessibility paragraphs objects about changed
1529 // CONTENT_FLOWS_FROM/_TO relation.
1530 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1531 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1533 ViewShell* pViewShell( pFrm->GetShell() );
1534 // no notification, if <ViewShell> is in construction
1535 if ( pViewShell && !pViewShell->IsInConstructor() &&
1536 pViewShell->GetLayout() &&
1537 pViewShell->GetLayout()->IsAnyShellAccessible() )
1539 pViewShell->InvalidateAccessibleParaFlowRelation(
1540 dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1541 dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1544 // <--
1545 pFrm->CheckDirChange();
1547 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1548 // for setting position at newly inserted frame
1549 lcl_SetPos( *pFrm, *pLay );
1551 // OD 20.11.2002 #105405# - no page, no invalidate.
1552 if ( pPage )
1554 // OD 18.09.2002 #100522#
1555 // invalidate page in order to force format and paint of
1556 // inserted section frame
1557 pFrm->InvalidatePage( pPage );
1559 // FME 10.11.2003 #112243#
1560 // Invalidate fly content flag:
1561 if ( pFrm->IsInFly() )
1562 pPage->InvalidateFlyCntnt();
1564 // OD 14.11.2002 #104684# - invalidate page content in order to
1565 // force format and paint of section content.
1566 pPage->InvalidateCntnt();
1569 pLay = (SwLayoutFrm*)pFrm;
1570 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1571 pLay = pLay->GetNextLayoutLeaf();
1572 pPrv = 0;
1575 else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
1577 ASSERT( pActualSection, "Sectionende ohne Anfang?" );
1578 ASSERT( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(),
1579 "Sectionende mit falschen Start Node?" );
1581 //Section schliessen, ggf. die umgebende Section wieder
1582 //aktivieren.
1583 SwActualSection *pTmp = pActualSection->GetUpper();
1584 delete pActualSection;
1585 pLay = pLay->FindSctFrm();
1586 if ( 0 != (pActualSection = pTmp) )
1588 //Koennte noch sein, das der letzte SectionFrm leer geblieben
1589 //ist. Dann ist es jetzt an der Zeit ihn zu entfernen.
1590 if ( !pLay->ContainsCntnt() )
1592 SwFrm *pTmpFrm = pLay;
1593 pLay = pTmpFrm->GetUpper();
1594 pPrv = pTmpFrm->GetPrev();
1595 pTmpFrm->Remove();
1596 delete pTmpFrm;
1598 else
1600 pPrv = pLay;
1601 pLay = pLay->GetUpper();
1604 // new section frame
1605 pFrm = pActualSection->GetSectionNode()->MakeFrm();
1606 pFrm->InsertBehind( pLay, pPrv );
1607 static_cast<SwSectionFrm*>(pFrm)->Init();
1609 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1610 // for setting position at newly inserted frame
1611 lcl_SetPos( *pFrm, *pLay );
1613 SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm();
1615 // a follow has to be appended to the new section frame
1616 SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow();
1617 if ( pFollow )
1619 pOuterSectionFrm->SetFollow( NULL );
1620 pOuterSectionFrm->InvalidateSize();
1621 ((SwSectionFrm*)pFrm)->SetFollow( pFollow );
1624 // Wir wollen keine leeren Teile zuruecklassen
1625 if( ! pOuterSectionFrm->IsColLocked() &&
1626 ! pOuterSectionFrm->ContainsCntnt() )
1628 pOuterSectionFrm->DelEmpty( TRUE );
1629 delete pOuterSectionFrm;
1631 pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm );
1633 pLay = (SwLayoutFrm*)pFrm;
1634 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1635 pLay = pLay->GetNextLayoutLeaf();
1636 pPrv = 0;
1638 else
1640 //Nix mehr mit Sections, es geht direkt hinter dem SectionFrame
1641 //weiter.
1642 pPrv = pLay;
1643 pLay = pLay->GetUpper();
1646 else if( pNd->IsStartNode() &&
1647 SwFlyStartNode == ((SwStartNode*)pNd)->GetStartNodeType() )
1649 if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects )
1651 SwFlyFrm* pFly = pLay->FindFlyFrm();
1652 if( pFly )
1653 AppendObjs( pTbl, nIndex, pFly, pPage );
1656 else
1657 // Weder Cntnt noch Tabelle noch Section,
1658 // also muessen wir fertig sein.
1659 break;
1661 ++nIndex;
1662 // Der Endnode wird nicht mehr mitgenommen, es muss vom
1663 // Aufrufenden (Section/MakeFrms()) sichergestellt sein, dass das Ende
1664 // des Bereichs vor dem EndIndex liegt!
1665 if ( nEndIndex && nIndex >= nEndIndex )
1666 break;
1669 if ( pActualSection )
1671 //Kann passieren, dass noch eine leere (Follow-)Section uebrig geblieben ist.
1672 if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() )
1674 pLay->Remove();
1675 delete pLay;
1677 delete pActualSection;
1680 if ( bPages ) //Jetzt noch die Flys verbinden lassen.
1682 if ( !bDontCreateObjects )
1683 AppendAllObjs( pTbl );
1684 bObjsDirect = TRUE;
1687 if( pPageMaker )
1689 pPageMaker->CheckFlyCache( pPage );
1690 delete pPageMaker;
1691 if( pDoc->GetLayoutCache() )
1693 #ifndef PRODUCT
1694 #if OSL_DEBUG_LEVEL > 1
1695 pDoc->GetLayoutCache()->CompareLayout( *pDoc );
1696 #endif
1697 #endif
1698 pDoc->GetLayoutCache()->ClearImpl();
1702 pDoc->UnblockIdling();
1703 if(pLayout)
1704 pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
1708 void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
1709 const SwNodeIndex &rEndIdx )
1711 bObjsDirect = FALSE;
1713 SwNodeIndex aTmp( rSttIdx );
1714 ULONG nEndIdx = rEndIdx.GetIndex();
1715 SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp,
1716 pDoc->GetNodes()[ nEndIdx-1 ]);
1717 if ( pNd )
1719 BOOL bApres = aTmp < rSttIdx;
1720 SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
1721 SwFrm* pFrm;
1722 while( 0 != (pFrm = aNode2Layout.NextFrm()) )
1724 SwLayoutFrm *pUpper = pFrm->GetUpper();
1725 SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm();
1726 BOOL bOldLock, bOldFtn;
1727 if( pFtnFrm )
1729 bOldFtn = pFtnFrm->IsColLocked();
1730 pFtnFrm->ColLock();
1732 else
1733 bOldFtn = TRUE;
1734 SwSectionFrm* pSct = pUpper->FindSctFrm();
1735 // Es sind innerhalb von Fussnoten nur die Bereiche interessant,
1736 // die in den Fussnoten liegen, nicht etwa die (spaltigen) Bereiche,
1737 // in denen die Fussnoten(Container) liegen.
1738 // #109767# Table frame is in section, insert section in cell frame.
1739 if( pSct && ( pFtnFrm && !pSct->IsInFtn() ) || pUpper->IsCellFrm() )
1740 pSct = NULL;
1741 if( pSct )
1742 { // damit der SectionFrm nicht zerstoert wird durch pTmp->MoveFwd()
1743 bOldLock = pSct->IsColLocked();
1744 pSct->ColLock();
1746 else
1747 bOldLock = TRUE;
1749 // Wenn pFrm sich nicht bewegen kann, koennen wir auch niemanden
1750 // auf die naechste Seite schieben. Innerhalb eines Rahmens auch
1751 // nicht ( in der 1. Spalte eines Rahmens waere pFrm Moveable()! )
1752 // Auch in spaltigen Bereichen in Tabellen waere pFrm Moveable.
1753 BOOL bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
1754 BOOL bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() &&
1755 (!pFrm->IsInTab() || pFrm->IsTabFrm() );
1756 if ( bMoveNext && bAllowMove )
1758 SwFrm *pMove = pFrm;
1759 SwFrm *pPrev = pFrm->GetPrev();
1760 SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove );
1761 ASSERT( pTmp, "Missing FlowFrm" );
1763 if ( bApres )
1765 // Wir wollen, dass der Rest der Seite leer ist, d.h.
1766 // der naechste muss auf die naechste Seite wandern.
1767 // Dieser kann auch in der naechsten Spalte stehen!
1768 ASSERT( !pTmp->HasFollow(), "Follows forbidden" );
1769 pPrev = pFrm;
1770 // Wenn unser umgebender SectionFrm einen Next besitzt,
1771 // so soll dieser ebenfalls gemoved werden!
1772 pMove = pFrm->GetIndNext();
1773 SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm();
1774 if( pCol )
1775 pCol = (SwColumnFrm*)pCol->GetNext();
1778 if( pCol && !pMove )
1779 { // Bisher haben wir keinen Nachfolger gefunden
1780 // jetzt gucken wir in die naechste Spalte
1781 pMove = pCol->ContainsAny();
1782 if( pCol->GetNext() )
1783 pCol = (SwColumnFrm*)pCol->GetNext();
1784 else if( pCol->IsInSct() )
1785 { // Wenn es keine naechste Spalte gibt, wir aber
1786 // innerhalb eines spaltigen Bereichs sind,
1787 // koennte es noch ausserhalb des Bereich
1788 // (Seiten-)Spalten geben
1789 pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm();
1790 if( pCol )
1791 pCol = (SwColumnFrm*)pCol->GetNext();
1793 else
1794 pCol = NULL;
1796 // Falls hier verschrottete SectionFrms herumgammeln,
1797 // muessen diese uebersprungen werden.
1798 while( pMove && pMove->IsSctFrm() &&
1799 !((SwSectionFrm*)pMove)->GetSection() )
1800 pMove = pMove->GetNext();
1801 } while( !pMove && pCol );
1803 if( pMove )
1805 if ( pMove->IsCntntFrm() )
1806 pTmp = (SwCntntFrm*)pMove;
1807 else if ( pMove->IsTabFrm() )
1808 pTmp = (SwTabFrm*)pMove;
1809 else if ( pMove->IsSctFrm() )
1811 pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1812 if( pMove )
1813 pTmp = SwFlowFrm::CastFlowFrm( pMove );
1814 else
1815 pTmp = NULL;
1818 else
1819 pTmp = 0;
1821 else
1823 ASSERT( !pTmp->IsFollow(), "Follows really forbidden" );
1824 // Bei Bereichen muss natuerlich der Inhalt auf die Reise
1825 // geschickt werden.
1826 if( pMove->IsSctFrm() )
1828 while( pMove && pMove->IsSctFrm() &&
1829 !((SwSectionFrm*)pMove)->GetSection() )
1830 pMove = pMove->GetNext();
1831 if( pMove && pMove->IsSctFrm() )
1832 pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1833 if( pMove )
1834 pTmp = SwFlowFrm::CastFlowFrm( pMove );
1835 else
1836 pTmp = NULL;
1840 if( pTmp )
1842 SwFrm* pOldUp = pTmp->GetFrm()->GetUpper();
1843 // MoveFwd==TRUE bedeutet, dass wir auf der gleichen
1844 // Seite geblieben sind, wir wollen aber die Seite wechseln,
1845 // sofern dies moeglich ist
1846 BOOL bTmpOldLock = pTmp->IsJoinLocked();
1847 pTmp->LockJoin();
1848 while( pTmp->MoveFwd( TRUE, FALSE, TRUE ) )
1850 if( pOldUp == pTmp->GetFrm()->GetUpper() )
1851 break;
1852 pOldUp = pTmp->GetFrm()->GetUpper();
1854 if( !bTmpOldLock )
1855 pTmp->UnlockJoin();
1857 ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(),
1858 pFrm->IsInDocBody(), nEndIdx, pPrev );
1860 else
1862 BOOL bSplit;
1863 SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev();
1864 // Wenn in einen SectionFrm ein anderer eingefuegt wird,
1865 // muss dieser aufgebrochen werden
1866 if( pSct && rSttIdx.GetNode().IsSectionNode() )
1868 bSplit = pSct->SplitSect( pFrm, bApres );
1869 // Wenn pSct nicht aufgespalten werden konnte
1870 if( !bSplit && !bApres )
1872 pUpper = pSct->GetUpper();
1873 pPrv = pSct->GetPrev();
1876 else
1877 bSplit = FALSE;
1878 ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), FALSE,
1879 nEndIdx, pPrv );
1880 // OD 23.06.2003 #108784# - correction: append objects doesn't
1881 // depend on value of <bAllowMove>
1882 if( !bDontCreateObjects )
1884 const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1885 if( pTbl->Count() )
1886 AppendAllObjs( pTbl );
1889 // Wenn nichts eingefuegt wurde, z.B. ein ausgeblendeter Bereich,
1890 // muss das Splitten rueckgaengig gemacht werden
1891 if( bSplit && pSct && pSct->GetNext()
1892 && pSct->GetNext()->IsSctFrm() )
1893 pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() );
1894 if( pFrm->IsInFly() )
1895 pFrm->FindFlyFrm()->_Invalidate();
1896 if( pFrm->IsInTab() )
1897 pFrm->InvalidateSize();
1900 SwPageFrm *pPage = pUpper->FindPageFrm();
1901 SwFrm::CheckPageDescs( pPage, FALSE );
1902 if( !bOldFtn )
1903 pFtnFrm->ColUnlock();
1904 if( !bOldLock )
1906 pSct->ColUnlock();
1907 // Zum Beispiel beim Einfuegen von gelinkten Bereichen,
1908 // die wiederum Bereiche enthalten, kann pSct jetzt leer sein
1909 // und damit ruhig zerstoert werden.
1910 if( !pSct->ContainsCntnt() )
1912 pSct->DelEmpty( TRUE );
1913 pDoc->GetRootFrm()->RemoveFromList( pSct );
1914 delete pSct;
1920 bObjsDirect = TRUE;
1924 /*************************************************************************
1926 |* SwBorderAttrs::Ctor, DTor
1928 |* Ersterstellung MA 19. May. 93
1929 |* Letzte Aenderung MA 25. Jan. 97
1931 |*************************************************************************/
1933 SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) :
1934 SwCacheObj( pMod ),
1935 rAttrSet( pConstructor->IsCntntFrm()
1936 ? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet()
1937 : ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ),
1938 rUL ( rAttrSet.GetULSpace() ),
1939 // --> OD 2008-12-04 #i96772#
1940 // LRSpaceItem is copied due to the possibility that it is adjusted - see below
1941 rLR ( rAttrSet.GetLRSpace() ),
1942 // <--
1943 rBox ( rAttrSet.GetBox() ),
1944 rShadow ( rAttrSet.GetShadow() ),
1945 aFrmSize( rAttrSet.GetFrmSize().GetSize() )
1947 // --> OD 2008-12-02 #i96772#
1948 const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor);
1949 if ( pTxtFrm )
1951 pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR );
1954 //Achtung: Die USHORTs fuer die gecache'ten Werte werden absichtlich
1955 //nicht initialisiert!
1957 //Muessen alle einmal berechnet werden:
1958 bTopLine = bBottomLine = bLeftLine = bRightLine =
1959 bTop = bBottom = bLine = TRUE;
1961 bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = FALSE;
1962 // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev>
1963 // and <bJoinedWithNext>, which aren't initialized by default.
1964 bCachedJoinedWithPrev = FALSE;
1965 bCachedJoinedWithNext = FALSE;
1967 bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL));
1970 SwBorderAttrs::~SwBorderAttrs()
1972 ((SwModify*)pOwner)->SetInCache( FALSE );
1975 /*************************************************************************
1977 |* SwBorderAttrs::CalcTop(), CalcBottom(), CalcLeft(), CalcRight()
1979 |* Beschreibung Die Calc-Methoden errechnen zusaetzlich zu den
1980 |* von den Attributen vorgegebenen Groessen einen Sicherheitsabstand.
1981 |* der Sicherheitsabstand wird nur einkalkuliert, wenn Umrandung und/oder
1982 |* Schatten im Spiel sind; er soll vermeiden, dass aufgrund der
1983 |* groben physikalischen Gegebenheiten Raender usw. uebermalt werden.
1984 |* Ersterstellung MA 19. May. 93
1985 |* Letzte Aenderung MA 08. Jul. 93
1987 |*************************************************************************/
1989 void SwBorderAttrs::_CalcTop()
1991 nTop = CalcTopLine() + rUL.GetUpper();
1992 bTop = FALSE;
1995 void SwBorderAttrs::_CalcBottom()
1997 nBottom = CalcBottomLine() + rUL.GetLower();
1998 bBottom = FALSE;
2001 long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const
2003 long nRight=0;
2005 if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
2006 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2007 // and right border are painted on the right respectively left.
2008 if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
2009 nRight = CalcLeftLine();
2010 else
2011 nRight = CalcRightLine();
2014 // for paragraphs, "left" is "before text" and "right" is "after text"
2015 if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
2016 nRight += rLR.GetLeft();
2017 else
2018 nRight += rLR.GetRight();
2020 // --> OD 2008-01-21 #newlistlevelattrs#
2021 // correction: retrieve left margin for numbering in R2L-layout
2022 if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
2024 nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
2026 // <--
2028 return nRight;
2031 long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const
2033 long nLeft=0;
2035 if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
2036 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
2037 // and right border are painted on the right respectively left.
2038 if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
2039 nLeft = CalcRightLine();
2040 else
2041 nLeft = CalcLeftLine();
2044 // for paragraphs, "left" is "before text" and "right" is "after text"
2045 if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
2046 nLeft += rLR.GetRight();
2047 else
2048 nLeft += rLR.GetLeft();
2051 // --> OD 2008-01-21 #newlistlevelattrs#
2052 // correction: do not retrieve left margin for numbering in R2L-layout
2053 // if ( pCaller->IsTxtFrm() )
2054 if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() )
2055 // <--
2057 nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
2060 return nLeft;
2063 /*************************************************************************
2065 |* SwBorderAttrs::CalcTopLine(), CalcBottomLine(),
2066 |* CalcLeftLine(), CalcRightLine()
2068 |* Beschreibung Berechnung der Groessen fuer Umrandung und Schatten.
2069 |* Es kann auch ohne Linien ein Abstand erwuenscht sein,
2070 |* dieser wird dann nicht vom Attribut sondern hier
2071 |* beruecksichtigt (bBorderDist, z.B. fuer Zellen).
2072 |* Ersterstellung MA 21. May. 93
2073 |* Letzte Aenderung MA 07. Jun. 99
2075 |*************************************************************************/
2077 void SwBorderAttrs::_CalcTopLine()
2079 nTopLine = (bBorderDist && !rBox.GetTop())
2080 ? rBox.GetDistance (BOX_LINE_TOP)
2081 : rBox.CalcLineSpace(BOX_LINE_TOP);
2082 nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP);
2083 bTopLine = FALSE;
2086 void SwBorderAttrs::_CalcBottomLine()
2088 nBottomLine = (bBorderDist && !rBox.GetBottom())
2089 ? rBox.GetDistance (BOX_LINE_BOTTOM)
2090 : rBox.CalcLineSpace(BOX_LINE_BOTTOM);
2091 nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM);
2092 bBottomLine = FALSE;
2095 void SwBorderAttrs::_CalcLeftLine()
2097 nLeftLine = (bBorderDist && !rBox.GetLeft())
2098 ? rBox.GetDistance (BOX_LINE_LEFT)
2099 : rBox.CalcLineSpace(BOX_LINE_LEFT);
2100 nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT);
2101 bLeftLine = FALSE;
2104 void SwBorderAttrs::_CalcRightLine()
2106 nRightLine = (bBorderDist && !rBox.GetRight())
2107 ? rBox.GetDistance (BOX_LINE_RIGHT)
2108 : rBox.CalcLineSpace(BOX_LINE_RIGHT);
2109 nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT);
2110 bRightLine = FALSE;
2113 /*************************************************************************
2115 |* SwBorderAttrs::_IsLine()
2117 |* Ersterstellung MA 29. Sep. 94
2118 |* Letzte Aenderung MA 29. Sep. 94
2120 |*************************************************************************/
2122 void SwBorderAttrs::_IsLine()
2124 bIsLine = rBox.GetTop() || rBox.GetBottom() ||
2125 rBox.GetLeft()|| rBox.GetRight();
2126 bLine = FALSE;
2129 /*************************************************************************
2131 |* SwBorderAttrs::CmpLeftRightLine(), IsTopLine(), IsBottomLine()
2133 |* Die Umrandungen benachbarter Absaetze werden nach folgendem
2134 |* Algorithmus zusammengefasst:
2136 |* 1. Die Umrandung oben faellt weg, wenn der Vorgaenger dieselbe
2137 |* Umrandung oben aufweist und 3. Zutrifft.
2138 |* Zusaetzlich muss der Absatz mindestens rechts oder links oder
2139 |* unten eine Umrandung haben.
2140 |* 2. Die Umrandung unten faellt weg, wenn der Nachfolger dieselbe
2141 |* Umrandung untern aufweist und 3. Zustrifft.
2142 |* Zusaetzlich muss der Absatz mindestens rechts oder links oder
2143 |* oben eine Umrandung haben.
2144 |* 3. Die Umrandungen links und rechts vor Vorgaenger bzw. Nachfolger
2145 |* sind identisch.
2147 |* Ersterstellung MA 22. Mar. 95
2148 |* Letzte Aenderung MA 22. May. 95
2150 |*************************************************************************/
2151 inline int CmpLines( const SvxBorderLine *pL1, const SvxBorderLine *pL2 )
2153 return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
2156 // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
2157 // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
2158 // instead of only the right LR-spacing, because R2L-layout has to be
2159 // considered.
2160 BOOL SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
2161 const SwFrm *pCaller,
2162 const SwFrm *pCmp ) const
2164 return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft() ) &&
2165 CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
2166 CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
2167 // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
2168 CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
2171 BOOL SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm,
2172 const SwFrm& _rCmpFrm ) const
2174 BOOL bReturnVal = FALSE;
2176 SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm );
2177 const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
2178 if ( rShadow == rCmpAttrs.GetShadow() &&
2179 CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
2180 CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
2181 CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm )
2184 bReturnVal = TRUE;
2187 return bReturnVal;
2190 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2191 // previous frame. Calculated value saved in cached value <bJoinedWithPrev>
2192 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>
2193 void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm,
2194 const SwFrm* _pPrevFrm )
2196 // set default
2197 bJoinedWithPrev = FALSE;
2199 if ( _rFrm.IsTxtFrm() )
2201 // text frame can potentially join with previous text frame, if
2202 // corresponding attribute set is set at previous text frame.
2203 // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this
2204 // one as previous frame.
2205 const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev();
2206 // OD 2004-02-13 #i25029# - skip hidden text frames.
2207 while ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2208 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
2210 pPrevFrm = pPrevFrm->GetPrev();
2212 if ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2213 pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue()
2216 bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) );
2220 // valid cache status, if demanded
2221 // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm>
2222 // is set.
2223 bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm;
2226 // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2227 // next frame. Calculated value saved in cached value <bJoinedWithNext>
2228 void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm )
2230 // set default
2231 bJoinedWithNext = FALSE;
2233 if ( _rFrm.IsTxtFrm() )
2235 // text frame can potentially join with next text frame, if
2236 // corresponding attribute set is set at current text frame.
2237 // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2238 const SwFrm* pNextFrm = _rFrm.GetNext();
2239 while ( pNextFrm && pNextFrm->IsTxtFrm() &&
2240 static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() )
2242 pNextFrm = pNextFrm->GetNext();
2244 if ( pNextFrm && pNextFrm->IsTxtFrm() &&
2245 _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue()
2248 bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) );
2252 // valid cache status, if demanded
2253 bCachedJoinedWithNext = bCacheGetLine;
2256 // OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev>
2257 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to
2258 // method <_CalcJoindWithPrev(..)>.
2259 BOOL SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm,
2260 const SwFrm* _pPrevFrm ) const
2262 if ( !bCachedJoinedWithPrev || _pPrevFrm )
2264 // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter
2265 const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm );
2268 return bJoinedWithPrev;
2271 BOOL SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const
2273 if ( !bCachedJoinedWithNext )
2275 const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm );
2278 return bJoinedWithNext;
2281 // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to
2282 // method <JoinedWithPrev>
2283 void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm,
2284 const SwFrm* _pPrevFrm )
2286 USHORT nRet = CalcTopLine();
2288 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2289 // OD 2004-02-26 #i25029# - add 2nd parameter
2290 if ( JoinedWithPrev( _rFrm, _pPrevFrm ) )
2292 nRet = 0;
2295 bCachedGetTopLine = bCacheGetLine;
2297 nGetTopLine = nRet;
2300 void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm )
2302 USHORT nRet = CalcBottomLine();
2304 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2305 if ( JoinedWithNext( _rFrm ) )
2307 nRet = 0;
2310 bCachedGetBottomLine = bCacheGetLine;
2312 nGetBottomLine = nRet;
2315 /*************************************************************************
2317 |* SwBorderAttrAccess::CTor
2319 |* Ersterstellung MA 20. Mar. 95
2320 |* Letzte Aenderung MA 29. Nov. 95
2322 |*************************************************************************/
2324 SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) :
2325 SwCacheAccess( rCach, (pFrm->IsCntntFrm() ?
2326 (void*)((SwCntntFrm*)pFrm)->GetNode() :
2327 (void*)((SwLayoutFrm*)pFrm)->GetFmt()),
2328 (BOOL)(pFrm->IsCntntFrm() ?
2329 ((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() :
2330 ((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ),
2331 pConstructor( pFrm )
2335 /*************************************************************************
2337 |* SwBorderAttrAccess::NewObj, Get
2339 |* Ersterstellung MA 20. Mar. 95
2340 |* Letzte Aenderung MA 20. Mar. 95
2342 |*************************************************************************/
2344 SwCacheObj *SwBorderAttrAccess::NewObj()
2346 ((SwModify*)pOwner)->SetInCache( TRUE );
2347 return new SwBorderAttrs( (SwModify*)pOwner, pConstructor );
2350 SwBorderAttrs *SwBorderAttrAccess::Get()
2352 return (SwBorderAttrs*)SwCacheAccess::Get();
2355 /*************************************************************************
2357 |* SwOrderIter::Ctor
2359 |* Ersterstellung MA 06. Jan. 95
2360 |* Letzte Aenderung MA 22. Nov. 95
2362 |*************************************************************************/
2364 SwOrderIter::SwOrderIter( const SwPageFrm *pPg, BOOL bFlys ) :
2365 pPage( pPg ),
2366 pCurrent( 0 ),
2367 bFlysOnly( bFlys )
2371 /*************************************************************************
2373 |* SwOrderIter::Top()
2375 |* Ersterstellung MA 06. Jan. 95
2376 |* Letzte Aenderung MA 22. Nov. 95
2378 |*************************************************************************/
2380 const SdrObject *SwOrderIter::Top()
2382 pCurrent = 0;
2383 if ( pPage->GetSortedObjs() )
2385 UINT32 nTopOrd = 0;
2386 const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2387 if ( pObjs->Count() )
2389 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2390 for ( USHORT i = 0; i < pObjs->Count(); ++i )
2392 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2393 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2394 continue;
2395 UINT32 nTmp = pObj->GetOrdNumDirect();
2396 if ( nTmp >= nTopOrd )
2398 nTopOrd = nTmp;
2399 pCurrent = pObj;
2404 return pCurrent;
2407 /*************************************************************************
2409 |* SwOrderIter::Bottom()
2411 |* Ersterstellung MA 06. Jan. 95
2412 |* Letzte Aenderung MA 22. Nov. 95
2414 |*************************************************************************/
2416 const SdrObject *SwOrderIter::Bottom()
2418 pCurrent = 0;
2419 if ( pPage->GetSortedObjs() )
2421 UINT32 nBotOrd = USHRT_MAX;
2422 const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2423 if ( pObjs->Count() )
2425 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2426 for ( USHORT i = 0; i < pObjs->Count(); ++i )
2428 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2429 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2430 continue;
2431 UINT32 nTmp = pObj->GetOrdNumDirect();
2432 if ( nTmp < nBotOrd )
2434 nBotOrd = nTmp;
2435 pCurrent = pObj;
2440 return pCurrent;
2443 /*************************************************************************
2445 |* SwOrderIter::Next()
2447 |* Ersterstellung MA 06. Jan. 95
2448 |* Letzte Aenderung MA 22. Nov. 95
2450 |*************************************************************************/
2452 const SdrObject *SwOrderIter::Next()
2454 const UINT32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2455 pCurrent = 0;
2456 if ( pPage->GetSortedObjs() )
2458 UINT32 nOrd = USHRT_MAX;
2459 const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2460 if ( pObjs->Count() )
2462 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2463 for ( USHORT i = 0; i < pObjs->Count(); ++i )
2465 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2466 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2467 continue;
2468 UINT32 nTmp = pObj->GetOrdNumDirect();
2469 if ( nTmp > nCurOrd && nTmp < nOrd )
2471 nOrd = nTmp;
2472 pCurrent = pObj;
2477 return pCurrent;
2480 /*************************************************************************
2482 |* SwOrderIter::Prev()
2484 |* Ersterstellung MA 06. Jan. 95
2485 |* Letzte Aenderung MA 22. Nov. 95
2487 |*************************************************************************/
2489 const SdrObject *SwOrderIter::Prev()
2491 const UINT32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2492 pCurrent = 0;
2493 if ( pPage->GetSortedObjs() )
2495 UINT32 nOrd = 0;
2496 const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2497 if ( pObjs->Count() )
2499 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen!
2500 for ( USHORT i = 0; i < pObjs->Count(); ++i )
2502 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2503 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2504 continue;
2505 UINT32 nTmp = pObj->GetOrdNumDirect();
2506 if ( nTmp < nCurOrd && nTmp >= nOrd )
2508 nOrd = nTmp;
2509 pCurrent = pObj;
2514 return pCurrent;
2517 /*************************************************************************
2519 |* SaveCntnt(), RestoreCntnt()
2521 |* Ersterstellung MA 10. Jun. 93
2522 |* Letzte Aenderung MA 07. Mar. 95
2524 |*************************************************************************/
2526 //Unterstruktur eines LayoutFrms fuer eine Aktion aufheben und wieder
2527 //restaurieren.
2528 //Neuer Algorithmus: Es ist unuetz jeden Nachbarn einzeln zu betrachten und
2529 //die Pointer sauber zu setzen (Upper, Nachbarn, usw.)
2530 //Es reicht vollkommen jeweils eine Einzelkette zu loesen, und mit dem
2531 //Letzen der Einzelkette nachzuschauen ob noch eine weitere Kette
2532 //angeheangt werden muss. Es brauchen nur die Pointer korrigiert werden,
2533 //die zur Verkettung notwendig sind. So koennen Beipspielsweise die Pointer
2534 //auf die Upper auf den alten Uppern stehenbleiben. Korrigiert werden die
2535 //Pointer dann im RestoreCntnt. Zwischenzeitlich ist sowieso jeder Zugriff
2536 //verboten.
2537 //Unterwegs werden die Flys bei der Seite abgemeldet.
2539 // --> OD 2004-11-29 #115759# - 'remove' also drawing object from page and
2540 // at-fly anchored objects from page
2541 void MA_FASTCALL lcl_RemoveObjsFromPage( SwFrm* _pFrm )
2543 ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_RemoveFlysFromPage." );
2544 SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2545 for ( USHORT i = 0; i < rObjs.Count(); ++i )
2547 SwAnchoredObject* pObj = rObjs[i];
2548 // --> OD 2004-11-29 #115759# - reset member, at which the anchored
2549 // object orients its vertical position
2550 pObj->ClearVertPosOrientFrm();
2551 // <--
2552 // --> OD 2005-03-03 #i43913#
2553 pObj->ResetLayoutProcessBools();
2554 // <--
2555 // --> OD 2004-11-29 #115759# - remove also lower objects of as-character
2556 // anchored Writer fly frames from page
2557 if ( pObj->ISA(SwFlyFrm) )
2559 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2561 // --> OD 2004-11-29 #115759# - remove also direct lowers of Writer
2562 // fly frame from page
2563 if ( pFlyFrm->GetDrawObjs() )
2565 ::lcl_RemoveObjsFromPage( pFlyFrm );
2567 // <--
2569 SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt();
2570 while ( pCnt )
2572 if ( pCnt->GetDrawObjs() )
2573 ::lcl_RemoveObjsFromPage( pCnt );
2574 pCnt = pCnt->GetNextCntntFrm();
2576 if ( pFlyFrm->IsFlyFreeFrm() )
2578 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
2579 pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm );
2582 // <--
2583 // --> OD 2004-11-29 #115759# - remove also drawing objects from page
2584 else if ( pObj->ISA(SwAnchoredDrawObject) )
2586 if ( pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_IN_CNTNT )
2588 pObj->GetPageFrm()->RemoveDrawObjFromPage(
2589 *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2592 // <--
2596 SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart )
2598 if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
2599 lcl_RemoveFtns( (SwColumnFrm*)pLay->Lower(), TRUE, TRUE );
2601 SwFrm *pSav;
2602 if ( 0 == (pSav = pLay->ContainsAny()) )
2603 return 0;
2605 if( pSav->IsInFtn() && !pLay->IsInFtn() )
2608 pSav = pSav->FindNext();
2609 while( pSav && pSav->IsInFtn() );
2610 if( !pSav || !pLay->IsAnLower( pSav ) )
2611 return NULL;
2614 // Tables should be saved as a whole, expection:
2615 // The contents of a section or a cell inside a table should be saved
2616 if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) )
2617 while ( !pSav->IsTabFrm() )
2618 pSav = pSav->GetUpper();
2620 if( pSav->IsInSct() )
2621 { // Jetzt wird der oberste Bereich gesucht, der innerhalb von pLay ist.
2622 SwFrm* pSect = pLay->FindSctFrm();
2623 SwFrm *pTmp = pSav;
2626 pSav = pTmp;
2627 pTmp = pSav->GetUpper() ? pSav->GetUpper()->FindSctFrm() : NULL;
2628 } while ( pTmp != pSect );
2631 SwFrm *pFloat = pSav;
2632 if( !pStart )
2633 pStart = pSav;
2634 BOOL bGo = pStart == pSav;
2637 if( bGo )
2638 pFloat->GetUpper()->pLower = 0; //Die Teilkette ausklinken.
2640 //Das Ende der Teilkette suchen, unterwegs die Flys abmelden.
2643 if( bGo )
2645 if ( pFloat->IsCntntFrm() )
2647 if ( pFloat->GetDrawObjs() )
2648 ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat );
2650 else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() )
2652 SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt();
2653 if( pCnt )
2656 { if ( pCnt->GetDrawObjs() )
2657 ::lcl_RemoveObjsFromPage( pCnt );
2658 pCnt = pCnt->GetNextCntntFrm();
2659 } while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) );
2662 else {
2663 ASSERT( !pFloat, "Neuer Float-Frame?" );
2666 if ( pFloat->GetNext() )
2668 if( bGo )
2669 pFloat->pUpper = NULL;
2670 pFloat = pFloat->GetNext();
2671 if( !bGo && pFloat == pStart )
2673 bGo = TRUE;
2674 pFloat->pPrev->pNext = NULL;
2675 pFloat->pPrev = NULL;
2678 else
2679 break;
2681 } while ( pFloat );
2683 //Die naechste Teilkette suchen und die Ketten miteinander verbinden.
2684 SwFrm *pTmp = pFloat->FindNext();
2685 if( bGo )
2686 pFloat->pUpper = NULL;
2688 if( !pLay->IsInFtn() )
2689 while( pTmp && pTmp->IsInFtn() )
2690 pTmp = pTmp->FindNext();
2692 if ( !pLay->IsAnLower( pTmp ) )
2693 pTmp = 0;
2695 if ( pTmp && bGo )
2697 pFloat->pNext = pTmp; //Die beiden Ketten verbinden.
2698 pFloat->pNext->pPrev = pFloat;
2700 pFloat = pTmp;
2701 bGo = bGo || ( pStart == pFloat );
2702 } while ( pFloat );
2704 return bGo ? pStart : NULL;
2707 // --> OD 2004-11-29 #115759# - add also drawing objects to page and at-fly
2708 // anchored objects to page
2709 void MA_FASTCALL lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage )
2711 ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_AddFlysToPage." );
2712 SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2713 for ( USHORT i = 0; i < rObjs.Count(); ++i )
2715 SwAnchoredObject* pObj = rObjs[i];
2717 // --> OD 2004-11-29 #115759# - unlock position of anchored object
2718 // in order to get the object's position calculated.
2719 pObj->UnlockPosition();
2720 // <--
2721 // --> OD 2004-11-29 #115759# - add also lower objects of as-character
2722 // anchored Writer fly frames from page
2723 if ( pObj->ISA(SwFlyFrm) )
2725 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2726 if ( pObj->ISA(SwFlyFreeFrm) )
2728 _pPage->AppendFlyToPage( pFlyFrm );
2730 pFlyFrm->_InvalidatePos();
2731 pFlyFrm->_InvalidateSize();
2732 pFlyFrm->InvalidatePage( _pPage );
2734 // --> OD 2004-11-29 #115759# - add also at-fly anchored objects
2735 // to page
2736 if ( pFlyFrm->GetDrawObjs() )
2738 ::lcl_AddObjsToPage( pFlyFrm, _pPage );
2740 // <--
2742 SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt();
2743 while ( pCnt )
2745 if ( pCnt->GetDrawObjs() )
2746 ::lcl_AddObjsToPage( pCnt, _pPage );
2747 pCnt = pCnt->GetNextCntntFrm();
2750 // <--
2751 // --> OD 2004-11-29 #115759# - remove also drawing objects from page
2752 else if ( pObj->ISA(SwAnchoredDrawObject) )
2754 if ( pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_IN_CNTNT )
2756 pObj->InvalidateObjPos();
2757 _pPage->AppendDrawObjToPage(
2758 *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2761 // <--
2765 void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow )
2767 ASSERT( pSav && pParent, "Kein Save oder Parent fuer Restore." );
2768 SWRECTFN( pParent )
2770 //Wenn es bereits FlowFrms unterhalb des neuen Parent gibt, so wird die
2771 //Kette, beginnend mit pSav, hinter dem letzten angehaengt.
2772 //Die Teile werden kurzerhand insertet und geeignet invalidiert.
2773 //Unterwegs werden die Flys der CntntFrms bei der Seite angemeldet.
2775 SwPageFrm *pPage = pParent->FindPageFrm();
2777 if ( pPage )
2778 pPage->InvalidatePage( pPage ); //Invalides Layout anmelden.
2780 //Vorgaenger festellen und die Verbindung herstellen bzw. initialisieren.
2781 pSav->pPrev = pSibling;
2782 SwFrm* pNxt;
2783 if ( pSibling )
2785 pNxt = pSibling->pNext;
2786 pSibling->pNext = pSav;
2787 pSibling->_InvalidatePrt();
2788 ((SwCntntFrm*)pSibling)->InvalidatePage( pPage );//Invaliden Cntnt anmelden.
2789 if ( ((SwCntntFrm*)pSibling)->GetFollow() )
2790 pSibling->Prepare( PREP_CLEAR, 0, sal_False );
2792 else
2793 { pNxt = pParent->pLower;
2794 pParent->pLower = pSav;
2795 pSav->pUpper = pParent; //Schon mal setzen, sonst ist fuer das
2796 //invalidate der Parent (z.B. ein Fly) nicht klar.
2797 //Invaliden Cntnt anmelden.
2798 if ( pSav->IsCntntFrm() )
2799 ((SwCntntFrm*)pSav)->InvalidatePage( pPage );
2800 else
2801 { // pSav koennte auch ein leerer SectFrm sein
2802 SwCntntFrm* pCnt = pParent->ContainsCntnt();
2803 if( pCnt )
2804 pCnt->InvalidatePage( pPage );
2808 //Der Parent muss entsprechend gegrow'ed werden.
2809 SwTwips nGrowVal = 0;
2810 SwFrm* pLast;
2812 { pSav->pUpper = pParent;
2813 nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)();
2814 pSav->_InvalidateAll();
2816 //Jetzt die Flys anmelden, fuer TxtFrms gleich geeignet invalidieren.
2817 if ( pSav->IsCntntFrm() )
2819 if ( pSav->IsTxtFrm() &&
2820 ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX )
2821 ((SwTxtFrm*)pSav)->Init(); //Ich bin sein Freund.
2823 if ( pPage && pSav->GetDrawObjs() )
2824 ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage );
2826 else
2827 { SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt();
2828 if( pBlub )
2831 { if ( pPage && pBlub->GetDrawObjs() )
2832 ::lcl_AddObjsToPage( pBlub, pPage );
2833 if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() &&
2834 ((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX )
2835 ((SwTxtFrm*)pBlub)->Init(); //Ich bin sein Freund.
2836 pBlub = pBlub->GetNextCntntFrm();
2837 } while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub ));
2840 pLast = pSav;
2841 pSav = pSav->GetNext();
2843 } while ( pSav );
2845 if( pNxt )
2847 pLast->pNext = pNxt;
2848 pNxt->pPrev = pLast;
2851 if ( bGrow )
2852 pParent->Grow( nGrowVal );
2855 /*************************************************************************
2857 |* SqRt() Berechnung der Quadratwurzel, damit die math.lib
2858 |* nicht auch noch dazugelinkt werden muss.
2860 |* Ersterstellung OK ??
2861 |* Letzte Aenderung MA 09. Jan. 97
2863 |*************************************************************************/
2865 ULONG MA_FASTCALL SqRt( BigInt nX )
2867 BigInt nErg = 1;
2869 if ( !nX.IsNeg() )
2871 BigInt nOldErg = 1;
2872 for ( int i = 0; i <= 5; i++ )
2874 nErg = (nOldErg + (nX / nOldErg)) / BigInt(2);
2875 nOldErg = nErg;
2878 return nErg >= BigInt(SAL_MAX_UINT32) ? ULONG_MAX : (ULONG)nErg;
2881 /*************************************************************************
2883 |* InsertNewPage() Einsetzen einer neuen Seite.
2885 |* Ersterstellung MA 01. Jul. 93
2886 |* Letzte Aenderung MA 31. Jul. 95
2888 |*************************************************************************/
2890 SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
2891 BOOL bOdd, BOOL bInsertEmpty, BOOL bFtn,
2892 SwFrm *pSibling )
2894 SwPageFrm *pRet;
2895 SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc();
2896 SwFrmFmt *pFmt = bOdd ? rDesc.GetRightFmt() : rDesc.GetLeftFmt();
2897 //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben
2898 //eine Leerseite einfuegen.
2899 if ( !pFmt )
2901 pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt();
2902 ASSERT( pFmt, "Descriptor without any format?!" );
2903 bInsertEmpty = !bInsertEmpty;
2905 if( bInsertEmpty )
2907 SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
2908 ((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc;
2909 pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pTmpDesc );
2910 pRet->Paste( pUpper, pSibling );
2911 pRet->PreparePage( bFtn );
2913 pRet = new SwPageFrm( pFmt, &rDesc );
2914 pRet->Paste( pUpper, pSibling );
2915 pRet->PreparePage( bFtn );
2916 if ( pRet->GetNext() )
2917 ((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet );
2918 return pRet;
2922 /*************************************************************************
2924 |* RegistFlys(), Regist() Die beiden folgenden Methoden durchsuchen rekursiv
2925 |* eine Layoutstruktur und melden alle FlyFrms, die einen beliebigen Frm
2926 |* innerhalb der Struktur als Anker haben bei der Seite an.
2928 |* Ersterstellung MA 08. Jul. 93
2929 |* Letzte Aenderung MA 07. Jul. 95
2931 |*************************************************************************/
2933 void MA_FASTCALL lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch )
2935 SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs();
2936 for ( USHORT i = 0; i < pObjs->Count(); ++i )
2938 SwAnchoredObject* pObj = (*pObjs)[i];
2939 if ( pObj->ISA(SwFlyFrm) )
2941 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
2942 //Ggf. ummelden, nicht anmelden wenn bereits bekannt.
2943 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()>
2944 SwPageFrm *pPg = pFly->IsFlyFreeFrm()
2945 ? pFly->GetPageFrm() : pFly->FindPageFrm();
2946 if ( pPg != pPage )
2948 if ( pPg )
2949 pPg->RemoveFlyFromPage( pFly );
2950 pPage->AppendFlyToPage( pFly );
2952 ::RegistFlys( pPage, pFly );
2954 else
2956 // --> OD 2008-04-22 #i87493#
2957 if ( pPage != pObj->GetPageFrm() )
2959 // --> OD 2004-07-02 #i28701#
2960 if ( pObj->GetPageFrm() )
2961 pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj );
2962 pPage->AppendDrawObjToPage( *pObj );
2963 // <--
2965 // <--
2968 const SwFlyFrm* pFly = pAnch->FindFlyFrm();
2969 if ( pFly &&
2970 pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
2971 pObj->GetDrawObj()->GetPage() )
2973 pObj->DrawObj()->GetPage()->SetObjectOrdNum(
2974 pObj->GetDrawObj()->GetOrdNumDirect(),
2975 pFly->GetVirtDrawObj()->GetOrdNumDirect() + 1 );
2980 void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay )
2982 if ( pLay->GetDrawObjs() )
2983 ::lcl_Regist( pPage, pLay );
2984 const SwFrm *pFrm = pLay->Lower();
2985 while ( pFrm )
2987 if ( pFrm->IsLayoutFrm() )
2988 ::RegistFlys( pPage, (const SwLayoutFrm*)pFrm );
2989 else if ( pFrm->GetDrawObjs() )
2990 ::lcl_Regist( pPage, pFrm );
2991 pFrm = pFrm->GetNext();
2995 /*************************************************************************
2997 |* void Notify()
2999 |* Beschreibung Benachrichtigt den Hintergrund je nach der
3000 |* Veraenderung zwischen altem und neuem Rechteckt.
3001 |* Ersterstellung MA 18. Jun. 93
3002 |* Letzte Aenderung MA 06. Jun. 96
3004 |*************************************************************************/
3006 void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
3007 const SwRect* pOldPrt )
3009 const SwRect aFrm( pFly->GetObjRectWithSpaces() );
3010 if ( rOld.Pos() != aFrm.Pos() )
3011 { //Positionsaenderung, alten und neuen Bereich invalidieren
3012 if ( rOld.HasArea() &&
3013 rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < WEIT_WECH )
3015 pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE );
3017 pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
3019 else if ( rOld.SSize() != aFrm.SSize() )
3020 { //Groessenaenderung, den Bereich der Verlassen wurde bzw. jetzt
3021 //ueberdeckt wird invalidieren.
3022 //Der Einfachheit halber wird hier bewusst jeweils ein Twip
3023 //unnoetig invalidiert.
3025 ViewShell *pSh = pFly->GetShell();
3026 if( pSh && rOld.HasArea() )
3027 pSh->InvalidateWindows( rOld );
3029 // --> OD 2005-08-19 #i51941# - consider case that fly frame isn't
3030 // registered at the old page <pOld>
3031 SwPageFrm* pPageFrm = pFly->FindPageFrm();
3032 if ( pOld != pPageFrm )
3034 pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE );
3036 // <--
3038 if ( rOld.Left() != aFrm.Left() )
3040 SwRect aTmp( rOld );
3041 aTmp.Union( aFrm );
3042 aTmp.Left( Min(aFrm.Left(), rOld.Left()) );
3043 aTmp.Right( Max(aFrm.Left(), rOld.Left()) );
3044 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
3046 SwTwips nOld = rOld.Right();
3047 SwTwips nNew = aFrm.Right();
3048 if ( nOld != nNew )
3050 SwRect aTmp( rOld );
3051 aTmp.Union( aFrm );
3052 aTmp.Left( Min(nNew, nOld) );
3053 aTmp.Right( Max(nNew, nOld) );
3054 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
3056 if ( rOld.Top() != aFrm.Top() )
3058 SwRect aTmp( rOld );
3059 aTmp.Union( aFrm );
3060 aTmp.Top( Min(aFrm.Top(), rOld.Top()) );
3061 aTmp.Bottom( Max(aFrm.Top(), rOld.Top()) );
3062 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
3064 nOld = rOld.Bottom();
3065 nNew = aFrm.Bottom();
3066 if ( nOld != nNew )
3068 SwRect aTmp( rOld );
3069 aTmp.Union( aFrm );
3070 aTmp.Top( Min(nNew, nOld) );
3071 aTmp.Bottom( Max(nNew, nOld) );
3072 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
3075 else if ( pOldPrt && *pOldPrt != pFly->Prt() &&
3076 pFly->GetFmt()->GetSurround().IsContour() )
3078 // #i24097#
3079 pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
3083 /*************************************************************************
3085 |* NotifyBackground()
3087 |*************************************************************************/
3089 void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect )
3091 SwTwips nBottom = rRect.Bottom();
3092 while( pFrm )
3094 if( pFrm->IsLayoutFrm() )
3096 if( rRect.IsOver( pFrm->Frm() ) )
3097 lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect );
3099 else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() )
3101 if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() )
3102 pFrm->InvalidateSize();
3103 else
3104 pFrm->InvalidateNextPos();
3106 pFrm = pFrm->GetNext();
3110 void MA_FASTCALL lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt,
3111 const SwRect &rRect, const PrepareHint eHint )
3113 if ( pCnt->IsTxtFrm() )
3115 SwRect aCntPrt( pCnt->Prt() );
3116 aCntPrt.Pos() += pCnt->Frm().Pos();
3117 if ( eHint == PREP_FLY_ATTR_CHG )
3119 // --> OD 2004-10-20 #i35640# - use given rectangle <rRect> instead
3120 // of current bound rectangle
3121 if ( aCntPrt.IsOver( rRect ) )
3122 // <--
3123 pCnt->Prepare( PREP_FLY_ATTR_CHG );
3125 // --> OD 2004-11-01 #i23129# - only invalidate, if the text frame
3126 // printing area overlaps with the given rectangle.
3127 else if ( aCntPrt.IsOver( rRect ) )
3128 // <--
3129 pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) );
3130 if ( pCnt->GetDrawObjs() )
3132 const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
3133 for ( USHORT i = 0; i < rObjs.Count(); ++i )
3135 SwAnchoredObject* pObj = rObjs[i];
3136 if ( pObj->ISA(SwFlyFrm) )
3138 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
3139 if ( pFly->IsFlyInCntFrm() )
3141 SwCntntFrm *pCntnt = pFly->ContainsCntnt();
3142 while ( pCntnt )
3144 ::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint );
3145 pCntnt = pCntnt->GetNextCntntFrm();
3154 void Notify_Background( const SdrObject* pObj,
3155 SwPageFrm* pPage,
3156 const SwRect& rRect,
3157 const PrepareHint eHint,
3158 const BOOL bInva )
3161 //Wenn der Frm gerade erstmalig sinnvoll positioniert wurde, braucht der
3162 //alte Bereich nicht benachrichtigt werden.
3163 if ( eHint == PREP_FLY_LEAVE && rRect.Top() == WEIT_WECH )
3164 return;
3166 SwLayoutFrm* pArea;
3167 SwFlyFrm *pFlyFrm = 0;
3168 SwFrm* pAnchor;
3169 if( pObj->ISA(SwVirtFlyDrawObj) )
3171 pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
3172 pAnchor = pFlyFrm->AnchorFrm();
3174 else
3176 pFlyFrm = NULL;
3177 pAnchor = const_cast<SwFrm*>(
3178 GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() );
3180 if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() )
3181 pArea = pAnchor->FindFlyFrm();
3182 else
3183 pArea = pPage;
3184 SwCntntFrm *pCnt = 0;
3185 if ( pArea )
3187 if( PREP_FLY_ARRIVE != eHint )
3188 lcl_CheckFlowBack( pArea, rRect );
3190 //Es reagieren sowieso nur die auf den Anker folgenden auf den Fly, also
3191 //brauchen diese nicht abgeklappert werden.
3192 //Ausnahme sind ist natuerlich das LEAVE, denn der Fly koennte ja von
3193 //"oben" kommen.
3194 // Wenn der Anker auf der vorhergehenden Seite liegt, muss ebenfalls
3195 // die gesamte Seite abgearbeitet werden. (47722)
3196 // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
3197 // on the object positioning, the complete area has to be processed,
3198 // because content frames before the anchor frame also have to consider
3199 // the object for the text wrapping.
3200 // --> OD 2004-08-25 #i3317# - The complete area has always been
3201 // processed.
3203 pCnt = pArea->ContainsCntnt();
3205 // <--
3207 SwFrm *pLastTab = 0;
3209 while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
3211 ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
3212 if ( pCnt->IsInTab() )
3214 SwLayoutFrm* pCell = pCnt->GetUpper();
3215 // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
3216 // instead of <GetCurrentBoundRect()>, because a recalculation
3217 // of the bounding rectangle isn't intended here.
3218 if ( pCell->IsCellFrm() &&
3219 ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) ||
3220 pCell->Frm().IsOver( rRect ) ) )
3221 // <--
3223 const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient();
3224 if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
3225 pCell->InvalidatePrt();
3227 SwTabFrm *pTab = pCnt->FindTabFrm();
3228 if ( pTab != pLastTab )
3230 pLastTab = pTab;
3231 // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()>
3232 // instead of <GetCurrentBoundRect()>, because a recalculation
3233 // of the bounding rectangle isn't intended here.
3234 if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) ||
3235 pTab->Frm().IsOver( rRect ) )
3236 // <--
3238 if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) )
3239 pTab->InvalidatePrt();
3243 pCnt = pCnt->GetNextCntntFrm();
3245 // #108745# Sorry, but this causes nothing but trouble. I remove these lines
3246 // taking the risk that the footer frame will have a wrong height
3247 // if( pPage->Lower() )
3248 // {
3249 // SwFrm* pFrm = pPage->Lower();
3250 // while( pFrm->GetNext() )
3251 // pFrm = pFrm->GetNext();
3252 // if( pFrm->IsFooterFrm() &&
3253 // ( ( pFrm->Frm().IsOver( pObj->GetBoundRect() ) ||
3254 // pFrm->Frm().IsOver( rRect ) ) ) )
3255 // pFrm->InvalidateSize();
3256 // }
3257 // --> OD 2007-07-24 #128702# - make code robust
3258 if ( pPage && pPage->GetSortedObjs() )
3259 // <--
3261 pObj->GetOrdNum();
3262 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
3263 for ( USHORT i = 0; i < rObjs.Count(); ++i )
3265 SwAnchoredObject* pAnchoredObj = rObjs[i];
3266 if ( pAnchoredObj->ISA(SwFlyFrm) )
3268 if( pAnchoredObj->GetDrawObj() == pObj )
3269 continue;
3270 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
3271 if ( pFly->Frm().Top() == WEIT_WECH )
3272 continue;
3274 if ( !pFlyFrm ||
3275 (!pFly->IsLowerOf( pFlyFrm ) &&
3276 pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
3278 pCnt = pFly->ContainsCntnt();
3279 while ( pCnt )
3281 ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
3282 pCnt = pCnt->GetNextCntntFrm();
3285 if( pFly->IsFlyLayFrm() )
3287 if( pFly->Lower() && pFly->Lower()->IsColumnFrm() &&
3288 pFly->Frm().Bottom() >= rRect.Top() &&
3289 pFly->Frm().Top() <= rRect.Bottom() &&
3290 pFly->Frm().Right() >= rRect.Left() &&
3291 pFly->Frm().Left() <= rRect.Right() )
3293 pFly->InvalidateSize();
3296 //Flys, die ueber mir liegen muessen/mussten evtl.
3297 //ausweichen, wenn sie eine automatische Ausrichtung haben.
3298 //das ist unabhaengig von meinem Attribut, weil dies sich
3299 //gerade geaendert haben kann und eben deshalb
3300 //umformatiert wurde.
3301 else if ( pFly->IsFlyAtCntFrm() &&
3302 pObj->GetOrdNumDirect() <
3303 pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
3304 pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) )
3306 const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
3307 if ( text::HoriOrientation::NONE != rH.GetHoriOrient() &&
3308 text::HoriOrientation::CENTER != rH.GetHoriOrient() &&
3309 ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
3310 (pFly->Frm().Bottom() >= rRect.Top() &&
3311 pFly->Frm().Top() <= rRect.Bottom()) )
3312 pFly->InvalidatePos();
3317 if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
3318 pAnchor->GetUpper()->InvalidateSize();
3320 // --> OD 2008-01-30 #i82258# - make code robust
3321 ViewShell* pSh = 0;
3322 if ( bInva && pPage &&
3323 0 != (pSh = pPage->GetShell()) )
3325 pSh->InvalidateWindows( rRect );
3327 // <--
3330 /*************************************************************************
3332 |* GetVirtualUpper() liefert bei absatzgebundenen Objekten den Upper
3333 |* des Ankers. Falls es sich dabei um verkettete Rahmen oder
3334 |* Fussnoten handelt, wird ggf. der "virtuelle" Upper ermittelt.
3336 |*************************************************************************/
3338 const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos )
3340 if( pFrm->IsTxtFrm() )
3342 pFrm = pFrm->GetUpper();
3343 if( !pFrm->Frm().IsInside( rPos ) )
3345 if( pFrm->IsFtnFrm() )
3347 const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow();
3348 while( pTmp )
3350 if( pTmp->Frm().IsInside( rPos ) )
3351 return pTmp;
3352 pTmp = pTmp->GetFollow();
3355 else
3357 SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm();
3358 while( pTmp )
3360 if( pTmp->Frm().IsInside( rPos ) )
3361 return pTmp;
3362 pTmp = pTmp->GetNextLink();
3367 return pFrm;
3370 /*************************************************************************
3372 |* IsLowerOf()
3374 |*************************************************************************/
3376 BOOL Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj )
3378 Point aPos;
3379 const SwFrm* pFrm;
3380 if( pObj->ISA(SwVirtFlyDrawObj) )
3382 const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm();
3383 pFrm = pFly->GetAnchorFrm();
3384 aPos = pFly->Frm().Pos();
3386 else
3388 pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm();
3389 aPos = pObj->GetCurrentBoundRect().TopLeft();
3391 ASSERT( pFrm, "8-( Fly is lost in Space." );
3392 pFrm = GetVirtualUpper( pFrm, aPos );
3394 { if ( pFrm == pCurrFrm )
3395 return TRUE;
3396 if( pFrm->IsFlyFrm() )
3398 aPos = pFrm->Frm().Pos();
3399 pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3401 else
3402 pFrm = pFrm->GetUpper();
3403 } while ( pFrm );
3404 return FALSE;
3407 const SwFrm *FindKontext( const SwFrm *pFrm, USHORT nAdditionalKontextTyp )
3409 //Liefert die Umgebung des Frm in die kein Fly aus einer anderen
3410 //Umgebung hineinragen kann.
3411 const USHORT nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
3412 FRM_FTN | FRM_FLY |
3413 FRM_TAB | FRM_ROW | FRM_CELL |
3414 nAdditionalKontextTyp;
3416 { if ( pFrm->GetType() & nTyp )
3417 break;
3418 pFrm = pFrm->GetUpper();
3419 } while( pFrm );
3420 return pFrm;
3423 BOOL IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm )
3425 const SwFrm *pKontext = FindKontext( pInnerFrm, 0 );
3427 const USHORT nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
3428 FRM_FTN | FRM_FLY |
3429 FRM_TAB | FRM_ROW | FRM_CELL;
3431 { if ( pFrm->GetType() & nTyp )
3433 if( pFrm == pKontext )
3434 return TRUE;
3435 if( pFrm->IsCellFrm() )
3436 return FALSE;
3438 if( pFrm->IsFlyFrm() )
3440 Point aPos( pFrm->Frm().Pos() );
3441 pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3443 else
3444 pFrm = pFrm->GetUpper();
3445 } while( pFrm );
3447 return FALSE;
3451 //---------------------------------
3453 SwTwips MA_FASTCALL lcl_CalcCellRstHeight( SwLayoutFrm *pCell )
3455 if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() )
3457 SwFrm *pLow = pCell->Lower();
3458 long nHeight = 0, nFlyAdd = 0;
3461 long nLow = pLow->Frm().Height();
3462 if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() )
3463 nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height();
3464 else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() )
3465 nLow += ((SwSectionFrm*)pLow)->Undersize();
3466 nFlyAdd = Max( 0L, nFlyAdd - nLow );
3467 nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
3468 nHeight += nLow;
3469 pLow = pLow->GetNext();
3470 } while ( pLow );
3471 if ( nFlyAdd )
3472 nHeight += nFlyAdd;
3474 //Der Border will natuerlich auch mitspielen, er kann leider nicht
3475 //aus PrtArea und Frm errechnet werden, da diese in beliebiger
3476 //Kombination ungueltig sein koennen.
3477 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
3478 const SwBorderAttrs &rAttrs = *aAccess.Get();
3479 nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
3481 return pCell->Frm().Height() - nHeight;
3483 else
3485 long nRstHeight = 0;
3486 SwFrm *pLow = pCell->Lower();
3488 { nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow );
3489 pLow = pLow->GetNext();
3491 } while ( pLow );
3493 return nRstHeight;
3497 SwTwips MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow )
3499 SwTwips nRstHeight = LONG_MAX;
3500 SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower();
3501 while ( pLow )
3503 nRstHeight = Min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) );
3504 pLow = (SwLayoutFrm*)pLow->GetNext();
3506 return nRstHeight;
3509 const SwFrm* MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage )
3511 if ( !rRect.IsOver( pPage->Frm() ) )
3513 const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper());
3514 const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0;
3515 if ( pTmpPage )
3516 pPage = pTmpPage;
3519 return pPage;
3522 SwFrm* GetFrmOfModify( SwModify& rMod, USHORT nFrmType, const Point* pPoint,
3523 const SwPosition *pPos, const BOOL bCalcFrm )
3525 SwFrm *pMinFrm = 0, *pTmpFrm;
3526 SwRect aCalcRect;
3527 bool bClientIterChanged = false;
3529 SwClientIter aIter( rMod );
3530 do {
3531 pMinFrm = 0;
3532 sal_uInt64 nMinDist = 0;
3533 bClientIterChanged = false;
3535 for( pTmpFrm = (SwFrm*)aIter.First( TYPE( SwFrm )); pTmpFrm;
3536 pTmpFrm = (SwFrm*)aIter.Next() )
3538 if( pTmpFrm->GetType() & nFrmType &&
3539 (!pTmpFrm->IsFlowFrm() ||
3540 !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() ))
3542 if( pPoint )
3544 // --> FME 2006-02-03 #127369#
3545 // Set pointer to be watched. If a client is removed from
3546 // rMod (e.g., by deleting a frame), the bWatchDeleted flag
3547 // is set at the SwClientIter.
3548 const bool bWatchClientSet = pMinFrm != 0;
3549 aIter.SetWatchClient( pMinFrm );
3550 // <--
3552 if( bCalcFrm )
3554 // --> OD 2005-03-04 #b6234250# - format parent Writer
3555 // fly frame, if it isn't been formatted yet.
3556 // Note: The Writer fly frame could be the frame itself.
3557 SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() );
3558 if ( pFlyFrm &&
3559 pFlyFrm->Frm().Pos().X() == WEIT_WECH &&
3560 pFlyFrm->Frm().Pos().Y() == WEIT_WECH )
3562 SwObjectFormatter::FormatObj( *pFlyFrm );
3564 // <--
3565 pTmpFrm->Calc();
3568 // --> FME 2006-02-03 #127369#
3569 // The SwClientIter list has changed. Restart.
3570 // aIter.IsChanged basically checks if pTmpFrm has been
3571 // deleted. bWatchClientSet && aIter.GetWatchClient()
3572 // checks if pMinFrm has been deleted.
3573 // <--
3574 if( aIter.IsChanged() || ( bWatchClientSet && !aIter.GetWatchClient() ) )
3576 bClientIterChanged = true;
3577 break;
3580 // bei Flys ggfs. ueber den Parent gehen wenn sie selbst
3581 // nocht nicht "formatiert" sind
3582 if( !bCalcFrm && nFrmType & FRM_FLY &&
3583 ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() &&
3584 WEIT_WECH == pTmpFrm->Frm().Pos().X() &&
3585 WEIT_WECH == pTmpFrm->Frm().Pos().Y() )
3586 aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm();
3587 else
3588 aCalcRect = pTmpFrm->Frm();
3590 if ( aCalcRect.IsInside( *pPoint ) )
3592 pMinFrm = pTmpFrm;
3593 break;
3596 // Point not in rectangle. Compare distances:
3597 const Point aCalcRectCenter = aCalcRect.Center();
3598 const Point aDiff = aCalcRectCenter - *pPoint;
3599 const sal_uInt64 nCurrentDist = aDiff.X() * aDiff.X() + aDiff.Y() * aDiff.Y(); // opt: no sqrt
3600 if ( !pMinFrm || nCurrentDist < nMinDist )
3602 pMinFrm = pTmpFrm;
3603 nMinDist = nCurrentDist;
3606 else
3608 // Wenn kein pPoint angegeben ist, dann reichen
3609 // wir irgendeinen raus: den ersten!
3610 pMinFrm = pTmpFrm;
3611 break;
3615 } while( bClientIterChanged );
3617 if( pPos && pMinFrm && pMinFrm->IsTxtFrm() )
3618 return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos );
3620 return pMinFrm;
3623 BOOL IsExtraData( const SwDoc *pDoc )
3625 const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
3626 return rInf.IsPaintLineNumbers() ||
3627 rInf.IsCountInFlys() ||
3628 ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE &&
3629 pDoc->GetRedlineTbl().Count());
3632 // OD 22.09.2003 #110978#
3633 const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const
3635 SwRect aPrtWithoutHeaderFooter( Prt() );
3636 aPrtWithoutHeaderFooter.Pos() += Frm().Pos();
3638 const SwFrm* pLowerFrm = Lower();
3639 while ( pLowerFrm )
3641 // Note: independent on text direction page header and page footer are
3642 // always at top respectively at bottom of the page frame.
3643 if ( pLowerFrm->IsHeaderFrm() )
3645 aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() +
3646 pLowerFrm->Frm().Height() );
3648 if ( pLowerFrm->IsFooterFrm() )
3650 aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() -
3651 pLowerFrm->Frm().Height() );
3654 pLowerFrm = pLowerFrm->GetNext();
3657 return aPrtWithoutHeaderFooter;
3660 /** method to determine the spacing values of a frame
3662 OD 2004-03-10 #i28701#
3663 OD 2009-08-28 #i102458#
3664 Add output parameter <obIsLineSpacingProportional>
3666 @author OD
3668 void GetSpacingValuesOfFrm( const SwFrm& rFrm,
3669 SwTwips& onLowerSpacing,
3670 SwTwips& onLineSpacing,
3671 bool& obIsLineSpacingProportional )
3673 if ( !rFrm.IsFlowFrm() )
3675 onLowerSpacing = 0;
3676 onLineSpacing = 0;
3678 else
3680 const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace();
3681 onLowerSpacing = rULSpace.GetLower();
3683 onLineSpacing = 0;
3684 obIsLineSpacingProportional = false;
3685 if ( rFrm.IsTxtFrm() )
3687 onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace();
3688 obIsLineSpacingProportional =
3689 onLineSpacing != 0 &&
3690 static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0;
3693 ASSERT( onLowerSpacing >= 0 && onLineSpacing >= 0,
3694 "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" );
3698 /** method to get the content of the table cell, skipping content from nested tables
3700 const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell )
3702 const SwCntntFrm* pCntnt = rCell.ContainsCntnt();
3703 const SwTabFrm* pTab = rCell.FindTabFrm();
3705 while ( pCntnt && rCell.IsAnLower( pCntnt ) )
3707 const SwTabFrm* pTmpTab = pCntnt->FindTabFrm();
3708 if ( pTmpTab != pTab )
3710 pCntnt = pTmpTab->FindLastCntnt();
3711 if ( pCntnt )
3713 pCntnt = pCntnt->FindNextCnt();
3716 else
3717 break;
3719 return pCntnt;
3722 /** Can be used to check if a frame has been deleted
3724 bool SwDeletionChecker::HasBeenDeleted()
3726 if ( !mpFrm || !mpRegIn )
3727 return false;
3729 SwClientIter aIter( const_cast<SwModify&>(*mpRegIn) );
3730 const SwClient* pLast = aIter.GoStart();
3732 while ( pLast )
3734 if ( pLast->ISA( SwFrm ) && pLast == mpFrm )
3735 return false;
3737 pLast = aIter++;
3740 return true;