Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svx/svdmodel.hxx>
21 : #include <svx/svdpage.hxx>
22 : #include <editeng/brushitem.hxx>
23 : #include <editeng/shaditem.hxx>
24 : #include <editeng/ulspitem.hxx>
25 : #include <editeng/boxitem.hxx>
26 : #include <editeng/lspcitem.hxx>
27 :
28 : #include <fmtornt.hxx>
29 : #include <fmthdft.hxx>
30 : #include <fmtfsize.hxx>
31 : #include <fmtsrnd.hxx>
32 : #include <docary.hxx>
33 : #include <lineinfo.hxx>
34 : #include <swmodule.hxx>
35 : #include "pagefrm.hxx"
36 : #include "colfrm.hxx"
37 : #include "fesh.hxx"
38 : #include "viewimp.hxx"
39 : #include "viewopt.hxx"
40 : #include "dflyobj.hxx"
41 : #include "dcontact.hxx"
42 : #include "frmtool.hxx"
43 : #include "tabfrm.hxx"
44 : #include "rowfrm.hxx"
45 : #include "ftnfrm.hxx"
46 : #include "txtfrm.hxx"
47 : #include "notxtfrm.hxx"
48 : #include "flyfrms.hxx"
49 : #include "layact.hxx"
50 : #include "pagedesc.hxx"
51 : #include "section.hxx"
52 : #include "sectfrm.hxx"
53 : #include "node2lay.hxx"
54 : #include "ndole.hxx"
55 : #include "hints.hxx"
56 : #include <layhelp.hxx>
57 : #include <laycache.hxx>
58 : #include <rootfrm.hxx>
59 : #include <paratr.hxx>
60 : #include <sortedobjs.hxx>
61 : #include <objectformatter.hxx>
62 : #include <switerator.hxx>
63 :
64 : // ftnfrm.cxx:
65 : void sw_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
66 :
67 : using namespace ::com::sun::star;
68 :
69 : bool bObjsDirect = true;
70 : bool bDontCreateObjects = false;
71 : bool bSetCompletePaintOnInvalidate = false;
72 :
73 : sal_uInt8 StackHack::nCnt = 0;
74 : sal_Bool StackHack::bLocked = sal_False;
75 :
76 0 : SwFrmNotify::SwFrmNotify( SwFrm *pF ) :
77 : pFrm( pF ),
78 0 : aFrm( pF->Frm() ),
79 0 : aPrt( pF->Prt() ),
80 : bInvaKeep( sal_False ),
81 0 : bValidSize( pF->GetValidSizeFlag() ),
82 0 : mbFrmDeleted( false ) // #i49383#
83 : {
84 0 : if ( pF->IsTxtFrm() )
85 : {
86 0 : mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( true );
87 0 : mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( false );
88 : }
89 : else
90 : {
91 0 : mnFlyAnchorOfst = 0;
92 0 : mnFlyAnchorOfstNoWrap = 0;
93 : }
94 :
95 0 : bHadFollow = pF->IsCntntFrm() ?
96 0 : (((SwCntntFrm*)pF)->GetFollow() ? sal_True : sal_False) :
97 0 : sal_False;
98 0 : }
99 :
100 0 : SwFrmNotify::~SwFrmNotify()
101 : {
102 : // #i49383#
103 0 : if ( mbFrmDeleted )
104 : {
105 0 : return;
106 : }
107 :
108 0 : SWRECTFN( pFrm )
109 0 : const bool bAbsP = POS_DIFF( aFrm, pFrm->Frm() );
110 : const bool bChgWidth =
111 0 : (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)();
112 : const bool bChgHeight =
113 0 : (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)();
114 0 : const bool bChgFlyBasePos = pFrm->IsTxtFrm() &&
115 0 : ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( true ) ) ||
116 0 : ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( false ) ) );
117 :
118 0 : if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() )
119 : {
120 0 : SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm );
121 :
122 0 : if ( !pFlow->IsFollow() )
123 : {
124 0 : if ( !pFrm->GetIndPrev() )
125 : {
126 0 : if ( bInvaKeep )
127 : {
128 0 : SwFrm *pPre = pFrm->FindPrev();
129 0 : if ( pPre && pPre->IsFlowFrm() )
130 : {
131 : // 1. pPre wants to keep with me:
132 0 : bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev();
133 :
134 : // 2. pPre is a table and the last row wants to keep with me:
135 0 : if ( !bInvalidPrePos && pPre->IsTabFrm() )
136 : {
137 0 : SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre);
138 0 : if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) )
139 : {
140 0 : SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower());
141 0 : if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
142 0 : bInvalidPrePos = true;
143 : }
144 : }
145 :
146 0 : if ( bInvalidPrePos )
147 0 : pPre->InvalidatePos();
148 : }
149 : }
150 : }
151 0 : else if ( !pFlow->HasFollow() )
152 : {
153 0 : long nOldHeight = (aFrm.*fnRect->fnGetHeight)();
154 0 : long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)();
155 0 : if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) )
156 0 : pFlow->CheckKeep();
157 : }
158 : }
159 : }
160 :
161 0 : if ( bAbsP )
162 : {
163 0 : pFrm->SetCompletePaint();
164 :
165 0 : SwFrm* pNxt = pFrm->GetIndNext();
166 : // #121888# - skip empty section frames
167 0 : while ( pNxt &&
168 0 : pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() )
169 : {
170 0 : pNxt = pNxt->GetIndNext();
171 : }
172 :
173 0 : if ( pNxt )
174 0 : pNxt->InvalidatePos();
175 : else
176 : {
177 : // #104100# - correct condition for setting retouche
178 : // flag for vertical layout.
179 0 : if( pFrm->IsRetoucheFrm() &&
180 0 : (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 )
181 : {
182 0 : pFrm->SetRetouche();
183 : }
184 :
185 : // A fresh follow frame does not have to be invalidated, because
186 : // it is already formatted:
187 0 : if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() )
188 : {
189 0 : if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() )
190 0 : pFrm->InvalidateNextPos();
191 : }
192 : }
193 : }
194 :
195 : //For each resize of the background graphics is a repaint necessary.
196 : const bool bPrtWidth =
197 0 : (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)();
198 : const bool bPrtHeight =
199 0 : (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)();
200 0 : if ( bPrtWidth || bPrtHeight )
201 : {
202 0 : const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos();
203 0 : if ( GPOS_NONE != ePos && GPOS_TILED != ePos )
204 0 : pFrm->SetCompletePaint();
205 : }
206 : else
207 : {
208 : // #97597# - consider case that *only* margins between
209 : // frame and printing area has changed. Then, frame has to be repainted,
210 : // in order to force paint of the margin areas.
211 0 : if ( !bAbsP && (bChgWidth || bChgHeight) )
212 : {
213 0 : pFrm->SetCompletePaint();
214 : }
215 : }
216 :
217 0 : const bool bPrtP = POS_DIFF( aPrt, pFrm->Prt() );
218 0 : if ( bAbsP || bPrtP || bChgWidth || bChgHeight ||
219 0 : bPrtWidth || bPrtHeight || bChgFlyBasePos )
220 : {
221 0 : if( pFrm->IsAccessibleFrm() )
222 : {
223 0 : SwRootFrm *pRootFrm = pFrm->getRootFrm();
224 0 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
225 0 : pRootFrm->GetCurrShell() )
226 : {
227 0 : pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm );
228 : }
229 : }
230 :
231 : // Notification of anchored objects
232 0 : if ( pFrm->GetDrawObjs() )
233 : {
234 0 : const SwSortedObjs &rObjs = *pFrm->GetDrawObjs();
235 0 : SwPageFrm* pPageFrm = 0;
236 0 : for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i )
237 : {
238 : // OD 2004-03-31 #i26791# - no general distinction between
239 : // Writer fly frames and drawing objects
240 0 : bool bNotify = false;
241 0 : bool bNotifySize = false;
242 0 : SwAnchoredObject* pObj = rObjs[i];
243 0 : SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() );
244 : // #115759#
245 0 : const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar();
246 0 : if ( !bAnchoredAsChar )
247 : {
248 : // Notify object, which aren't anchored as-character:
249 :
250 : // always notify objects, if frame position has changed
251 : // or if the object is to-page|to-fly anchored.
252 0 : if ( bAbsP ||
253 0 : pContact->ObjAnchoredAtPage() ||
254 0 : pContact->ObjAnchoredAtFly() )
255 : {
256 0 : bNotify = true;
257 :
258 : // assure that to-fly anchored Writer fly frames are
259 : // registered at the correct page frame, if frame
260 : // position has changed.
261 0 : if ( bAbsP && pContact->ObjAnchoredAtFly() &&
262 0 : pObj->ISA(SwFlyFrm) )
263 : {
264 : // determine to-fly anchored Writer fly frame
265 0 : SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
266 : // determine page frame of to-fly anchored
267 : // Writer fly frame
268 0 : SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm();
269 : // determine page frame, if needed.
270 0 : if ( !pPageFrm )
271 : {
272 0 : pPageFrm = pFrm->FindPageFrm();
273 : }
274 0 : if ( pPageFrm != pFlyPageFrm )
275 : {
276 : OSL_ENSURE( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" );
277 0 : if( pFlyPageFrm )
278 0 : pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm );
279 : else
280 0 : pPageFrm->AppendFlyToPage( pFlyFrm );
281 : }
282 : }
283 : }
284 : // otherwise the objects are notified in dependence to
285 : // its positioning and alignment
286 : else
287 : {
288 : const SwFmtVertOrient& rVert =
289 0 : pContact->GetFmt()->GetVertOrient();
290 0 : if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
291 0 : rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
292 0 : rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
293 0 : ( bChgHeight || bPrtHeight ) )
294 : {
295 0 : bNotify = true;
296 : }
297 0 : if ( !bNotify )
298 : {
299 : const SwFmtHoriOrient& rHori =
300 0 : pContact->GetFmt()->GetHoriOrient();
301 0 : if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
302 0 : rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
303 0 : rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
304 0 : ( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
305 : {
306 0 : bNotify = true;
307 : }
308 : }
309 : }
310 : }
311 0 : else if ( bPrtWidth )
312 : {
313 : // Notify as-character anchored objects, if printing area
314 : // width has changed.
315 0 : bNotify = true;
316 0 : bNotifySize = true;
317 : }
318 :
319 : // perform notification via the corresponding invalidations
320 0 : if ( bNotify )
321 : {
322 0 : if ( pObj->ISA(SwFlyFrm) )
323 : {
324 0 : SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
325 0 : if ( bNotifySize )
326 0 : pFlyFrm->_InvalidateSize();
327 : // #115759# - no invalidation of
328 : // position for as-character anchored objects.
329 0 : if ( !bAnchoredAsChar )
330 : {
331 0 : pFlyFrm->_InvalidatePos();
332 : }
333 0 : pFlyFrm->_Invalidate();
334 : }
335 0 : else if ( pObj->ISA(SwAnchoredDrawObject) )
336 : {
337 : // #115759# - no invalidation of
338 : // position for as-character anchored objects.
339 0 : if ( !bAnchoredAsChar )
340 : {
341 0 : pObj->InvalidateObjPos();
342 : }
343 : }
344 : else
345 : {
346 : OSL_FAIL( "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." );
347 : }
348 : }
349 : }
350 0 : }
351 : }
352 0 : else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() )
353 : {
354 0 : SwRootFrm *pRootFrm = pFrm->getRootFrm();
355 0 : if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
356 0 : pRootFrm->GetCurrShell() )
357 : {
358 0 : pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm );
359 : }
360 : }
361 :
362 : // #i9046# Automatic frame width
363 0 : SwFlyFrm* pFly = 0;
364 : // #i35879# Do not trust the inf flags. pFrm does not
365 : // necessarily have to have an upper!
366 0 : if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) )
367 : {
368 : // #i61999#
369 : // no invalidation of columned Writer fly frames, because automatic
370 : // width doesn't make sense for such Writer fly frames.
371 0 : if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() )
372 : {
373 0 : const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize();
374 :
375 : // This could be optimized. Basically the fly frame only has to
376 : // be invalidated, if the first line of pFrm (if pFrm is a content
377 : // frame, for other frame types its the print area) has changed its
378 : // size and pFrm was responsible for the current width of pFly. On
379 : // the other hand, this is only rarely used and re-calculation of
380 : // the fly frame does not cause too much trouble. So we keep it this
381 : // way:
382 0 : if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() )
383 : {
384 : // #i50668#, #i50998# - invalidation of position
385 : // of as-character anchored fly frames not needed and can cause
386 : // layout loops
387 0 : if ( !pFly->ISA(SwFlyInCntFrm) )
388 : {
389 0 : pFly->InvalidatePos();
390 : }
391 0 : pFly->InvalidateSize();
392 : }
393 : }
394 : }
395 0 : }
396 :
397 0 : SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) :
398 : SwFrmNotify( pLayFrm ),
399 0 : bLowersComplete( sal_False )
400 : {
401 0 : }
402 :
403 : // OD 2004-05-11 #i28701# - local method to invalidate the position of all
404 : // frames inclusive its floating screen objects, which are lowers of the given
405 : // layout frame
406 0 : static void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm )
407 : {
408 0 : if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() )
409 : {
410 0 : _rLayoutFrm.InvalidateObjs( true, false );
411 : }
412 :
413 0 : SwFrm* pLowerFrm = _rLayoutFrm.Lower();
414 0 : while ( pLowerFrm )
415 : {
416 0 : pLowerFrm->InvalidatePos();
417 0 : if ( pLowerFrm->IsTxtFrm() )
418 : {
419 0 : static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD );
420 : }
421 0 : else if ( pLowerFrm->IsTabFrm() )
422 : {
423 0 : pLowerFrm->InvalidatePrt();
424 : }
425 :
426 0 : pLowerFrm->InvalidateObjs( true, false );
427 :
428 0 : pLowerFrm = pLowerFrm->GetNext();
429 : };
430 0 : }
431 :
432 0 : SwLayNotify::~SwLayNotify()
433 : {
434 : // #i49383#
435 0 : if ( mbFrmDeleted )
436 : {
437 0 : return;
438 : }
439 :
440 0 : SwLayoutFrm *pLay = GetLay();
441 0 : SWRECTFN( pLay )
442 0 : bool bNotify = false;
443 0 : if ( pLay->Prt().SSize() != aPrt.SSize() )
444 : {
445 0 : if ( !IsLowersComplete() )
446 : {
447 : bool bInvaPercent;
448 :
449 0 : if ( pLay->IsRowFrm() )
450 : {
451 0 : bInvaPercent = true;
452 0 : long nNew = (pLay->Prt().*fnRect->fnGetHeight)();
453 0 : if( nNew != (aPrt.*fnRect->fnGetHeight)() )
454 0 : ((SwRowFrm*)pLay)->AdjustCells( nNew, sal_True);
455 0 : if( (pLay->Prt().*fnRect->fnGetWidth)()
456 0 : != (aPrt.*fnRect->fnGetWidth)() )
457 0 : ((SwRowFrm*)pLay)->AdjustCells( 0, sal_False );
458 : }
459 : else
460 : {
461 : //Proportional adoption of the internal.
462 : //1. If the formatted is no Fly
463 : //2. If he contains no columns
464 : //3. If the Fly has a fixed hight and the columns
465 : // are next to be.
466 : // Hoehe danebenliegen.
467 : //4. Never at SectionFrms.
468 : bool bLow;
469 0 : if( pLay->IsFlyFrm() )
470 : {
471 0 : if ( pLay->Lower() )
472 : {
473 0 : bLow = !pLay->Lower()->IsColumnFrm() ||
474 0 : (pLay->Lower()->Frm().*fnRect->fnGetHeight)()
475 0 : != (pLay->Prt().*fnRect->fnGetHeight)();
476 : }
477 : else
478 0 : bLow = false;
479 : }
480 0 : else if( pLay->IsSctFrm() )
481 : {
482 0 : if ( pLay->Lower() )
483 : {
484 0 : if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() )
485 0 : bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height();
486 : else
487 0 : bLow = pLay->Prt().Width() != aPrt.Width();
488 : }
489 : else
490 0 : bLow = false;
491 : }
492 0 : else if( pLay->IsFooterFrm() && !pLay->HasFixSize() )
493 0 : bLow = pLay->Prt().Width() != aPrt.Width();
494 : else
495 0 : bLow = true;
496 0 : bInvaPercent = bLow;
497 0 : if ( bLow )
498 : {
499 0 : pLay->ChgLowersProp( aPrt.SSize() );
500 : }
501 : // If the PrtArea has been extended, it might be possible that the chain of parts
502 : // can take another frame. As a result, the "possible right one" needs to be
503 : // invalidated. This only pays off if this or its Uppers are moveable sections.
504 : // A PrtArea has been extended if width or height are larger than before.
505 0 : if ( (pLay->Prt().Height() > aPrt.Height() ||
506 0 : pLay->Prt().Width() > aPrt.Width()) &&
507 0 : (pLay->IsMoveable() || pLay->IsFlyFrm()) )
508 : {
509 0 : SwFrm *pTmpFrm = pLay->Lower();
510 0 : if ( pTmpFrm && pTmpFrm->IsFlowFrm() )
511 : {
512 0 : while ( pTmpFrm->GetNext() )
513 0 : pTmpFrm = pTmpFrm->GetNext();
514 0 : pTmpFrm->InvalidateNextPos();
515 : }
516 : }
517 : }
518 0 : bNotify = true;
519 : //EXPENSIVE!! But how we do it more elegant?
520 0 : if( bInvaPercent )
521 0 : pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() );
522 : }
523 0 : if ( pLay->IsTabFrm() )
524 : //So that _only_ the shadow is drawn while resizing.
525 0 : ((SwTabFrm*)pLay)->SetComplete();
526 : else
527 : {
528 0 : const SwViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
529 0 : if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
530 0 : !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) )
531 : //Thereby the subordinates are retouched clean.
532 : //Example problem: Take the Flys with the handles and downsize.
533 : //Not for body and page, otherwise it flickers when loading HTML.
534 0 : pLay->SetCompletePaint();
535 : }
536 : }
537 : //Notify Lower if the position has changed.
538 0 : const bool bPrtPos = POS_DIFF( aPrt, pLay->Prt() );
539 0 : const bool bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() );
540 0 : const bool bSize = pLay->Frm().SSize() != aFrm.SSize();
541 :
542 0 : if ( bPos && pLay->Lower() && !IsLowersComplete() )
543 0 : pLay->Lower()->InvalidatePos();
544 :
545 0 : if ( bPrtPos )
546 0 : pLay->SetCompletePaint();
547 :
548 : //Inform the Follower if the SSize has changed.
549 0 : if ( bSize )
550 : {
551 0 : if( pLay->GetNext() )
552 : {
553 0 : if ( pLay->GetNext()->IsLayoutFrm() )
554 0 : pLay->GetNext()->_InvalidatePos();
555 : else
556 0 : pLay->GetNext()->InvalidatePos();
557 : }
558 0 : else if( pLay->IsSctFrm() )
559 0 : pLay->InvalidateNextPos();
560 : }
561 0 : if ( !IsLowersComplete() &&
562 0 : !(pLay->GetType()&(FRM_FLY|FRM_SECTION) &&
563 0 : pLay->Lower() && pLay->Lower()->IsColumnFrm()) &&
564 0 : (bPos || bNotify) && !(pLay->GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page
565 : {
566 : // #i44016# - force unlock of position of lower objects.
567 : // #i43913# - no unlock of position of objects,
568 : // if <pLay> is a cell frame, and its table frame resp. its parent table
569 : // frame is locked.
570 : // #i47458# - force unlock of position of lower objects,
571 : // only if position of layout frame has changed.
572 0 : bool bUnlockPosOfObjs( bPos );
573 0 : if ( bUnlockPosOfObjs && pLay->IsCellFrm() )
574 : {
575 0 : SwTabFrm* pTabFrm( pLay->FindTabFrm() );
576 0 : if ( pTabFrm &&
577 0 : ( pTabFrm->IsJoinLocked() ||
578 0 : ( pTabFrm->IsFollow() &&
579 0 : pTabFrm->FindMaster()->IsJoinLocked() ) ) )
580 : {
581 0 : bUnlockPosOfObjs = false;
582 : }
583 : }
584 : // #i49383# - check for footnote frame, if unlock
585 : // of position of lower objects is allowed.
586 0 : else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() )
587 : {
588 0 : bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs();
589 : }
590 : // #i51303# - no unlock of object positions for sections
591 0 : else if ( bUnlockPosOfObjs && pLay->IsSctFrm() )
592 : {
593 0 : bUnlockPosOfObjs = false;
594 : }
595 0 : pLay->NotifyLowerObjs( bUnlockPosOfObjs );
596 : }
597 0 : if ( bPos && pLay->IsFtnFrm() && pLay->Lower() )
598 : {
599 : // OD 2004-05-11 #i28701#
600 0 : ::lcl_InvalidatePosOfLowers( *pLay );
601 : }
602 0 : if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm()
603 0 : && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() )
604 0 : ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize();
605 0 : }
606 :
607 0 : SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) :
608 : SwLayNotify( pFlyFrm ),
609 : // #115759# - keep correct page frame - the page frame
610 : // the Writer fly frame is currently registered at.
611 0 : pOldPage( pFlyFrm->GetPageFrm() ),
612 0 : aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() )
613 : {
614 0 : }
615 :
616 0 : SwFlyNotify::~SwFlyNotify()
617 : {
618 : // #i49383#
619 0 : if ( mbFrmDeleted )
620 : {
621 0 : return;
622 : }
623 :
624 0 : SwFlyFrm *pFly = GetFly();
625 0 : if ( pFly->IsNotifyBack() )
626 : {
627 0 : SwViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
628 0 : SwViewImp *pImp = pSh ? pSh->Imp() : 0;
629 0 : if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
630 : {
631 : //If in the LayAction the IsAgain is set it can be
632 : //that the old page is destroyed in the meantime!
633 0 : ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt );
634 : // #i35640# - additional notify anchor text frame,
635 : // if Writer fly frame has changed its page
636 0 : if ( pFly->GetAnchorFrm()->IsTxtFrm() &&
637 0 : pFly->GetPageFrm() != pOldPage )
638 : {
639 0 : pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
640 : }
641 : }
642 0 : pFly->ResetNotifyBack();
643 : }
644 :
645 : //Have the size or the positon changed,
646 : //so should the view know this.
647 0 : SWRECTFN( pFly )
648 0 : const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() );
649 0 : const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize();
650 0 : const bool bPrtChgd = aPrt != pFly->Prt();
651 0 : if ( bPosChgd || bFrmChgd || bPrtChgd )
652 : {
653 0 : pFly->NotifyDrawObj();
654 : }
655 0 : if ( bPosChgd && aFrm.Pos().X() != FAR_AWAY )
656 : {
657 : // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames.
658 : // reason: New positioning and alignment (e.g. to-paragraph anchored,
659 : // but aligned at page) are introduced.
660 : // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower
661 : // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>.
662 :
663 0 : if ( pFly->IsFlyAtCntFrm() )
664 : {
665 0 : SwFrm *pNxt = pFly->AnchorFrm()->FindNext();
666 0 : if ( pNxt )
667 : {
668 0 : pNxt->InvalidatePos();
669 : }
670 : }
671 :
672 : // #i26945# - notify anchor.
673 : // Needed for negative positioned Writer fly frames
674 0 : if ( pFly->GetAnchorFrm()->IsTxtFrm() )
675 : {
676 0 : pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
677 : }
678 : }
679 :
680 : // OD 2004-05-13 #i28701#
681 : // #i45180# - no adjustment of layout process flags and
682 : // further notifications/invalidations, if format is called by grow/shrink
683 0 : if ( pFly->ConsiderObjWrapInfluenceOnObjPos() &&
684 0 : ( !pFly->ISA(SwFlyFreeFrm) ||
685 0 : !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) )
686 : {
687 : // #i54138# - suppress restart of the layout process
688 : // on changed frame height.
689 : // Note: It doesn't seem to be necessary and can cause layout loops.
690 0 : if ( bPosChgd )
691 : {
692 : // indicate a restart of the layout process
693 0 : pFly->SetRestartLayoutProcess( true );
694 : }
695 : else
696 : {
697 : // lock position
698 0 : pFly->LockPosition();
699 :
700 0 : if ( !pFly->ConsiderForTextWrap() )
701 : {
702 : // indicate that object has to be considered for text wrap
703 0 : pFly->SetConsiderForTextWrap( true );
704 : // invalidate 'background' in order to allow its 'background'
705 : // to wrap around it.
706 : pFly->NotifyBackground( pFly->GetPageFrm(),
707 0 : pFly->GetObjRectWithSpaces(),
708 0 : PREP_FLY_ARRIVE );
709 : // invalidate position of anchor frame in order to force
710 : // a re-format of the anchor frame, which also causes a
711 : // re-format of the invalid previous frames of the anchor frame.
712 0 : pFly->AnchorFrm()->InvalidatePos();
713 : }
714 : }
715 : }
716 0 : }
717 :
718 0 : SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) :
719 : SwFrmNotify( pCntntFrm ),
720 : // OD 08.01.2004 #i11859#
721 : mbChkHeightOfLastLine( false ),
722 : mnHeightOfLastLine( 0L ),
723 : // OD 2004-02-26 #i25029#
724 : mbInvalidatePrevPrtArea( false ),
725 0 : mbBordersJoinedWithPrev( false )
726 : {
727 : // OD 08.01.2004 #i11859#
728 0 : if ( pCntntFrm->IsTxtFrm() )
729 : {
730 0 : SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm);
731 0 : if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) )
732 : {
733 0 : const SwAttrSet* pSet = pTxtFrm->GetAttrSet();
734 0 : const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
735 0 : if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
736 : {
737 0 : mbChkHeightOfLastLine = true;
738 0 : mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine();
739 : }
740 : }
741 : }
742 0 : }
743 :
744 0 : SwCntntNotify::~SwCntntNotify()
745 : {
746 : // #i49383#
747 0 : if ( mbFrmDeleted )
748 : {
749 0 : return;
750 : }
751 :
752 0 : SwCntntFrm *pCnt = GetCnt();
753 0 : if ( bSetCompletePaintOnInvalidate )
754 0 : pCnt->SetCompletePaint();
755 :
756 0 : SWRECTFN( pCnt )
757 0 : if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) ||
758 0 : pCnt->Frm().SSize() != aFrm.SSize()))
759 : {
760 0 : SwLayoutFrm* pCell = pCnt->GetUpper();
761 0 : while( !pCell->IsCellFrm() && pCell->GetUpper() )
762 0 : pCell = pCell->GetUpper();
763 : OSL_ENSURE( pCell->IsCellFrm(), "Where's my cell?" );
764 0 : if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() )
765 0 : pCell->InvalidatePrt(); //for the vertical allign.
766 : }
767 :
768 : // OD 2004-02-26 #i25029#
769 0 : if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
770 0 : pCnt->IsTxtFrm() &&
771 0 : !pCnt->IsFollow() && !pCnt->GetIndPrev() )
772 : {
773 : // determine previous frame
774 0 : SwFrm* pPrevFrm = pCnt->FindPrev();
775 : // skip empty section frames and hidden text frames
776 : {
777 0 : while ( pPrevFrm &&
778 0 : ( ( pPrevFrm->IsSctFrm() &&
779 0 : !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) ||
780 0 : ( pPrevFrm->IsTxtFrm() &&
781 0 : static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) )
782 : {
783 0 : pPrevFrm = pPrevFrm->FindPrev();
784 : }
785 : }
786 :
787 : // Invalidate printing area of found previous frame
788 0 : if ( pPrevFrm )
789 : {
790 0 : if ( pPrevFrm->IsSctFrm() )
791 : {
792 0 : if ( pCnt->IsInSct() )
793 : {
794 : // Note: found previous frame is a section frame and
795 : // <pCnt> is also inside a section.
796 : // Thus due to <mbBordersJoinedWithPrev>,
797 : // <pCnt> had joined its borders/shadow with the
798 : // last content of the found section.
799 : // Invalidate printing area of last content in found section.
800 : SwFrm* pLstCntntOfSctFrm =
801 0 : static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt();
802 0 : if ( pLstCntntOfSctFrm )
803 : {
804 0 : pLstCntntOfSctFrm->InvalidatePrt();
805 : }
806 : }
807 : }
808 : else
809 : {
810 0 : pPrevFrm->InvalidatePrt();
811 : }
812 : }
813 : }
814 :
815 0 : const bool bFirst = (aFrm.*fnRect->fnGetWidth)() == 0;
816 :
817 0 : if ( pCnt->IsNoTxtFrm() )
818 : {
819 : //Active PlugIn's or OLE-Objects should know something of the change
820 : //thereby they move their window appropriate.
821 0 : SwViewShell *pSh = pCnt->getRootFrm()->GetCurrShell();
822 0 : if ( pSh )
823 : {
824 : SwOLENode *pNd;
825 0 : if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) &&
826 0 : (pNd->GetOLEObj().IsOleRef() ||
827 0 : pNd->IsOLESizeInvalid()) )
828 : {
829 : const bool bNoTxtFrmPrtAreaChanged =
830 0 : ( aPrt.SSize().Width() != 0 &&
831 0 : aPrt.SSize().Height() != 0 ) &&
832 0 : aPrt.SSize() != pCnt->Prt().SSize();
833 : OSL_ENSURE( pCnt->IsInFly(), "OLE not in FlyFrm" );
834 0 : SwFlyFrm *pFly = pCnt->FindFlyFrm();
835 0 : svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
836 0 : SwFEShell *pFESh = 0;
837 0 : SwViewShell *pTmp = pSh;
838 0 : do
839 0 : { if ( pTmp->ISA( SwCrsrShell ) )
840 : {
841 0 : pFESh = (SwFEShell*)pTmp;
842 : // #108369#: Here used to be the condition if (!bFirst).
843 : // I think this should mean "do not call CalcAndSetScale"
844 : // if the frame is formatted for the first time.
845 : // Unfortunately this is not valid anymore since the
846 : // SwNoTxtFrm already gets a width during CalcLowerPreps.
847 : // Nevertheless, the indention of !bFirst seemed to be
848 : // to assure that the OLE objects have already been notified
849 : // if necessary before calling CalcAndSetScale.
850 : // So I replaced !bFirst by !IsOLESizeInvalid. There is
851 : // one additional problem specific to the word import:
852 : // The layout is calculated _before_ calling PrtOLENotify,
853 : // and the OLE objects are not invalidated during import.
854 : // Therefore I added the condition !IsUpdateExpFld,
855 : // have a look at the occurrence of CalcLayout in
856 : // uiview/view.cxx.
857 0 : if ( !pNd->IsOLESizeInvalid() &&
858 0 : !pSh->GetDoc()->IsUpdateExpFld() )
859 : pFESh->CalcAndSetScale( xObj,
860 0 : &pFly->Prt(), &pFly->Frm(),
861 0 : bNoTxtFrmPrtAreaChanged );
862 : }
863 0 : pTmp = (SwViewShell*)pTmp->GetNext();
864 : } while ( pTmp != pSh );
865 :
866 0 : if ( pFESh && pNd->IsOLESizeInvalid() )
867 : {
868 0 : pNd->SetOLESizeInvalid( sal_False );
869 0 : pFESh->CalcAndSetScale( xObj ); // create client
870 : }
871 : }
872 : //dito animated graphics
873 0 : if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() )
874 : {
875 0 : ((SwNoTxtFrm*)pCnt)->StopAnimation();
876 0 : pSh->InvalidateWindows( Frm() );
877 : }
878 : }
879 : }
880 :
881 0 : if ( bFirst )
882 : {
883 0 : pCnt->SetRetouche(); //fix(13870)
884 :
885 0 : SwDoc *pDoc = pCnt->GetNode()->GetDoc();
886 0 : if ( !pDoc->GetSpzFrmFmts()->empty() &&
887 0 : pDoc->DoesContainAtPageObjWithContentAnchor() && !pDoc->IsNewDoc() )
888 : {
889 : // If certain import filters for foreign file format import
890 : // AT_PAGE anchored objects, the corresponding page number is
891 : // typically not known. In this case the content position is
892 : // stored at which the anchored object is found in the
893 : // imported document.
894 : // When this content is formatted it is the time at which
895 : // the page is known. Thus, this data can be corrected now.
896 :
897 0 : const SwPageFrm *pPage = 0;
898 0 : SwNodeIndex *pIdx = 0;
899 0 : SwFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
900 :
901 0 : for ( sal_uInt16 i = 0; i < pTbl->size(); ++i )
902 : {
903 0 : SwFrmFmt *pFmt = (*pTbl)[i];
904 0 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
905 0 : if ( FLY_AT_PAGE != rAnch.GetAnchorId() ||
906 0 : rAnch.GetCntntAnchor() == 0 )
907 : {
908 0 : continue;
909 : }
910 :
911 0 : if ( !pIdx )
912 : {
913 0 : pIdx = new SwNodeIndex( *pCnt->GetNode() );
914 : }
915 0 : if ( rAnch.GetCntntAnchor()->nNode == *pIdx )
916 : {
917 : OSL_FAIL( "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." );
918 0 : if ( !pPage )
919 : {
920 0 : pPage = pCnt->FindPageFrm();
921 : }
922 0 : SwFmtAnchor aAnch( rAnch );
923 0 : aAnch.SetAnchor( 0 );
924 0 : aAnch.SetPageNum( pPage->GetPhyPageNum() );
925 0 : pFmt->SetFmtAttr( aAnch );
926 0 : if ( RES_DRAWFRMFMT != pFmt->Which() )
927 : {
928 0 : pFmt->MakeFrms();
929 0 : }
930 : }
931 : }
932 0 : delete pIdx;
933 : }
934 : }
935 :
936 : // OD 12.01.2004 #i11859# - invalidate printing area of following frame,
937 : // if height of last line has changed.
938 0 : if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine )
939 : {
940 0 : if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() )
941 : {
942 0 : pCnt->InvalidateNextPrtArea();
943 : }
944 : }
945 :
946 : // #i44049#
947 0 : if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) )
948 : {
949 0 : pCnt->InvalidateObjs( true );
950 : }
951 :
952 : // #i43255# - move code to invalidate at-character
953 : // anchored objects due to a change of its anchor character from
954 : // method <SwTxtFrm::Format(..)>.
955 0 : if ( pCnt->IsTxtFrm() )
956 : {
957 0 : SwTxtFrm* pMasterFrm = pCnt->IsFollow()
958 0 : ? static_cast<SwTxtFrm*>(pCnt)->FindMaster()
959 0 : : static_cast<SwTxtFrm*>(pCnt);
960 0 : if ( pMasterFrm && !pMasterFrm->IsFlyLock() &&
961 0 : pMasterFrm->GetDrawObjs() )
962 : {
963 0 : SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs();
964 0 : for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i )
965 : {
966 0 : SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
967 0 : if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
968 : == FLY_AT_CHAR )
969 : {
970 0 : pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() );
971 : }
972 : }
973 : }
974 : }
975 0 : }
976 :
977 0 : void AppendObjs( const SwFrmFmts *pTbl, sal_uLong nIndex,
978 : SwFrm *pFrm, SwPageFrm *pPage )
979 : {
980 0 : for ( sal_uInt16 i = 0; i < pTbl->size(); ++i )
981 : {
982 0 : SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i];
983 0 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
984 0 : if ( rAnch.GetCntntAnchor() &&
985 0 : (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) )
986 : {
987 0 : const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL
988 : //Is a frame or a SdrObject described?
989 0 : const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which();
990 : // OD 23.06.2003 #108784# - append also drawing objects anchored
991 : // as character.
992 0 : const bool bDrawObjInCntnt = bSdrObj &&
993 0 : (rAnch.GetAnchorId() == FLY_AS_CHAR);
994 :
995 0 : if( bFlyAtFly ||
996 0 : (rAnch.GetAnchorId() == FLY_AT_PARA) ||
997 0 : (rAnch.GetAnchorId() == FLY_AT_CHAR) ||
998 : bDrawObjInCntnt )
999 : {
1000 0 : SdrObject* pSdrObj = 0;
1001 0 : if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) )
1002 : {
1003 : OSL_ENSURE( !bSdrObj, "DrawObject not found." );
1004 0 : pFmt->GetDoc()->DelFrmFmt( pFmt );
1005 0 : --i;
1006 0 : continue;
1007 : }
1008 0 : if ( pSdrObj )
1009 : {
1010 0 : if ( !pSdrObj->GetPage() )
1011 : {
1012 0 : pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)->
1013 0 : InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect());
1014 : }
1015 :
1016 : SwDrawContact* pNew =
1017 0 : static_cast<SwDrawContact*>(GetUserCall( pSdrObj ));
1018 0 : if ( !pNew->GetAnchorFrm() )
1019 : {
1020 0 : pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) );
1021 : }
1022 : // OD 19.06.2003 #108784# - add 'virtual' drawing object,
1023 : // if necessary. But control objects have to be excluded.
1024 0 : else if ( !::CheckControlLayer( pSdrObj ) &&
1025 0 : pNew->GetAnchorFrm() != pFrm &&
1026 0 : !pNew->GetDrawObjectByAnchorFrm( *pFrm ) )
1027 : {
1028 0 : SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj();
1029 0 : pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) );
1030 :
1031 0 : pDrawVirtObj->ActionChanged();
1032 : }
1033 :
1034 : }
1035 : else
1036 : {
1037 : SwFlyFrm *pFly;
1038 0 : if( bFlyAtFly )
1039 0 : pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
1040 : else
1041 0 : pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm );
1042 0 : pFly->Lock();
1043 0 : pFrm->AppendFly( pFly );
1044 0 : pFly->Unlock();
1045 0 : if ( pPage )
1046 0 : ::RegistFlys( pPage, pFly );
1047 : }
1048 : }
1049 : }
1050 : }
1051 0 : }
1052 :
1053 0 : static bool lcl_ObjConnected( SwFrmFmt *pFmt, const SwFrm* pSib )
1054 : {
1055 0 : SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt );
1056 0 : if ( RES_FLYFRMFMT == pFmt->Which() )
1057 : {
1058 0 : const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0;
1059 : const SwFlyFrm* pTmpFrm;
1060 0 : for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
1061 : {
1062 0 : if(! pRoot || pRoot == pTmpFrm->getRootFrm() )
1063 0 : return true;
1064 : }
1065 : }
1066 : else
1067 : {
1068 0 : SwDrawContact *pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt);
1069 0 : if ( pContact )
1070 0 : return pContact->GetAnchorFrm() != 0;
1071 : }
1072 0 : return false;
1073 : }
1074 :
1075 : /** helper method to determine, if a <SwFrmFmt>, which has an object connected,
1076 : is located in header or footer.
1077 :
1078 : OD 23.06.2003 #108784#
1079 : */
1080 0 : static bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt )
1081 : {
1082 0 : bool bRetVal = false;
1083 :
1084 0 : const SwFmtAnchor& rAnch = _rFmt.GetAnchor();
1085 :
1086 0 : if (rAnch.GetAnchorId() != FLY_AT_PAGE)
1087 : {
1088 0 : bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode );
1089 : }
1090 :
1091 0 : return bRetVal;
1092 : }
1093 :
1094 0 : void AppendAllObjs( const SwFrmFmts *pTbl, const SwFrm* pSib )
1095 : {
1096 : //Connecting of all Objects, which are described in the SpzTbl with the
1097 : //layout.
1098 : //If nothing happens anymore we can stop. Then formats can still remain,
1099 : //because we neither use character bound frames nor objects which
1100 : //are anchored to character bounds.
1101 :
1102 0 : SwFrmFmts aCpy( *pTbl );
1103 :
1104 0 : sal_uInt16 nOldCnt = USHRT_MAX;
1105 :
1106 0 : while ( !aCpy.empty() && aCpy.size() != nOldCnt )
1107 : {
1108 0 : nOldCnt = aCpy.size();
1109 0 : for ( int i = 0; i < int(aCpy.size()); ++i )
1110 : {
1111 0 : SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ sal_uInt16(i) ];
1112 0 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
1113 0 : sal_Bool bRemove = sal_False;
1114 0 : if ((rAnch.GetAnchorId() == FLY_AT_PAGE) ||
1115 0 : (rAnch.GetAnchorId() == FLY_AS_CHAR))
1116 : {
1117 : //Page bounded are already anchored, character bounded
1118 : //I don't want here.
1119 0 : bRemove = sal_True;
1120 : }
1121 0 : else if ( sal_False == (bRemove = ::lcl_ObjConnected( pFmt, pSib )) ||
1122 0 : ::lcl_InHeaderOrFooter( *pFmt ) )
1123 : {
1124 : // OD 23.06.2003 #108784# - correction: for objects in header
1125 : // or footer create frames, in spite of the fact that an connected
1126 : // objects already exists.
1127 : //Call for Flys and DrawObjs only a MakeFrms if nor
1128 : //no dependent exists, otherwise, or if the MakeDrms creates no
1129 : //dependents, remove.
1130 0 : pFmt->MakeFrms();
1131 0 : bRemove = ::lcl_ObjConnected( pFmt, pSib );
1132 : }
1133 0 : if ( bRemove )
1134 : {
1135 0 : aCpy.erase( aCpy.begin() + i );
1136 0 : --i;
1137 : }
1138 : }
1139 : }
1140 0 : aCpy.clear();
1141 0 : }
1142 :
1143 : /** local method to set 'working' position for newly inserted frames
1144 :
1145 : OD 12.08.2003 #i17969#
1146 : */
1147 0 : static void lcl_SetPos( SwFrm& _rNewFrm,
1148 : const SwLayoutFrm& _rLayFrm )
1149 : {
1150 0 : SWRECTFN( (&_rLayFrm) )
1151 0 : (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() );
1152 : // move position by one SwTwip in text flow direction in order to get
1153 : // notifications for a new calculated position after its formatting.
1154 0 : if ( bVert )
1155 0 : _rNewFrm.Frm().Pos().X() -= 1;
1156 : else
1157 0 : _rNewFrm.Frm().Pos().Y() += 1;
1158 0 : }
1159 :
1160 0 : void _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc,
1161 : sal_uLong nIndex, sal_Bool bPages, sal_uLong nEndIndex,
1162 : SwFrm *pPrv )
1163 : {
1164 0 : pDoc->BlockIdling();
1165 0 : SwRootFrm* pLayout = pLay->getRootFrm();
1166 0 : const sal_Bool bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False;
1167 0 : if( bOldCallbackActionEnabled )
1168 0 : pLayout->SetCallbackActionEnabled( sal_False );
1169 :
1170 : //In the generation of the Layout will be bPage with sal_True handed over.
1171 : //Then will be new pages generated all x paragraphs already times in advance.
1172 : //On breaks and/or pagedescriptorchanges the correspondig will be generated
1173 : //immediately.
1174 : //The advantage is, that on one hand already a nearly realistic number of
1175 : //pages are created, but above all there are no almost endless long chain
1176 : //of paragraphs, which must be moved expensively until it reaches a tolarable
1177 : //reduced level.
1178 : //We'd like to think that 20 Paragraphs fit on one page.
1179 : //So that it does not become in extremly situations so violent we calculate depending
1180 : //on the node something to it.
1181 : //If in the DocStatistik a usable given pagenumber
1182 : //(Will be cared for while writing), so it will be presumed that this will be
1183 : //number of pages.
1184 0 : const bool bStartPercent = bPages && !nEndIndex;
1185 :
1186 0 : SwPageFrm *pPage = pLay->FindPageFrm();
1187 0 : const SwFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1188 0 : SwFrm *pFrm = 0;
1189 0 : sal_Bool bBreakAfter = sal_False;
1190 :
1191 0 : SwActualSection *pActualSection = 0;
1192 : SwLayHelper *pPageMaker;
1193 :
1194 : //If the layout will be created (bPages == sal_True) we do head on the progress
1195 : //Flys and DrawObjekte are not connected immediately, this
1196 : //happens only at the end of the function.
1197 0 : if ( bPages )
1198 : {
1199 : // Attention: the SwLayHelper class uses references to the content-,
1200 : // page-, layout-frame etc. and may change them!
1201 : pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay,
1202 0 : pActualSection, bBreakAfter, nIndex, 0 == nEndIndex );
1203 0 : if( bStartPercent )
1204 : {
1205 0 : const sal_uLong nPageCount = pPageMaker->CalcPageCount();
1206 0 : if( nPageCount )
1207 0 : bObjsDirect = false;
1208 : }
1209 : }
1210 : else
1211 0 : pPageMaker = NULL;
1212 :
1213 0 : if( pLay->IsInSct() &&
1214 0 : ( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hereby will newbies
1215 : // be intercepted, of which flags could not determined yet,
1216 : // for e.g. while inserting a table
1217 : {
1218 0 : SwSectionFrm* pSct = pLay->FindSctFrm();
1219 : // If content will be inserted in a footnote, which in an column area,
1220 : // the column area it is not allowed to be broken up.
1221 : // Only if in the inner of the footnote lies an area, is this a candidate
1222 : // for pActualSection.
1223 : // The same applies for areas in tables, if inside the table will be
1224 : // something inserted, it's only allowed to break up areas, which
1225 : // lies in the inside also.
1226 0 : if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) &&
1227 0 : ( !pLay->IsInTab() || pSct->IsInTab() ) )
1228 : {
1229 0 : pActualSection = new SwActualSection( 0, pSct, 0 );
1230 : OSL_ENSURE( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(),
1231 : "_InsertCnt: Wrong Call" );
1232 : }
1233 : }
1234 :
1235 : //If a section is "open", the pActualSection points to an SwActualSection.
1236 : //If the page breaks, for "open" sections a follow will created.
1237 : //For nested sections (which have, however, not a nested layout),
1238 : //the SwActualSection class has a member, which points to an upper(section).
1239 : //When the "inner" section finishs, the upper will used instead.
1240 :
1241 : while( true )
1242 : {
1243 0 : SwNode *pNd = pDoc->GetNodes()[nIndex];
1244 0 : if ( pNd->IsCntntNode() )
1245 : {
1246 0 : SwCntntNode* pNode = (SwCntntNode*)pNd;
1247 0 : pFrm = pNode->MakeFrm(pLay);
1248 0 : if( pPageMaker )
1249 0 : pPageMaker->CheckInsert( nIndex );
1250 :
1251 0 : pFrm->InsertBehind( pLay, pPrv );
1252 : // #i27138#
1253 : // notify accessibility paragraphs objects about changed
1254 : // CONTENT_FLOWS_FROM/_TO relation.
1255 : // Relation CONTENT_FLOWS_FROM for next paragraph will change
1256 : // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1257 0 : if ( pFrm->IsTxtFrm() )
1258 : {
1259 0 : SwViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1260 : // no notification, if <SwViewShell> is in construction
1261 0 : if ( pViewShell && !pViewShell->IsInConstructor() &&
1262 0 : pViewShell->GetLayout() &&
1263 0 : pViewShell->GetLayout()->IsAnyShellAccessible() )
1264 : {
1265 : pViewShell->InvalidateAccessibleParaFlowRelation(
1266 0 : dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1267 0 : dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1268 : // #i68958#
1269 : // The information flags of the text frame are validated
1270 : // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>.
1271 : // The information flags have to be invalidated, because
1272 : // it is possible, that the one of its upper frames
1273 : // isn't inserted into the layout.
1274 0 : pFrm->InvalidateInfFlags();
1275 : }
1276 : }
1277 : // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1278 : // for setting position at newly inserted frame
1279 0 : lcl_SetPos( *pFrm, *pLay );
1280 0 : pPrv = pFrm;
1281 :
1282 0 : if ( !pTbl->empty() && bObjsDirect && !bDontCreateObjects )
1283 0 : AppendObjs( pTbl, nIndex, pFrm, pPage );
1284 : }
1285 0 : else if ( pNd->IsTableNode() )
1286 : { //Should we have encountered a table?
1287 0 : SwTableNode *pTblNode = (SwTableNode*)pNd;
1288 :
1289 : // #108116# loading may produce table structures that GCLines
1290 : // needs to clean up. To keep table formulas correct, change
1291 : // all table formulas to internal (BOXPTR) representation.
1292 0 : SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() );
1293 0 : aMsgHnt.eFlags = TBL_BOXPTR;
1294 0 : pDoc->UpdateTblFlds( &aMsgHnt );
1295 0 : pTblNode->GetTable().GCLines();
1296 :
1297 0 : pFrm = pTblNode->MakeFrm( pLay );
1298 :
1299 0 : if( pPageMaker )
1300 0 : pPageMaker->CheckInsert( nIndex );
1301 :
1302 0 : pFrm->InsertBehind( pLay, pPrv );
1303 : // #i27138#
1304 : // notify accessibility paragraphs objects about changed
1305 : // CONTENT_FLOWS_FROM/_TO relation.
1306 : // Relation CONTENT_FLOWS_FROM for next paragraph will change
1307 : // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1308 : {
1309 0 : SwViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1310 : // no notification, if <SwViewShell> is in construction
1311 0 : if ( pViewShell && !pViewShell->IsInConstructor() &&
1312 0 : pViewShell->GetLayout() &&
1313 0 : pViewShell->GetLayout()->IsAnyShellAccessible() )
1314 : {
1315 : pViewShell->InvalidateAccessibleParaFlowRelation(
1316 0 : dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1317 0 : dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1318 : }
1319 : }
1320 0 : if ( bObjsDirect && !pTbl->empty() )
1321 0 : ((SwTabFrm*)pFrm)->RegistFlys();
1322 : // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1323 : // for setting position at newly inserted frame
1324 0 : lcl_SetPos( *pFrm, *pLay );
1325 :
1326 0 : pPrv = pFrm;
1327 : //Set the index to the endnode of the table section.
1328 0 : nIndex = pTblNode->EndOfSectionIndex();
1329 :
1330 0 : SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm;
1331 0 : while ( pTmpFrm )
1332 : {
1333 0 : pTmpFrm->CheckDirChange();
1334 0 : pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL;
1335 0 : }
1336 :
1337 : }
1338 0 : else if ( pNd->IsSectionNode() )
1339 : {
1340 0 : SwSectionNode *pNode = (SwSectionNode*)pNd;
1341 0 : if( pNode->GetSection().CalcHiddenFlag() )
1342 : // is hidden, skip the area
1343 0 : nIndex = pNode->EndOfSectionIndex();
1344 : else
1345 : {
1346 0 : pFrm = pNode->MakeFrm( pLay );
1347 : pActualSection = new SwActualSection( pActualSection,
1348 0 : (SwSectionFrm*)pFrm, pNode );
1349 0 : if ( pActualSection->GetUpper() )
1350 : {
1351 : //Insert behind the Upper, the "Follow" of the Upper will be
1352 : //generated at the EndNode.
1353 0 : SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm();
1354 0 : pFrm->InsertBehind( pTmp->GetUpper(), pTmp );
1355 : // OD 25.03.2003 #108339# - direct initialization of section
1356 : // after insertion in the layout
1357 0 : static_cast<SwSectionFrm*>(pFrm)->Init();
1358 : }
1359 : else
1360 : {
1361 0 : pFrm->InsertBehind( pLay, pPrv );
1362 : // OD 25.03.2003 #108339# - direct initialization of section
1363 : // after insertion in the layout
1364 0 : static_cast<SwSectionFrm*>(pFrm)->Init();
1365 :
1366 : // #i33963#
1367 : // Do not trust the IsInFtn flag. If we are currently
1368 : // building up a table, the upper of pPrv may be a cell
1369 : // frame, but the cell frame does not have an upper yet.
1370 0 : if( pPrv && 0 != pPrv->ImplFindFtnFrm() )
1371 : {
1372 0 : if( pPrv->IsSctFrm() )
1373 0 : pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt();
1374 0 : if( pPrv && pPrv->IsTxtFrm() )
1375 0 : ((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, false );
1376 : }
1377 : }
1378 : // #i27138#
1379 : // notify accessibility paragraphs objects about changed
1380 : // CONTENT_FLOWS_FROM/_TO relation.
1381 : // Relation CONTENT_FLOWS_FROM for next paragraph will change
1382 : // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1383 : {
1384 0 : SwViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() );
1385 : // no notification, if <SwViewShell> is in construction
1386 0 : if ( pViewShell && !pViewShell->IsInConstructor() &&
1387 0 : pViewShell->GetLayout() &&
1388 0 : pViewShell->GetLayout()->IsAnyShellAccessible() )
1389 : {
1390 : pViewShell->InvalidateAccessibleParaFlowRelation(
1391 0 : dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )),
1392 0 : dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) );
1393 : }
1394 : }
1395 0 : pFrm->CheckDirChange();
1396 :
1397 : // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1398 : // for setting position at newly inserted frame
1399 0 : lcl_SetPos( *pFrm, *pLay );
1400 :
1401 : // OD 20.11.2002 #105405# - no page, no invalidate.
1402 0 : if ( pPage )
1403 : {
1404 : // OD 18.09.2002 #100522#
1405 : // invalidate page in order to force format and paint of
1406 : // inserted section frame
1407 0 : pFrm->InvalidatePage( pPage );
1408 :
1409 : // FME 10.11.2003 #112243#
1410 : // Invalidate fly content flag:
1411 0 : if ( pFrm->IsInFly() )
1412 0 : pPage->InvalidateFlyCntnt();
1413 :
1414 : // OD 14.11.2002 #104684# - invalidate page content in order to
1415 : // force format and paint of section content.
1416 0 : pPage->InvalidateCntnt();
1417 : }
1418 :
1419 0 : pLay = (SwLayoutFrm*)pFrm;
1420 0 : if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1421 0 : pLay = pLay->GetNextLayoutLeaf();
1422 0 : pPrv = 0;
1423 : }
1424 : }
1425 0 : else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )
1426 : {
1427 : OSL_ENSURE( pActualSection, "Sectionende ohne Anfang?" );
1428 : OSL_ENSURE( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(),
1429 : "Sectionende mit falschen Start Node?" );
1430 :
1431 : //Close the section, where appropriate activate the surrounding
1432 : //section again.
1433 0 : SwActualSection *pTmp = pActualSection ? pActualSection->GetUpper() : NULL;
1434 0 : delete pActualSection;
1435 0 : pLay = pLay->FindSctFrm();
1436 0 : if ( 0 != (pActualSection = pTmp) )
1437 : {
1438 : //Could be, that the last SectionFrm remains empty.
1439 : //Then now is the time to remove them.
1440 0 : if ( !pLay->ContainsCntnt() )
1441 : {
1442 0 : SwFrm *pTmpFrm = pLay;
1443 0 : pLay = pTmpFrm->GetUpper();
1444 0 : pPrv = pTmpFrm->GetPrev();
1445 0 : pTmpFrm->Remove();
1446 0 : delete pTmpFrm;
1447 : }
1448 : else
1449 : {
1450 0 : pPrv = pLay;
1451 0 : pLay = pLay->GetUpper();
1452 : }
1453 :
1454 : // new section frame
1455 0 : pFrm = pActualSection->GetSectionNode()->MakeFrm( pLay );
1456 0 : pFrm->InsertBehind( pLay, pPrv );
1457 0 : static_cast<SwSectionFrm*>(pFrm)->Init();
1458 :
1459 : // OD 12.08.2003 #i17969# - consider horizontal/vertical layout
1460 : // for setting position at newly inserted frame
1461 0 : lcl_SetPos( *pFrm, *pLay );
1462 :
1463 0 : SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm();
1464 :
1465 : // a follow has to be appended to the new section frame
1466 0 : SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow();
1467 0 : if ( pFollow )
1468 : {
1469 0 : pOuterSectionFrm->SetFollow( NULL );
1470 0 : pOuterSectionFrm->InvalidateSize();
1471 0 : ((SwSectionFrm*)pFrm)->SetFollow( pFollow );
1472 : }
1473 :
1474 : // We don't want to leave empty parts back.
1475 0 : if( ! pOuterSectionFrm->IsColLocked() &&
1476 0 : ! pOuterSectionFrm->ContainsCntnt() )
1477 : {
1478 0 : pOuterSectionFrm->DelEmpty( sal_True );
1479 0 : delete pOuterSectionFrm;
1480 : }
1481 0 : pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm );
1482 :
1483 0 : pLay = (SwLayoutFrm*)pFrm;
1484 0 : if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() )
1485 0 : pLay = pLay->GetNextLayoutLeaf();
1486 0 : pPrv = 0;
1487 : }
1488 : else
1489 : {
1490 : //Nothing more with sections, it goes on right behind
1491 : //the SectionFrame.
1492 0 : pPrv = pLay;
1493 0 : pLay = pLay->GetUpper();
1494 : }
1495 : }
1496 0 : else if( pNd->IsStartNode() &&
1497 0 : SwFlyStartNode == ((SwStartNode*)pNd)->GetStartNodeType() )
1498 : {
1499 0 : if ( !pTbl->empty() && bObjsDirect && !bDontCreateObjects )
1500 : {
1501 0 : SwFlyFrm* pFly = pLay->FindFlyFrm();
1502 0 : if( pFly )
1503 0 : AppendObjs( pTbl, nIndex, pFly, pPage );
1504 : }
1505 : }
1506 : else
1507 : // Neither Cntnt nor table nor section,
1508 : // so we have to be ready.
1509 0 : break;
1510 :
1511 0 : ++nIndex;
1512 : // Do not consider the end node. The caller (section/MakeFrms()) has to ensure that the end
1513 : // of this area is positioned before EndIndex!
1514 0 : if ( nEndIndex && nIndex >= nEndIndex )
1515 0 : break;
1516 : }
1517 :
1518 0 : if ( pActualSection )
1519 : {
1520 : // Might happen that an empty (Follow-)Section is left over.
1521 0 : if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() )
1522 : {
1523 0 : pLay->Remove();
1524 0 : delete pLay;
1525 : }
1526 0 : delete pActualSection;
1527 : }
1528 :
1529 0 : if ( bPages ) // let the Flys connect to each other
1530 : {
1531 0 : if ( !bDontCreateObjects )
1532 0 : AppendAllObjs( pTbl, pLayout );
1533 0 : bObjsDirect = true;
1534 : }
1535 :
1536 0 : if( pPageMaker )
1537 : {
1538 0 : pPageMaker->CheckFlyCache( pPage );
1539 0 : delete pPageMaker;
1540 0 : if( pDoc->GetLayoutCache() )
1541 : {
1542 : #ifdef DBG_UTIL
1543 : pDoc->GetLayoutCache()->CompareLayout( *pDoc );
1544 : #endif
1545 0 : pDoc->GetLayoutCache()->ClearImpl();
1546 : }
1547 : }
1548 :
1549 0 : pDoc->UnblockIdling();
1550 0 : if( bOldCallbackActionEnabled )
1551 0 : pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled );
1552 0 : }
1553 :
1554 0 : void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx,
1555 : const SwNodeIndex &rEndIdx )
1556 : {
1557 0 : bObjsDirect = false;
1558 :
1559 0 : SwNodeIndex aTmp( rSttIdx );
1560 0 : sal_uLong nEndIdx = rEndIdx.GetIndex();
1561 0 : SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp,
1562 0 : pDoc->GetNodes()[ nEndIdx-1 ]);
1563 0 : if ( pNd )
1564 : {
1565 0 : sal_Bool bApres = aTmp < rSttIdx;
1566 0 : SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() );
1567 : SwFrm* pFrm;
1568 0 : while( 0 != (pFrm = aNode2Layout.NextFrm()) )
1569 : {
1570 0 : SwLayoutFrm *pUpper = pFrm->GetUpper();
1571 0 : SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm();
1572 : sal_Bool bOldLock, bOldFtn;
1573 0 : if( pFtnFrm )
1574 : {
1575 0 : bOldFtn = pFtnFrm->IsColLocked();
1576 0 : pFtnFrm->ColLock();
1577 : }
1578 : else
1579 0 : bOldFtn = sal_True;
1580 0 : SwSectionFrm* pSct = pUpper->FindSctFrm();
1581 : // Inside of footnotes only those areas are interesting that are inside of them. But
1582 : // not the ones (e.g. column areas) in which are the footnote containers positioned.
1583 : // #109767# Table frame is in section, insert section in cell frame.
1584 0 : if( pSct && ((pFtnFrm && !pSct->IsInFtn()) || pUpper->IsCellFrm()) )
1585 0 : pSct = NULL;
1586 0 : if( pSct )
1587 : { // to prevent pTmp->MoveFwd from destroying the SectionFrm
1588 0 : bOldLock = pSct->IsColLocked();
1589 0 : pSct->ColLock();
1590 : }
1591 : else
1592 0 : bOldLock = sal_True;
1593 :
1594 : // If pFrm cannot be moved, it is not possible to move it to the next page. This applies
1595 : // also for frames (in the first column of a frame pFrm is moveable) and column
1596 : // sections of tables (also here pFrm is moveable).
1597 0 : bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120;
1598 0 : bool bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() &&
1599 0 : (!pFrm->IsInTab() || pFrm->IsTabFrm() );
1600 0 : if ( bMoveNext && bAllowMove )
1601 : {
1602 0 : SwFrm *pMove = pFrm;
1603 0 : SwFrm *pPrev = pFrm->GetPrev();
1604 0 : SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove );
1605 : OSL_ENSURE( pTmp, "Missing FlowFrm" );
1606 :
1607 0 : if ( bApres )
1608 : {
1609 : // The rest of this page should be empty. Thus, the following one has to move to
1610 : // the next page (it might also be located in the following column).
1611 : OSL_ENSURE( !pTmp->HasFollow(), "Follows forbidden" );
1612 0 : pPrev = pFrm;
1613 : // If the surrounding SectionFrm has a "next" one,
1614 : // so this one needs to be moved as well.
1615 0 : pMove = pFrm->GetIndNext();
1616 0 : SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm();
1617 0 : if( pCol )
1618 0 : pCol = (SwColumnFrm*)pCol->GetNext();
1619 0 : do
1620 : {
1621 0 : if( pCol && !pMove )
1622 : { // No successor so far, look into the next column
1623 0 : pMove = pCol->ContainsAny();
1624 0 : if( pCol->GetNext() )
1625 0 : pCol = (SwColumnFrm*)pCol->GetNext();
1626 0 : else if( pCol->IsInSct() )
1627 : { // If there is no following column but we are in a column frame,
1628 : // there might be (page) columns outside of it.
1629 0 : pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm();
1630 0 : if( pCol )
1631 0 : pCol = (SwColumnFrm*)pCol->GetNext();
1632 : }
1633 : else
1634 0 : pCol = NULL;
1635 : }
1636 : // skip invalid SectionFrms
1637 0 : while( pMove && pMove->IsSctFrm() &&
1638 0 : !((SwSectionFrm*)pMove)->GetSection() )
1639 0 : pMove = pMove->GetNext();
1640 0 : } while( !pMove && pCol );
1641 :
1642 0 : if( pMove )
1643 : {
1644 0 : if ( pMove->IsCntntFrm() )
1645 0 : pTmp = (SwCntntFrm*)pMove;
1646 0 : else if ( pMove->IsTabFrm() )
1647 0 : pTmp = (SwTabFrm*)pMove;
1648 0 : else if ( pMove->IsSctFrm() )
1649 : {
1650 0 : pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1651 0 : if( pMove )
1652 0 : pTmp = SwFlowFrm::CastFlowFrm( pMove );
1653 : else
1654 0 : pTmp = NULL;
1655 : }
1656 : }
1657 : else
1658 0 : pTmp = 0;
1659 : }
1660 : else
1661 : {
1662 : OSL_ENSURE( !pTmp->IsFollow(), "Follows really forbidden" );
1663 : // move the _content_ of a section frame
1664 0 : if( pMove->IsSctFrm() )
1665 : {
1666 0 : while( pMove && pMove->IsSctFrm() &&
1667 0 : !((SwSectionFrm*)pMove)->GetSection() )
1668 0 : pMove = pMove->GetNext();
1669 0 : if( pMove && pMove->IsSctFrm() )
1670 0 : pMove = ((SwSectionFrm*)pMove)->ContainsAny();
1671 0 : if( pMove )
1672 0 : pTmp = SwFlowFrm::CastFlowFrm( pMove );
1673 : else
1674 0 : pTmp = NULL;
1675 : }
1676 : }
1677 :
1678 0 : if( pTmp )
1679 : {
1680 0 : SwFrm* pOldUp = pTmp->GetFrm()->GetUpper();
1681 : // MoveFwd==sal_True means that we are still on the same page.
1682 : // But since we want to move if possible!
1683 0 : sal_Bool bTmpOldLock = pTmp->IsJoinLocked();
1684 0 : pTmp->LockJoin();
1685 0 : while( pTmp->MoveFwd( sal_True, sal_False, sal_True ) )
1686 : {
1687 0 : if( pOldUp == pTmp->GetFrm()->GetUpper() )
1688 0 : break;
1689 0 : pOldUp = pTmp->GetFrm()->GetUpper();
1690 : }
1691 0 : if( !bTmpOldLock )
1692 0 : pTmp->UnlockJoin();
1693 : }
1694 : ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(),
1695 0 : pFrm->IsInDocBody(), nEndIdx, pPrev );
1696 : }
1697 : else
1698 : {
1699 : sal_Bool bSplit;
1700 0 : SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev();
1701 : // If the section frame is inserted into another one, it must be split.
1702 0 : if( pSct && rSttIdx.GetNode().IsSectionNode() )
1703 : {
1704 0 : bSplit = pSct->SplitSect( pFrm, bApres );
1705 0 : if( !bSplit && !bApres )
1706 : {
1707 0 : pUpper = pSct->GetUpper();
1708 0 : pPrv = pSct->GetPrev();
1709 : }
1710 : }
1711 : else
1712 0 : bSplit = sal_False;
1713 :
1714 : ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), sal_False,
1715 0 : nEndIdx, pPrv );
1716 : // OD 23.06.2003 #108784# - correction: append objects doesn't
1717 : // depend on value of <bAllowMove>
1718 0 : if( !bDontCreateObjects )
1719 : {
1720 0 : const SwFrmFmts *pTbl = pDoc->GetSpzFrmFmts();
1721 0 : if( !pTbl->empty() )
1722 0 : AppendAllObjs( pTbl, pUpper );
1723 : }
1724 :
1725 : // If nothing was added (e.g. a hidden section), the split must be reversed.
1726 0 : if( bSplit && pSct && pSct->GetNext()
1727 0 : && pSct->GetNext()->IsSctFrm() )
1728 0 : pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() );
1729 0 : if( pFrm->IsInFly() )
1730 0 : pFrm->FindFlyFrm()->_Invalidate();
1731 0 : if( pFrm->IsInTab() )
1732 0 : pFrm->InvalidateSize();
1733 : }
1734 :
1735 0 : SwPageFrm *pPage = pUpper->FindPageFrm();
1736 0 : SwFrm::CheckPageDescs( pPage, sal_False );
1737 0 : if( !bOldFtn )
1738 0 : pFtnFrm->ColUnlock();
1739 0 : if( !bOldLock )
1740 : {
1741 0 : pSct->ColUnlock();
1742 : // pSct might be empty (e.g. when inserting linked section containing further
1743 : // sections) and can be destroyed in such cases.
1744 0 : if( !pSct->ContainsCntnt() )
1745 : {
1746 0 : pSct->DelEmpty( sal_True );
1747 0 : pUpper->getRootFrm()->RemoveFromList( pSct );
1748 0 : delete pSct;
1749 : }
1750 : }
1751 0 : }
1752 : }
1753 :
1754 0 : bObjsDirect = true;
1755 0 : }
1756 :
1757 0 : SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) :
1758 : SwCacheObj( pMod ),
1759 0 : rAttrSet( pConstructor->IsCntntFrm()
1760 0 : ? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet()
1761 0 : : ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ),
1762 0 : rUL ( rAttrSet.GetULSpace() ),
1763 : // #i96772#
1764 : // LRSpaceItem is copied due to the possibility that it is adjusted - see below
1765 0 : rLR ( rAttrSet.GetLRSpace() ),
1766 0 : rBox ( rAttrSet.GetBox() ),
1767 0 : rShadow ( rAttrSet.GetShadow() ),
1768 0 : aFrmSize( rAttrSet.GetFrmSize().GetSize() )
1769 : {
1770 : // #i96772#
1771 0 : const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor);
1772 0 : if ( pTxtFrm )
1773 : {
1774 0 : pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR );
1775 : }
1776 0 : else if ( pConstructor->IsNoTxtFrm() )
1777 : {
1778 0 : rLR = SvxLRSpaceItem ( RES_LR_SPACE );
1779 : }
1780 :
1781 : // Caution: The USHORTs for the cached values are not initialized by intention!
1782 :
1783 : // everything needs to be calculated at least once:
1784 : bTopLine = bBottomLine = bLeftLine = bRightLine =
1785 0 : bTop = bBottom = bLine = sal_True;
1786 :
1787 0 : bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = sal_False;
1788 : // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev>
1789 : // and <bJoinedWithNext>, which aren't initialized by default.
1790 0 : bCachedJoinedWithPrev = sal_False;
1791 0 : bCachedJoinedWithNext = sal_False;
1792 :
1793 0 : bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL));
1794 0 : }
1795 :
1796 0 : SwBorderAttrs::~SwBorderAttrs()
1797 : {
1798 0 : ((SwModify*)pOwner)->SetInCache( sal_False );
1799 0 : }
1800 :
1801 : /* All calc methods calculate a safety distance in addition to the values given by the attributes.
1802 : * This safety distance is only added when working with borders and/or shadows to prevent that
1803 : * e.g. borders are painted over.
1804 : */
1805 :
1806 0 : void SwBorderAttrs::_CalcTop()
1807 : {
1808 0 : nTop = CalcTopLine() + rUL.GetUpper();
1809 0 : bTop = sal_False;
1810 0 : }
1811 :
1812 0 : void SwBorderAttrs::_CalcBottom()
1813 : {
1814 0 : nBottom = CalcBottomLine() + rUL.GetLower();
1815 0 : bBottom = sal_False;
1816 0 : }
1817 :
1818 0 : long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const
1819 : {
1820 0 : long nRight=0;
1821 :
1822 0 : if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
1823 : // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
1824 : // and right border are painted on the right respectively left.
1825 0 : if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
1826 0 : nRight = CalcLeftLine();
1827 : else
1828 0 : nRight = CalcRightLine();
1829 :
1830 : }
1831 : // for paragraphs, "left" is "before text" and "right" is "after text"
1832 0 : if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1833 0 : nRight += rLR.GetLeft();
1834 : else
1835 0 : nRight += rLR.GetRight();
1836 :
1837 : // correction: retrieve left margin for numbering in R2L-layout
1838 0 : if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1839 : {
1840 0 : nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
1841 : }
1842 :
1843 0 : return nRight;
1844 : }
1845 :
1846 : /// Tries to detect if this paragraph has a floating table attached.
1847 0 : static bool lcl_hasTabFrm(const SwTxtFrm* pTxtFrm)
1848 : {
1849 0 : if (pTxtFrm->GetDrawObjs())
1850 : {
1851 0 : const SwSortedObjs* pSortedObjs = pTxtFrm->GetDrawObjs();
1852 0 : if (pSortedObjs->Count() > 0)
1853 : {
1854 0 : SwAnchoredObject* pObject = (*pSortedObjs)[0];
1855 0 : if (pObject->IsA(TYPE(SwFlyFrm)))
1856 : {
1857 0 : SwFlyFrm* pFly = (SwFlyFrm*)pObject;
1858 0 : if (pFly->Lower() && pFly->Lower()->IsTabFrm())
1859 0 : return true;
1860 : }
1861 : }
1862 : }
1863 0 : return false;
1864 : }
1865 :
1866 0 : long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const
1867 : {
1868 0 : long nLeft=0;
1869 :
1870 0 : if (!pCaller->IsTxtFrm() || !((SwTxtFrm*)pCaller)->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::INVERT_BORDER_SPACING)) {
1871 : // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left
1872 : // and right border are painted on the right respectively left.
1873 0 : if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() )
1874 0 : nLeft = CalcRightLine();
1875 : else
1876 0 : nLeft = CalcLeftLine();
1877 : }
1878 :
1879 : // for paragraphs, "left" is "before text" and "right" is "after text"
1880 0 : if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() )
1881 0 : nLeft += rLR.GetRight();
1882 : else
1883 : {
1884 0 : bool bIgnoreMargin = false;
1885 0 : if (pCaller->IsTxtFrm())
1886 : {
1887 0 : const SwTxtFrm* pTxtFrm = (const SwTxtFrm*)pCaller;
1888 0 : if (pTxtFrm->GetTxtNode()->GetDoc()->get(IDocumentSettingAccess::FLOATTABLE_NOMARGINS))
1889 : {
1890 : // If this is explicitly requested, ignore the margins next to the floating table.
1891 0 : if (lcl_hasTabFrm(pTxtFrm))
1892 0 : bIgnoreMargin = true;
1893 : // TODO here we only handle the first two paragraphs, would be nice to generalize this.
1894 0 : else if (pTxtFrm->FindPrev() && pTxtFrm->FindPrev()->IsTxtFrm() && lcl_hasTabFrm((const SwTxtFrm*)pTxtFrm->FindPrev()))
1895 0 : bIgnoreMargin = true;
1896 : }
1897 : }
1898 0 : if (!bIgnoreMargin)
1899 0 : nLeft += rLR.GetLeft();
1900 : }
1901 :
1902 : // correction: do not retrieve left margin for numbering in R2L-layout
1903 0 : if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() )
1904 : {
1905 0 : nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum();
1906 : }
1907 :
1908 0 : return nLeft;
1909 : }
1910 :
1911 : /* Calculated values for borders and shadows.
1912 : * It might be that a distance is wanted even without lines. This will be
1913 : * considered here and not by the attribute (e.g. bBorderDist for cells).
1914 : */
1915 :
1916 0 : void SwBorderAttrs::_CalcTopLine()
1917 : {
1918 0 : nTopLine = (bBorderDist && !rBox.GetTop())
1919 0 : ? rBox.GetDistance (BOX_LINE_TOP)
1920 0 : : rBox.CalcLineSpace(BOX_LINE_TOP);
1921 0 : nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP);
1922 0 : bTopLine = sal_False;
1923 0 : }
1924 :
1925 0 : void SwBorderAttrs::_CalcBottomLine()
1926 : {
1927 0 : nBottomLine = (bBorderDist && !rBox.GetBottom())
1928 0 : ? rBox.GetDistance (BOX_LINE_BOTTOM)
1929 0 : : rBox.CalcLineSpace(BOX_LINE_BOTTOM);
1930 0 : nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM);
1931 0 : bBottomLine = sal_False;
1932 0 : }
1933 :
1934 0 : void SwBorderAttrs::_CalcLeftLine()
1935 : {
1936 0 : nLeftLine = (bBorderDist && !rBox.GetLeft())
1937 0 : ? rBox.GetDistance (BOX_LINE_LEFT)
1938 0 : : rBox.CalcLineSpace(BOX_LINE_LEFT);
1939 0 : nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT);
1940 0 : bLeftLine = sal_False;
1941 0 : }
1942 :
1943 0 : void SwBorderAttrs::_CalcRightLine()
1944 : {
1945 0 : nRightLine = (bBorderDist && !rBox.GetRight())
1946 0 : ? rBox.GetDistance (BOX_LINE_RIGHT)
1947 0 : : rBox.CalcLineSpace(BOX_LINE_RIGHT);
1948 0 : nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT);
1949 0 : bRightLine = sal_False;
1950 0 : }
1951 :
1952 0 : void SwBorderAttrs::_IsLine()
1953 : {
1954 0 : bIsLine = rBox.GetTop() || rBox.GetBottom() ||
1955 0 : rBox.GetLeft()|| rBox.GetRight();
1956 0 : bLine = sal_False;
1957 0 : }
1958 :
1959 : /* The borders of neighboring paragraphs are condensed by following algorithm:
1960 : *
1961 : * 1. No top border if the predecessor has the same top border and (3) applies.
1962 : * In addition, the paragraph needs to have a border at at least one side (left/right/bottom).
1963 : * 2. No bottom border if the successor has the same bottom border and (3) applies.
1964 : * In addition, the paragraph needs to have a border at at least one side (left/right/top).
1965 : * 3. The borders on the left and right side are identical between the current and the
1966 : * pre-/succeeding paragraph.
1967 : */
1968 :
1969 0 : inline bool CmpLines( const editeng::SvxBorderLine *pL1, const editeng::SvxBorderLine *pL2 )
1970 : {
1971 0 : return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) );
1972 : }
1973 :
1974 : // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs"
1975 : // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()>
1976 : // instead of only the right LR-spacing, because R2L-layout has to be
1977 : // considered.
1978 0 : sal_Bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs,
1979 : const SwFrm *pCaller,
1980 : const SwFrm *pCmp ) const
1981 : {
1982 0 : return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft() ) &&
1983 0 : CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) &&
1984 0 : CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) &&
1985 : // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>.
1986 0 : CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) );
1987 : }
1988 :
1989 0 : sal_Bool SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm,
1990 : const SwFrm& _rCmpFrm ) const
1991 : {
1992 0 : sal_Bool bReturnVal = sal_False;
1993 :
1994 0 : SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm );
1995 0 : const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get();
1996 0 : if ( rShadow == rCmpAttrs.GetShadow() &&
1997 0 : CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) &&
1998 0 : CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) &&
1999 0 : CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm )
2000 : )
2001 : {
2002 0 : bReturnVal = sal_True;
2003 : }
2004 :
2005 0 : return bReturnVal;
2006 : }
2007 :
2008 : // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2009 : // previous frame. Calculated value saved in cached value <bJoinedWithPrev>
2010 : // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>
2011 0 : void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm,
2012 : const SwFrm* _pPrevFrm )
2013 : {
2014 : // set default
2015 0 : bJoinedWithPrev = sal_False;
2016 :
2017 0 : if ( _rFrm.IsTxtFrm() )
2018 : {
2019 : // text frame can potentially join with previous text frame, if
2020 : // corresponding attribute set is set at previous text frame.
2021 : // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this
2022 : // one as previous frame.
2023 0 : const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev();
2024 : // OD 2004-02-13 #i25029# - skip hidden text frames.
2025 0 : while ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2026 0 : static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() )
2027 : {
2028 0 : pPrevFrm = pPrevFrm->GetPrev();
2029 : }
2030 0 : if ( pPrevFrm && pPrevFrm->IsTxtFrm() &&
2031 0 : pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue()
2032 : )
2033 : {
2034 0 : bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) );
2035 : }
2036 : }
2037 :
2038 : // valid cache status, if demanded
2039 : // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm>
2040 : // is set.
2041 0 : bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm;
2042 0 : }
2043 :
2044 : // OD 21.05.2003 #108789# - method to determine, if borders are joined with
2045 : // next frame. Calculated value saved in cached value <bJoinedWithNext>
2046 0 : void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm )
2047 : {
2048 : // set default
2049 0 : bJoinedWithNext = sal_False;
2050 :
2051 0 : if ( _rFrm.IsTxtFrm() )
2052 : {
2053 : // text frame can potentially join with next text frame, if
2054 : // corresponding attribute set is set at current text frame.
2055 : // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames.
2056 0 : const SwFrm* pNextFrm = _rFrm.GetNext();
2057 0 : while ( pNextFrm && pNextFrm->IsTxtFrm() &&
2058 0 : static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() )
2059 : {
2060 0 : pNextFrm = pNextFrm->GetNext();
2061 : }
2062 0 : if ( pNextFrm && pNextFrm->IsTxtFrm() &&
2063 0 : _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue()
2064 : )
2065 : {
2066 0 : bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) );
2067 : }
2068 : }
2069 :
2070 : // valid cache status, if demanded
2071 0 : bCachedJoinedWithNext = bCacheGetLine;
2072 0 : }
2073 :
2074 : // OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev>
2075 : // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to
2076 : // method <_CalcJoindWithPrev(..)>.
2077 0 : sal_Bool SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm,
2078 : const SwFrm* _pPrevFrm ) const
2079 : {
2080 0 : if ( !bCachedJoinedWithPrev || _pPrevFrm )
2081 : {
2082 : // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter
2083 0 : const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm );
2084 : }
2085 :
2086 0 : return bJoinedWithPrev;
2087 : }
2088 :
2089 0 : sal_Bool SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const
2090 : {
2091 0 : if ( !bCachedJoinedWithNext )
2092 : {
2093 0 : const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm );
2094 : }
2095 :
2096 0 : return bJoinedWithNext;
2097 : }
2098 :
2099 : // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to
2100 : // method <JoinedWithPrev>
2101 0 : void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm,
2102 : const SwFrm* _pPrevFrm )
2103 : {
2104 0 : sal_uInt16 nRet = CalcTopLine();
2105 :
2106 : // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2107 : // OD 2004-02-26 #i25029# - add 2nd parameter
2108 0 : if ( JoinedWithPrev( _rFrm, _pPrevFrm ) )
2109 : {
2110 0 : nRet = 0;
2111 : }
2112 :
2113 0 : bCachedGetTopLine = bCacheGetLine;
2114 :
2115 0 : nGetTopLine = nRet;
2116 0 : }
2117 :
2118 0 : void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm )
2119 : {
2120 0 : sal_uInt16 nRet = CalcBottomLine();
2121 :
2122 : // OD 21.05.2003 #108789# - use new method <JoinWithPrev()>
2123 0 : if ( JoinedWithNext( _rFrm ) )
2124 : {
2125 0 : nRet = 0;
2126 : }
2127 :
2128 0 : bCachedGetBottomLine = bCacheGetLine;
2129 :
2130 0 : nGetBottomLine = nRet;
2131 0 : }
2132 :
2133 : /*************************************************************************/
2134 :
2135 0 : SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) :
2136 0 : SwCacheAccess( rCach, (pFrm->IsCntntFrm() ?
2137 : (void*)((SwCntntFrm*)pFrm)->GetNode() :
2138 0 : (void*)((SwLayoutFrm*)pFrm)->GetFmt()),
2139 0 : (sal_Bool)(pFrm->IsCntntFrm() ?
2140 0 : ((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() :
2141 0 : ((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ),
2142 0 : pConstructor( pFrm )
2143 : {
2144 0 : }
2145 :
2146 0 : SwCacheObj *SwBorderAttrAccess::NewObj()
2147 : {
2148 0 : ((SwModify*)pOwner)->SetInCache( sal_True );
2149 0 : return new SwBorderAttrs( (SwModify*)pOwner, pConstructor );
2150 : }
2151 :
2152 0 : SwBorderAttrs *SwBorderAttrAccess::Get()
2153 : {
2154 0 : return (SwBorderAttrs*)SwCacheAccess::Get();
2155 : }
2156 :
2157 0 : SwOrderIter::SwOrderIter( const SwPageFrm *pPg, sal_Bool bFlys ) :
2158 : pPage( pPg ),
2159 : pCurrent( 0 ),
2160 0 : bFlysOnly( bFlys )
2161 : {
2162 0 : }
2163 :
2164 0 : const SdrObject *SwOrderIter::Top()
2165 : {
2166 0 : pCurrent = 0;
2167 0 : if ( pPage->GetSortedObjs() )
2168 : {
2169 0 : const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2170 0 : if ( pObjs->Count() )
2171 : {
2172 0 : sal_uInt32 nTopOrd = 0;
2173 0 : (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2174 0 : for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2175 : {
2176 0 : const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2177 0 : if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2178 0 : continue;
2179 0 : sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2180 0 : if ( nTmp >= nTopOrd )
2181 : {
2182 0 : nTopOrd = nTmp;
2183 0 : pCurrent = pObj;
2184 : }
2185 : }
2186 : }
2187 : }
2188 0 : return pCurrent;
2189 : }
2190 :
2191 0 : const SdrObject *SwOrderIter::Bottom()
2192 : {
2193 0 : pCurrent = 0;
2194 0 : if ( pPage->GetSortedObjs() )
2195 : {
2196 0 : sal_uInt32 nBotOrd = USHRT_MAX;
2197 0 : const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2198 0 : if ( pObjs->Count() )
2199 : {
2200 0 : (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2201 0 : for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2202 : {
2203 0 : const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2204 0 : if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2205 0 : continue;
2206 0 : sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2207 0 : if ( nTmp < nBotOrd )
2208 : {
2209 0 : nBotOrd = nTmp;
2210 0 : pCurrent = pObj;
2211 : }
2212 : }
2213 : }
2214 : }
2215 0 : return pCurrent;
2216 : }
2217 :
2218 0 : const SdrObject *SwOrderIter::Next()
2219 : {
2220 0 : const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2221 0 : pCurrent = 0;
2222 0 : if ( pPage->GetSortedObjs() )
2223 : {
2224 0 : sal_uInt32 nOrd = USHRT_MAX;
2225 0 : const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2226 0 : if ( pObjs->Count() )
2227 : {
2228 0 : (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2229 0 : for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2230 : {
2231 0 : const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2232 0 : if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2233 0 : continue;
2234 0 : sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2235 0 : if ( nTmp > nCurOrd && nTmp < nOrd )
2236 : {
2237 0 : nOrd = nTmp;
2238 0 : pCurrent = pObj;
2239 : }
2240 : }
2241 : }
2242 : }
2243 0 : return pCurrent;
2244 : }
2245 :
2246 0 : const SdrObject *SwOrderIter::Prev()
2247 : {
2248 0 : const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0;
2249 0 : pCurrent = 0;
2250 0 : if ( pPage->GetSortedObjs() )
2251 : {
2252 0 : const SwSortedObjs *pObjs = pPage->GetSortedObjs();
2253 0 : if ( pObjs->Count() )
2254 : {
2255 0 : sal_uInt32 nOrd = 0;
2256 0 : (*pObjs)[0]->GetDrawObj()->GetOrdNum(); // force updating
2257 0 : for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2258 : {
2259 0 : const SdrObject* pObj = (*pObjs)[i]->GetDrawObj();
2260 0 : if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) )
2261 0 : continue;
2262 0 : sal_uInt32 nTmp = pObj->GetOrdNumDirect();
2263 0 : if ( nTmp < nCurOrd && nTmp >= nOrd )
2264 : {
2265 0 : nOrd = nTmp;
2266 0 : pCurrent = pObj;
2267 : }
2268 : }
2269 : }
2270 : }
2271 0 : return pCurrent;
2272 : }
2273 :
2274 : /// Keep and restore the substructure of a layout frame for an action.
2275 : // New algorithm:
2276 : // Do not look at each neighbor one by one to set all pointers correctly.
2277 : // It is sufficient to detach a part of a chain and check if another chain needs to be added
2278 : // when attaching it again. Only the pointers necessary for the chain connection need to be
2279 : // adjusted. The correction happens in RestoreCntnt(). In between all access is restricted.
2280 : // During this action, the Flys are detached from the page.
2281 :
2282 : // #115759# - 'remove' also drawing object from page and
2283 : // at-fly anchored objects from page
2284 0 : static void lcl_RemoveObjsFromPage( SwFrm* _pFrm )
2285 : {
2286 : OSL_ENSURE( _pFrm->GetDrawObjs(), "no DrawObjs in lcl_RemoveObjsFromPage." );
2287 0 : SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2288 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2289 : {
2290 0 : SwAnchoredObject* pObj = rObjs[i];
2291 : // #115759# - reset member, at which the anchored
2292 : // object orients its vertical position
2293 0 : pObj->ClearVertPosOrientFrm();
2294 : // #i43913#
2295 0 : pObj->ResetLayoutProcessBools();
2296 : // #115759# - remove also lower objects of as-character
2297 : // anchored Writer fly frames from page
2298 0 : if ( pObj->ISA(SwFlyFrm) )
2299 : {
2300 0 : SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2301 :
2302 : // #115759# - remove also direct lowers of Writer
2303 : // fly frame from page
2304 0 : if ( pFlyFrm->GetDrawObjs() )
2305 : {
2306 0 : ::lcl_RemoveObjsFromPage( pFlyFrm );
2307 : }
2308 :
2309 0 : SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt();
2310 0 : while ( pCnt )
2311 : {
2312 0 : if ( pCnt->GetDrawObjs() )
2313 0 : ::lcl_RemoveObjsFromPage( pCnt );
2314 0 : pCnt = pCnt->GetNextCntntFrm();
2315 : }
2316 0 : if ( pFlyFrm->IsFlyFreeFrm() )
2317 : {
2318 : // #i28701# - use new method <GetPageFrm()>
2319 0 : pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm );
2320 : }
2321 : }
2322 : // #115759# - remove also drawing objects from page
2323 0 : else if ( pObj->ISA(SwAnchoredDrawObject) )
2324 : {
2325 0 : if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
2326 : {
2327 : pObj->GetPageFrm()->RemoveDrawObjFromPage(
2328 0 : *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2329 : }
2330 : }
2331 : }
2332 0 : }
2333 :
2334 0 : SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart )
2335 : {
2336 0 : if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() )
2337 0 : sw_RemoveFtns( (SwColumnFrm*)pLay->Lower(), sal_True, sal_True );
2338 :
2339 : SwFrm *pSav;
2340 0 : if ( 0 == (pSav = pLay->ContainsAny()) )
2341 0 : return 0;
2342 :
2343 0 : if( pSav->IsInFtn() && !pLay->IsInFtn() )
2344 : {
2345 0 : do
2346 0 : pSav = pSav->FindNext();
2347 0 : while( pSav && pSav->IsInFtn() );
2348 0 : if( !pSav || !pLay->IsAnLower( pSav ) )
2349 0 : return NULL;
2350 : }
2351 :
2352 : // Tables should be saved as a whole, expection:
2353 : // The contents of a section or a cell inside a table should be saved
2354 0 : if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) )
2355 0 : while ( !pSav->IsTabFrm() )
2356 0 : pSav = pSav->GetUpper();
2357 :
2358 0 : if( pSav->IsInSct() )
2359 : { // search the upmost section inside of pLay
2360 0 : SwFrm* pSect = pLay->FindSctFrm();
2361 0 : SwFrm *pTmp = pSav;
2362 0 : do
2363 : {
2364 0 : pSav = pTmp;
2365 0 : pTmp = (pSav && pSav->GetUpper()) ? pSav->GetUpper()->FindSctFrm() : NULL;
2366 : } while ( pTmp != pSect );
2367 : }
2368 :
2369 0 : SwFrm *pFloat = pSav;
2370 0 : if( !pStart )
2371 0 : pStart = pSav;
2372 0 : bool bGo = pStart == pSav;
2373 0 : do
2374 : {
2375 0 : if( bGo )
2376 0 : pFloat->GetUpper()->pLower = 0; // detach the chain part
2377 :
2378 : // search the end of the chain part, remove Flys on the way
2379 0 : do
2380 : {
2381 0 : if( bGo )
2382 : {
2383 0 : if ( pFloat->IsCntntFrm() )
2384 : {
2385 0 : if ( pFloat->GetDrawObjs() )
2386 0 : ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat );
2387 : }
2388 0 : else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() )
2389 : {
2390 0 : SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt();
2391 0 : if( pCnt )
2392 : {
2393 0 : do
2394 0 : { if ( pCnt->GetDrawObjs() )
2395 0 : ::lcl_RemoveObjsFromPage( pCnt );
2396 0 : pCnt = pCnt->GetNextCntntFrm();
2397 0 : } while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) );
2398 : }
2399 : }
2400 : else {
2401 : OSL_ENSURE( !pFloat, "new FloatFrame?" );
2402 : }
2403 : }
2404 0 : if ( pFloat->GetNext() )
2405 : {
2406 0 : if( bGo )
2407 0 : pFloat->mpUpper = NULL;
2408 0 : pFloat = pFloat->GetNext();
2409 0 : if( !bGo && pFloat == pStart )
2410 : {
2411 0 : bGo = true;
2412 0 : pFloat->mpPrev->mpNext = NULL;
2413 0 : pFloat->mpPrev = NULL;
2414 : }
2415 : }
2416 : else
2417 0 : break;
2418 :
2419 : } while ( pFloat );
2420 :
2421 : // search next chain part and connect both chains
2422 0 : SwFrm *pTmp = pFloat->FindNext();
2423 0 : if( bGo )
2424 0 : pFloat->mpUpper = NULL;
2425 :
2426 0 : if( !pLay->IsInFtn() )
2427 0 : while( pTmp && pTmp->IsInFtn() )
2428 0 : pTmp = pTmp->FindNext();
2429 :
2430 0 : if ( !pLay->IsAnLower( pTmp ) )
2431 0 : pTmp = 0;
2432 :
2433 0 : if ( pTmp && bGo )
2434 : {
2435 0 : pFloat->mpNext = pTmp; // connect both chains
2436 0 : pFloat->mpNext->mpPrev = pFloat;
2437 : }
2438 0 : pFloat = pTmp;
2439 0 : bGo = bGo || ( pStart == pFloat );
2440 : } while ( pFloat );
2441 :
2442 0 : return bGo ? pStart : NULL;
2443 : }
2444 :
2445 : // #115759# - add also drawing objects to page and at-fly
2446 : // anchored objects to page
2447 0 : static void lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage )
2448 : {
2449 : OSL_ENSURE( _pFrm->GetDrawObjs(), "no DrawObjs in lcl_AddObjsToPage." );
2450 0 : SwSortedObjs &rObjs = *_pFrm->GetDrawObjs();
2451 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2452 : {
2453 0 : SwAnchoredObject* pObj = rObjs[i];
2454 :
2455 : // #115759# - unlock position of anchored object
2456 : // in order to get the object's position calculated.
2457 0 : pObj->UnlockPosition();
2458 : // #115759# - add also lower objects of as-character
2459 : // anchored Writer fly frames from page
2460 0 : if ( pObj->ISA(SwFlyFrm) )
2461 : {
2462 0 : SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj);
2463 0 : if ( pObj->ISA(SwFlyFreeFrm) )
2464 : {
2465 0 : _pPage->AppendFlyToPage( pFlyFrm );
2466 : }
2467 0 : pFlyFrm->_InvalidatePos();
2468 0 : pFlyFrm->_InvalidateSize();
2469 0 : pFlyFrm->InvalidatePage( _pPage );
2470 :
2471 : // #115759# - add also at-fly anchored objects
2472 : // to page
2473 0 : if ( pFlyFrm->GetDrawObjs() )
2474 : {
2475 0 : ::lcl_AddObjsToPage( pFlyFrm, _pPage );
2476 : }
2477 :
2478 0 : SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt();
2479 0 : while ( pCnt )
2480 : {
2481 0 : if ( pCnt->GetDrawObjs() )
2482 0 : ::lcl_AddObjsToPage( pCnt, _pPage );
2483 0 : pCnt = pCnt->GetNextCntntFrm();
2484 : }
2485 : }
2486 : // #115759# - remove also drawing objects from page
2487 0 : else if ( pObj->ISA(SwAnchoredDrawObject) )
2488 : {
2489 0 : if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR)
2490 : {
2491 0 : pObj->InvalidateObjPos();
2492 : _pPage->AppendDrawObjToPage(
2493 0 : *(static_cast<SwAnchoredDrawObject*>(pObj)) );
2494 : }
2495 : }
2496 : }
2497 0 : }
2498 :
2499 0 : void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow )
2500 : {
2501 : OSL_ENSURE( pSav && pParent, "no Save or Parent provided for RestoreCntnt." );
2502 0 : SWRECTFN( pParent )
2503 :
2504 : // If there are already FlowFrms below the new parent, so add the chain (starting with pSav)
2505 : // after the last one. The parts are inserted and invalidated if needed.
2506 : // On the way, the Flys of the CntntFrms are registered at the page.
2507 :
2508 0 : SwPageFrm *pPage = pParent->FindPageFrm();
2509 :
2510 0 : if ( pPage )
2511 0 : pPage->InvalidatePage( pPage );
2512 :
2513 : // determine predecessor and establish connection or initialize
2514 0 : pSav->mpPrev = pSibling;
2515 : SwFrm* pNxt;
2516 0 : if ( pSibling )
2517 : {
2518 0 : pNxt = pSibling->mpNext;
2519 0 : pSibling->mpNext = pSav;
2520 0 : pSibling->_InvalidatePrt();
2521 0 : ((SwCntntFrm*)pSibling)->InvalidatePage( pPage );
2522 0 : if ( ((SwCntntFrm*)pSibling)->GetFollow() )
2523 0 : pSibling->Prepare( PREP_CLEAR, 0, false );
2524 : }
2525 : else
2526 0 : { pNxt = pParent->pLower;
2527 0 : pParent->pLower = pSav;
2528 0 : pSav->mpUpper = pParent; // set here already, so that it is explicit when invalidating
2529 :
2530 0 : if ( pSav->IsCntntFrm() )
2531 0 : ((SwCntntFrm*)pSav)->InvalidatePage( pPage );
2532 : else
2533 : { // pSav might be an empty SectFrm
2534 0 : SwCntntFrm* pCnt = pParent->ContainsCntnt();
2535 0 : if( pCnt )
2536 0 : pCnt->InvalidatePage( pPage );
2537 : }
2538 : }
2539 :
2540 : // the parent needs to grow appropiately
2541 0 : SwTwips nGrowVal = 0;
2542 : SwFrm* pLast;
2543 0 : do
2544 0 : { pSav->mpUpper = pParent;
2545 0 : nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)();
2546 0 : pSav->_InvalidateAll();
2547 :
2548 : // register Flys, if TxtFrms than also invalidate appropriately
2549 0 : if ( pSav->IsCntntFrm() )
2550 : {
2551 0 : if ( pSav->IsTxtFrm() &&
2552 0 : ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX )
2553 0 : ((SwTxtFrm*)pSav)->Init(); // I am its friend
2554 :
2555 0 : if ( pPage && pSav->GetDrawObjs() )
2556 0 : ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage );
2557 : }
2558 : else
2559 0 : { SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt();
2560 0 : if( pBlub )
2561 : {
2562 0 : do
2563 0 : { if ( pPage && pBlub->GetDrawObjs() )
2564 0 : ::lcl_AddObjsToPage( pBlub, pPage );
2565 0 : if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() &&
2566 0 : ((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX )
2567 0 : ((SwTxtFrm*)pBlub)->Init(); // I am its friend
2568 0 : pBlub = pBlub->GetNextCntntFrm();
2569 0 : } while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub ));
2570 : }
2571 : }
2572 0 : pLast = pSav;
2573 0 : pSav = pSav->GetNext();
2574 :
2575 : } while ( pSav );
2576 :
2577 0 : if( pNxt )
2578 : {
2579 0 : pLast->mpNext = pNxt;
2580 0 : pNxt->mpPrev = pLast;
2581 : }
2582 :
2583 0 : if ( bGrow )
2584 0 : pParent->Grow( nGrowVal );
2585 0 : }
2586 :
2587 0 : SwPageFrm * InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper,
2588 : bool bOdd, bool bFirst, bool bInsertEmpty, sal_Bool bFtn,
2589 : SwFrm *pSibling )
2590 : {
2591 : SwPageFrm *pRet;
2592 0 : SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc();
2593 0 : if (bFirst)
2594 : {
2595 0 : if (rDesc.IsFirstShared())
2596 : {
2597 : // We need to fallback to left or right page format, decide it now.
2598 : // FIXME: is this still needed?
2599 0 : if (bOdd)
2600 : {
2601 0 : rDesc.GetFirstMaster().SetFmtAttr( rDesc.GetMaster().GetHeader() );
2602 0 : rDesc.GetFirstMaster().SetFmtAttr( rDesc.GetMaster().GetFooter() );
2603 : // fdo#60250 copy margins for mirrored pages
2604 0 : rDesc.GetFirstMaster().SetFmtAttr( rDesc.GetMaster().GetLRSpace() );
2605 : }
2606 : else
2607 : {
2608 0 : rDesc.GetFirstLeft().SetFmtAttr( rDesc.GetLeft().GetHeader() );
2609 0 : rDesc.GetFirstLeft().SetFmtAttr( rDesc.GetLeft().GetFooter() );
2610 0 : rDesc.GetFirstLeft().SetFmtAttr( rDesc.GetLeft().GetLRSpace() );
2611 : }
2612 : }
2613 : }
2614 0 : SwFrmFmt *pFmt(bOdd ? rDesc.GetRightFmt(bFirst) : rDesc.GetLeftFmt(bFirst));
2615 : // If there is no FrmFmt for this page, add an empty page
2616 0 : if ( !pFmt )
2617 : {
2618 0 : pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt();
2619 : OSL_ENSURE( pFmt, "Descriptor without any format?!" );
2620 0 : bInsertEmpty = !bInsertEmpty;
2621 : }
2622 0 : if( bInsertEmpty )
2623 : {
2624 0 : SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ?
2625 0 : ((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc;
2626 0 : pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pUpper, pTmpDesc );
2627 0 : pRet->Paste( pUpper, pSibling );
2628 0 : pRet->PreparePage( bFtn );
2629 : }
2630 0 : pRet = new SwPageFrm( pFmt, pUpper, &rDesc );
2631 0 : pRet->Paste( pUpper, pSibling );
2632 0 : pRet->PreparePage( bFtn );
2633 0 : if ( pRet->GetNext() )
2634 0 : ((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet );
2635 0 : return pRet;
2636 : }
2637 :
2638 : /* The following two methods search the layout structure recursively and
2639 : * register all Flys at the page that have a Frm in this structure as an anchor.
2640 : */
2641 :
2642 0 : static void lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch )
2643 : {
2644 0 : SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs();
2645 0 : for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i )
2646 : {
2647 0 : SwAnchoredObject* pObj = (*pObjs)[i];
2648 0 : if ( pObj->ISA(SwFlyFrm) )
2649 : {
2650 0 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
2651 : // register (not if already known)
2652 : // #i28701# - use new method <GetPageFrm()>
2653 0 : SwPageFrm *pPg = pFly->IsFlyFreeFrm()
2654 0 : ? pFly->GetPageFrm() : pFly->FindPageFrm();
2655 0 : if ( pPg != pPage )
2656 : {
2657 0 : if ( pPg )
2658 0 : pPg->RemoveFlyFromPage( pFly );
2659 0 : pPage->AppendFlyToPage( pFly );
2660 : }
2661 0 : ::RegistFlys( pPage, pFly );
2662 : }
2663 : else
2664 : {
2665 : // #i87493#
2666 0 : if ( pPage != pObj->GetPageFrm() )
2667 : {
2668 : // #i28701#
2669 0 : if ( pObj->GetPageFrm() )
2670 0 : pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj );
2671 0 : pPage->AppendDrawObjToPage( *pObj );
2672 : }
2673 : }
2674 :
2675 0 : const SwFlyFrm* pFly = pAnch->FindFlyFrm();
2676 0 : if ( pFly &&
2677 0 : pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() &&
2678 0 : pObj->GetDrawObj()->GetPage() )
2679 : {
2680 : //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed.
2681 0 : pObj->DrawObj()->GetPage()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(),
2682 0 : pObj->GetDrawObj()->GetOrdNumDirect() );
2683 : }
2684 : }
2685 0 : }
2686 :
2687 0 : void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay )
2688 : {
2689 0 : if ( pLay->GetDrawObjs() )
2690 0 : ::lcl_Regist( pPage, pLay );
2691 0 : const SwFrm *pFrm = pLay->Lower();
2692 0 : while ( pFrm )
2693 : {
2694 0 : if ( pFrm->IsLayoutFrm() )
2695 0 : ::RegistFlys( pPage, (const SwLayoutFrm*)pFrm );
2696 0 : else if ( pFrm->GetDrawObjs() )
2697 0 : ::lcl_Regist( pPage, pFrm );
2698 0 : pFrm = pFrm->GetNext();
2699 : }
2700 0 : }
2701 :
2702 : /// Notify the background based on the difference between old and new rectangle
2703 0 : void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld,
2704 : const SwRect* pOldPrt )
2705 : {
2706 0 : const SwRect aFrm( pFly->GetObjRectWithSpaces() );
2707 0 : if ( rOld.Pos() != aFrm.Pos() )
2708 : { // changed position, invalidate old and new area
2709 0 : if ( rOld.HasArea() &&
2710 0 : rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < FAR_AWAY )
2711 : {
2712 0 : pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE );
2713 : }
2714 0 : pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
2715 : }
2716 0 : else if ( rOld.SSize() != aFrm.SSize() )
2717 : { // changed size, invalidate the area that was left or is now overlapped
2718 : // For simplicity, we purposely invalidate a Twip even if not needed.
2719 :
2720 0 : SwViewShell *pSh = pFly->getRootFrm()->GetCurrShell();
2721 0 : if( pSh && rOld.HasArea() )
2722 0 : pSh->InvalidateWindows( rOld );
2723 :
2724 : // #i51941# - consider case that fly frame isn't
2725 : // registered at the old page <pOld>
2726 0 : SwPageFrm* pPageFrm = pFly->FindPageFrm();
2727 0 : if ( pOld != pPageFrm )
2728 : {
2729 0 : pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE );
2730 : }
2731 :
2732 0 : if ( rOld.Left() != aFrm.Left() )
2733 : {
2734 0 : SwRect aTmp( rOld );
2735 0 : aTmp.Union( aFrm );
2736 0 : aTmp.Left( std::min(aFrm.Left(), rOld.Left()) );
2737 0 : aTmp.Right( std::max(aFrm.Left(), rOld.Left()) );
2738 0 : pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2739 : }
2740 0 : SwTwips nOld = rOld.Right();
2741 0 : SwTwips nNew = aFrm.Right();
2742 0 : if ( nOld != nNew )
2743 : {
2744 0 : SwRect aTmp( rOld );
2745 0 : aTmp.Union( aFrm );
2746 0 : aTmp.Left( std::min(nNew, nOld) );
2747 0 : aTmp.Right( std::max(nNew, nOld) );
2748 0 : pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2749 : }
2750 0 : if ( rOld.Top() != aFrm.Top() )
2751 : {
2752 0 : SwRect aTmp( rOld );
2753 0 : aTmp.Union( aFrm );
2754 0 : aTmp.Top( std::min(aFrm.Top(), rOld.Top()) );
2755 0 : aTmp.Bottom( std::max(aFrm.Top(), rOld.Top()) );
2756 0 : pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2757 : }
2758 0 : nOld = rOld.Bottom();
2759 0 : nNew = aFrm.Bottom();
2760 0 : if ( nOld != nNew )
2761 : {
2762 0 : SwRect aTmp( rOld );
2763 0 : aTmp.Union( aFrm );
2764 0 : aTmp.Top( std::min(nNew, nOld) );
2765 0 : aTmp.Bottom( std::max(nNew, nOld) );
2766 0 : pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
2767 : }
2768 : }
2769 0 : else if ( pOldPrt && *pOldPrt != pFly->Prt() &&
2770 0 : pFly->GetFmt()->GetSurround().IsContour() )
2771 : {
2772 : // #i24097#
2773 0 : pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE );
2774 : }
2775 0 : }
2776 :
2777 0 : static void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect )
2778 : {
2779 0 : SwTwips nBottom = rRect.Bottom();
2780 0 : while( pFrm )
2781 : {
2782 0 : if( pFrm->IsLayoutFrm() )
2783 : {
2784 0 : if( rRect.IsOver( pFrm->Frm() ) )
2785 0 : lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect );
2786 : }
2787 0 : else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() )
2788 : {
2789 0 : if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() )
2790 0 : pFrm->InvalidateSize();
2791 : else
2792 0 : pFrm->InvalidateNextPos();
2793 : }
2794 0 : pFrm = pFrm->GetNext();
2795 : }
2796 0 : }
2797 :
2798 0 : static void lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt,
2799 : const SwRect &rRect, const PrepareHint eHint )
2800 : {
2801 0 : if ( pCnt->IsTxtFrm() )
2802 : {
2803 0 : SwRect aCntPrt( pCnt->Prt() );
2804 0 : aCntPrt.Pos() += pCnt->Frm().Pos();
2805 0 : if ( eHint == PREP_FLY_ATTR_CHG )
2806 : {
2807 : // #i35640# - use given rectangle <rRect> instead
2808 : // of current bound rectangle
2809 0 : if ( aCntPrt.IsOver( rRect ) )
2810 0 : pCnt->Prepare( PREP_FLY_ATTR_CHG );
2811 : }
2812 : // #i23129# - only invalidate, if the text frame
2813 : // printing area overlaps with the given rectangle.
2814 0 : else if ( aCntPrt.IsOver( rRect ) )
2815 0 : pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) );
2816 0 : if ( pCnt->GetDrawObjs() )
2817 : {
2818 0 : const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
2819 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2820 : {
2821 0 : SwAnchoredObject* pObj = rObjs[i];
2822 0 : if ( pObj->ISA(SwFlyFrm) )
2823 : {
2824 0 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj);
2825 0 : if ( pFly->IsFlyInCntFrm() )
2826 : {
2827 0 : SwCntntFrm *pCntnt = pFly->ContainsCntnt();
2828 0 : while ( pCntnt )
2829 : {
2830 0 : ::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint );
2831 0 : pCntnt = pCntnt->GetNextCntntFrm();
2832 : }
2833 : }
2834 : }
2835 : }
2836 : }
2837 : }
2838 0 : }
2839 :
2840 0 : void Notify_Background( const SdrObject* pObj,
2841 : SwPageFrm* pPage,
2842 : const SwRect& rRect,
2843 : const PrepareHint eHint,
2844 : const sal_Bool bInva )
2845 : {
2846 : // If the frame was positioned correctly for the first time, do not inform the old area
2847 0 : if ( eHint == PREP_FLY_LEAVE && rRect.Top() == FAR_AWAY )
2848 0 : return;
2849 :
2850 : SwLayoutFrm* pArea;
2851 0 : SwFlyFrm *pFlyFrm = 0;
2852 : SwFrm* pAnchor;
2853 0 : if( pObj->ISA(SwVirtFlyDrawObj) )
2854 : {
2855 0 : pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
2856 0 : pAnchor = pFlyFrm->AnchorFrm();
2857 : }
2858 : else
2859 : {
2860 0 : pFlyFrm = NULL;
2861 : pAnchor = const_cast<SwFrm*>(
2862 0 : GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() );
2863 : }
2864 0 : if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() )
2865 0 : pArea = pAnchor->FindFlyFrm();
2866 : else
2867 0 : pArea = pPage;
2868 0 : SwCntntFrm *pCnt = 0;
2869 0 : if ( pArea )
2870 : {
2871 0 : if( PREP_FLY_ARRIVE != eHint )
2872 0 : lcl_CheckFlowBack( pArea, rRect );
2873 :
2874 : // Only the Flys following this anchor are reacting. Thus, those do not
2875 : // need to be processed.
2876 : // An exception is LEAVE, since the Fly might come "from above".
2877 : // If the anchor is positioned on the previous page, the whole page
2878 : // needs to be processed (47722).
2879 : // OD 2004-05-13 #i28701# - If the wrapping style has to be considered
2880 : // on the object positioning, the complete area has to be processed,
2881 : // because content frames before the anchor frame also have to consider
2882 : // the object for the text wrapping.
2883 : // #i3317# - The complete area has always been
2884 : // processed.
2885 : {
2886 0 : pCnt = pArea->ContainsCntnt();
2887 : }
2888 : }
2889 0 : SwFrm *pLastTab = 0;
2890 :
2891 0 : while ( pCnt && pArea && pArea->IsAnLower( pCnt ) )
2892 : {
2893 0 : ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
2894 0 : if ( pCnt->IsInTab() )
2895 : {
2896 0 : SwLayoutFrm* pCell = pCnt->GetUpper();
2897 : // #i40606# - use <GetLastBoundRect()>
2898 : // instead of <GetCurrentBoundRect()>, because a recalculation
2899 : // of the bounding rectangle isn't intended here.
2900 0 : if ( pCell->IsCellFrm() &&
2901 0 : ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) ||
2902 0 : pCell->Frm().IsOver( rRect ) ) )
2903 : {
2904 0 : const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient();
2905 0 : if ( text::VertOrientation::NONE != rOri.GetVertOrient() )
2906 0 : pCell->InvalidatePrt();
2907 : }
2908 0 : SwTabFrm *pTab = pCnt->FindTabFrm();
2909 0 : if ( pTab != pLastTab )
2910 : {
2911 0 : pLastTab = pTab;
2912 : // #i40606# - use <GetLastBoundRect()>
2913 : // instead of <GetCurrentBoundRect()>, because a recalculation
2914 : // of the bounding rectangle isn't intended here.
2915 0 : if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) ||
2916 0 : pTab->Frm().IsOver( rRect ) )
2917 : {
2918 0 : if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) )
2919 0 : pTab->InvalidatePrt();
2920 : }
2921 : }
2922 : }
2923 0 : pCnt = pCnt->GetNextCntntFrm();
2924 : }
2925 : // #128702# - make code robust
2926 0 : if ( pPage && pPage->GetSortedObjs() )
2927 : {
2928 0 : pObj->GetOrdNum();
2929 0 : const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
2930 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2931 : {
2932 0 : SwAnchoredObject* pAnchoredObj = rObjs[i];
2933 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
2934 : {
2935 0 : if( pAnchoredObj->GetDrawObj() == pObj )
2936 0 : continue;
2937 0 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
2938 0 : if ( pFly->Frm().Top() == FAR_AWAY )
2939 0 : continue;
2940 :
2941 0 : if ( !pFlyFrm ||
2942 0 : (!pFly->IsLowerOf( pFlyFrm ) &&
2943 0 : pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect()))
2944 : {
2945 0 : pCnt = pFly->ContainsCntnt();
2946 0 : while ( pCnt )
2947 : {
2948 0 : ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint );
2949 0 : pCnt = pCnt->GetNextCntntFrm();
2950 : }
2951 : }
2952 0 : if( pFly->IsFlyLayFrm() )
2953 : {
2954 0 : if( pFly->Lower() && pFly->Lower()->IsColumnFrm() &&
2955 0 : pFly->Frm().Bottom() >= rRect.Top() &&
2956 0 : pFly->Frm().Top() <= rRect.Bottom() &&
2957 0 : pFly->Frm().Right() >= rRect.Left() &&
2958 0 : pFly->Frm().Left() <= rRect.Right() )
2959 : {
2960 0 : pFly->InvalidateSize();
2961 : }
2962 : }
2963 : // Flys above myself might sidestep if they have an automatic
2964 : // alignment. This happens independently of my attributes since
2965 : // this might have been changed as well.
2966 0 : else if ( pFly->IsFlyAtCntFrm() &&
2967 0 : pObj->GetOrdNumDirect() <
2968 0 : pFly->GetVirtDrawObj()->GetOrdNumDirect() &&
2969 0 : pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) )
2970 : {
2971 0 : const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient();
2972 0 : if ( text::HoriOrientation::NONE != rH.GetHoriOrient() &&
2973 0 : text::HoriOrientation::CENTER != rH.GetHoriOrient() &&
2974 0 : ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) &&
2975 0 : (pFly->Frm().Bottom() >= rRect.Top() &&
2976 0 : pFly->Frm().Top() <= rRect.Bottom()) )
2977 0 : pFly->InvalidatePos();
2978 : }
2979 : }
2980 : }
2981 : }
2982 0 : if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT
2983 0 : pAnchor->GetUpper()->InvalidateSize();
2984 :
2985 : // #i82258# - make code robust
2986 0 : SwViewShell* pSh = 0;
2987 0 : if ( bInva && pPage &&
2988 0 : 0 != (pSh = pPage->getRootFrm()->GetCurrShell()) )
2989 : {
2990 0 : pSh->InvalidateWindows( rRect );
2991 : }
2992 : }
2993 :
2994 : /// Provides the Upper of an anchor in paragraph-bound objects. If the latter
2995 : /// is a chained border or a footnote, the "virtual" Upper might be returne.
2996 0 : const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos )
2997 : {
2998 0 : if( pFrm->IsTxtFrm() )
2999 : {
3000 0 : pFrm = pFrm->GetUpper();
3001 0 : if( !pFrm->Frm().IsInside( rPos ) )
3002 : {
3003 0 : if( pFrm->IsFtnFrm() )
3004 : {
3005 0 : const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow();
3006 0 : while( pTmp )
3007 : {
3008 0 : if( pTmp->Frm().IsInside( rPos ) )
3009 0 : return pTmp;
3010 0 : pTmp = pTmp->GetFollow();
3011 : }
3012 : }
3013 : else
3014 : {
3015 0 : SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm();
3016 0 : while( pTmp )
3017 : {
3018 0 : if( pTmp->Frm().IsInside( rPos ) )
3019 0 : return pTmp;
3020 0 : pTmp = pTmp->GetNextLink();
3021 : }
3022 : }
3023 : }
3024 : }
3025 0 : return pFrm;
3026 : }
3027 :
3028 0 : bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj )
3029 : {
3030 0 : Point aPos;
3031 : const SwFrm* pFrm;
3032 0 : if( pObj->ISA(SwVirtFlyDrawObj) )
3033 : {
3034 0 : const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm();
3035 0 : pFrm = pFly->GetAnchorFrm();
3036 0 : aPos = pFly->Frm().Pos();
3037 : }
3038 : else
3039 : {
3040 0 : pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm(pObj);
3041 0 : aPos = pObj->GetCurrentBoundRect().TopLeft();
3042 : }
3043 : OSL_ENSURE( pFrm, "8-( Fly is lost in Space." );
3044 0 : pFrm = GetVirtualUpper( pFrm, aPos );
3045 0 : do
3046 0 : { if ( pFrm == pCurrFrm )
3047 0 : return true;
3048 0 : if( pFrm->IsFlyFrm() )
3049 : {
3050 0 : aPos = pFrm->Frm().Pos();
3051 0 : pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3052 : }
3053 : else
3054 0 : pFrm = pFrm->GetUpper();
3055 : } while ( pFrm );
3056 0 : return false;
3057 : }
3058 :
3059 : /// provides the area of a frame in that no Fly from another area can overlap
3060 0 : const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp )
3061 : {
3062 : const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
3063 : FRM_FTN | FRM_FLY |
3064 : FRM_TAB | FRM_ROW | FRM_CELL |
3065 0 : nAdditionalKontextTyp;
3066 0 : do
3067 0 : { if ( pFrm->GetType() & nTyp )
3068 0 : break;
3069 0 : pFrm = pFrm->GetUpper();
3070 : } while( pFrm );
3071 0 : return pFrm;
3072 : }
3073 :
3074 0 : bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm )
3075 : {
3076 0 : const SwFrm *pKontext = FindKontext( pInnerFrm, 0 );
3077 :
3078 : const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT |
3079 : FRM_FTN | FRM_FLY |
3080 0 : FRM_TAB | FRM_ROW | FRM_CELL;
3081 0 : do
3082 0 : { if ( pFrm->GetType() & nTyp )
3083 : {
3084 0 : if( pFrm == pKontext )
3085 0 : return true;
3086 0 : if( pFrm->IsCellFrm() )
3087 0 : return false;
3088 : }
3089 0 : if( pFrm->IsFlyFrm() )
3090 : {
3091 0 : Point aPos( pFrm->Frm().Pos() );
3092 0 : pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos );
3093 : }
3094 : else
3095 0 : pFrm = pFrm->GetUpper();
3096 : } while( pFrm );
3097 :
3098 0 : return false;
3099 : }
3100 :
3101 0 : static SwTwips lcl_CalcCellRstHeight( SwLayoutFrm *pCell )
3102 : {
3103 0 : if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() )
3104 : {
3105 0 : SwFrm *pLow = pCell->Lower();
3106 0 : long nHeight = 0, nFlyAdd = 0;
3107 0 : do
3108 : {
3109 0 : long nLow = pLow->Frm().Height();
3110 0 : if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() )
3111 0 : nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height();
3112 0 : else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() )
3113 0 : nLow += ((SwSectionFrm*)pLow)->Undersize();
3114 0 : nFlyAdd = std::max( 0L, nFlyAdd - nLow );
3115 0 : nFlyAdd = std::max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) );
3116 0 : nHeight += nLow;
3117 0 : pLow = pLow->GetNext();
3118 : } while ( pLow );
3119 0 : if ( nFlyAdd )
3120 0 : nHeight += nFlyAdd;
3121 :
3122 : // The border cannot be calculated based on PrtArea and Frm, since both can be invalid.
3123 0 : SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell );
3124 0 : const SwBorderAttrs &rAttrs = *aAccess.Get();
3125 0 : nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom();
3126 :
3127 0 : return pCell->Frm().Height() - nHeight;
3128 : }
3129 : else
3130 : {
3131 0 : long nRstHeight = 0;
3132 0 : SwFrm *pLow = pCell->Lower();
3133 0 : do
3134 0 : { nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow );
3135 0 : pLow = pLow->GetNext();
3136 :
3137 : } while ( pLow );
3138 :
3139 0 : return nRstHeight;
3140 : }
3141 : }
3142 :
3143 0 : SwTwips CalcRowRstHeight( SwLayoutFrm *pRow )
3144 : {
3145 0 : SwTwips nRstHeight = LONG_MAX;
3146 0 : SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower();
3147 0 : while ( pLow )
3148 : {
3149 0 : nRstHeight = std::min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) );
3150 0 : pLow = (SwLayoutFrm*)pLow->GetNext();
3151 : }
3152 0 : return nRstHeight;
3153 : }
3154 :
3155 0 : const SwFrm* FindPage( const SwRect &rRect, const SwFrm *pPage )
3156 : {
3157 0 : if ( !rRect.IsOver( pPage->Frm() ) )
3158 : {
3159 0 : const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper());
3160 0 : const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0;
3161 0 : if ( pTmpPage )
3162 0 : pPage = pTmpPage;
3163 : }
3164 :
3165 0 : return pPage;
3166 : }
3167 :
3168 0 : class SwFrmHolder : private SfxListener
3169 : {
3170 : SwFrm* pFrm;
3171 : bool bSet;
3172 : virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
3173 : public:
3174 0 : SwFrmHolder() : pFrm(0), bSet(false) {}
3175 : void SetFrm( SwFrm* pHold );
3176 0 : SwFrm* GetFrm() { return pFrm; }
3177 : void Reset();
3178 0 : bool IsSet() { return bSet; }
3179 : };
3180 :
3181 0 : void SwFrmHolder::SetFrm( SwFrm* pHold )
3182 : {
3183 0 : bSet = true;
3184 0 : pFrm = pHold;
3185 0 : StartListening(*pHold);
3186 0 : }
3187 :
3188 0 : void SwFrmHolder::Reset()
3189 : {
3190 0 : if (pFrm)
3191 0 : EndListening(*pFrm);
3192 0 : bSet = false;
3193 0 : pFrm = 0;
3194 0 : }
3195 :
3196 0 : void SwFrmHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
3197 : {
3198 0 : if ( rHint.IsA(TYPE(SfxSimpleHint)) )
3199 : {
3200 0 : if ( ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DYING && &rBC == pFrm )
3201 0 : pFrm = 0;
3202 : }
3203 0 : }
3204 :
3205 0 : SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const& rMod, sal_uInt16 const nFrmType,
3206 : const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm )
3207 : {
3208 0 : SwFrm *pMinFrm = 0, *pTmpFrm;
3209 0 : SwFrmHolder aHolder;
3210 0 : SwRect aCalcRect;
3211 0 : bool bClientIterChanged = false;
3212 :
3213 0 : SwIterator<SwFrm,SwModify> aIter( rMod );
3214 0 : do {
3215 0 : pMinFrm = 0;
3216 0 : aHolder.Reset();
3217 0 : sal_uInt64 nMinDist = 0;
3218 0 : bClientIterChanged = false;
3219 :
3220 0 : for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() )
3221 : {
3222 0 : if( pTmpFrm->GetType() & nFrmType &&
3223 0 : ( !pLayout || pLayout == pTmpFrm->getRootFrm() ) &&
3224 0 : (!pTmpFrm->IsFlowFrm() ||
3225 0 : !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() ))
3226 : {
3227 0 : if( pPoint )
3228 : {
3229 : // watch for Frm being deleted
3230 0 : if ( pMinFrm )
3231 0 : aHolder.SetFrm( pMinFrm );
3232 : else
3233 0 : aHolder.Reset();
3234 :
3235 0 : if( bCalcFrm )
3236 : {
3237 : // - format parent Writer
3238 : // fly frame, if it isn't been formatted yet.
3239 : // Note: The Writer fly frame could be the frame itself.
3240 0 : SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() );
3241 0 : if ( pFlyFrm &&
3242 0 : pFlyFrm->Frm().Pos().X() == FAR_AWAY &&
3243 0 : pFlyFrm->Frm().Pos().Y() == FAR_AWAY )
3244 : {
3245 0 : SwObjectFormatter::FormatObj( *pFlyFrm );
3246 : }
3247 0 : pTmpFrm->Calc();
3248 : }
3249 :
3250 : // #127369#
3251 : // aIter.IsChanged checks if the current pTmpFrm has been deleted while
3252 : // it is the current iterator
3253 : // FrmHolder watches for deletion of the current pMinFrm
3254 0 : if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrm() ) )
3255 : {
3256 : // restart iteration
3257 0 : bClientIterChanged = true;
3258 0 : break;
3259 : }
3260 :
3261 : // for Flys go via the parent if the Fly is not yet "formatted"
3262 0 : if( !bCalcFrm && nFrmType & FRM_FLY &&
3263 0 : ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() &&
3264 0 : FAR_AWAY == pTmpFrm->Frm().Pos().getX() &&
3265 0 : FAR_AWAY == pTmpFrm->Frm().Pos().getY() )
3266 0 : aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm();
3267 : else
3268 0 : aCalcRect = pTmpFrm->Frm();
3269 :
3270 0 : if ( aCalcRect.IsInside( *pPoint ) )
3271 : {
3272 0 : pMinFrm = pTmpFrm;
3273 0 : break;
3274 : }
3275 :
3276 : // Point not in rectangle. Compare distances:
3277 0 : const Point aCalcRectCenter = aCalcRect.Center();
3278 0 : const Point aDiff = aCalcRectCenter - *pPoint;
3279 0 : const sal_uInt64 nCurrentDist = aDiff.getX() * aDiff.getX() + aDiff.getY() * aDiff.getY(); // opt: no sqrt
3280 0 : if ( !pMinFrm || nCurrentDist < nMinDist )
3281 : {
3282 0 : pMinFrm = pTmpFrm;
3283 0 : nMinDist = nCurrentDist;
3284 : }
3285 : }
3286 : else
3287 : {
3288 : // if no pPoint is provided, take the first one
3289 0 : pMinFrm = pTmpFrm;
3290 0 : break;
3291 : }
3292 : }
3293 : }
3294 : } while( bClientIterChanged );
3295 :
3296 0 : if( pPos && pMinFrm && pMinFrm->IsTxtFrm() )
3297 0 : return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos );
3298 :
3299 0 : return pMinFrm;
3300 : }
3301 :
3302 0 : bool IsExtraData( const SwDoc *pDoc )
3303 : {
3304 0 : const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo();
3305 0 : return rInf.IsPaintLineNumbers() ||
3306 0 : rInf.IsCountInFlys() ||
3307 0 : ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE &&
3308 0 : !pDoc->GetRedlineTbl().empty());
3309 : }
3310 :
3311 : // OD 22.09.2003 #110978#
3312 0 : const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const
3313 : {
3314 0 : SwRect aPrtWithoutHeaderFooter( Prt() );
3315 0 : aPrtWithoutHeaderFooter.Pos() += Frm().Pos();
3316 :
3317 0 : const SwFrm* pLowerFrm = Lower();
3318 0 : while ( pLowerFrm )
3319 : {
3320 : // Note: independent on text direction page header and page footer are
3321 : // always at top respectively at bottom of the page frame.
3322 0 : if ( pLowerFrm->IsHeaderFrm() )
3323 : {
3324 0 : aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() +
3325 0 : pLowerFrm->Frm().Height() );
3326 : }
3327 0 : if ( pLowerFrm->IsFooterFrm() )
3328 : {
3329 0 : aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() -
3330 0 : pLowerFrm->Frm().Height() );
3331 : }
3332 :
3333 0 : pLowerFrm = pLowerFrm->GetNext();
3334 : }
3335 :
3336 0 : return aPrtWithoutHeaderFooter;
3337 : }
3338 :
3339 : /** method to determine the spacing values of a frame
3340 :
3341 : OD 2004-03-10 #i28701#
3342 : OD 2009-08-28 #i102458#
3343 : Add output parameter <obIsLineSpacingProportional>
3344 : */
3345 0 : void GetSpacingValuesOfFrm( const SwFrm& rFrm,
3346 : SwTwips& onLowerSpacing,
3347 : SwTwips& onLineSpacing,
3348 : bool& obIsLineSpacingProportional )
3349 : {
3350 0 : if ( !rFrm.IsFlowFrm() )
3351 : {
3352 0 : onLowerSpacing = 0;
3353 0 : onLineSpacing = 0;
3354 : }
3355 : else
3356 : {
3357 0 : const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace();
3358 0 : onLowerSpacing = rULSpace.GetLower();
3359 :
3360 0 : onLineSpacing = 0;
3361 0 : obIsLineSpacingProportional = false;
3362 0 : if ( rFrm.IsTxtFrm() )
3363 : {
3364 0 : onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace();
3365 : obIsLineSpacingProportional =
3366 0 : onLineSpacing != 0 &&
3367 0 : static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0;
3368 : }
3369 :
3370 : OSL_ENSURE( onLowerSpacing >= 0 && onLineSpacing >= 0,
3371 : "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" );
3372 : }
3373 0 : }
3374 :
3375 : /// get the content of the table cell, skipping content from nested tables
3376 0 : const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell )
3377 : {
3378 0 : const SwCntntFrm* pCntnt = rCell.ContainsCntnt();
3379 0 : const SwTabFrm* pTab = rCell.FindTabFrm();
3380 :
3381 0 : while ( pCntnt && rCell.IsAnLower( pCntnt ) )
3382 : {
3383 0 : const SwTabFrm* pTmpTab = pCntnt->FindTabFrm();
3384 0 : if ( pTmpTab != pTab )
3385 : {
3386 0 : pCntnt = pTmpTab->FindLastCntnt();
3387 0 : if ( pCntnt )
3388 :
3389 0 : pCntnt = pCntnt->FindNextCnt();
3390 :
3391 : }
3392 : else
3393 0 : break;
3394 : }
3395 0 : return pCntnt;
3396 : }
3397 :
3398 : /// Can be used to check if a frame has been deleted
3399 0 : bool SwDeletionChecker::HasBeenDeleted()
3400 : {
3401 0 : if ( !mpFrm || !mpRegIn )
3402 0 : return false;
3403 :
3404 0 : SwIterator<SwFrm,SwModify> aIter(*mpRegIn);
3405 0 : SwFrm* pLast = aIter.First();
3406 0 : while ( pLast )
3407 : {
3408 0 : if ( pLast == mpFrm )
3409 0 : return false;
3410 0 : pLast = aIter.Next();
3411 : }
3412 :
3413 0 : return true;
3414 : }
3415 :
3416 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|