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