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