1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
42 #include <viewopt.hxx>
43 #include <dflyobj.hxx>
46 #include <frmtool.hxx>
47 #include <pagedesc.hxx> // SwPageDesc
48 #include <tgrditem.hxx>
49 #include <dbg_lay.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()
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
89 Prt().Pos().Y() = nPrtOfstX
;
91 Prt().Pos().Y() = Frm().Width() - ( nPrtOfstX
+ Prt().Width() );
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
100 Prt().Pos().X() = nPrtOfstY
;
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
124 nOfstX
= rRect
.Left() - Frm().Left();
125 nOfstY
= rRect
.Top() - Frm().Top();
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
138 rRect
.Left(Frm().Left() + nOfstY
);
142 rRect
.Left( Frm().Left() + Frm().Height() - nOfstY
);
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
162 rPoint
.X() = Frm().Left() + nOfstY
;
166 rPoint
.X() = Frm().Left() + Frm().Height() - nOfstY
;
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
);
184 // Calculates the coordinates of a rectangle when switching from
185 // vertical to horizontal layout.
186 void SwTxtFrm::SwitchVerticalToHorizontal( SwRect
& rRect
) const
190 // calc offset inside frame
192 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
194 nOfstX
= rRect
.Left() - Frm().Left();
198 nOfstX
= Frm().Left() + Frm().Height() - ( rRect
.Left() + rRect
.Width() );
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
220 // calc offset inside frame
222 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
224 nOfstX
= rPoint
.X() - Frm().Left();
228 nOfstX
= Frm().Left() + Frm().Height() - rPoint
.X();
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
);
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() ) ) )
257 ((SwTxtFrm
*)pFrm
)->SwapWidthAndHeight();
261 SwFrmSwapper::~SwFrmSwapper()
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
);
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;
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 /*************************************************************************
335 *************************************************************************/
337 void SwTxtFrm::Init()
339 OSL_ENSURE( !IsLocked(), "+SwTxtFrm::Init: this ist locked." );
344 //Die Flags direkt setzen um ResetPreps und damit ein unnuetzes GetPara
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
)
358 , mnFlyAnchorOfst( 0 )
359 , mnFlyAnchorOfstNoWrap( 0 )
361 , mnHeightOfLastLine( 0 ) // OD 2004-03-17 #i11860#
362 , mnAdditionalFirstLineOffset( 0 )
364 , nCacheIdx( MSHRT_MAX
)
366 , bFormatted( false )
368 , bJustWidow( false )
370 , bInFtnConnect( false )
374 , bFieldFollow( false )
375 , bHasAnimation( false )
376 , bIsSwapped( false )
377 , mbFollowFormatAllowed( true ) // OD 14.03.2003 #i11760#
382 /*************************************************************************
383 * SwTxtFrm::~SwTxtFrm()
384 *************************************************************************/
385 SwTxtFrm::~SwTxtFrm()
387 // Remove associated SwParaPortion from pTxtCache
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()) )
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" );
420 const bool bHiddenCharsHidePara
= GetTxtNode()->HasHiddenCharAttribute( true );
421 const bool bHiddenParaField
= GetTxtNode()->HasHiddenParaField();
422 const ViewShell
* pVsh
= getRootFrm()->GetCurrShell();
424 if ( pVsh
&& ( bHiddenCharsHidePara
|| bHiddenParaField
) )
427 ( bHiddenParaField
&&
428 ( !pVsh
->GetViewOptions()->IsShowHiddenPara() &&
429 !pVsh
->GetViewOptions()->IsFldName() ) ) ||
430 ( bHiddenCharsHidePara
&&
431 !pVsh
->GetViewOptions()->IsShowHiddenChar() ) )
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
460 /*************************************************************************
461 * SwTxtFrm::HideFootnotes()
462 *************************************************************************/
463 void SwTxtFrm::HideFootnotes( xub_StrLen nStart
, xub_StrLen nEnd
)
465 const SwpHints
*pHints
= GetTxtNode()->GetpSwpHints();
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();
481 pPage
= FindPageFrm();
482 pPage
->RemoveFtn( this, (SwTxtFtn
*)pHt
);
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
)
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
) );
522 const SwFrmFmt
* pFrmFmt
=
523 static_cast<const SwTxtFlyCnt
*>(pHint
)->GetFlyCnt().GetFrmFmt();
524 if ( pFrmFmt
->Which() == RES_FLYFRMFMT
)
526 SwNodeIndex nCntntIndex
= *(pFrmFmt
->GetCntnt().GetCntntIdx());
528 if ( nCntntIndex
.GetNode().IsNoTxtNode() )
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
)();
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()
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());
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
);
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 );
613 // under certain conditions
614 if ( nHiddenStart
!= STRING_LEN
&& bShouldBeHidden
&&
615 sw_HideObj( *this, eAnchorType
, nObjAnchorPos
, (*GetDrawObjs())[i
] ) )
616 pContact
->MoveObjToInvisibleLayer( pObj
);
618 pContact
->MoveObjToVisibleLayer( pObj
);
622 OSL_FAIL( "<SwTxtFrm::HideAndShowObjects()> - object not anchored at/inside paragraph!?" );
630 SwTxtFrm
*pMaster
= FindMaster();
631 OSL_ENSURE(pMaster
, "SwTxtFrm without master");
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
) ) )
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
) ) )
671 return nFound
<= STRING_LEN
672 ? static_cast<xub_StrLen
>(nFound
)
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.
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() )
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
)
720 SetWidow( sal_False
);
721 SwParaPortion
*pPara
= GetPara();
723 sal_Bool bInv
= sal_False
;
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
730 *(pPara
->GetDelta()) += nD
;
733 SwCharRange
&rReformat
= *(pPara
->GetReformat());
734 if(aRange
!= rReformat
) {
735 if( STRING_LEN
== rReformat
.Len() )
747 /*************************************************************************
748 * SwTxtFrm::CalcLineSpace()
749 *************************************************************************/
751 void SwTxtFrm::CalcLineSpace()
753 OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
754 "SwTxtFrm::CalcLineSpace with swapped frame!" );
756 if( IsLocked() || !HasPara() )
759 SwParaPortion
*pPara
;
761 GetTxtNode()->GetSwAttrSet().GetLRSpace().IsAutoFirst() ||
762 ( pPara
= GetPara() )->IsFixLineHeight() )
768 Size
aNewSize( Prt().SSize() );
770 SwTxtFormatInfo
aInf( this );
771 SwTxtFormatter
aLine( this, &aInf
);
772 if( aLine
.GetDropLines() )
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() );
789 aTmpFrm
.Height( Prt().Height() );
791 aTmpFrm
.Height( aNewSize
.Height() );
792 if( aInf
.GetTxtFly()->Relax( aTmpFrm
) )
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.
810 // Alles nimmt seinen gewohnten Gang ...
811 pPara
->SetPrepAdjust();
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();
837 if( pTxtNode
->GetWrong() )
838 pTxtNode
->GetWrong()->Move( nPos
, nCnt
);
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
);
848 xub_StrLen nLen
= (xub_StrLen
)nCnt
;
849 if( pTxtNode
->GetWrong() )
850 pTxtNode
->GetWrong()->Invalidate( nPos
, nLen
);
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() )
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 );
872 pTxtNode
->SetSmartTagDirty( true );
875 SwRootFrm
*pRootFrm
= rFrm
.getRootFrm();
878 pRootFrm
->SetNeedGrammarCheck( sal_True
);
881 SwPageFrm
*pPage
= rFrm
.FindPageFrm();
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
)
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();
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 /*************************************************************************
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
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
);
940 SET_WRONG( 0, STRING_LEN
, false );
941 SetDerivedR2L( sal_False
);
943 // OD 09.12.2002 #105576# - Force complete paint due to existing
951 // Im gelockten Zustand werden keine Bestellungen angenommen.
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
;
970 nPos
= ((SwInsTxt
*)pNew
)->nPos
;
971 nLen
= ((SwInsTxt
*)pNew
)->nLen
;
972 if( IsIdxInside( nPos
, nLen
) )
976 // 6969: Aktualisierung der NumPortions auch bei leeren Zeilen!
980 Prepare( PREP_CLEAR
);
983 _InvalidateRange( SwCharRange( nPos
, nLen
), nLen
);
985 SET_WRONG( nPos
, nLen
, true )
986 SET_SCRIPT_INVAL( nPos
)
987 bSetFldsDirty
= sal_True
;
989 lcl_ModifyOfst( this, nPos
, nLen
);
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
;
1000 lcl_ModifyOfst( this, nPos
, STRING_LEN
);
1005 nPos
= ((SwDelTxt
*)pNew
)->nStart
;
1006 nLen
= ((SwDelTxt
*)pNew
)->nLen
;
1009 if( IsIdxInside( nPos
, nLen
) )
1014 InvalidateRange( SwCharRange( nPos
, 1 ), m
);
1016 SET_WRONG( nPos
, m
, true )
1017 SET_SCRIPT_INVAL( nPos
)
1018 bSetFldsDirty
= bRecalcFtnFlag
= sal_True
;
1020 lcl_ModifyOfst( this, nPos
, nLen
);
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.
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
)
1050 ViewShell
* pViewSh
= getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
1053 pViewSh
->InvalidateAccessibleParaAttrs( *this );
1057 case RES_OBJECTDYING
:
1060 case RES_PARATR_LINESPACING
:
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();
1081 case RES_TXTATR_FIELD
:
1083 nPos
= *((SwFmtFld
*)pNew
)->GetTxtFld()->GetStart();
1084 if( IsIdxInside( nPos
, 1 ) )
1089 // opt: invalidate aufs Window ?
1094 _InvalidateRange( SwCharRange( nPos
, 1 ) );
1096 bSetFldsDirty
= sal_True
;
1098 if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
1099 SET_WRONG( nPos
, nPos
+ 1, false )
1102 case RES_TXTATR_FTN
:
1104 nPos
= *((SwFmtFtn
*)pNew
)->GetTxtFtn()->GetStart();
1105 if( IsInFtn() || IsIdxInside( nPos
, 1 ) )
1106 Prepare( PREP_FTN
, ((SwFmtFtn
*)pNew
)->GetTxtFtn() );
1110 case RES_ATTRSET_CHG
:
1112 InvalidateLineNum();
1114 SwAttrSet
& rNewSet
= *((SwAttrSetChg
*)pNew
)->GetChgSet();
1115 const SfxPoolItem
* pItem
;
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
);
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
)
1140 // opt: invalidate aufs Window ?
1145 _InvalidateRange( SwCharRange( nPos
, 1 ) );
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
);
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();
1172 if( IsInSct() && !GetPrev() )
1174 SwSectionFrm
*pSect
= FindSctFrm();
1175 if( pSect
->ContainsAny() == this )
1176 pSect
->InvalidatePrt();
1182 if ( SFX_ITEM_SET
== rNewSet
.GetItemState( RES_PARATR_SPLIT
,
1187 Prepare( PREP_CLEAR
);
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
) ||
1235 rNewSet
.GetItemState( RES_CHRATR_CJK_LANGUAGE
, sal_False
) ||
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
) ||
1242 rNewSet
.GetItemState( RES_CHRATR_CJK_FONT
, sal_False
) ||
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
);
1251 // OD 09.12.2002 #105576# - Force complete paint due to existing
1259 if( getRootFrm()->GetCurrShell() )
1261 Prepare( PREP_CLEAR
);
1267 SwAttrSetChg
aOldSet( *(SwAttrSetChg
*)pOld
);
1268 SwAttrSetChg
aNewSet( *(SwAttrSetChg
*)pNew
);
1272 aOldSet
.ClearItem( RES_TXTATR_FTN
);
1273 aNewSet
.ClearItem( RES_TXTATR_FTN
);
1277 aOldSet
.ClearItem( RES_TXTATR_FIELD
);
1278 aNewSet
.ClearItem( RES_TXTATR_FIELD
);
1280 if ( 0x04 & nClear
)
1284 aOldSet
.ClearItem( RES_PARATR_LINESPACING
);
1285 aNewSet
.ClearItem( RES_PARATR_LINESPACING
);
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
);
1301 SwCntntFrm::Modify( pOld
, pNew
);
1304 if (isA11yRelevantAttribute(nWhich
))
1307 ViewShell
* pViewSh
= getRootFrm() ? getRootFrm()->GetCurrShell() : 0;
1310 pViewSh
->InvalidateAccessibleParaAttrs( *this );
1316 // 6870: SwDocPosUpdate auswerten.
1317 case RES_DOCPOS_UPDATE
:
1321 const SwDocPosUpdate
*pDocPos
= (const SwDocPosUpdate
*)pOld
;
1322 if( pDocPos
->nDocPos
<= aFrm
.Top() )
1324 const SwFmtFld
*pFld
= (const SwFmtFld
*)pNew
;
1326 SwCharRange( *pFld
->GetTxtFld()->GetStart(), 1 ) );
1331 case RES_PARATR_SPLIT
:
1334 Prepare( PREP_CLEAR
);
1335 bSetFldsDirty
= sal_True
;
1338 SetDerivedR2L( sal_False
);
1343 Prepare( PREP_CLEAR
);
1347 //Wird z.B. bei HiddenPara mit 0 gerufen.
1349 if ( 0 != (pNxt
= FindNext()) )
1350 pNxt
->InvalidatePrt();
1356 GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( true, GetNode(), 1 );
1358 if ( bRecalcFtnFlag
)
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();
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 );
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 );
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();
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
);
1409 xub_StrLen nTmpLen
= aLine
.GetCurr()->GetLen();
1410 while( nHave
&& aLine
.PrevLine() )
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.
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() );
1433 GetFollow()->SetOfst( aLine
.GetEnd() );
1434 aLine
.TruncLines( sal_True
);
1435 if( pPara
->IsFollowField() )
1436 GetFollow()->SetFieldFollow( sal_True
);
1448 /*************************************************************************
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() )
1459 rPos
= pFrm
->GetOfst();
1463 if( !rFtnInfo
.aQuoVadis
.Len() )
1465 if( pFrm
->HasFollow() )
1466 rPos
= pFrm
->GetFollow()->GetOfst();
1468 rPos
= pFrm
->GetTxt().Len();
1470 --rPos
; // unser letztes Zeichen
1475 void SwTxtFrm::Prepare( const PrepareHint ePrep
, const void* pVoid
,
1478 SwFrmSwapper
aSwapper( this, sal_False
);
1480 #if OSL_DEBUG_LEVEL > 1
1481 const SwTwips nDbgY
= Frm().Top();
1489 case PREP_BOSS_CHGD
:
1490 SetInvalidVert( sal_True
); // Test
1491 case PREP_WIDOWS_ORPHANS
:
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() )
1506 // Gibt es ueberhaupt Flys auf der Seite ?
1507 SwTxtFly
aTxtFly( this );
1508 if( aTxtFly
.IsOn() )
1510 // Ueberlappt irgendein Fly ?
1512 if ( aTxtFly
.IsOn() || IsUndersized() )
1515 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue())
1518 GETGRID( FindPageFrm() )
1519 if ( pGrid
&& GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1522 // #i28701# - consider anchored objects
1523 if ( GetDrawObjs() )
1533 if( !HasPara() && PREP_MUST_FIT
!= ePrep
)
1535 SetInvalidVert( sal_True
); // Test
1536 OSL_ENSURE( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" );
1544 //Objekt mit Locking aus dem Cache holen.
1545 SwTxtLineAccess
aAccess( this );
1546 SwParaPortion
*pPara
= aAccess
.GetPara();
1550 case PREP_MOVEFTN
: Frm().Height(0);
1555 case PREP_ADJUST_FRM
: pPara
->SetPrepAdjust( sal_True
);
1556 if( IsFtnNumFrm() != pPara
->IsFtnNum() ||
1559 InvalidateRange( SwCharRange( 0, 1 ), 1);
1560 if( GetOfst() && !IsFollow() )
1564 case PREP_MUST_FIT
: pPara
->SetPrepMustFit( sal_True
);
1566 case PREP_WIDOWS_ORPHANS
: pPara
->SetPrepAdjust( sal_True
);
1570 // MustFit ist staerker als alles anderes
1571 if( pPara
->IsPrepMustFit() )
1573 // Siehe Kommentar in WidowsAndOrphans::FindOrphans und CalcPreps()
1574 PrepWidows( *(const MSHORT
*)pVoid
, bNotify
);
1579 SwTxtFtn
*pFtn
= (SwTxtFtn
*)pVoid
;
1582 // Bin ich der erste TxtFrm einer Fussnote ?
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);
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();
1599 InvalidateRange( SwCharRange( nPos
, 1 ), 1);
1605 // Wir sind also der TxtFrm _mit_ der Fussnote
1606 const xub_StrLen nPos
= *pFtn
->GetStart();
1607 InvalidateRange( SwCharRange( nPos
, 1 ), 1);
1611 case PREP_BOSS_CHGD
:
1615 SetInvalidVert( sal_False
);
1616 sal_Bool bOld
= IsVertical();
1617 SetInvalidVert( sal_True
);
1618 if( bOld
!= IsVertical() )
1619 InvalidateRange( SwCharRange( GetOfst(), STRING_LEN
) );
1624 xub_StrLen nNxtOfst
= GetFollow()->GetOfst();
1627 InvalidateRange( SwCharRange( nNxtOfst
, 1 ), 1);
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();
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
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() )
1671 InvalidateRange( SwCharRange( GetOfst(), 1 ), 1);
1676 case PREP_POS_CHGD
:
1678 if ( GetValidPrtAreaFlag() )
1680 GETGRID( FindPageFrm() )
1681 if ( pGrid
&& GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1685 // Falls wir mit niemandem ueberlappen:
1686 // Ueberlappte irgendein Fly _vor_ der Positionsaenderung ?
1687 sal_Bool bFormat
= pPara
->HasFly();
1692 SwTwips nTmpBottom
= GetUpper()->Frm().Top() +
1693 GetUpper()->Prt().Bottom();
1694 if( nTmpBottom
< Frm().Bottom() )
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()
1717 // Gibt es ueberhaupt Flys auf der Seite ?
1718 SwTxtFly
aTxtFly( this );
1719 if( aTxtFly
.IsOn() )
1721 // Ueberlappt irgendein Fly ?
1723 bFormat
= aTxtFly
.IsOn() || IsUndersized();
1733 if( pPara
->GetRepaint()->HasArea() )
1742 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1743 Prepare( PREP_REGISTER
, 0, bNotify
);
1744 // Durch Positionsverschiebungen mit Ftns muessen die
1745 // Frames neu adjustiert werden.
1748 Prepare( PREP_ADJUST_FRM
, 0, bNotify
);
1752 return; // damit kein SetPrep() erfolgt.
1757 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1759 pPara
->SetPrepAdjust( sal_True
);
1764 if ( 0 != ( pNxt
= GetIndNext() ) )
1766 pNxt
->_InvalidatePrt();
1767 if ( pNxt
->IsLayoutFrm() )
1768 pNxt
->InvalidatePage();
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
1784 --nPos
; // das Zeichen vor unserem Follow
1785 InvalidateRange( SwCharRange( nPos
, 1 ), 0 );
1792 if( lcl_ErgoVadis( this, nPos
, ePrep
) )
1793 InvalidateRange( SwCharRange( nPos
, 1 ), 0 );
1796 case PREP_FLY_ATTR_CHG
:
1800 xub_StrLen nWhere
= CalcFlyPos( (SwFrmFmt
*)pVoid
);
1801 OSL_ENSURE( STRING_LEN
!= nWhere
, "Prepare: Why me?" );
1802 InvalidateRange( SwCharRange( nWhere
, 1 ) );
1805 // else ... Laufe in den Default-Switch
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 );
1821 if( pPara
->GetRepaint()->HasArea() )
1825 if( GetOfst() && !IsFollow() )
1832 return; // damit kein SetPrep() erfolgt.
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 * --------------------------------------------------*/
1851 SwParaPortion
*pOldPara
;
1852 SwRect aOldFrm
, aOldPrt
;
1854 SwTestFormat( SwTxtFrm
* pTxtFrm
, const SwFrm
* pPrv
, SwTwips nMaxHeight
);
1858 SwTestFormat::SwTestFormat( SwTxtFrm
* pTxtFrm
, const SwFrm
* pPre
, SwTwips nMaxHeight
)
1861 aOldFrm
= pFrm
->Frm();
1862 aOldPrt
= pFrm
->Prt();
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
) );
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 )
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()
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" );
1954 //Kann gut sein, dass mir der IdleCollector mir die gecachten
1955 //Informationen entzogen hat.
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
)
1966 SwTwips nHeight
= bVert
? Prt().SSize().Width() : Prt().SSize().Height();
1967 if( rMaxHeight
< nHeight
)
1971 rMaxHeight
-= nHeight
;
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() ) )
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
);
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();
2006 ( pFoll
->IsVertical() ?
2007 !pFoll
->Frm().Width() :
2008 !pFoll
->Frm().Height() ) )
2009 pFoll
= pFoll
->GetFollow();
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
;
2028 // Ist Aufspalten ueberhaupt notwendig?
2029 if ( 0 != ( bSplit
= !aFrmBreak
.IsInside( aLine
) ) )
2030 bRet
= !aFrmBreak
.IsKeepAlways() && aFrmBreak
.WouldFit( aLine
, rMaxHeight
, bTst
);
2033 //Wir brauchen die Gesamthoehe inklusive der aktuellen Zeile
2037 rMaxHeight
-= aLine
.GetLineHeight();
2038 } while ( aLine
.Next() );
2047 /*************************************************************************
2048 * SwTxtFrm::GetParHeight()
2049 *************************************************************************/
2051 KSHORT
SwTxtFrm::GetParHeight() const
2053 OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
2054 "SwTxtFrm::GetParHeight with swapped frame" );
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();
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();
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();
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
) )
2117 /*************************************************************************
2118 * SwTxtFrm::CalcFitToContent()
2119 *************************************************************************/
2121 SwTwips
SwTxtFrm::CalcFitToContent()
2124 // If we are currently locked, we better return with a
2125 // fairly reasonable value:
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
;
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
);
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()
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 );
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();
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
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
)
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.
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
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.
2295 SwFntObj
*pOldFont
= pLastFont
;
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
);
2306 Font aOldFont
= pOut
->GetFont();
2307 aFont
.SetFntChg( sal_True
);
2308 aFont
.ChgPhysFnt( pVsh
, *pOut
);
2309 mnHeightOfLastLine
= aFont
.GetHeight( pVsh
, *pOut
);
2310 pLastFont
->Unlock();
2312 pOut
->SetFont( aOldFont
);
2317 // new determination of last line height - take actually height of last line
2319 // assure same results, if paragraph is undersized
2320 if ( IsUndersized() )
2322 mnHeightOfLastLine
= 0;
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();
2345 SwTwips nAscent
, nDescent
, nDummy1
, nDummy2
;
2346 // #i47162# - suppress consideration of
2347 // fly content portions and the line portion.
2348 pLineLayout
->MaxAscentDescent( nAscent
, nDescent
,
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 );
2366 mnHeightOfLastLine
= nNewHeightOfLastLine
;
2373 // invalidate printing area, if height of last line changes
2374 if ( mnHeightOfLastLine
!= mnOldHeightOfLastLine
)
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
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
)
2409 // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()>
2410 nRet
= GetHeightOfLastLine();
2413 nTmp
*= rSpace
.GetPropLineSpace();
2422 case SVX_INTER_LINE_SPACE_FIX
:
2424 if ( rSpace
.GetInterLineSpace() > 0 )
2425 nRet
= rSpace
.GetInterLineSpace();
2434 /*************************************************************************
2435 * SwTxtFrm::FirstLineHeight()
2436 *************************************************************************/
2438 KSHORT
SwTxtFrm::FirstLineHeight() const
2442 if( IsEmpty() && IsValid() )
2443 return IsVertical() ? (KSHORT
)Prt().Width() : (KSHORT
)Prt().Height();
2446 const SwParaPortion
*pPara
= GetPara();
2450 return pPara
->Height();
2453 MSHORT
SwTxtFrm::GetLineCount( xub_StrLen nPos
)
2456 SwTxtFrm
*pFrm
= this;
2459 pFrm
->GetFormatted();
2460 if( !pFrm
->HasPara() )
2462 SwTxtSizeInfo
aInf( pFrm
);
2463 SwTxtMargin
aLine( pFrm
, &aInf
);
2464 if( STRING_LEN
== nPos
)
2467 aLine
.CharToLine( nPos
);
2468 nRet
= nRet
+ aLine
.GetLineNr();
2469 pFrm
= pFrm
->GetFollow();
2470 } while ( pFrm
&& pFrm
->GetOfst() <= nPos
);
2474 void SwTxtFrm::ChgThisLines()
2476 //not necassary to format here (GerFormatted etc.), because we have to come from there!
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() )
2487 nNew
= (sal_uLong
)aLine
.GetLineNr();
2493 if( aLine
.GetCurr()->HasCntnt() )
2495 } while ( aLine
.NextLine() );
2498 else if ( rInf
.IsCountBlankLines() )
2501 if ( nNew
!= nThisLines
)
2503 if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() )
2505 nAllLines
-= nThisLines
;
2507 nAllLines
+= nThisLines
;
2508 SwFrm
*pNxt
= GetNextCntntFrm();
2509 while( pNxt
&& pNxt
->IsInTab() )
2511 if( 0 != (pNxt
= pNxt
->FindTabFrm()) )
2512 pNxt
= pNxt
->FindNextCnt();
2515 pNxt
->InvalidateLineNum();
2517 //Extend repaint to the bottom.
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.
2531 void SwTxtFrm::RecalcAllLines()
2535 const SwAttrSet
*pAttrSet
= GetAttrSet();
2539 const sal_uLong nOld
= GetAllLines();
2540 const SwFmtLineNumber
&rLineNum
= pAttrSet
->GetLineNumber();
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 )
2554 SwCntntFrm
*pPrv
= GetPrevCntntFrm();
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() )
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();
2574 (pNxt
->IsInTab() || pNxt
->IsInDocBody() != IsInDocBody()) )
2575 pNxt
= pNxt
->GetNextCntntFrm();
2578 if ( pNxt
->GetUpper() != GetUpper() )
2579 pNxt
->InvalidateLineNum();
2581 pNxt
->_InvalidateLineNum();
2587 void SwTxtFrm::VisitPortions( SwPortionHandler
& rPH
) const
2589 const SwParaPortion
* pPara
= GetPara();
2594 rPH
.Skip( GetOfst() );
2596 const SwLineLayout
* pLine
= pPara
;
2599 const SwLinePortion
* pPor
= pLine
->GetFirstPortion();
2602 pPor
->HandlePortion( rPH
);
2603 pPor
= pPor
->GetPortion();
2607 pLine
= pLine
->GetNext();
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
,
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
)();
2657 if ( (aFlyRect
.*fnRect
->fnGetLeft
)() -
2658 (aRect
.*fnRect
->fnGetLeft
)() >= 0 )
2660 (aFlyRect
.*fnRect
->fnSetLeft
)(
2661 (aRect
.*fnRect
->fnGetRight
)() + 1 );
2662 nRet
= (aRect
.*fnRect
->fnGetRight
)();
2671 while ( (aFlyRect
.*fnRect
->fnGetWidth
)() > 0 );
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
) )
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();
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
;
2741 pCurShell
->InvalidateWindows( aRec
);
2745 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */