Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / sw / source / core / text / txtfrm.cxx
blobd76c4fa2cacfbfec0b6de2cf31bc361d3e1649d6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <hints.hxx>
22 #include <svl/ctloptions.hxx>
23 #include <sfx2/printer.hxx>
24 #include <sfx2/sfxuno.hxx>
25 #include <editeng/langitem.hxx>
26 #include <editeng/lspcitem.hxx>
27 #include <editeng/lrspitem.hxx>
28 #include <editeng/ulspitem.hxx>
29 #include <editeng/brshitem.hxx>
30 #include <editeng/pgrditem.hxx>
31 #include <swmodule.hxx>
32 #include <SwSmartTagMgr.hxx>
33 #include <doc.hxx> // GetDoc()
34 #include "rootfrm.hxx"
35 #include <pagefrm.hxx> // InvalidateSpelling
36 #include <rootfrm.hxx>
37 #include <viewsh.hxx> // ViewShell
38 #include <pam.hxx> // SwPosition
39 #include <ndtxt.hxx> // SwTxtNode
40 #include <txtatr.hxx>
41 #include <paratr.hxx>
42 #include <viewopt.hxx>
43 #include <dflyobj.hxx>
44 #include <flyfrm.hxx>
45 #include <tabfrm.hxx>
46 #include <frmtool.hxx>
47 #include <pagedesc.hxx> // SwPageDesc
48 #include <tgrditem.hxx>
49 #include <dbg_lay.hxx>
50 #include <fmtfld.hxx>
51 #include <fmtftn.hxx>
52 #include <txtfld.hxx>
53 #include <txtftn.hxx>
54 #include <charatr.hxx>
55 #include <ftninfo.hxx>
56 #include <fmtline.hxx>
57 #include <txtfrm.hxx> // SwTxtFrm
58 #include <sectfrm.hxx> // SwSectFrm
59 #include <itrform2.hxx> // Iteratoren
60 #include <widorp.hxx> // SwFrmBreak
61 #include <txtcache.hxx>
62 #include <fntcache.hxx> // GetLineSpace benutzt pLastFont
63 #include <SwGrammarMarkUp.hxx>
64 #include <lineinfo.hxx>
65 #include <SwPortionHandler.hxx>
66 #include <dcontact.hxx>
67 #include <sortedobjs.hxx>
68 #include <txtflcnt.hxx> // SwTxtFlyCnt
69 #include <fmtflcnt.hxx> // SwFmtFlyCnt
70 #include <fmtcntnt.hxx> // SwFmtCntnt
71 #include <numrule.hxx>
72 #include <swtable.hxx>
73 #include <fldupde.hxx>
74 #include <IGrammarContact.hxx>
75 #include <switerator.hxx>
78 TYPEINIT1( SwTxtFrm, SwCntntFrm );
80 // Switches width and height of the text frame
81 void SwTxtFrm::SwapWidthAndHeight()
83 if ( ! bIsSwapped )
85 const long nPrtOfstX = Prt().Pos().X();
86 Prt().Pos().X() = Prt().Pos().Y();
87 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
88 if( IsVertLR() )
89 Prt().Pos().Y() = nPrtOfstX;
90 else
91 Prt().Pos().Y() = Frm().Width() - ( nPrtOfstX + Prt().Width() );
94 else
96 const long nPrtOfstY = Prt().Pos().Y();
97 Prt().Pos().Y() = Prt().Pos().X();
98 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
99 if( IsVertLR() )
100 Prt().Pos().X() = nPrtOfstY;
101 else
102 Prt().Pos().X() = Frm().Height() - ( nPrtOfstY + Prt().Height() );
105 const long nFrmWidth = Frm().Width();
106 Frm().Width( Frm().Height() );
107 Frm().Height( nFrmWidth );
108 const long nPrtWidth = Prt().Width();
109 Prt().Width( Prt().Height() );
110 Prt().Height( nPrtWidth );
112 bIsSwapped = ! bIsSwapped;
115 // Calculates the coordinates of a rectangle when switching from
116 // horizontal to vertical layout.
117 void SwTxtFrm::SwitchHorizontalToVertical( SwRect& rRect ) const
119 // calc offset inside frame
120 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
121 long nOfstX, nOfstY;
122 if ( IsVertLR() )
124 nOfstX = rRect.Left() - Frm().Left();
125 nOfstY = rRect.Top() - Frm().Top();
127 else
129 nOfstX = rRect.Left() - Frm().Left();
130 nOfstY = rRect.Top() + rRect.Height() - Frm().Top();
133 const long nWidth = rRect.Width();
134 const long nHeight = rRect.Height();
136 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
137 if ( IsVertLR() )
138 rRect.Left(Frm().Left() + nOfstY);
139 else
141 if ( bIsSwapped )
142 rRect.Left( Frm().Left() + Frm().Height() - nOfstY );
143 else
144 // frame is rotated
145 rRect.Left( Frm().Left() + Frm().Width() - nOfstY );
148 rRect.Top( Frm().Top() + nOfstX );
149 rRect.Width( nHeight );
150 rRect.Height( nWidth );
153 // Calculates the coordinates of a point when switching from
154 // horizontal to vertical layout.
155 void SwTxtFrm::SwitchHorizontalToVertical( Point& rPoint ) const
157 // calc offset inside frame
158 const long nOfstX = rPoint.X() - Frm().Left();
159 const long nOfstY = rPoint.Y() - Frm().Top();
160 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
161 if ( IsVertLR() )
162 rPoint.X() = Frm().Left() + nOfstY;
163 else
165 if ( bIsSwapped )
166 rPoint.X() = Frm().Left() + Frm().Height() - nOfstY;
167 else
168 // calc rotated coords
169 rPoint.X() = Frm().Left() + Frm().Width() - nOfstY;
172 rPoint.Y() = Frm().Top() + nOfstX;
175 // Calculates the a limit value when switching from
176 // horizontal to vertical layout.
177 long SwTxtFrm::SwitchHorizontalToVertical( long nLimit ) const
179 Point aTmp( 0, nLimit );
180 SwitchHorizontalToVertical( aTmp );
181 return aTmp.X();
184 // Calculates the coordinates of a rectangle when switching from
185 // vertical to horizontal layout.
186 void SwTxtFrm::SwitchVerticalToHorizontal( SwRect& rRect ) const
188 long nOfstX;
190 // calc offset inside frame
192 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
193 if ( IsVertLR() )
194 nOfstX = rRect.Left() - Frm().Left();
195 else
197 if ( bIsSwapped )
198 nOfstX = Frm().Left() + Frm().Height() - ( rRect.Left() + rRect.Width() );
199 else
200 nOfstX = Frm().Left() + Frm().Width() - ( rRect.Left() + rRect.Width() );
203 const long nOfstY = rRect.Top() - Frm().Top();
204 const long nWidth = rRect.Height();
205 const long nHeight = rRect.Width();
207 // calc rotated coords
208 rRect.Left( Frm().Left() + nOfstY );
209 rRect.Top( Frm().Top() + nOfstX );
210 rRect.Width( nWidth );
211 rRect.Height( nHeight );
214 // Calculates the coordinates of a point when switching from
215 // vertical to horizontal layout.
216 void SwTxtFrm::SwitchVerticalToHorizontal( Point& rPoint ) const
218 long nOfstX;
220 // calc offset inside frame
222 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
223 if ( IsVertLR() )
224 nOfstX = rPoint.X() - Frm().Left();
225 else
227 if ( bIsSwapped )
228 nOfstX = Frm().Left() + Frm().Height() - rPoint.X();
229 else
230 nOfstX = Frm().Left() + Frm().Width() - rPoint.X();
233 const long nOfstY = rPoint.Y() - Frm().Top();
235 // calc rotated coords
236 rPoint.X() = Frm().Left() + nOfstY;
237 rPoint.Y() = Frm().Top() + nOfstX;
240 // Calculates the a limit value when switching from
241 // vertical to horizontal layout.
242 long SwTxtFrm::SwitchVerticalToHorizontal( long nLimit ) const
244 Point aTmp( nLimit, 0 );
245 SwitchVerticalToHorizontal( aTmp );
246 return aTmp.Y();
249 SwFrmSwapper::SwFrmSwapper( const SwTxtFrm* pTxtFrm, sal_Bool bSwapIfNotSwapped )
250 : pFrm( pTxtFrm ), bUndo( sal_False )
252 if ( pFrm->IsVertical() &&
253 ( ( bSwapIfNotSwapped && ! pFrm->IsSwapped() ) ||
254 ( ! bSwapIfNotSwapped && pFrm->IsSwapped() ) ) )
256 bUndo = sal_True;
257 ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
261 SwFrmSwapper::~SwFrmSwapper()
263 if ( bUndo )
264 ((SwTxtFrm*)pFrm)->SwapWidthAndHeight();
267 void SwTxtFrm::SwitchLTRtoRTL( SwRect& rRect ) const
269 SWAP_IF_NOT_SWAPPED( this )
271 long nWidth = rRect.Width();
272 rRect.Left( 2 * ( Frm().Left() + Prt().Left() ) +
273 Prt().Width() - rRect.Right() - 1 );
275 rRect.Width( nWidth );
277 UNDO_SWAP( this )
280 void SwTxtFrm::SwitchLTRtoRTL( Point& rPoint ) const
282 SWAP_IF_NOT_SWAPPED( this )
284 rPoint.X() = 2 * ( Frm().Left() + Prt().Left() ) + Prt().Width() - rPoint.X() - 1;
286 UNDO_SWAP( this )
289 SwLayoutModeModifier::SwLayoutModeModifier( const OutputDevice& rOutp ) :
290 rOut( rOutp ), nOldLayoutMode( rOutp.GetLayoutMode() )
294 SwLayoutModeModifier::~SwLayoutModeModifier()
296 ((OutputDevice&)rOut).SetLayoutMode( nOldLayoutMode );
299 void SwLayoutModeModifier::Modify( sal_Bool bChgToRTL )
301 ((OutputDevice&)rOut).SetLayoutMode( bChgToRTL ?
302 TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL :
303 TEXT_LAYOUT_BIDI_STRONG );
306 void SwLayoutModeModifier::SetAuto()
308 const sal_uLong nNewLayoutMode = nOldLayoutMode & ~TEXT_LAYOUT_BIDI_STRONG;
309 ((OutputDevice&)rOut).SetLayoutMode( nNewLayoutMode );
312 SwDigitModeModifier::SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang ) :
313 rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() )
315 LanguageType eLang = eCurLang;
316 const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals();
318 if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals )
319 eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
320 else if ( SvtCTLOptions::NUMERALS_ARABIC == nTextNumerals )
321 eLang = LANGUAGE_ENGLISH;
322 else if ( SvtCTLOptions::NUMERALS_SYSTEM == nTextNumerals )
323 eLang = ::GetAppLanguage();
325 ((OutputDevice&)rOut).SetDigitLanguage( eLang );
328 SwDigitModeModifier::~SwDigitModeModifier()
330 ((OutputDevice&)rOut).SetDigitLanguage( nOldLanguageType );
333 /*************************************************************************
334 * SwTxtFrm::Init()
335 *************************************************************************/
337 void SwTxtFrm::Init()
339 OSL_ENSURE( !IsLocked(), "+SwTxtFrm::Init: this ist locked." );
340 if( !IsLocked() )
342 ClearPara();
343 ResetBlinkPor();
344 //Die Flags direkt setzen um ResetPreps und damit ein unnuetzes GetPara
345 //einzusparen.
346 // Nicht bOrphan, bLocked oder bWait auf sal_False setzen !
347 // bOrphan = bFlag7 = bFlag8 = sal_False;
351 /*************************************************************************
352 * SwTxtFrm::SwTxtFrm()
353 *************************************************************************/
354 SwTxtFrm::SwTxtFrm(SwTxtNode * const pNode, SwFrm* pSib )
355 : SwCntntFrm( pNode, pSib )
356 , nAllLines( 0 )
357 , nThisLines( 0 )
358 , mnFlyAnchorOfst( 0 )
359 , mnFlyAnchorOfstNoWrap( 0 )
360 , mnFtnLine( 0 )
361 , mnHeightOfLastLine( 0 ) // OD 2004-03-17 #i11860#
362 , mnAdditionalFirstLineOffset( 0 )
363 , nOfst( 0 )
364 , nCacheIdx( MSHRT_MAX )
365 , bLocked( false )
366 , bFormatted( false )
367 , bWidow( false )
368 , bJustWidow( false )
369 , bEmpty( false )
370 , bInFtnConnect( false )
371 , bFtn( false )
372 , bRepaint( false )
373 , bBlinkPor( false )
374 , bFieldFollow( false )
375 , bHasAnimation( false )
376 , bIsSwapped( false )
377 , mbFollowFormatAllowed( true ) // OD 14.03.2003 #i11760#
379 nType = FRMC_TXT;
382 /*************************************************************************
383 * SwTxtFrm::~SwTxtFrm()
384 *************************************************************************/
385 SwTxtFrm::~SwTxtFrm()
387 // Remove associated SwParaPortion from pTxtCache
388 ClearPara();
391 const XubString& SwTxtFrm::GetTxt() const
393 return GetTxtNode()->GetTxt();
396 void SwTxtFrm::ResetPreps()
398 if ( GetCacheIdx() != MSHRT_MAX )
400 SwParaPortion *pPara;
401 if( 0 != (pPara = GetPara()) )
402 pPara->ResetPreps();
406 /*************************************************************************
407 * SwTxtFrm::IsHiddenNow()
408 *************************************************************************/
409 sal_Bool SwTxtFrm::IsHiddenNow() const
411 SwFrmSwapper aSwapper( this, sal_True );
413 if( !Frm().Width() && IsValid() && GetUpper()->IsValid() )
414 //bei Stackueberlauf (StackHack) invalid!
416 // OSL_FAIL( "SwTxtFrm::IsHiddenNow: thin frame" );
417 return sal_True;
420 const bool bHiddenCharsHidePara = GetTxtNode()->HasHiddenCharAttribute( true );
421 const bool bHiddenParaField = GetTxtNode()->HasHiddenParaField();
422 const ViewShell* pVsh = getRootFrm()->GetCurrShell();
424 if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
426 if (
427 ( bHiddenParaField &&
428 ( !pVsh->GetViewOptions()->IsShowHiddenPara() &&
429 !pVsh->GetViewOptions()->IsFldName() ) ) ||
430 ( bHiddenCharsHidePara &&
431 !pVsh->GetViewOptions()->IsShowHiddenChar() ) )
433 return sal_True;
437 return sal_False;
441 /*************************************************************************
442 * SwTxtFrm::HideHidden()
443 *************************************************************************/
444 // Entfernt die Anhaengsel des Textfrms wenn dieser hidden ist
446 void SwTxtFrm::HideHidden()
448 OSL_ENSURE( !GetFollow() && IsHiddenNow(),
449 "HideHidden on visible frame of hidden frame has follow" );
451 const xub_StrLen nEnd = STRING_LEN;
452 HideFootnotes( GetOfst(), nEnd );
453 // OD 2004-01-15 #110582#
454 HideAndShowObjects();
456 //Die Formatinfos sind jetzt obsolete
457 ClearPara();
460 /*************************************************************************
461 * SwTxtFrm::HideFootnotes()
462 *************************************************************************/
463 void SwTxtFrm::HideFootnotes( xub_StrLen nStart, xub_StrLen nEnd )
465 const SwpHints *pHints = GetTxtNode()->GetpSwpHints();
466 if( pHints )
468 const sal_uInt16 nSize = pHints->Count();
469 SwPageFrm *pPage = 0;
470 for ( sal_uInt16 i = 0; i < nSize; ++i )
472 const SwTxtAttr *pHt = (*pHints)[i];
473 if ( pHt->Which() == RES_TXTATR_FTN )
475 const xub_StrLen nIdx = *pHt->GetStart();
476 if ( nEnd < nIdx )
477 break;
478 if( nStart <= nIdx )
480 if( !pPage )
481 pPage = FindPageFrm();
482 pPage->RemoveFtn( this, (SwTxtFtn*)pHt );
489 // #120729# - hotfix
490 // as-character anchored graphics, which are used for a graphic bullet list.
491 // As long as these graphic bullet list aren't imported, do not hide a
492 // at-character anchored object, if
493 // (a) the document is an imported WW8 document -
494 // checked by checking certain compatibility options -,
495 // (b) the paragraph is the last content in the document and
496 // (c) the anchor character is an as-character anchored graphic.
497 bool sw_HideObj( const SwTxtFrm& _rFrm,
498 const RndStdIds _eAnchorType,
499 const xub_StrLen _nObjAnchorPos,
500 SwAnchoredObject* _pAnchoredObj )
502 bool bRet( true );
504 if (_eAnchorType == FLY_AT_CHAR)
506 const IDocumentSettingAccess* pIDSA = _rFrm.GetTxtNode()->getIDocumentSettingAccess();
507 if ( !pIDSA->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING) &&
508 !pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING) &&
509 !pIDSA->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS) &&
510 pIDSA->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) &&
511 _rFrm.IsInDocBody() && !_rFrm.FindNextCnt() )
513 const sal_Unicode cAnchorChar =
514 _rFrm.GetTxtNode()->GetTxt().GetChar( _nObjAnchorPos );
515 if ( cAnchorChar == CH_TXTATR_BREAKWORD )
517 const SwTxtAttr* const pHint(
518 _rFrm.GetTxtNode()->GetTxtAttrForCharAt(_nObjAnchorPos,
519 RES_TXTATR_FLYCNT) );
520 if ( pHint )
522 const SwFrmFmt* pFrmFmt =
523 static_cast<const SwTxtFlyCnt*>(pHint)->GetFlyCnt().GetFrmFmt();
524 if ( pFrmFmt->Which() == RES_FLYFRMFMT )
526 SwNodeIndex nCntntIndex = *(pFrmFmt->GetCntnt().GetCntntIdx());
527 ++nCntntIndex;
528 if ( nCntntIndex.GetNode().IsNoTxtNode() )
530 bRet = false;
531 // set needed data structure values for object positioning
532 SWRECTFN( (&_rFrm) );
533 SwRect aLastCharRect( _rFrm.Frm() );
534 (aLastCharRect.*fnRect->fnSetWidth)( 1 );
535 _pAnchoredObj->maLastCharRect = aLastCharRect;
536 _pAnchoredObj->mnLastTopOfLine = (aLastCharRect.*fnRect->fnGetTop)();
544 return bRet;
546 /*************************************************************************
547 * SwTxtFrm::HideAndShowObjects()
548 *************************************************************************/
549 /** method to hide/show objects
551 OD 2004-01-15 #110582#
552 method hides respectively shows objects, which are anchored at paragraph,
553 at/as a character of the paragraph, corresponding to the paragraph and
554 paragraph portion visibility.
556 - is called from HideHidden() - should hide objects in hidden paragraphs and
557 - from _Format() - should hide/show objects in partly visible paragraphs
559 void SwTxtFrm::HideAndShowObjects()
561 if ( GetDrawObjs() )
563 if ( IsHiddenNow() )
565 // complete paragraph is hidden. Thus, hide all objects
566 for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i )
568 SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
569 SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
570 // #120729# - hotfix
571 // under certain conditions
572 const RndStdIds eAnchorType( pContact->GetAnchorId() );
573 const xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
574 if ((eAnchorType != FLY_AT_CHAR) ||
575 sw_HideObj( *this, eAnchorType, nObjAnchorPos,
576 (*GetDrawObjs())[i] ))
578 pContact->MoveObjToInvisibleLayer( pObj );
582 else
584 // paragraph is visible, but can contain hidden text portion.
585 // first we check if objects are allowed to be hidden:
586 const SwTxtNode& rNode = *GetTxtNode();
587 const ViewShell* pVsh = getRootFrm()->GetCurrShell();
588 const bool bShouldBeHidden = !pVsh || !pVsh->GetWin() ||
589 !pVsh->GetViewOptions()->IsShowHiddenChar();
591 // Thus, show all objects, which are anchored at paragraph and
592 // hide/show objects, which are anchored at/as character, according
593 // to the visibility of the anchor character.
594 for ( sal_uInt32 i = 0; i < GetDrawObjs()->Count(); ++i )
596 SdrObject* pObj = (*GetDrawObjs())[i]->DrawObj();
597 SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
598 // #120729# - determine anchor type only once
599 const RndStdIds eAnchorType( pContact->GetAnchorId() );
601 if (eAnchorType == FLY_AT_PARA)
603 pContact->MoveObjToVisibleLayer( pObj );
605 else if ((eAnchorType == FLY_AT_CHAR) ||
606 (eAnchorType == FLY_AS_CHAR))
608 xub_StrLen nHiddenStart;
609 xub_StrLen nHiddenEnd;
610 xub_StrLen nObjAnchorPos = pContact->GetCntntAnchorIndex().GetIndex();
611 SwScriptInfo::GetBoundsOfHiddenRange( rNode, nObjAnchorPos, nHiddenStart, nHiddenEnd, 0 );
612 // #120729# - hotfix
613 // under certain conditions
614 if ( nHiddenStart != STRING_LEN && bShouldBeHidden &&
615 sw_HideObj( *this, eAnchorType, nObjAnchorPos, (*GetDrawObjs())[i] ) )
616 pContact->MoveObjToInvisibleLayer( pObj );
617 else
618 pContact->MoveObjToVisibleLayer( pObj );
620 else
622 OSL_FAIL( "<SwTxtFrm::HideAndShowObjects()> - object not anchored at/inside paragraph!?" );
628 if (IsFollow())
630 SwTxtFrm *pMaster = FindMaster();
631 OSL_ENSURE(pMaster, "SwTxtFrm without master");
632 if (pMaster)
633 pMaster->HideAndShowObjects();
637 /*************************************************************************
638 * SwTxtFrm::FindBrk()
640 * Liefert die erste Trennmoeglichkeit in der aktuellen Zeile zurueck.
641 * Die Methode wird in SwTxtFrm::Format() benutzt, um festzustellen, ob
642 * die Vorgaengerzeile mitformatiert werden muss.
643 * nFound ist <= nEndLine.
644 *************************************************************************/
646 xub_StrLen SwTxtFrm::FindBrk( const XubString &rTxt,
647 const xub_StrLen nStart,
648 const xub_StrLen nEnd ) const
650 // #i104291# - applying patch to avoid overflow.
651 unsigned long nFound = nStart;
652 const xub_StrLen nEndLine = Min( nEnd, rTxt.Len() );
654 // Wir ueberlesen erst alle Blanks am Anfang der Zeile (vgl. Bug 2235).
655 while( nFound <= nEndLine &&
656 ' ' == rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) )
658 nFound++;
661 // Eine knifflige Sache mit den TxtAttr-Dummy-Zeichen (hier "$"):
662 // "Dr.$Meyer" am Anfang der zweiten Zeile. Dahinter ein Blank eingegeben
663 // und das Wort rutscht nicht in die erste Zeile, obwohl es ginge.
664 // Aus diesem Grund nehmen wir das Dummy-Zeichen noch mit.
665 while( nFound <= nEndLine &&
666 ' ' != rTxt.GetChar( static_cast<xub_StrLen>(nFound) ) )
668 nFound++;
671 return nFound <= STRING_LEN
672 ? static_cast<xub_StrLen>(nFound)
673 : STRING_LEN;
676 /*************************************************************************
677 * SwTxtFrm::IsIdxInside()
678 *************************************************************************/
680 sal_Bool SwTxtFrm::IsIdxInside( const xub_StrLen nPos, const xub_StrLen nLen ) const
682 if( GetOfst() > nPos + nLen ) // d.h., der Bereich liegt komplett vor uns.
683 return sal_False;
685 if( !GetFollow() ) // der Bereich liegt nicht komplett vor uns,
686 return sal_True; // nach uns kommt niemand mehr.
688 const xub_StrLen nMax = GetFollow()->GetOfst();
690 // der Bereich liegt nicht komplett hinter uns bzw.
691 // unser Text ist geloescht worden.
692 if( nMax > nPos || nMax > GetTxt().Len() )
693 return sal_True;
695 // changes made in the first line of a follow can modify the master
696 const SwParaPortion* pPara = GetFollow()->GetPara();
697 return pPara && ( nPos <= nMax + pPara->GetLen() );
700 /*************************************************************************
701 * SwTxtFrm::InvalidateRange()
702 *************************************************************************/
703 inline void SwTxtFrm::InvalidateRange(const SwCharRange &aRange, const long nD)
705 if ( IsIdxInside( aRange.Start(), aRange.Len() ) )
706 _InvalidateRange( aRange, nD );
709 /*************************************************************************
710 * SwTxtFrm::_InvalidateRange()
711 *************************************************************************/
713 void SwTxtFrm::_InvalidateRange( const SwCharRange &aRange, const long nD)
715 if ( !HasPara() )
716 { InvalidateSize();
717 return;
720 SetWidow( sal_False );
721 SwParaPortion *pPara = GetPara();
723 sal_Bool bInv = sal_False;
724 if( 0 != nD )
726 //Auf nDelta werden die Differenzen zwischen alter und
727 //neuer Zeilenlaenge aufaddiert, deshalb ist es negativ,
728 //wenn Zeichen eingefuegt wurden, positiv, wenn Zeichen
729 //geloescht wurden.
730 *(pPara->GetDelta()) += nD;
731 bInv = sal_True;
733 SwCharRange &rReformat = *(pPara->GetReformat());
734 if(aRange != rReformat) {
735 if( STRING_LEN == rReformat.Len() )
736 rReformat = aRange;
737 else
738 rReformat += aRange;
739 bInv = sal_True;
741 if(bInv)
743 InvalidateSize();
747 /*************************************************************************
748 * SwTxtFrm::CalcLineSpace()
749 *************************************************************************/
751 void SwTxtFrm::CalcLineSpace()
753 OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
754 "SwTxtFrm::CalcLineSpace with swapped frame!" );
756 if( IsLocked() || !HasPara() )
757 return;
759 SwParaPortion *pPara;
760 if( GetDrawObjs() ||
761 GetTxtNode()->GetSwAttrSet().GetLRSpace().IsAutoFirst() ||
762 ( pPara = GetPara() )->IsFixLineHeight() )
764 Init();
765 return;
768 Size aNewSize( Prt().SSize() );
770 SwTxtFormatInfo aInf( this );
771 SwTxtFormatter aLine( this, &aInf );
772 if( aLine.GetDropLines() )
774 Init();
775 return;
778 aLine.Top();
779 aLine.RecalcRealHeight();
781 aNewSize.Height() = (aLine.Y() - Frm().Top()) + aLine.GetLineHeight();
783 SwTwips nDelta = aNewSize.Height() - Prt().Height();
784 // 4291: Unterlauf bei Flys
785 if( aInf.GetTxtFly()->IsOn() )
787 SwRect aTmpFrm( Frm() );
788 if( nDelta < 0 )
789 aTmpFrm.Height( Prt().Height() );
790 else
791 aTmpFrm.Height( aNewSize.Height() );
792 if( aInf.GetTxtFly()->Relax( aTmpFrm ) )
794 Init();
795 return;
799 if( nDelta )
801 SwTxtFrmBreak aBreak( this );
802 if( GetFollow() || aBreak.IsBreakNow( aLine ) )
804 // Wenn es einen Follow() gibt, oder wenn wir an dieser
805 // Stelle aufbrechen muessen, so wird neu formatiert.
806 Init();
808 else
810 // Alles nimmt seinen gewohnten Gang ...
811 pPara->SetPrepAdjust();
812 pPara->SetPrep();
818 // SET_WRONG( nPos, nCnt, bMove )
820 #define SET_WRONG( nPos, nCnt, bMove ) \
822 lcl_SetWrong( *this, nPos, nCnt, bMove ); \
825 static void lcl_SetWrong( SwTxtFrm& rFrm, xub_StrLen nPos, long nCnt, bool bMove )
827 if ( !rFrm.IsFollow() )
829 SwTxtNode* pTxtNode = rFrm.GetTxtNode();
830 IGrammarContact* pGrammarContact = getGrammarContact( *pTxtNode );
831 SwGrammarMarkUp* pWrongGrammar = pGrammarContact ?
832 pGrammarContact->getGrammarCheck( *pTxtNode, false ) :
833 pTxtNode->GetGrammarCheck();
834 bool bGrammarProxy = pWrongGrammar != pTxtNode->GetGrammarCheck();
835 if( bMove )
837 if( pTxtNode->GetWrong() )
838 pTxtNode->GetWrong()->Move( nPos, nCnt );
839 if( pWrongGrammar )
840 pWrongGrammar->MoveGrammar( nPos, nCnt );
841 if( bGrammarProxy && pTxtNode->GetGrammarCheck() )
842 pTxtNode->GetGrammarCheck()->MoveGrammar( nPos, nCnt );
843 if( pTxtNode->GetSmartTags() )
844 pTxtNode->GetSmartTags()->Move( nPos, nCnt );
846 else
848 xub_StrLen nLen = (xub_StrLen)nCnt;
849 if( pTxtNode->GetWrong() )
850 pTxtNode->GetWrong()->Invalidate( nPos, nLen );
851 if( pWrongGrammar )
852 pWrongGrammar->Invalidate( nPos, nLen );
853 if( pTxtNode->GetSmartTags() )
854 pTxtNode->GetSmartTags()->Invalidate( nPos, nLen );
856 if ( !pTxtNode->GetWrong() && !pTxtNode->IsWrongDirty() )
858 pTxtNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
859 pTxtNode->GetWrong()->SetInvalid( nPos, nPos + (sal_uInt16)( nCnt > 0 ? nCnt : 1 ) );
861 if ( !pTxtNode->GetSmartTags() && !pTxtNode->IsSmartTagDirty() )
863 // SMARTTAGS
864 pTxtNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) );
865 pTxtNode->GetSmartTags()->SetInvalid( nPos, nPos + (sal_uInt16)( nCnt > 0 ? nCnt : 1 ) );
867 pTxtNode->SetWrongDirty( true );
868 pTxtNode->SetGrammarCheckDirty( true );
869 pTxtNode->SetWordCountDirty( true );
870 pTxtNode->SetAutoCompleteWordDirty( true );
871 // SMARTTAGS
872 pTxtNode->SetSmartTagDirty( true );
875 SwRootFrm *pRootFrm = rFrm.getRootFrm();
876 if (pRootFrm)
878 pRootFrm->SetNeedGrammarCheck( sal_True );
881 SwPageFrm *pPage = rFrm.FindPageFrm();
882 if( pPage )
884 pPage->InvalidateSpelling();
885 pPage->InvalidateAutoCompleteWords();
886 pPage->InvalidateWordCount();
887 pPage->InvalidateSmartTags();
892 // SET_SCRIPT_INVAL( nPos )
895 #define SET_SCRIPT_INVAL( nPos )\
896 lcl_SetScriptInval( *this, nPos );
898 static void lcl_SetScriptInval( SwTxtFrm& rFrm, xub_StrLen nPos )
900 if( rFrm.GetPara() )
901 rFrm.GetPara()->GetScriptInfo().SetInvalidity( nPos );
904 static void lcl_ModifyOfst( SwTxtFrm* pFrm, xub_StrLen nPos, xub_StrLen nLen )
906 while( pFrm && pFrm->GetOfst() <= nPos )
907 pFrm = pFrm->GetFollow();
908 while( pFrm )
910 pFrm->ManipOfst( pFrm->GetOfst() + nLen );
911 pFrm = pFrm->GetFollow();
915 //Related: fdo#56031 filter out attribute changes that don't matter for
916 //humans/a11y to stop flooding the destination mortal with useless noise
917 static bool isA11yRelevantAttribute(MSHORT nWhich)
919 return nWhich != RES_CHRATR_RSID;
922 /*************************************************************************
923 * SwTxtFrm::Modify()
924 *************************************************************************/
926 void SwTxtFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
928 const MSHORT nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
930 //Wuensche die FrmAttribute betreffen werden von der Basisklasse
931 //verarbeitet.
932 if( IsInRange( aFrmFmtSetRange, nWhich ) || RES_FMT_CHG == nWhich )
934 SwCntntFrm::Modify( pOld, pNew );
935 if( nWhich == RES_FMT_CHG && getRootFrm()->GetCurrShell() )
937 // Collection hat sich geaendert
938 Prepare( PREP_CLEAR );
939 _InvalidatePrt();
940 SET_WRONG( 0, STRING_LEN, false );
941 SetDerivedR2L( sal_False );
942 CheckDirChange();
943 // OD 09.12.2002 #105576# - Force complete paint due to existing
944 // indents.
945 SetCompletePaint();
946 InvalidateLineNum();
948 return;
951 // Im gelockten Zustand werden keine Bestellungen angenommen.
952 if( IsLocked() )
953 return;
955 // Dies spart Stack, man muss nur aufpassen,
956 // dass sie Variablen gesetzt werden.
957 xub_StrLen nPos, nLen;
958 sal_Bool bSetFldsDirty = sal_False;
959 sal_Bool bRecalcFtnFlag = sal_False;
961 switch( nWhich )
963 case RES_LINENUMBER:
965 InvalidateLineNum();
967 break;
968 case RES_INS_TXT:
970 nPos = ((SwInsTxt*)pNew)->nPos;
971 nLen = ((SwInsTxt*)pNew)->nLen;
972 if( IsIdxInside( nPos, nLen ) )
974 if( !nLen )
976 // 6969: Aktualisierung der NumPortions auch bei leeren Zeilen!
977 if( nPos )
978 InvalidateSize();
979 else
980 Prepare( PREP_CLEAR );
982 else
983 _InvalidateRange( SwCharRange( nPos, nLen ), nLen );
985 SET_WRONG( nPos, nLen, true )
986 SET_SCRIPT_INVAL( nPos )
987 bSetFldsDirty = sal_True;
988 if( HasFollow() )
989 lcl_ModifyOfst( this, nPos, nLen );
991 break;
992 case RES_DEL_CHR:
994 nPos = ((SwDelChr*)pNew)->nPos;
995 InvalidateRange( SwCharRange( nPos, 1 ), -1 );
996 SET_WRONG( nPos, -1, true )
997 SET_SCRIPT_INVAL( nPos )
998 bSetFldsDirty = bRecalcFtnFlag = sal_True;
999 if( HasFollow() )
1000 lcl_ModifyOfst( this, nPos, STRING_LEN );
1002 break;
1003 case RES_DEL_TXT:
1005 nPos = ((SwDelTxt*)pNew)->nStart;
1006 nLen = ((SwDelTxt*)pNew)->nLen;
1007 long m = nLen;
1008 m *= -1;
1009 if( IsIdxInside( nPos, nLen ) )
1011 if( !nLen )
1012 InvalidateSize();
1013 else
1014 InvalidateRange( SwCharRange( nPos, 1 ), m );
1016 SET_WRONG( nPos, m, true )
1017 SET_SCRIPT_INVAL( nPos )
1018 bSetFldsDirty = bRecalcFtnFlag = sal_True;
1019 if( HasFollow() )
1020 lcl_ModifyOfst( this, nPos, nLen );
1022 break;
1023 case RES_UPDATE_ATTR:
1025 nPos = ((SwUpdateAttr*)pNew)->nStart;
1026 nLen = ((SwUpdateAttr*)pNew)->nEnd - nPos;
1027 if( IsIdxInside( nPos, nLen ) )
1029 // Es muss in jedem Fall neu formatiert werden,
1030 // auch wenn der invalidierte Bereich null ist.
1031 // Beispiel: leere Zeile, 14Pt einstellen !
1032 // if( !nLen ) nLen = 1;
1034 // 6680: FtnNummern muessen formatiert werden.
1035 if( !nLen )
1036 nLen = 1;
1038 _InvalidateRange( SwCharRange( nPos, nLen) );
1039 MSHORT nTmp = ((SwUpdateAttr*)pNew)->nWhichAttr;
1041 if( ! nTmp || RES_TXTATR_CHARFMT == nTmp || RES_TXTATR_AUTOFMT == nTmp ||
1042 RES_FMT_CHG == nTmp || RES_ATTRSET_CHG == nTmp )
1044 SET_WRONG( nPos, nPos + nLen, false )
1045 SET_SCRIPT_INVAL( nPos )
1049 // #i104008#
1050 ViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
1051 if ( pViewSh )
1053 pViewSh->InvalidateAccessibleParaAttrs( *this );
1056 break;
1057 case RES_OBJECTDYING:
1058 break;
1060 case RES_PARATR_LINESPACING:
1062 CalcLineSpace();
1063 InvalidateSize();
1064 _InvalidatePrt();
1065 if( IsInSct() && !GetPrev() )
1067 SwSectionFrm *pSect = FindSctFrm();
1068 if( pSect->ContainsAny() == this )
1069 pSect->InvalidatePrt();
1072 // OD 09.01.2004 #i11859# - correction:
1073 // (1) Also invalidate next frame on next page/column.
1074 // (2) Skip empty sections and hidden paragraphs
1075 // Thus, use method <InvalidateNextPrtArea()>
1076 InvalidateNextPrtArea();
1078 SetCompletePaint();
1080 break;
1081 case RES_TXTATR_FIELD:
1083 nPos = *((SwFmtFld*)pNew)->GetTxtFld()->GetStart();
1084 if( IsIdxInside( nPos, 1 ) )
1086 if( pNew == pOld )
1088 // Nur repainten
1089 // opt: invalidate aufs Window ?
1090 InvalidatePage();
1091 SetCompletePaint();
1093 else
1094 _InvalidateRange( SwCharRange( nPos, 1 ) );
1096 bSetFldsDirty = sal_True;
1097 // ST2
1098 if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
1099 SET_WRONG( nPos, nPos + 1, false )
1101 break;
1102 case RES_TXTATR_FTN :
1104 nPos = *((SwFmtFtn*)pNew)->GetTxtFtn()->GetStart();
1105 if( IsInFtn() || IsIdxInside( nPos, 1 ) )
1106 Prepare( PREP_FTN, ((SwFmtFtn*)pNew)->GetTxtFtn() );
1107 break;
1110 case RES_ATTRSET_CHG:
1112 InvalidateLineNum();
1114 SwAttrSet& rNewSet = *((SwAttrSetChg*)pNew)->GetChgSet();
1115 const SfxPoolItem* pItem;
1116 int nClear = 0;
1117 MSHORT nCount = rNewSet.Count();
1119 if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FTN,
1120 sal_False, &pItem ))
1122 nPos = *((SwFmtFtn*)pItem)->GetTxtFtn()->GetStart();
1123 if( IsIdxInside( nPos, 1 ) )
1124 Prepare( PREP_FTN, pNew );
1125 nClear = 0x01;
1126 --nCount;
1129 if( SFX_ITEM_SET == rNewSet.GetItemState( RES_TXTATR_FIELD,
1130 sal_False, &pItem ))
1132 nPos = *((SwFmtFld*)pItem)->GetTxtFld()->GetStart();
1133 if( IsIdxInside( nPos, 1 ) )
1135 const SfxPoolItem& rOldItem = ((SwAttrSetChg*)pOld)->
1136 GetChgSet()->Get( RES_TXTATR_FIELD );
1137 if( pItem == &rOldItem )
1139 // Nur repainten
1140 // opt: invalidate aufs Window ?
1141 InvalidatePage();
1142 SetCompletePaint();
1144 else
1145 _InvalidateRange( SwCharRange( nPos, 1 ) );
1147 nClear |= 0x02;
1148 --nCount;
1150 sal_Bool bLineSpace = SFX_ITEM_SET == rNewSet.GetItemState(
1151 RES_PARATR_LINESPACING, sal_False ),
1152 bRegister = SFX_ITEM_SET == rNewSet.GetItemState(
1153 RES_PARATR_REGISTER, sal_False );
1154 if ( bLineSpace || bRegister )
1156 Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM );
1157 CalcLineSpace();
1158 InvalidateSize();
1159 _InvalidatePrt();
1161 // OD 09.01.2004 #i11859# - correction:
1162 // (1) Also invalidate next frame on next page/column.
1163 // (2) Skip empty sections and hidden paragraphs
1164 // Thus, use method <InvalidateNextPrtArea()>
1165 InvalidateNextPrtArea();
1167 SetCompletePaint();
1168 nClear |= 0x04;
1169 if ( bLineSpace )
1171 --nCount;
1172 if( IsInSct() && !GetPrev() )
1174 SwSectionFrm *pSect = FindSctFrm();
1175 if( pSect->ContainsAny() == this )
1176 pSect->InvalidatePrt();
1179 if ( bRegister )
1180 --nCount;
1182 if ( SFX_ITEM_SET == rNewSet.GetItemState( RES_PARATR_SPLIT,
1183 sal_False ))
1185 if ( GetPrev() )
1186 CheckKeep();
1187 Prepare( PREP_CLEAR );
1188 InvalidateSize();
1189 nClear |= 0x08;
1190 --nCount;
1193 if( SFX_ITEM_SET == rNewSet.GetItemState( RES_BACKGROUND, sal_False)
1194 && !IsFollow() && GetDrawObjs() )
1196 SwSortedObjs *pObjs = GetDrawObjs();
1197 for ( int i = 0; GetDrawObjs() && i < int(pObjs->Count()); ++i )
1199 SwAnchoredObject* pAnchoredObj = (*pObjs)[MSHORT(i)];
1200 if ( pAnchoredObj->ISA(SwFlyFrm) )
1202 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1203 if( !pFly->IsFlyInCntFrm() )
1205 const SvxBrushItem &rBack =
1206 pFly->GetAttrSet()->GetBackground();
1207 // OD 20.08.2002 #99657# #GetTransChg#
1208 // following condition determines, if the fly frame
1209 // "inherites" the background color of text frame.
1210 // This is the case, if fly frame background
1211 // color is "no fill"/"auto fill" and if the fly frame
1212 // has no background graphic.
1213 // Thus, check complete fly frame background
1214 // color and *not* only its transparency value
1215 if ( (rBack.GetColor() == COL_TRANSPARENT) &&
1216 rBack.GetGraphicPos() == GPOS_NONE )
1218 pFly->SetCompletePaint();
1219 pFly->InvalidatePage();
1226 if ( SFX_ITEM_SET ==
1227 rNewSet.GetItemState( RES_TXTATR_CHARFMT, sal_False ) )
1229 SET_WRONG( 0, STRING_LEN, false )
1230 SET_SCRIPT_INVAL( 0 )
1232 else if ( SFX_ITEM_SET ==
1233 rNewSet.GetItemState( RES_CHRATR_LANGUAGE, sal_False ) ||
1234 SFX_ITEM_SET ==
1235 rNewSet.GetItemState( RES_CHRATR_CJK_LANGUAGE, sal_False ) ||
1236 SFX_ITEM_SET ==
1237 rNewSet.GetItemState( RES_CHRATR_CTL_LANGUAGE, sal_False ) )
1238 SET_WRONG( 0, STRING_LEN, false )
1239 else if ( SFX_ITEM_SET ==
1240 rNewSet.GetItemState( RES_CHRATR_FONT, sal_False ) ||
1241 SFX_ITEM_SET ==
1242 rNewSet.GetItemState( RES_CHRATR_CJK_FONT, sal_False ) ||
1243 SFX_ITEM_SET ==
1244 rNewSet.GetItemState( RES_CHRATR_CTL_FONT, sal_False ) )
1245 SET_SCRIPT_INVAL( 0 )
1246 else if ( SFX_ITEM_SET ==
1247 rNewSet.GetItemState( RES_FRAMEDIR, sal_False ) )
1249 SetDerivedR2L( sal_False );
1250 CheckDirChange();
1251 // OD 09.12.2002 #105576# - Force complete paint due to existing
1252 // indents.
1253 SetCompletePaint();
1257 if( nCount )
1259 if( getRootFrm()->GetCurrShell() )
1261 Prepare( PREP_CLEAR );
1262 _InvalidatePrt();
1265 if( nClear )
1267 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld );
1268 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew );
1270 if( 0x01 & nClear )
1272 aOldSet.ClearItem( RES_TXTATR_FTN );
1273 aNewSet.ClearItem( RES_TXTATR_FTN );
1275 if( 0x02 & nClear )
1277 aOldSet.ClearItem( RES_TXTATR_FIELD );
1278 aNewSet.ClearItem( RES_TXTATR_FIELD );
1280 if ( 0x04 & nClear )
1282 if ( bLineSpace )
1284 aOldSet.ClearItem( RES_PARATR_LINESPACING );
1285 aNewSet.ClearItem( RES_PARATR_LINESPACING );
1287 if ( bRegister )
1289 aOldSet.ClearItem( RES_PARATR_REGISTER );
1290 aNewSet.ClearItem( RES_PARATR_REGISTER );
1293 if ( 0x08 & nClear )
1295 aOldSet.ClearItem( RES_PARATR_SPLIT );
1296 aNewSet.ClearItem( RES_PARATR_SPLIT );
1298 SwCntntFrm::Modify( &aOldSet, &aNewSet );
1300 else
1301 SwCntntFrm::Modify( pOld, pNew );
1304 if (isA11yRelevantAttribute(nWhich))
1306 // #i88069#
1307 ViewShell* pViewSh = getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
1308 if ( pViewSh )
1310 pViewSh->InvalidateAccessibleParaAttrs( *this );
1314 break;
1316 // 6870: SwDocPosUpdate auswerten.
1317 case RES_DOCPOS_UPDATE:
1319 if( pOld && pNew )
1321 const SwDocPosUpdate *pDocPos = (const SwDocPosUpdate*)pOld;
1322 if( pDocPos->nDocPos <= aFrm.Top() )
1324 const SwFmtFld *pFld = (const SwFmtFld *)pNew;
1325 InvalidateRange(
1326 SwCharRange( *pFld->GetTxtFld()->GetStart(), 1 ) );
1329 break;
1331 case RES_PARATR_SPLIT:
1332 if ( GetPrev() )
1333 CheckKeep();
1334 Prepare( PREP_CLEAR );
1335 bSetFldsDirty = sal_True;
1336 break;
1337 case RES_FRAMEDIR :
1338 SetDerivedR2L( sal_False );
1339 CheckDirChange();
1340 break;
1341 default:
1343 Prepare( PREP_CLEAR );
1344 _InvalidatePrt();
1345 if ( !nWhich )
1347 //Wird z.B. bei HiddenPara mit 0 gerufen.
1348 SwFrm *pNxt;
1349 if ( 0 != (pNxt = FindNext()) )
1350 pNxt->InvalidatePrt();
1353 } // switch
1355 if( bSetFldsDirty )
1356 GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( true, GetNode(), 1 );
1358 if ( bRecalcFtnFlag )
1359 CalcFtnFlag();
1362 bool SwTxtFrm::GetInfo( SfxPoolItem &rHnt ) const
1364 if ( RES_VIRTPAGENUM_INFO == rHnt.Which() && IsInDocBody() && ! IsFollow() )
1366 SwVirtPageNumInfo &rInfo = (SwVirtPageNumInfo&)rHnt;
1367 const SwPageFrm *pPage = FindPageFrm();
1368 if ( pPage )
1370 if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
1372 //Das sollte er sein (kann allenfalls temporaer anders sein,
1373 // sollte uns das beunruhigen?)
1374 rInfo.SetInfo( pPage, this );
1375 return false;
1377 if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
1378 (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
1380 //Das koennte er sein.
1381 rInfo.SetInfo( pPage, this );
1385 return true;
1388 /*************************************************************************
1389 * SwTxtFrm::PrepWidows()
1390 *************************************************************************/
1392 void SwTxtFrm::PrepWidows( const MSHORT nNeed, sal_Bool bNotify )
1394 OSL_ENSURE(GetFollow() && nNeed, "+SwTxtFrm::Prepare: lost all friends");
1396 SwParaPortion *pPara = GetPara();
1397 if ( !pPara )
1398 return;
1399 pPara->SetPrepWidows( sal_True );
1401 MSHORT nHave = nNeed;
1403 // Wir geben ein paar Zeilen ab und schrumpfen im CalcPreps()
1404 SWAP_IF_NOT_SWAPPED( this )
1406 SwTxtSizeInfo aInf( this );
1407 SwTxtMargin aLine( this, &aInf );
1408 aLine.Bottom();
1409 xub_StrLen nTmpLen = aLine.GetCurr()->GetLen();
1410 while( nHave && aLine.PrevLine() )
1412 if( nTmpLen )
1413 --nHave;
1414 nTmpLen = aLine.GetCurr()->GetLen();
1416 // In dieser Ecke tummelten sich einige Bugs: 7513, 7606.
1417 // Wenn feststeht, dass Zeilen abgegeben werden koennen,
1418 // muss der Master darueber hinaus die Widow-Regel ueberpruefen.
1419 if( !nHave )
1421 sal_Bool bSplit;
1422 if( !IsFollow() ) //Nur ein Master entscheidet ueber Orphans
1424 const WidowsAndOrphans aWidOrp( this );
1425 bSplit = ( aLine.GetLineNr() >= aWidOrp.GetOrphansLines() &&
1426 aLine.GetLineNr() >= aLine.GetDropLines() );
1428 else
1429 bSplit = sal_True;
1431 if( bSplit )
1433 GetFollow()->SetOfst( aLine.GetEnd() );
1434 aLine.TruncLines( sal_True );
1435 if( pPara->IsFollowField() )
1436 GetFollow()->SetFieldFollow( sal_True );
1439 if ( bNotify )
1441 _InvalidateSize();
1442 InvalidatePage();
1445 UNDO_SWAP( this )
1448 /*************************************************************************
1449 * SwTxtFrm::Prepare
1450 *************************************************************************/
1452 static sal_Bool lcl_ErgoVadis( SwTxtFrm* pFrm, xub_StrLen &rPos, const PrepareHint ePrep )
1454 const SwFtnInfo &rFtnInfo = pFrm->GetNode()->GetDoc()->GetFtnInfo();
1455 if( ePrep == PREP_ERGOSUM )
1457 if( !rFtnInfo.aErgoSum.Len() )
1458 return sal_False;;
1459 rPos = pFrm->GetOfst();
1461 else
1463 if( !rFtnInfo.aQuoVadis.Len() )
1464 return sal_False;
1465 if( pFrm->HasFollow() )
1466 rPos = pFrm->GetFollow()->GetOfst();
1467 else
1468 rPos = pFrm->GetTxt().Len();
1469 if( rPos )
1470 --rPos; // unser letztes Zeichen
1472 return sal_True;
1475 void SwTxtFrm::Prepare( const PrepareHint ePrep, const void* pVoid,
1476 sal_Bool bNotify )
1478 SwFrmSwapper aSwapper( this, sal_False );
1480 #if OSL_DEBUG_LEVEL > 1
1481 const SwTwips nDbgY = Frm().Top();
1482 (void)nDbgY;
1483 #endif
1485 if ( IsEmpty() )
1487 switch ( ePrep )
1489 case PREP_BOSS_CHGD:
1490 SetInvalidVert( sal_True ); // Test
1491 case PREP_WIDOWS_ORPHANS:
1492 case PREP_WIDOWS:
1493 case PREP_FTN_GONE : return;
1495 case PREP_POS_CHGD :
1497 // Auch in (spaltigen) Bereichen ist ein InvalidateSize notwendig,
1498 // damit formatiert wird und ggf. das bUndersized gesetzt wird.
1499 if( IsInFly() || IsInSct() )
1501 SwTwips nTmpBottom = GetUpper()->Frm().Top() +
1502 GetUpper()->Prt().Bottom();
1503 if( nTmpBottom < Frm().Bottom() )
1504 break;
1506 // Gibt es ueberhaupt Flys auf der Seite ?
1507 SwTxtFly aTxtFly( this );
1508 if( aTxtFly.IsOn() )
1510 // Ueberlappt irgendein Fly ?
1511 aTxtFly.Relax();
1512 if ( aTxtFly.IsOn() || IsUndersized() )
1513 break;
1515 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue())
1516 break;
1518 GETGRID( FindPageFrm() )
1519 if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1520 break;
1522 // #i28701# - consider anchored objects
1523 if ( GetDrawObjs() )
1524 break;
1526 return;
1528 default:
1529 break;
1533 if( !HasPara() && PREP_MUST_FIT != ePrep )
1535 SetInvalidVert( sal_True ); // Test
1536 OSL_ENSURE( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" );
1537 if ( bNotify )
1538 InvalidateSize();
1539 else
1540 _InvalidateSize();
1541 return;
1544 //Objekt mit Locking aus dem Cache holen.
1545 SwTxtLineAccess aAccess( this );
1546 SwParaPortion *pPara = aAccess.GetPara();
1548 switch( ePrep )
1550 case PREP_MOVEFTN : Frm().Height(0);
1551 Prt().Height(0);
1552 _InvalidatePrt();
1553 _InvalidateSize();
1554 // KEIN break
1555 case PREP_ADJUST_FRM : pPara->SetPrepAdjust( sal_True );
1556 if( IsFtnNumFrm() != pPara->IsFtnNum() ||
1557 IsUndersized() )
1559 InvalidateRange( SwCharRange( 0, 1 ), 1);
1560 if( GetOfst() && !IsFollow() )
1561 _SetOfst( 0 );
1563 break;
1564 case PREP_MUST_FIT : pPara->SetPrepMustFit( sal_True );
1565 /* no break here */
1566 case PREP_WIDOWS_ORPHANS : pPara->SetPrepAdjust( sal_True );
1567 break;
1569 case PREP_WIDOWS :
1570 // MustFit ist staerker als alles anderes
1571 if( pPara->IsPrepMustFit() )
1572 return;
1573 // Siehe Kommentar in WidowsAndOrphans::FindOrphans und CalcPreps()
1574 PrepWidows( *(const MSHORT *)pVoid, bNotify );
1575 break;
1577 case PREP_FTN :
1579 SwTxtFtn *pFtn = (SwTxtFtn *)pVoid;
1580 if( IsInFtn() )
1582 // Bin ich der erste TxtFrm einer Fussnote ?
1583 if( !GetPrev() )
1584 // Wir sind also ein TxtFrm der Fussnote, die
1585 // die Fussnotenzahl zur Anzeige bringen muss.
1586 // Oder den ErgoSum-Text...
1587 InvalidateRange( SwCharRange( 0, 1 ), 1);
1589 if( !GetNext() )
1591 // Wir sind der letzte Ftn, jetzt muessten die
1592 // QuoVadis-Texte geupdated werden.
1593 const SwFtnInfo &rFtnInfo = GetNode()->GetDoc()->GetFtnInfo();
1594 if( !pPara->UpdateQuoVadis( rFtnInfo.aQuoVadis ) )
1596 xub_StrLen nPos = pPara->GetParLen();
1597 if( nPos )
1598 --nPos;
1599 InvalidateRange( SwCharRange( nPos, 1 ), 1);
1603 else
1605 // Wir sind also der TxtFrm _mit_ der Fussnote
1606 const xub_StrLen nPos = *pFtn->GetStart();
1607 InvalidateRange( SwCharRange( nPos, 1 ), 1);
1609 break;
1611 case PREP_BOSS_CHGD :
1613 // Test
1615 SetInvalidVert( sal_False );
1616 sal_Bool bOld = IsVertical();
1617 SetInvalidVert( sal_True );
1618 if( bOld != IsVertical() )
1619 InvalidateRange( SwCharRange( GetOfst(), STRING_LEN ) );
1622 if( HasFollow() )
1624 xub_StrLen nNxtOfst = GetFollow()->GetOfst();
1625 if( nNxtOfst )
1626 --nNxtOfst;
1627 InvalidateRange( SwCharRange( nNxtOfst, 1 ), 1);
1629 if( IsInFtn() )
1631 xub_StrLen nPos;
1632 if( lcl_ErgoVadis( this, nPos, PREP_QUOVADIS ) )
1633 InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1634 if( lcl_ErgoVadis( this, nPos, PREP_ERGOSUM ) )
1635 InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1637 // 4739: Wenn wir ein Seitennummernfeld besitzen, muessen wir
1638 // die Stellen invalidieren.
1639 SwpHints *pHints = GetTxtNode()->GetpSwpHints();
1640 if( pHints )
1642 const sal_uInt16 nSize = pHints->Count();
1643 const xub_StrLen nEnd = GetFollow() ?
1644 GetFollow()->GetOfst() : STRING_LEN;
1645 for ( sal_uInt16 i = 0; i < nSize; ++i )
1647 const SwTxtAttr *pHt = (*pHints)[i];
1648 const xub_StrLen nStart = *pHt->GetStart();
1649 if( nStart >= GetOfst() )
1651 if( nStart >= nEnd )
1652 i = nSize; // fuehrt das Ende herbei
1653 else
1655 // 4029: wenn wir zurueckfliessen und eine Ftn besitzen, so
1656 // fliesst die Ftn in jedem Fall auch mit. Damit sie nicht im
1657 // Weg steht, schicken wir uns ein ADJUST_FRM.
1658 // pVoid != 0 bedeutet MoveBwd()
1659 const MSHORT nWhich = pHt->Which();
1660 if( RES_TXTATR_FIELD == nWhich ||
1661 (HasFtn() && pVoid && RES_TXTATR_FTN == nWhich))
1662 InvalidateRange( SwCharRange( nStart, 1 ), 1 );
1667 // A new boss, a new chance for growing
1668 if( IsUndersized() )
1670 _InvalidateSize();
1671 InvalidateRange( SwCharRange( GetOfst(), 1 ), 1);
1673 break;
1676 case PREP_POS_CHGD :
1678 if ( GetValidPrtAreaFlag() )
1680 GETGRID( FindPageFrm() )
1681 if ( pGrid && GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1682 InvalidatePrt();
1685 // Falls wir mit niemandem ueberlappen:
1686 // Ueberlappte irgendein Fly _vor_ der Positionsaenderung ?
1687 sal_Bool bFormat = pPara->HasFly();
1688 if( !bFormat )
1690 if( IsInFly() )
1692 SwTwips nTmpBottom = GetUpper()->Frm().Top() +
1693 GetUpper()->Prt().Bottom();
1694 if( nTmpBottom < Frm().Bottom() )
1695 bFormat = sal_True;
1697 if( !bFormat )
1699 if ( GetDrawObjs() )
1701 const sal_uInt32 nCnt = GetDrawObjs()->Count();
1702 for ( MSHORT i = 0; i < nCnt; ++i )
1704 SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
1705 // #i28701# - consider all
1706 // to-character anchored objects
1707 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId()
1708 == FLY_AT_CHAR )
1710 bFormat = sal_True;
1711 break;
1715 if( !bFormat )
1717 // Gibt es ueberhaupt Flys auf der Seite ?
1718 SwTxtFly aTxtFly( this );
1719 if( aTxtFly.IsOn() )
1721 // Ueberlappt irgendein Fly ?
1722 aTxtFly.Relax();
1723 bFormat = aTxtFly.IsOn() || IsUndersized();
1729 if( bFormat )
1731 if( !IsLocked() )
1733 if( pPara->GetRepaint()->HasArea() )
1734 SetCompletePaint();
1735 Init();
1736 pPara = 0;
1737 _InvalidateSize();
1740 else
1742 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1743 Prepare( PREP_REGISTER, 0, bNotify );
1744 // Durch Positionsverschiebungen mit Ftns muessen die
1745 // Frames neu adjustiert werden.
1746 else if( HasFtn() )
1748 Prepare( PREP_ADJUST_FRM, 0, bNotify );
1749 _InvalidateSize();
1751 else
1752 return; // damit kein SetPrep() erfolgt.
1754 break;
1756 case PREP_REGISTER:
1757 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1759 pPara->SetPrepAdjust( sal_True );
1760 CalcLineSpace();
1761 InvalidateSize();
1762 _InvalidatePrt();
1763 SwFrm* pNxt;
1764 if ( 0 != ( pNxt = GetIndNext() ) )
1766 pNxt->_InvalidatePrt();
1767 if ( pNxt->IsLayoutFrm() )
1768 pNxt->InvalidatePage();
1770 SetCompletePaint();
1772 break;
1773 case PREP_FTN_GONE :
1775 // Wenn ein Follow uns ruft, weil eine Fussnote geloescht wird, muss unsere
1776 // letzte Zeile formatiert werden, damit ggf. die erste Zeile des Follows
1777 // hochrutschen kann, die extra auf die naechste Seite gerutscht war, um mit
1778 // der Fussnote zusammen zu sein, insbesondere bei spaltigen Bereichen.
1779 OSL_ENSURE( GetFollow(), "PREP_FTN_GONE darf nur vom Follow gerufen werden" );
1780 xub_StrLen nPos = GetFollow()->GetOfst();
1781 if( IsFollow() && GetOfst() == nPos ) // falls wir gar keine Textmasse besitzen,
1782 FindMaster()->Prepare( PREP_FTN_GONE ); // rufen wir das Prepare unseres Masters
1783 if( nPos )
1784 --nPos; // das Zeichen vor unserem Follow
1785 InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1786 return;
1788 case PREP_ERGOSUM:
1789 case PREP_QUOVADIS:
1791 xub_StrLen nPos;
1792 if( lcl_ErgoVadis( this, nPos, ePrep ) )
1793 InvalidateRange( SwCharRange( nPos, 1 ), 0 );
1795 break;
1796 case PREP_FLY_ATTR_CHG:
1798 if( pVoid )
1800 xub_StrLen nWhere = CalcFlyPos( (SwFrmFmt*)pVoid );
1801 OSL_ENSURE( STRING_LEN != nWhere, "Prepare: Why me?" );
1802 InvalidateRange( SwCharRange( nWhere, 1 ) );
1803 return;
1805 // else ... Laufe in den Default-Switch
1807 case PREP_CLEAR:
1808 default:
1810 if( IsLocked() )
1812 if( PREP_FLY_ARRIVE == ePrep || PREP_FLY_LEAVE == ePrep )
1814 xub_StrLen nLen = ( GetFollow() ? GetFollow()->GetOfst() :
1815 STRING_LEN ) - GetOfst();
1816 InvalidateRange( SwCharRange( GetOfst(), nLen ), 0 );
1819 else
1821 if( pPara->GetRepaint()->HasArea() )
1822 SetCompletePaint();
1823 Init();
1824 pPara = 0;
1825 if( GetOfst() && !IsFollow() )
1826 _SetOfst( 0 );
1827 if ( bNotify )
1828 InvalidateSize();
1829 else
1830 _InvalidateSize();
1832 return; // damit kein SetPrep() erfolgt.
1835 if( pPara )
1836 pPara->SetPrep( sal_True );
1839 /* --------------------------------------------------
1840 * Kleine Hilfsklasse mit folgender Funktion:
1841 * Sie soll eine Probeformatierung vorbereiten.
1842 * Der Frame wird in Groesse und Position angepasst, sein SwParaPortion zur Seite
1843 * gestellt und eine neue erzeugt, dazu wird formatiert mit gesetztem bTestFormat.
1844 * Im Dtor wird der TxtFrm wieder in seinen alten Zustand zurueckversetzt.
1846 * --------------------------------------------------*/
1848 class SwTestFormat
1850 SwTxtFrm *pFrm;
1851 SwParaPortion *pOldPara;
1852 SwRect aOldFrm, aOldPrt;
1853 public:
1854 SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPrv, SwTwips nMaxHeight );
1855 ~SwTestFormat();
1858 SwTestFormat::SwTestFormat( SwTxtFrm* pTxtFrm, const SwFrm* pPre, SwTwips nMaxHeight )
1859 : pFrm( pTxtFrm )
1861 aOldFrm = pFrm->Frm();
1862 aOldPrt = pFrm->Prt();
1864 SWRECTFN( pFrm )
1865 SwTwips nLower = (pFrm->*fnRect->fnGetBottomMargin)();
1867 pFrm->Frm() = pFrm->GetUpper()->Prt();
1868 pFrm->Frm() += pFrm->GetUpper()->Frm().Pos();
1870 (pFrm->Frm().*fnRect->fnSetHeight)( nMaxHeight );
1871 if( pFrm->GetPrev() )
1872 (pFrm->Frm().*fnRect->fnSetPosY)(
1873 (pFrm->GetPrev()->Frm().*fnRect->fnGetBottom)() -
1874 ( bVert ? nMaxHeight + 1 : 0 ) );
1876 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pFrm );
1877 const SwBorderAttrs &rAttrs = *aAccess.Get();
1878 (pFrm->Prt().*fnRect->fnSetPosX)( rAttrs.CalcLeft( pFrm ) );
1880 if( pPre )
1882 SwTwips nUpper = pFrm->CalcUpperSpace( &rAttrs, pPre );
1883 (pFrm->Prt().*fnRect->fnSetPosY)( nUpper );
1885 (pFrm->Prt().*fnRect->fnSetHeight)(
1886 Max( 0L , (pFrm->Frm().*fnRect->fnGetHeight)() -
1887 (pFrm->Prt().*fnRect->fnGetTop)() - nLower ) );
1888 (pFrm->Prt().*fnRect->fnSetWidth)(
1889 (pFrm->Frm().*fnRect->fnGetWidth)() -
1890 ( rAttrs.CalcLeft( pFrm ) + rAttrs.CalcRight( pFrm ) ) );
1891 pOldPara = pFrm->HasPara() ? pFrm->GetPara() : NULL;
1892 pFrm->SetPara( new SwParaPortion(), sal_False );
1894 OSL_ENSURE( ! pFrm->IsSwapped(), "A frame is swapped before _Format" );
1896 if ( pFrm->IsVertical() )
1897 pFrm->SwapWidthAndHeight();
1899 SwTxtFormatInfo aInf( pFrm, sal_False, sal_True, sal_True );
1900 SwTxtFormatter aLine( pFrm, &aInf );
1902 pFrm->_Format( aLine, aInf );
1904 if ( pFrm->IsVertical() )
1905 pFrm->SwapWidthAndHeight();
1907 OSL_ENSURE( ! pFrm->IsSwapped(), "A frame is swapped after _Format" );
1910 SwTestFormat::~SwTestFormat()
1912 pFrm->Frm() = aOldFrm;
1913 pFrm->Prt() = aOldPrt;
1914 pFrm->SetPara( pOldPara );
1917 sal_Bool SwTxtFrm::TestFormat( const SwFrm* pPrv, SwTwips &rMaxHeight, sal_Bool &bSplit )
1919 PROTOCOL_ENTER( this, PROT_TESTFORMAT, 0, 0 )
1921 if( IsLocked() && GetUpper()->Prt().Width() <= 0 )
1922 return sal_False;
1924 SwTestFormat aSave( this, pPrv, rMaxHeight );
1926 return SwTxtFrm::WouldFit( rMaxHeight, bSplit, sal_True );
1930 /*************************************************************************
1931 * SwTxtFrm::WouldFit()
1932 *************************************************************************/
1934 /* SwTxtFrm::WouldFit()
1935 * sal_True: wenn ich aufspalten kann.
1936 * Es soll und braucht nicht neu formatiert werden.
1937 * Wir gehen davon aus, dass bereits formatiert wurde und dass
1938 * die Formatierungsdaten noch aktuell sind.
1939 * Wir gehen davon aus, dass die Framebreiten des evtl. Masters und
1940 * Follows gleich sind. Deswegen wird kein FindBreak() mit FindOrphans()
1941 * gerufen.
1942 * Die benoetigte Hoehe wird von nMaxHeight abgezogen!
1945 sal_Bool SwTxtFrm::WouldFit( SwTwips &rMaxHeight, sal_Bool &bSplit, sal_Bool bTst )
1947 OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
1948 "SwTxtFrm::WouldFit with swapped frame" );
1949 SWRECTFN( this );
1951 if( IsLocked() )
1952 return sal_False;
1954 //Kann gut sein, dass mir der IdleCollector mir die gecachten
1955 //Informationen entzogen hat.
1956 if( !IsEmpty() )
1957 GetFormatted();
1959 // OD 2004-05-24 #i27801# - correction: 'short cut' for empty paragraph
1960 // can *not* be applied, if test format is in progress. The test format doesn't
1961 // adjust the frame and the printing area - see method <SwTxtFrm::_Format(..)>,
1962 // which is called in <SwTxtFrm::TestFormat(..)>
1963 if ( IsEmpty() && !bTst )
1965 bSplit = sal_False;
1966 SwTwips nHeight = bVert ? Prt().SSize().Width() : Prt().SSize().Height();
1967 if( rMaxHeight < nHeight )
1968 return sal_False;
1969 else
1971 rMaxHeight -= nHeight;
1972 return sal_True;
1976 // In sehr unguenstigen Faellen kann GetPara immer noch 0 sein.
1977 // Dann returnen wir sal_True, um auf der neuen Seite noch einmal
1978 // anformatiert zu werden.
1979 OSL_ENSURE( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" );
1980 if( !HasPara() || ( !(Frm().*fnRect->fnGetHeight)() && IsHiddenNow() ) )
1981 return sal_True;
1983 // Da das Orphan-Flag nur sehr fluechtig existiert, wird als zweite
1984 // Bedingung ueberprueft, ob die Rahmengroesse durch CalcPreps
1985 // auf riesengross gesetzt wird, um ein MoveFwd zu erzwingen.
1986 if( IsWidow() || ( bVert ?
1987 ( 0 == Frm().Left() ) :
1988 ( LONG_MAX - 20000 < Frm().Bottom() ) ) )
1990 SetWidow(sal_False);
1991 if ( GetFollow() )
1993 // Wenn wir hier durch eine Widow-Anforderung unseres Follows gelandet
1994 // sind, wird ueberprueft, ob es ueberhaupt einen Follow mit einer
1995 // echten Hoehe gibt, andernfalls (z.B. in neu angelegten SctFrms)
1996 // ignorieren wir das IsWidow() und pruefen doch noch, ob wir
1997 // genung Platz finden.
1998 if( ( ( ! bVert && LONG_MAX - 20000 >= Frm().Bottom() ) ||
1999 ( bVert && 0 < Frm().Left() ) ) &&
2000 ( GetFollow()->IsVertical() ?
2001 !GetFollow()->Frm().Width() :
2002 !GetFollow()->Frm().Height() ) )
2004 SwTxtFrm* pFoll = GetFollow()->GetFollow();
2005 while( pFoll &&
2006 ( pFoll->IsVertical() ?
2007 !pFoll->Frm().Width() :
2008 !pFoll->Frm().Height() ) )
2009 pFoll = pFoll->GetFollow();
2010 if( pFoll )
2011 return sal_False;
2013 else
2014 return sal_False;
2018 SWAP_IF_NOT_SWAPPED( this );
2020 SwTxtSizeInfo aInf( this );
2021 SwTxtMargin aLine( this, &aInf );
2023 WidowsAndOrphans aFrmBreak( this, rMaxHeight, bSplit );
2025 sal_Bool bRet = sal_True;
2027 aLine.Bottom();
2028 // Ist Aufspalten ueberhaupt notwendig?
2029 if ( 0 != ( bSplit = !aFrmBreak.IsInside( aLine ) ) )
2030 bRet = !aFrmBreak.IsKeepAlways() && aFrmBreak.WouldFit( aLine, rMaxHeight, bTst );
2031 else
2033 //Wir brauchen die Gesamthoehe inklusive der aktuellen Zeile
2034 aLine.Top();
2037 rMaxHeight -= aLine.GetLineHeight();
2038 } while ( aLine.Next() );
2041 UNDO_SWAP( this )
2043 return bRet;
2047 /*************************************************************************
2048 * SwTxtFrm::GetParHeight()
2049 *************************************************************************/
2051 KSHORT SwTxtFrm::GetParHeight() const
2053 OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
2054 "SwTxtFrm::GetParHeight with swapped frame" );
2056 if( !HasPara() )
2057 { // Fuer nichtleere Absaetze ist dies ein Sonderfall, da koennen wir
2058 // bei UnderSized ruhig nur 1 Twip mehr anfordern.
2059 KSHORT nRet = (KSHORT)Prt().SSize().Height();
2060 if( IsUndersized() )
2062 if( IsEmpty() || GetTxt().Len() == 0 )
2063 nRet = (KSHORT)EmptyHeight();
2064 else
2065 ++nRet;
2067 return nRet;
2070 // FME, OD 08.01.2004 #i11859# - refactoring and improve code
2071 const SwLineLayout* pLineLayout = GetPara();
2072 KSHORT nHeight = pLineLayout->GetRealHeight();
2073 if( GetOfst() && !IsFollow() ) // Ist dieser Absatz gescrollt? Dann ist unsere
2074 nHeight *= 2; // bisherige Hoehe mind. eine Zeilenhoehe zu gering
2075 // OD 2004-03-04 #115793#
2076 while ( pLineLayout && pLineLayout->GetNext() )
2078 pLineLayout = pLineLayout->GetNext();
2079 nHeight = nHeight + pLineLayout->GetRealHeight();
2082 return nHeight;
2086 /*************************************************************************
2087 * SwTxtFrm::GetFormatted()
2088 *************************************************************************/
2090 // returnt this _immer_ im formatierten Zustand!
2091 SwTxtFrm* SwTxtFrm::GetFormatted( bool bForceQuickFormat )
2093 SWAP_IF_SWAPPED( this )
2095 //Kann gut sein, dass mir der IdleCollector mir die gecachten
2096 //Informationen entzogen hat. Calc() ruft unser Format.
2097 //Nicht bei leeren Absaetzen!
2098 if( !HasPara() && !(IsValid() && IsEmpty()) )
2100 // Calc() muss gerufen werden, weil unsere Frameposition
2101 // nicht stimmen muss.
2102 const sal_Bool bFormat = GetValidSizeFlag();
2103 Calc();
2104 // Es kann durchaus sein, dass Calc() das Format()
2105 // nicht anstiess (weil wir einst vom Idle-Zerstoerer
2106 // aufgefordert wurden unsere Formatinformationen wegzuschmeissen).
2107 // 6995: Optimierung mit FormatQuick()
2108 if( bFormat && !FormatQuick( bForceQuickFormat ) )
2109 Format();
2112 UNDO_SWAP( this )
2114 return this;
2117 /*************************************************************************
2118 * SwTxtFrm::CalcFitToContent()
2119 *************************************************************************/
2121 SwTwips SwTxtFrm::CalcFitToContent()
2123 // #i31490#
2124 // If we are currently locked, we better return with a
2125 // fairly reasonable value:
2126 if ( IsLocked() )
2127 return Prt().Width();
2129 SwParaPortion* pOldPara = GetPara();
2130 SwParaPortion *pDummy = new SwParaPortion();
2131 SetPara( pDummy, false );
2132 const SwPageFrm* pPage = FindPageFrm();
2134 const Point aOldFrmPos = Frm().Pos();
2135 const SwTwips nOldFrmWidth = Frm().Width();
2136 const SwTwips nOldPrtWidth = Prt().Width();
2137 const SwTwips nPageWidth = GetUpper()->IsVertical() ?
2138 pPage->Prt().Height() :
2139 pPage->Prt().Width();
2141 Frm().Width( nPageWidth );
2142 Prt().Width( nPageWidth );
2144 // #i25422# objects anchored as character in RTL
2145 if ( IsRightToLeft() )
2146 Frm().Pos().X() += nOldFrmWidth - nPageWidth;
2148 // #i31490#
2149 SwTxtFrmLocker aLock( this );
2151 SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True );
2152 aInf.SetIgnoreFly( sal_True );
2153 SwTxtFormatter aLine( this, &aInf );
2154 SwHookOut aHook( aInf );
2156 // #i54031# - assure mininum of MINLAY twips.
2157 const SwTwips nMax = Max( (SwTwips)MINLAY,
2158 aLine._CalcFitToContent() + 1 );
2160 Frm().Width( nOldFrmWidth );
2161 Prt().Width( nOldPrtWidth );
2163 // #i25422# objects anchored as character in RTL
2164 if ( IsRightToLeft() )
2165 Frm().Pos() = aOldFrmPos;
2168 SetPara( pOldPara );
2170 return nMax;
2173 /** simulate format for a list item paragraph, whose list level attributes
2174 are in LABEL_ALIGNMENT mode, in order to determine additional first
2175 line offset for the real text formatting due to the value of label
2176 adjustment attribute of the list level.
2178 void SwTxtFrm::CalcAdditionalFirstLineOffset()
2180 if ( IsLocked() )
2181 return;
2183 // reset additional first line offset
2184 mnAdditionalFirstLineOffset = 0;
2186 const SwTxtNode* pTxtNode( GetTxtNode() );
2187 if ( pTxtNode && pTxtNode->IsNumbered() && pTxtNode->IsCountedInList() &&
2188 pTxtNode->GetNumRule() )
2190 const SwNumFmt& rNumFmt =
2191 pTxtNode->GetNumRule()->Get( static_cast<sal_uInt16>(pTxtNode->GetActualListLevel()) );
2192 if ( rNumFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
2194 // keep current paragraph portion and apply dummy paragraph portion
2195 SwParaPortion* pOldPara = GetPara();
2196 SwParaPortion *pDummy = new SwParaPortion();
2197 SetPara( pDummy, false );
2199 // lock paragraph
2200 SwTxtFrmLocker aLock( this );
2202 // simulate text formatting
2203 SwTxtFormatInfo aInf( this, sal_False, sal_True, sal_True );
2204 aInf.SetIgnoreFly( sal_True );
2205 SwTxtFormatter aLine( this, &aInf );
2206 SwHookOut aHook( aInf );
2207 aLine._CalcFitToContent();
2209 // determine additional first line offset
2210 const SwLinePortion* pFirstPortion = aLine.GetCurr()->GetFirstPortion();
2211 if ( pFirstPortion->InNumberGrp() && !pFirstPortion->IsFtnNumPortion() )
2213 SwTwips nNumberPortionWidth( pFirstPortion->Width() );
2215 const SwLinePortion* pPortion = pFirstPortion->GetPortion();
2216 while ( pPortion &&
2217 pPortion->InNumberGrp() && !pPortion->IsFtnNumPortion())
2219 nNumberPortionWidth += pPortion->Width();
2220 pPortion = pPortion->GetPortion();
2223 if ( ( IsRightToLeft() &&
2224 rNumFmt.GetNumAdjust() == SVX_ADJUST_LEFT ) ||
2225 ( !IsRightToLeft() &&
2226 rNumFmt.GetNumAdjust() == SVX_ADJUST_RIGHT ) )
2228 mnAdditionalFirstLineOffset = -nNumberPortionWidth;
2230 else if ( rNumFmt.GetNumAdjust() == SVX_ADJUST_CENTER )
2232 mnAdditionalFirstLineOffset = -(nNumberPortionWidth/2);
2236 // restore paragraph portion
2237 SetPara( pOldPara );
2242 /** determine height of last line for the calculation of the proportional line
2243 spacing
2245 OD 08.01.2004 #i11859#
2246 OD 2004-03-17 #i11860# - method <GetHeightOfLastLineForPropLineSpacing()>
2247 replace by method <_CalcHeightOfLastLine()>. Height of last line will be
2248 stored in new member <mnHeightOfLastLine> and can be accessed via method
2249 <GetHeightOfLastLine()>
2250 OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
2251 in order to force the usage of the former algorithm to determine the
2252 height of the last line, which uses the font.
2254 void SwTxtFrm::_CalcHeightOfLastLine( const bool _bUseFont )
2256 // #i71281#
2257 // invalidate printing area, if height of last line changes
2258 const SwTwips mnOldHeightOfLastLine( mnHeightOfLastLine );
2259 // determine output device
2260 ViewShell* pVsh = getRootFrm()->GetCurrShell();
2261 OSL_ENSURE( pVsh, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no ViewShell" );
2262 // #i78921# - make code robust, according to provided patch
2263 // There could be no <ViewShell> instance in the case of loading a binary
2264 // StarOffice file format containing an embedded Writer document.
2265 if ( !pVsh )
2267 return;
2269 OutputDevice* pOut = pVsh->GetOut();
2270 const IDocumentSettingAccess* pIDSA = GetTxtNode()->getIDocumentSettingAccess();
2271 if ( !pVsh->GetViewOptions()->getBrowseMode() ||
2272 pVsh->GetViewOptions()->IsPrtFormat() )
2274 pOut = GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
2276 OSL_ENSURE( pOut, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" );
2277 // #i78921# - make code robust, according to provided patch
2278 if ( !pOut )
2280 return;
2283 // determine height of last line
2285 if ( _bUseFont || pIDSA->get(IDocumentSettingAccess::OLD_LINE_SPACING ) )
2287 // former determination of last line height for proprotional line
2288 // spacing - take height of font set at the paragraph
2289 SwFont aFont( GetAttrSet(), pIDSA );
2291 // Wir muessen dafuer sorgen, dass am OutputDevice der Font
2292 // korrekt restauriert wird, sonst droht ein Last!=Owner.
2293 if ( pLastFont )
2295 SwFntObj *pOldFont = pLastFont;
2296 pLastFont = NULL;
2297 aFont.SetFntChg( sal_True );
2298 aFont.ChgPhysFnt( pVsh, *pOut );
2299 mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
2300 pLastFont->Unlock();
2301 pLastFont = pOldFont;
2302 pLastFont->SetDevFont( pVsh, *pOut );
2304 else
2306 Font aOldFont = pOut->GetFont();
2307 aFont.SetFntChg( sal_True );
2308 aFont.ChgPhysFnt( pVsh, *pOut );
2309 mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
2310 pLastFont->Unlock();
2311 pLastFont = NULL;
2312 pOut->SetFont( aOldFont );
2315 else
2317 // new determination of last line height - take actually height of last line
2318 // #i89000#
2319 // assure same results, if paragraph is undersized
2320 if ( IsUndersized() )
2322 mnHeightOfLastLine = 0;
2324 else
2326 bool bCalcHeightOfLastLine = true;
2327 if ( ( !HasPara() && IsEmpty( ) ) || GetTxt().Len( ) == 0 )
2329 mnHeightOfLastLine = EmptyHeight();
2330 bCalcHeightOfLastLine = false;
2333 if ( bCalcHeightOfLastLine )
2335 OSL_ENSURE( HasPara(),
2336 "<SwTxtFrm::_CalcHeightOfLastLine()> - missing paragraph portions." );
2337 const SwLineLayout* pLineLayout = GetPara();
2338 while ( pLineLayout && pLineLayout->GetNext() )
2340 // iteration to last line
2341 pLineLayout = pLineLayout->GetNext();
2343 if ( pLineLayout )
2345 SwTwips nAscent, nDescent, nDummy1, nDummy2;
2346 // #i47162# - suppress consideration of
2347 // fly content portions and the line portion.
2348 pLineLayout->MaxAscentDescent( nAscent, nDescent,
2349 nDummy1, nDummy2,
2350 0, true );
2351 // #i71281#
2352 // Suppress wrong invalidation of printing area, if method is
2353 // called recursive.
2354 // Thus, member <mnHeightOfLastLine> is only set directly, if
2355 // no recursive call is needed.
2356 const SwTwips nNewHeightOfLastLine = nAscent + nDescent;
2357 // #i47162# - if last line only contains
2358 // fly content portions, <mnHeightOfLastLine> is zero.
2359 // In this case determine height of last line by the font
2360 if ( nNewHeightOfLastLine == 0 )
2362 _CalcHeightOfLastLine( true );
2364 else
2366 mnHeightOfLastLine = nNewHeightOfLastLine;
2372 // #i71281#
2373 // invalidate printing area, if height of last line changes
2374 if ( mnHeightOfLastLine != mnOldHeightOfLastLine )
2376 InvalidatePrt();
2380 /*************************************************************************
2381 * SwTxtFrm::GetLineSpace()
2382 *************************************************************************/
2383 // OD 07.01.2004 #i11859# - change return data type
2384 // add default parameter <_bNoPropLineSpacing> to control, if the
2385 // value of a proportional line spacing is returned or not
2386 // OD 07.01.2004 - trying to describe purpose of method:
2387 // Method returns the value of the inter line spacing for a text frame.
2388 // Such a value exists for proportional line spacings ("1,5 Lines",
2389 // "Double", "Proportional" and for leading line spacing ("Leading").
2390 // By parameter <_bNoPropLineSpace> (default value false) it can be
2391 // controlled, if the value of a proportional line spacing is returned.
2392 long SwTxtFrm::GetLineSpace( const bool _bNoPropLineSpace ) const
2394 long nRet = 0;
2396 const SwAttrSet* pSet = GetAttrSet();
2397 const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing();
2399 switch( rSpace.GetInterLineSpaceRule() )
2401 case SVX_INTER_LINE_SPACE_PROP:
2403 // OD 07.01.2004 #i11859#
2404 if ( _bNoPropLineSpace )
2406 break;
2409 // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()>
2410 nRet = GetHeightOfLastLine();
2412 long nTmp = nRet;
2413 nTmp *= rSpace.GetPropLineSpace();
2414 nTmp /= 100;
2415 nTmp -= nRet;
2416 if ( nTmp > 0 )
2417 nRet = nTmp;
2418 else
2419 nRet = 0;
2421 break;
2422 case SVX_INTER_LINE_SPACE_FIX:
2424 if ( rSpace.GetInterLineSpace() > 0 )
2425 nRet = rSpace.GetInterLineSpace();
2427 break;
2428 default:
2429 break;
2431 return nRet;
2434 /*************************************************************************
2435 * SwTxtFrm::FirstLineHeight()
2436 *************************************************************************/
2438 KSHORT SwTxtFrm::FirstLineHeight() const
2440 if ( !HasPara() )
2442 if( IsEmpty() && IsValid() )
2443 return IsVertical() ? (KSHORT)Prt().Width() : (KSHORT)Prt().Height();
2444 return KSHRT_MAX;
2446 const SwParaPortion *pPara = GetPara();
2447 if ( !pPara )
2448 return KSHRT_MAX;
2450 return pPara->Height();
2453 MSHORT SwTxtFrm::GetLineCount( xub_StrLen nPos )
2455 MSHORT nRet = 0;
2456 SwTxtFrm *pFrm = this;
2459 pFrm->GetFormatted();
2460 if( !pFrm->HasPara() )
2461 break;
2462 SwTxtSizeInfo aInf( pFrm );
2463 SwTxtMargin aLine( pFrm, &aInf );
2464 if( STRING_LEN == nPos )
2465 aLine.Bottom();
2466 else
2467 aLine.CharToLine( nPos );
2468 nRet = nRet + aLine.GetLineNr();
2469 pFrm = pFrm->GetFollow();
2470 } while ( pFrm && pFrm->GetOfst() <= nPos );
2471 return nRet;
2474 void SwTxtFrm::ChgThisLines()
2476 //not necassary to format here (GerFormatted etc.), because we have to come from there!
2478 sal_uLong nNew = 0;
2479 const SwLineNumberInfo &rInf = GetNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo();
2480 if ( GetTxt().Len() && HasPara() )
2482 SwTxtSizeInfo aInf( this );
2483 SwTxtMargin aLine( this, &aInf );
2484 if ( rInf.IsCountBlankLines() )
2486 aLine.Bottom();
2487 nNew = (sal_uLong)aLine.GetLineNr();
2489 else
2493 if( aLine.GetCurr()->HasCntnt() )
2494 ++nNew;
2495 } while ( aLine.NextLine() );
2498 else if ( rInf.IsCountBlankLines() )
2499 nNew = 1;
2501 if ( nNew != nThisLines )
2503 if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() )
2505 nAllLines -= nThisLines;
2506 nThisLines = nNew;
2507 nAllLines += nThisLines;
2508 SwFrm *pNxt = GetNextCntntFrm();
2509 while( pNxt && pNxt->IsInTab() )
2511 if( 0 != (pNxt = pNxt->FindTabFrm()) )
2512 pNxt = pNxt->FindNextCnt();
2514 if( pNxt )
2515 pNxt->InvalidateLineNum();
2517 //Extend repaint to the bottom.
2518 if ( HasPara() )
2520 SwRepaint *pRepaint = GetPara()->GetRepaint();
2521 pRepaint->Bottom( Max( pRepaint->Bottom(),
2522 Frm().Top()+Prt().Bottom()));
2525 else //Paragraphs which are not counted should not manipulate the AllLines.
2526 nThisLines = nNew;
2531 void SwTxtFrm::RecalcAllLines()
2533 ValidateLineNum();
2535 const SwAttrSet *pAttrSet = GetAttrSet();
2537 if ( !IsInTab() )
2539 const sal_uLong nOld = GetAllLines();
2540 const SwFmtLineNumber &rLineNum = pAttrSet->GetLineNumber();
2541 sal_uLong nNewNum;
2542 const bool bRestart = GetTxtNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo().IsRestartEachPage();
2544 if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() )
2545 nNewNum = rLineNum.GetStartValue() - 1;
2546 //If it is a follow or not has not be considered if it is a restart at each page; the
2547 //restart should also take affekt at follows.
2548 else if ( bRestart && FindPageFrm()->FindFirstBodyCntnt() == this )
2550 nNewNum = 0;
2552 else
2554 SwCntntFrm *pPrv = GetPrevCntntFrm();
2555 while ( pPrv &&
2556 (pPrv->IsInTab() || pPrv->IsInDocBody() != IsInDocBody()) )
2557 pPrv = pPrv->GetPrevCntntFrm();
2559 // #i78254# Restart line numbering at page change
2560 // First body content may be in table!
2561 if ( bRestart && pPrv && pPrv->FindPageFrm() != FindPageFrm() )
2562 pPrv = 0;
2564 nNewNum = pPrv ? ((SwTxtFrm*)pPrv)->GetAllLines() : 0;
2566 if ( rLineNum.IsCount() )
2567 nNewNum += GetThisLines();
2569 if ( nOld != nNewNum )
2571 nAllLines = nNewNum;
2572 SwCntntFrm *pNxt = GetNextCntntFrm();
2573 while ( pNxt &&
2574 (pNxt->IsInTab() || pNxt->IsInDocBody() != IsInDocBody()) )
2575 pNxt = pNxt->GetNextCntntFrm();
2576 if ( pNxt )
2578 if ( pNxt->GetUpper() != GetUpper() )
2579 pNxt->InvalidateLineNum();
2580 else
2581 pNxt->_InvalidateLineNum();
2587 void SwTxtFrm::VisitPortions( SwPortionHandler& rPH ) const
2589 const SwParaPortion* pPara = GetPara();
2591 if( pPara )
2593 if ( IsFollow() )
2594 rPH.Skip( GetOfst() );
2596 const SwLineLayout* pLine = pPara;
2597 while ( pLine )
2599 const SwLinePortion* pPor = pLine->GetFirstPortion();
2600 while ( pPor )
2602 pPor->HandlePortion( rPH );
2603 pPor = pPor->GetPortion();
2606 rPH.LineBreak();
2607 pLine = pLine->GetNext();
2611 rPH.Finish();
2615 /*************************************************************************
2616 * SwTxtFrm::GetScriptInfo()
2617 *************************************************************************/
2619 const SwScriptInfo* SwTxtFrm::GetScriptInfo() const
2621 const SwParaPortion* pPara = GetPara();
2622 return pPara ? &pPara->GetScriptInfo() : 0;
2625 /*************************************************************************
2626 * lcl_CalcFlyBasePos()
2627 * Helper function for SwTxtFrm::CalcBasePosForFly()
2628 *************************************************************************/
2630 static SwTwips lcl_CalcFlyBasePos( const SwTxtFrm& rFrm, SwRect aFlyRect,
2631 SwTxtFly& rTxtFly )
2633 SWRECTFN( (&rFrm) )
2634 SwTwips nRet = rFrm.IsRightToLeft() ?
2635 (rFrm.Frm().*fnRect->fnGetRight)() :
2636 (rFrm.Frm().*fnRect->fnGetLeft)();
2640 SwRect aRect = rTxtFly.GetFrm( aFlyRect );
2641 if ( 0 != (aRect.*fnRect->fnGetWidth)() )
2643 if ( rFrm.IsRightToLeft() )
2645 if ( (aRect.*fnRect->fnGetRight)() -
2646 (aFlyRect.*fnRect->fnGetRight)() >= 0 )
2648 (aFlyRect.*fnRect->fnSetRight)(
2649 (aRect.*fnRect->fnGetLeft)() );
2650 nRet = (aRect.*fnRect->fnGetLeft)();
2652 else
2653 break;
2655 else
2657 if ( (aFlyRect.*fnRect->fnGetLeft)() -
2658 (aRect.*fnRect->fnGetLeft)() >= 0 )
2660 (aFlyRect.*fnRect->fnSetLeft)(
2661 (aRect.*fnRect->fnGetRight)() + 1 );
2662 nRet = (aRect.*fnRect->fnGetRight)();
2664 else
2665 break;
2668 else
2669 break;
2671 while ( (aFlyRect.*fnRect->fnGetWidth)() > 0 );
2673 return nRet;
2676 /*************************************************************************
2677 * SwTxtFrm::CalcBasePosForFly()
2678 *************************************************************************/
2680 void SwTxtFrm::CalcBaseOfstForFly()
2682 OSL_ENSURE( !IsVertical() || !IsSwapped(),
2683 "SwTxtFrm::CalcBasePosForFly with swapped frame!" );
2685 const SwNode* pNode = GetTxtNode();
2686 if ( !pNode->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_FLY_OFFSETS) )
2687 return;
2689 SWRECTFN( this )
2691 SwRect aFlyRect( Frm().Pos() + Prt().Pos(), Prt().SSize() );
2693 // Get first 'real' line and adjust position and height of line rectangle
2694 // OD 08.09.2003 #110978#, #108749#, #110354# - correct behaviour,
2695 // if no 'real' line exists (empty paragraph with and without a dummy portion)
2697 SwTwips nTop = (aFlyRect.*fnRect->fnGetTop)();
2698 const SwLineLayout* pLay = GetPara();
2699 SwTwips nLineHeight = 200;
2700 while( pLay && pLay->IsDummy() && pLay->GetNext() )
2702 nTop += pLay->Height();
2703 pLay = pLay->GetNext();
2705 if ( pLay )
2707 nLineHeight = pLay->Height();
2709 (aFlyRect.*fnRect->fnSetTopAndHeight)( nTop, nLineHeight );
2712 SwTxtFly aTxtFly( this );
2713 aTxtFly.SetIgnoreCurrentFrame( sal_True );
2714 aTxtFly.SetIgnoreContour( sal_True );
2715 // #118809# - ignore objects in page header|footer for
2716 // text frames not in page header|footer
2717 aTxtFly.SetIgnoreObjsInHeaderFooter( sal_True );
2718 SwTwips nRet1 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
2719 aTxtFly.SetIgnoreCurrentFrame( sal_False );
2720 SwTwips nRet2 = lcl_CalcFlyBasePos( *this, aFlyRect, aTxtFly );
2722 // make values relative to frame start position
2723 SwTwips nLeft = IsRightToLeft() ?
2724 (Frm().*fnRect->fnGetRight)() :
2725 (Frm().*fnRect->fnGetLeft)();
2727 mnFlyAnchorOfst = nRet1 - nLeft;
2728 mnFlyAnchorOfstNoWrap = nRet2 - nLeft;
2731 /* repaint all text frames of the given text node */
2732 void SwTxtFrm::repaintTextFrames( const SwTxtNode& rNode )
2734 SwIterator<SwTxtFrm,SwTxtNode> aIter( rNode );
2735 for( const SwTxtFrm *pFrm = aIter.First(); pFrm; pFrm = aIter.Next() )
2737 SwRect aRec( pFrm->PaintArea() );
2738 const SwRootFrm *pRootFrm = pFrm->getRootFrm();
2739 ViewShell *pCurShell = pRootFrm ? pRootFrm->GetCurrShell() : NULL;
2740 if( pCurShell )
2741 pCurShell->InvalidateWindows( aRec );
2745 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */