1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: txtfrm.cxx,v $
10 * $Revision: 1.108.30.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <hintids.hxx>
35 #include <svtools/ctloptions.hxx>
36 #include <sfx2/printer.hxx>
37 #include <sfx2/sfxuno.hxx>
38 #include <svx/langitem.hxx>
39 #include <svx/lspcitem.hxx>
40 #include <svx/lrspitem.hxx>
41 #include <svx/ulspitem.hxx>
42 #include <svx/brshitem.hxx>
43 #include <svx/pgrditem.hxx>
44 #include <swmodule.hxx>
45 #include <SwSmartTagMgr.hxx>
46 #include <doc.hxx> // GetDoc()
47 #include <pagefrm.hxx> // InvalidateSpelling
48 #include <rootfrm.hxx>
49 #include <viewsh.hxx> // ViewShell
50 #include <pam.hxx> // SwPosition
51 #include <ndtxt.hxx> // SwTxtNode
54 #include <viewopt.hxx>
55 #include <dflyobj.hxx>
58 #include <frmtool.hxx>
59 #include <pagedesc.hxx> // SwPageDesc
60 #include <tgrditem.hxx>
61 #include <dbg_lay.hxx>
66 #include <charatr.hxx>
67 #include <ftninfo.hxx>
69 #include <fmtline.hxx>
71 #include <txtfrm.hxx> // SwTxtFrm
72 #include <sectfrm.hxx> // SwSectFrm
73 #include <txtcfg.hxx> // DBG_LOOP
74 #include <itrform2.hxx> // Iteratoren
75 #include <widorp.hxx> // SwFrmBreak
76 #include <txtcache.hxx>
77 #include <fntcache.hxx> // GetLineSpace benutzt pLastFont
78 #include <SwGrammarMarkUp.hxx>
80 #include <lineinfo.hxx>
82 #include <SwPortionHandler.hxx>
83 // OD 2004-01-15 #110582#
84 #include <dcontact.hxx>
85 // OD 2004-05-24 #i28701#
86 #include <sortedobjs.hxx>
87 // --> OD 2005-03-30 #???#
88 #include <txtflcnt.hxx> // SwTxtFlyCnt
89 #include <fmtflcnt.hxx> // SwFmtFlyCnt
90 #include <fmtcntnt.hxx> // SwFmtCntnt
92 // --> OD 2008-01-31 #newlistlevelattrs#
93 #include <numrule.hxx>
95 #include <swtable.hxx>
96 #include <fldupde.hxx>
97 #include <IGrammarContact.hxx>
99 #if OSL_DEBUG_LEVEL > 1
100 #include <txtpaint.hxx> // DbgRect
101 extern const sal_Char
*GetPrepName( const enum PrepareHint ePrep
);
104 TYPEINIT1( SwTxtFrm
, SwCntntFrm
);
106 // Switches width and height of the text frame
107 void SwTxtFrm::SwapWidthAndHeight()
111 const long nPrtOfstX
= Prt().Pos().X();
112 Prt().Pos().X() = Prt().Pos().Y();
113 Prt().Pos().Y() = Frm().Width() - ( nPrtOfstX
+ Prt().Width() );
117 const long nPrtOfstY
= Prt().Pos().Y();
118 Prt().Pos().Y() = Prt().Pos().X();
119 Prt().Pos().X() = Frm().Height() - ( nPrtOfstY
+ Prt().Height() );
122 const long nFrmWidth
= Frm().Width();
123 Frm().Width( Frm().Height() );
124 Frm().Height( nFrmWidth
);
125 const long nPrtWidth
= Prt().Width();
126 Prt().Width( Prt().Height() );
127 Prt().Height( nPrtWidth
);
129 bIsSwapped
= ! bIsSwapped
;
132 // Calculates the coordinates of a rectangle when switching from
133 // horizontal to vertical layout.
134 void SwTxtFrm::SwitchHorizontalToVertical( SwRect
& rRect
) const
136 // calc offset inside frame
137 const long nOfstX
= rRect
.Left() - Frm().Left();
138 const long nOfstY
= rRect
.Top() + rRect
.Height() - Frm().Top();
139 const long nWidth
= rRect
.Width();
140 const long nHeight
= rRect
.Height();
143 rRect
.Left( Frm().Left() + Frm().Height() - nOfstY
);
146 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();
162 rPoint
.X() = Frm().Left() + Frm().Height() - nOfstY
;
164 // calc rotated coords
165 rPoint
.X() = Frm().Left() + Frm().Width() - nOfstY
;
167 rPoint
.Y() = Frm().Top() + nOfstX
;
170 // Calculates the a limit value when switching from
171 // horizontal to vertical layout.
172 long SwTxtFrm::SwitchHorizontalToVertical( long nLimit
) const
174 Point
aTmp( 0, nLimit
);
175 SwitchHorizontalToVertical( aTmp
);
179 // Calculates the coordinates of a rectangle when switching from
180 // vertical to horizontal layout.
181 void SwTxtFrm::SwitchVerticalToHorizontal( SwRect
& rRect
) const
185 // calc offset inside frame
187 nOfstX
= Frm().Left() + Frm().Height() - ( rRect
.Left() + rRect
.Width() );
189 nOfstX
= Frm().Left() + Frm().Width() - ( rRect
.Left() + rRect
.Width() );
191 const long nOfstY
= rRect
.Top() - Frm().Top();
192 const long nWidth
= rRect
.Height();
193 const long nHeight
= rRect
.Width();
195 // calc rotated coords
196 rRect
.Left( Frm().Left() + nOfstY
);
197 rRect
.Top( Frm().Top() + nOfstX
);
198 rRect
.Width( nWidth
);
199 rRect
.Height( nHeight
);
202 // Calculates the coordinates of a point when switching from
203 // vertical to horizontal layout.
204 void SwTxtFrm::SwitchVerticalToHorizontal( Point
& rPoint
) const
208 // calc offset inside frame
210 nOfstX
= Frm().Left() + Frm().Height() - rPoint
.X();
212 nOfstX
= Frm().Left() + Frm().Width() - rPoint
.X();
214 const long nOfstY
= rPoint
.Y() - Frm().Top();
216 // calc rotated coords
217 rPoint
.X() = Frm().Left() + nOfstY
;
218 rPoint
.Y() = Frm().Top() + nOfstX
;
221 // Calculates the a limit value when switching from
222 // vertical to horizontal layout.
223 long SwTxtFrm::SwitchVerticalToHorizontal( long nLimit
) const
225 Point
aTmp( nLimit
, 0 );
226 SwitchVerticalToHorizontal( aTmp
);
230 SwFrmSwapper::SwFrmSwapper( const SwTxtFrm
* pTxtFrm
, sal_Bool bSwapIfNotSwapped
)
231 : pFrm( pTxtFrm
), bUndo( sal_False
)
233 if ( pFrm
->IsVertical() &&
234 ( ( bSwapIfNotSwapped
&& ! pFrm
->IsSwapped() ) ||
235 ( ! bSwapIfNotSwapped
&& pFrm
->IsSwapped() ) ) )
238 ((SwTxtFrm
*)pFrm
)->SwapWidthAndHeight();
242 SwFrmSwapper::~SwFrmSwapper()
245 ((SwTxtFrm
*)pFrm
)->SwapWidthAndHeight();
248 void SwTxtFrm::SwitchLTRtoRTL( SwRect
& rRect
) const
250 SWAP_IF_NOT_SWAPPED( this )
252 long nWidth
= rRect
.Width();
253 rRect
.Left( 2 * ( Frm().Left() + Prt().Left() ) +
254 Prt().Width() - rRect
.Right() - 1 );
256 rRect
.Width( nWidth
);
261 void SwTxtFrm::SwitchLTRtoRTL( Point
& rPoint
) const
263 SWAP_IF_NOT_SWAPPED( this )
265 rPoint
.X() = 2 * ( Frm().Left() + Prt().Left() ) + Prt().Width() - rPoint
.X() - 1;
270 SwLayoutModeModifier::SwLayoutModeModifier( const OutputDevice
& rOutp
) :
271 rOut( rOutp
), nOldLayoutMode( rOutp
.GetLayoutMode() )
275 SwLayoutModeModifier::~SwLayoutModeModifier()
277 ((OutputDevice
&)rOut
).SetLayoutMode( nOldLayoutMode
);
280 void SwLayoutModeModifier::Modify( sal_Bool bChgToRTL
)
282 ((OutputDevice
&)rOut
).SetLayoutMode( bChgToRTL
?
283 TEXT_LAYOUT_BIDI_STRONG
| TEXT_LAYOUT_BIDI_RTL
:
284 TEXT_LAYOUT_BIDI_STRONG
);
287 void SwLayoutModeModifier::SetAuto()
289 const ULONG nNewLayoutMode
= nOldLayoutMode
& ~TEXT_LAYOUT_BIDI_STRONG
;
290 ((OutputDevice
&)rOut
).SetLayoutMode( nNewLayoutMode
);
293 SwDigitModeModifier::SwDigitModeModifier( const OutputDevice
& rOutp
, LanguageType eCurLang
) :
294 rOut( rOutp
), nOldLanguageType( rOutp
.GetDigitLanguage() )
296 LanguageType eLang
= eCurLang
;
297 const SvtCTLOptions::TextNumerals nTextNumerals
= SW_MOD()->GetCTLOptions().GetCTLTextNumerals();
299 if ( SvtCTLOptions::NUMERALS_HINDI
== nTextNumerals
)
300 eLang
= LANGUAGE_ARABIC_SAUDI_ARABIA
;
301 else if ( SvtCTLOptions::NUMERALS_ARABIC
== nTextNumerals
)
302 eLang
= LANGUAGE_ENGLISH
;
303 else if ( SvtCTLOptions::NUMERALS_SYSTEM
== nTextNumerals
)
304 eLang
= (LanguageType
)::GetAppLanguage();
306 ((OutputDevice
&)rOut
).SetDigitLanguage( eLang
);
309 SwDigitModeModifier::~SwDigitModeModifier()
311 ((OutputDevice
&)rOut
).SetDigitLanguage( nOldLanguageType
);
314 /*************************************************************************
316 *************************************************************************/
318 void SwTxtFrm::Init()
320 ASSERT( !IsLocked(), "+SwTxtFrm::Init: this ist locked." );
325 //Die Flags direkt setzen um ResetPreps und damit ein unnuetzes GetPara
327 // Nicht bOrphan, bLocked oder bWait auf sal_False setzen !
328 // bOrphan = bFlag7 = bFlag8 = sal_False;
332 /*************************************************************************
333 |* SwTxtFrm::CTORen/DTOR
334 |*************************************************************************/
336 void SwTxtFrm::InitCtor()
338 nCacheIdx
= MSHRT_MAX
;
343 mnFlyAnchorOfstNoWrap
= 0;
345 // OD 2004-03-17 #i11860#
346 mnHeightOfLastLine
= 0;
347 // --> OD 2008-01-31 #newlistlevelattrs#
348 mnAdditionalFirstLineOffset
= 0;
352 bLocked
= bFormatted
= bWidow
= bUndersized
= bJustWidow
=
353 bEmpty
= bInFtnConnect
= bFtn
= bRepaint
= bBlinkPor
=
354 bFieldFollow
= bHasAnimation
= bIsSwapped
= sal_False
;
355 // OD 14.03.2003 #i11760#
356 mbFollowFormatAllowed
= sal_True
;
359 /*************************************************************************
360 * SwTxtFrm::SwTxtFrm()
361 *************************************************************************/
362 SwTxtFrm::SwTxtFrm(SwTxtNode
* const pNode
)
368 /*************************************************************************
369 * SwTxtFrm::~SwTxtFrm()
370 *************************************************************************/
371 SwTxtFrm::~SwTxtFrm()
373 // Remove associated SwParaPortion from pTxtCache
377 const XubString
& SwTxtFrm::GetTxt() const
379 return GetTxtNode()->GetTxt();
382 void SwTxtFrm::ResetPreps()
384 if ( GetCacheIdx() != MSHRT_MAX
)
386 SwParaPortion
*pPara
;
387 if( 0 != (pPara
= GetPara()) )
392 /*************************************************************************
393 * SwTxtFrm::IsHiddenNow()
394 *************************************************************************/
395 sal_Bool
SwTxtFrm::IsHiddenNow() const
397 SwFrmSwapper
aSwapper( this, sal_True
);
399 if( !Frm().Width() && IsValid() && GetUpper()->IsValid() )
400 //bei Stackueberlauf (StackHack) invalid!
402 // ASSERT( false, "SwTxtFrm::IsHiddenNow: thin frame" );
406 const bool bHiddenCharsHidePara
= GetTxtNode()->HasHiddenCharAttribute( true );
407 const bool bHiddenParaField
= GetTxtNode()->HasHiddenParaField();
408 const ViewShell
* pVsh
= GetShell();
410 if ( pVsh
&& ( bHiddenCharsHidePara
|| bHiddenParaField
) )
413 ( bHiddenParaField
&&
414 ( !pVsh
->GetViewOptions()->IsShowHiddenPara() &&
415 !pVsh
->GetViewOptions()->IsFldName() ) ) ||
416 ( bHiddenCharsHidePara
&&
417 !pVsh
->GetViewOptions()->IsShowHiddenChar() ) )
427 /*************************************************************************
428 * SwTxtFrm::HideHidden()
429 *************************************************************************/
430 // Entfernt die Anhaengsel des Textfrms wenn dieser hidden ist
432 void SwTxtFrm::HideHidden()
434 ASSERT( !GetFollow() && IsHiddenNow(),
435 "HideHidden on visible frame of hidden frame has follow" );
437 const xub_StrLen nEnd
= STRING_LEN
;
438 HideFootnotes( GetOfst(), nEnd
);
439 // OD 2004-01-15 #110582#
440 HideAndShowObjects();
442 //Die Formatinfos sind jetzt obsolete
446 /*************************************************************************
447 * SwTxtFrm::HideFootnotes()
448 *************************************************************************/
449 void SwTxtFrm::HideFootnotes( xub_StrLen nStart
, xub_StrLen nEnd
)
451 const SwpHints
*pHints
= GetTxtNode()->GetpSwpHints();
454 const USHORT nSize
= pHints
->Count();
455 SwPageFrm
*pPage
= 0;
456 for ( USHORT i
= 0; i
< nSize
; ++i
)
458 const SwTxtAttr
*pHt
= (*pHints
)[i
];
459 if ( pHt
->Which() == RES_TXTATR_FTN
)
461 const xub_StrLen nIdx
= *pHt
->GetStart();
467 pPage
= FindPageFrm();
468 pPage
->RemoveFtn( this, (SwTxtFtn
*)pHt
);
475 // --> OD 2005-03-30 #120729# - hotfix: WW8 documents contain at its end hidden,
476 // as-character anchored graphics, which are used for a graphic bullet list.
477 // As long as these graphic bullet list aren't imported, do not hide a
478 // at-character anchored object, if
479 // (a) the document is an imported WW8 document -
480 // checked by checking certain compatibility options -,
481 // (b) the paragraph is the last content in the document and
482 // (c) the anchor character is an as-character anchored graphic.
483 bool lcl_HideObj( const SwTxtFrm
& _rFrm
,
484 const RndStdIds _eAnchorType
,
485 const xub_StrLen _nObjAnchorPos
,
486 SwAnchoredObject
* _pAnchoredObj
)
490 if ( _eAnchorType
== FLY_AUTO_CNTNT
)
492 const IDocumentSettingAccess
* pIDSA
= _rFrm
.GetTxtNode()->getIDocumentSettingAccess();
493 if ( !pIDSA
->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING
) &&
494 !pIDSA
->get(IDocumentSettingAccess::OLD_LINE_SPACING
) &&
495 !pIDSA
->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS
) &&
496 pIDSA
->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION
) &&
497 _rFrm
.IsInDocBody() && !_rFrm
.FindNextCnt() )
499 const xub_Unicode cAnchorChar
=
500 _rFrm
.GetTxtNode()->GetTxt().GetChar( _nObjAnchorPos
);
501 if ( cAnchorChar
== CH_TXTATR_BREAKWORD
)
504 const_cast<SwTxtFrm
&>(_rFrm
).GetTxtNode()->GetpSwpHints();
505 const SwTxtAttr
* pHint( 0 );
508 for ( USHORT i
= 0; i
< pHints
->Count(); ++i
)
510 SwTxtAttr
* pPos
= pHints
->GetTextHint(i
);
511 xub_StrLen nStart
= *pPos
->GetStart();
512 if ( _nObjAnchorPos
< nStart
)
514 if ( _nObjAnchorPos
== nStart
&& !pPos
->GetEnd() )
522 pHint
->Which() == RES_TXTATR_FLYCNT
)
524 const SwFrmFmt
* pFrmFmt
=
525 static_cast<const SwTxtFlyCnt
*>(pHint
)->GetFlyCnt().GetFrmFmt();
526 if ( pFrmFmt
->Which() == RES_FLYFRMFMT
)
528 SwNodeIndex nCntntIndex
= *(pFrmFmt
->GetCntnt().GetCntntIdx());
530 if ( nCntntIndex
.GetNode().IsNoTxtNode() )
533 // set needed data structure values for object positioning
534 SWRECTFN( (&_rFrm
) );
535 SwRect
aLastCharRect( _rFrm
.Frm() );
536 (aLastCharRect
.*fnRect
->fnSetWidth
)( 1 );
537 _pAnchoredObj
->maLastCharRect
= aLastCharRect
;
538 _pAnchoredObj
->mnLastTopOfLine
= (aLastCharRect
.*fnRect
->fnGetTop
)();
549 /*************************************************************************
550 * SwTxtFrm::HideAndShowObjects()
551 *************************************************************************/
552 /** method to hide/show objects
554 OD 2004-01-15 #110582#
555 method hides respectively shows objects, which are anchored at paragraph,
556 at/as a character of the paragraph, corresponding to the paragraph and
557 paragraph portion visibility.
559 - is called from HideHidden() - should hide objects in hidden paragraphs and
560 - from _Format() - should hide/show objects in partly visible paragraphs
564 void SwTxtFrm::HideAndShowObjects()
570 // complete paragraph is hidden. Thus, hide all objects
571 for ( sal_uInt32 i
= 0; i
< GetDrawObjs()->Count(); ++i
)
573 SdrObject
* pObj
= (*GetDrawObjs())[i
]->DrawObj();
574 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
575 // --> OD 2005-03-30 #120729# - hotfix: do not hide object
576 // under certain conditions
577 const RndStdIds
eAnchorType( pContact
->GetAnchorId() );
578 const xub_StrLen nObjAnchorPos
= pContact
->GetCntntAnchorIndex().GetIndex();
579 if ( eAnchorType
!= FLY_AUTO_CNTNT
||
580 lcl_HideObj( *this, eAnchorType
, nObjAnchorPos
, (*GetDrawObjs())[i
] ) )
582 pContact
->MoveObjToInvisibleLayer( pObj
);
589 // paragraph is visible, but can contain hidden text portion.
590 // first we check if objects are allowed to be hidden:
591 const SwTxtNode
& rNode
= *GetTxtNode();
592 const ViewShell
* pVsh
= GetShell();
593 const bool bShouldBeHidden
= !pVsh
|| !pVsh
->GetWin() ||
594 !pVsh
->GetViewOptions()->IsShowHiddenChar();
596 // Thus, show all objects, which are anchored at paragraph and
597 // hide/show objects, which are anchored at/as character, according
598 // to the visibility of the anchor character.
599 for ( sal_uInt32 i
= 0; i
< GetDrawObjs()->Count(); ++i
)
601 SdrObject
* pObj
= (*GetDrawObjs())[i
]->DrawObj();
602 SwContact
* pContact
= static_cast<SwContact
*>(pObj
->GetUserCall());
603 // --> OD 2005-03-30 #120729# - determine anchor type only once
604 const RndStdIds
eAnchorType( pContact
->GetAnchorId() );
607 if ( eAnchorType
== FLY_AT_CNTNT
)
609 pContact
->MoveObjToVisibleLayer( pObj
);
611 else if ( eAnchorType
== FLY_AUTO_CNTNT
||
612 eAnchorType
== FLY_IN_CNTNT
)
614 xub_StrLen nHiddenStart
;
615 xub_StrLen nHiddenEnd
;
616 xub_StrLen nObjAnchorPos
= pContact
->GetCntntAnchorIndex().GetIndex();
617 SwScriptInfo::GetBoundsOfHiddenRange( rNode
, nObjAnchorPos
, nHiddenStart
, nHiddenEnd
, 0 );
618 // --> OD 2005-03-30 #120729# - hotfix: do not hide object
619 // under certain conditions
620 if ( nHiddenStart
!= STRING_LEN
&& bShouldBeHidden
&&
621 lcl_HideObj( *this, eAnchorType
, nObjAnchorPos
, (*GetDrawObjs())[i
] ) )
623 pContact
->MoveObjToInvisibleLayer( pObj
);
625 pContact
->MoveObjToVisibleLayer( pObj
);
630 "<SwTxtFrm::HideAndShowObjects()> - object not anchored at/inside paragraph!?" );
638 FindMaster()->HideAndShowObjects();
642 /*************************************************************************
643 * SwTxtFrm::FindBrk()
645 * Liefert die erste Trennmoeglichkeit in der aktuellen Zeile zurueck.
646 * Die Methode wird in SwTxtFrm::Format() benutzt, um festzustellen, ob
647 * die Vorgaengerzeile mitformatiert werden muss.
648 * nFound ist <= nEndLine.
649 *************************************************************************/
651 xub_StrLen
SwTxtFrm::FindBrk( const XubString
&rTxt
,
652 const xub_StrLen nStart
, const xub_StrLen nEnd
) const
654 xub_StrLen nFound
= nStart
;
655 const xub_StrLen nEndLine
= Min( nEnd
, rTxt
.Len() );
657 // Wir ueberlesen erst alle Blanks am Anfang der Zeile (vgl. Bug 2235).
658 while( nFound
<= nEndLine
&& ' ' == rTxt
.GetChar( 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
&& ' ' != rTxt
.GetChar( nFound
) )
671 /*************************************************************************
672 * SwTxtFrm::IsIdxInside()
673 *************************************************************************/
675 sal_Bool
SwTxtFrm::IsIdxInside( const xub_StrLen nPos
, const xub_StrLen nLen
) const
677 if( GetOfst() > nPos
+ nLen
) // d.h., der Bereich liegt komplett vor uns.
680 if( !GetFollow() ) // der Bereich liegt nicht komplett vor uns,
681 return sal_True
; // nach uns kommt niemand mehr.
683 const xub_StrLen nMax
= GetFollow()->GetOfst();
685 // der Bereich liegt nicht komplett hinter uns bzw.
686 // unser Text ist geloescht worden.
687 if( nMax
> nPos
|| nMax
> GetTxt().Len() )
690 // changes made in the first line of a follow can modify the master
691 const SwParaPortion
* pPara
= GetFollow()->GetPara();
692 return pPara
&& ( nPos
<= nMax
+ pPara
->GetLen() );
695 /*************************************************************************
696 * SwTxtFrm::InvalidateRange()
697 *************************************************************************/
698 inline void SwTxtFrm::InvalidateRange(const SwCharRange
&aRange
, const long nD
)
700 if ( IsIdxInside( aRange
.Start(), aRange
.Len() ) )
701 _InvalidateRange( aRange
, nD
);
704 /*************************************************************************
705 * SwTxtFrm::_InvalidateRange()
706 *************************************************************************/
708 void SwTxtFrm::_InvalidateRange( const SwCharRange
&aRange
, const long nD
)
715 SetWidow( sal_False
);
716 SwParaPortion
*pPara
= GetPara();
718 sal_Bool bInv
= sal_False
;
721 //Auf nDelta werden die Differenzen zwischen alter und
722 //neuer Zeilenlaenge aufaddiert, deshalb ist es negativ,
723 //wenn Zeichen eingefuegt wurden, positiv, wenn Zeichen
725 *(pPara
->GetDelta()) += nD
;
728 SwCharRange
&rReformat
= *(pPara
->GetReformat());
729 if(aRange
!= rReformat
) {
730 if( STRING_LEN
== rReformat
.Len() )
738 // 90365: nD is passed to a follow two times
740 // ((SwTxtFrm*)GetFollow())->InvalidateRange( aRange, nD );
745 /*************************************************************************
746 * SwTxtFrm::CalcLineSpace()
747 *************************************************************************/
749 void SwTxtFrm::CalcLineSpace()
751 ASSERT( ! IsVertical() || ! IsSwapped(),
752 "SwTxtFrm::CalcLineSpace with swapped frame!" )
754 if( IsLocked() || !HasPara() )
757 SwParaPortion
*pPara
;
759 GetTxtNode()->GetSwAttrSet().GetLRSpace().IsAutoFirst() ||
760 ( pPara
= GetPara() )->IsFixLineHeight() )
766 Size
aNewSize( Prt().SSize() );
768 SwTxtFormatInfo
aInf( this );
769 SwTxtFormatter
aLine( this, &aInf
);
770 if( aLine
.GetDropLines() )
777 aLine
.RecalcRealHeight();
779 aNewSize
.Height() = (aLine
.Y() - Frm().Top()) + aLine
.GetLineHeight();
781 SwTwips nDelta
= aNewSize
.Height() - Prt().Height();
782 // 4291: Unterlauf bei Flys
783 if( aInf
.GetTxtFly()->IsOn() )
785 SwRect
aTmpFrm( Frm() );
787 aTmpFrm
.Height( Prt().Height() );
789 aTmpFrm
.Height( aNewSize
.Height() );
790 if( aInf
.GetTxtFly()->Relax( aTmpFrm
) )
799 SwTxtFrmBreak
aBreak( this );
800 if( GetFollow() || aBreak
.IsBreakNow( aLine
) )
802 // Wenn es einen Follow() gibt, oder wenn wir an dieser
803 // Stelle aufbrechen muessen, so wird neu formatiert.
808 // Alles nimmt seinen gewohnten Gang ...
809 pPara
->SetPrepAdjust();
816 // SET_WRONG( nPos, nCnt, bMove )
818 #define SET_WRONG( nPos, nCnt, bMove ) \
820 lcl_SetWrong( *this, nPos, nCnt, bMove ); \
823 void lcl_SetWrong( SwTxtFrm
& rFrm
, xub_StrLen nPos
, long nCnt
, bool bMove
)
825 if ( !rFrm
.IsFollow() )
827 SwTxtNode
* pTxtNode
= rFrm
.GetTxtNode();
828 IGrammarContact
* pGrammarContact
= getGrammarContact( *pTxtNode
);
829 SwGrammarMarkUp
* pWrongGrammar
= pGrammarContact
?
830 pGrammarContact
->getGrammarCheck( *pTxtNode
, false ) :
831 pTxtNode
->GetGrammarCheck();
832 bool bGrammarProxy
= pWrongGrammar
!= pTxtNode
->GetGrammarCheck();
835 if( pTxtNode
->GetWrong() )
836 pTxtNode
->GetWrong()->Move( nPos
, nCnt
);
838 pWrongGrammar
->MoveGrammar( nPos
, nCnt
);
839 if( bGrammarProxy
&& pTxtNode
->GetGrammarCheck() )
840 pTxtNode
->GetGrammarCheck()->MoveGrammar( nPos
, nCnt
);
841 if( pTxtNode
->GetSmartTags() )
842 pTxtNode
->GetSmartTags()->Move( nPos
, nCnt
);
846 xub_StrLen nLen
= (xub_StrLen
)nCnt
;
847 if( pTxtNode
->GetWrong() )
848 pTxtNode
->GetWrong()->Invalidate( nPos
, nLen
);
850 pWrongGrammar
->Invalidate( nPos
, nLen
);
851 if( pTxtNode
->GetSmartTags() )
852 pTxtNode
->GetSmartTags()->Invalidate( nPos
, nLen
);
854 if ( !pTxtNode
->GetWrong() && !pTxtNode
->IsWrongDirty() )
856 pTxtNode
->SetWrong( new SwWrongList( WRONGLIST_SPELL
) );
857 pTxtNode
->GetWrong()->SetInvalid( nPos
, nPos
+ (USHORT
)( nCnt
> 0 ? nCnt
: 1 ) );
859 if ( !pTxtNode
->GetSmartTags() && !pTxtNode
->IsSmartTagDirty() )
862 pTxtNode
->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG
) );
863 pTxtNode
->GetSmartTags()->SetInvalid( nPos
, nPos
+ (USHORT
)( nCnt
> 0 ? nCnt
: 1 ) );
865 pTxtNode
->SetWrongDirty( true );
866 pTxtNode
->SetGrammarCheckDirty( true );
867 pTxtNode
->SetWordCountDirty( true );
868 pTxtNode
->SetAutoCompleteWordDirty( true );
870 pTxtNode
->SetSmartTagDirty( true );
873 SwRootFrm
*pRootFrm
= rFrm
.FindRootFrm();
876 pRootFrm
->SetNeedGrammarCheck( TRUE
);
879 SwPageFrm
*pPage
= rFrm
.FindPageFrm();
882 pPage
->InvalidateSpelling();
883 pPage
->InvalidateAutoCompleteWords();
884 pPage
->InvalidateWordCount();
885 pPage
->InvalidateSmartTags();
890 // SET_SCRIPT_INVAL( nPos )
893 #define SET_SCRIPT_INVAL( nPos )\
894 lcl_SetScriptInval( *this, nPos );
896 void lcl_SetScriptInval( SwTxtFrm
& rFrm
, xub_StrLen nPos
)
899 rFrm
.GetPara()->GetScriptInfo().SetInvalidity( nPos
);
902 void lcl_ModifyOfst( SwTxtFrm
* pFrm
, xub_StrLen nPos
, xub_StrLen nLen
)
904 while( pFrm
&& pFrm
->GetOfst() <= nPos
)
905 pFrm
= pFrm
->GetFollow();
908 pFrm
->ManipOfst( pFrm
->GetOfst() + nLen
);
909 pFrm
= pFrm
->GetFollow();
913 /*************************************************************************
915 *************************************************************************/
917 void SwTxtFrm::Modify( SfxPoolItem
*pOld
, SfxPoolItem
*pNew
)
919 const MSHORT nWhich
= pOld
? pOld
->Which() : pNew
? pNew
->Which() : 0;
921 //Wuensche die FrmAttribute betreffen werden von der Basisklasse
923 if( IsInRange( aFrmFmtSetRange
, nWhich
) || RES_FMT_CHG
== nWhich
)
925 SwCntntFrm::Modify( pOld
, pNew
);
926 if( nWhich
== RES_FMT_CHG
&& GetShell() )
928 // Collection hat sich geaendert
929 Prepare( PREP_CLEAR
);
931 SET_WRONG( 0, STRING_LEN
, false );
932 SetDerivedR2L( sal_False
);
934 // OD 09.12.2002 #105576# - Force complete paint due to existing
942 // Im gelockten Zustand werden keine Bestellungen angenommen.
946 // Dies spart Stack, man muss nur aufpassen,
947 // dass sie Variablen gesetzt werden.
948 xub_StrLen nPos
, nLen
;
949 sal_Bool bSetFldsDirty
= sal_False
;
950 sal_Bool bRecalcFtnFlag
= sal_False
;
961 nPos
= ((SwInsChr
*)pNew
)->nPos
;
962 InvalidateRange( SwCharRange( nPos
, 1 ), 1 );
963 SET_WRONG( nPos
, 1, true )
964 SET_SCRIPT_INVAL( nPos
)
965 bSetFldsDirty
= sal_True
;
967 lcl_ModifyOfst( this, nPos
, 1 );
972 nPos
= ((SwInsTxt
*)pNew
)->nPos
;
973 nLen
= ((SwInsTxt
*)pNew
)->nLen
;
974 if( IsIdxInside( nPos
, nLen
) )
978 // 6969: Aktualisierung der NumPortions auch bei leeren Zeilen!
982 Prepare( PREP_CLEAR
);
985 _InvalidateRange( SwCharRange( nPos
, nLen
), nLen
);
987 SET_WRONG( nPos
, nLen
, true )
988 SET_SCRIPT_INVAL( nPos
)
989 bSetFldsDirty
= sal_True
;
991 lcl_ModifyOfst( this, nPos
, nLen
);
996 nPos
= ((SwDelChr
*)pNew
)->nPos
;
997 InvalidateRange( SwCharRange( nPos
, 1 ), -1 );
998 SET_WRONG( nPos
, -1, true )
999 SET_SCRIPT_INVAL( nPos
)
1000 bSetFldsDirty
= bRecalcFtnFlag
= sal_True
;
1002 lcl_ModifyOfst( this, nPos
, STRING_LEN
);
1007 nPos
= ((SwDelTxt
*)pNew
)->nStart
;
1008 nLen
= ((SwDelTxt
*)pNew
)->nLen
;
1011 if( IsIdxInside( nPos
, nLen
) )
1016 InvalidateRange( SwCharRange( nPos
, 1 ), m
);
1018 SET_WRONG( nPos
, m
, true )
1019 SET_SCRIPT_INVAL( nPos
)
1020 bSetFldsDirty
= bRecalcFtnFlag
= sal_True
;
1022 lcl_ModifyOfst( this, nPos
, nLen
);
1025 case RES_UPDATE_ATTR
:
1027 nPos
= ((SwUpdateAttr
*)pNew
)->nStart
;
1028 nLen
= ((SwUpdateAttr
*)pNew
)->nEnd
- nPos
;
1029 if( IsIdxInside( nPos
, nLen
) )
1031 // Es muss in jedem Fall neu formatiert werden,
1032 // auch wenn der invalidierte Bereich null ist.
1033 // Beispiel: leere Zeile, 14Pt einstellen !
1034 // if( !nLen ) nLen = 1;
1036 // 6680: FtnNummern muessen formatiert werden.
1040 _InvalidateRange( SwCharRange( nPos
, nLen
) );
1041 MSHORT nTmp
= ((SwUpdateAttr
*)pNew
)->nWhichAttr
;
1043 if( ! nTmp
|| RES_TXTATR_CHARFMT
== nTmp
|| RES_TXTATR_AUTOFMT
== nTmp
||
1044 RES_FMT_CHG
== nTmp
|| RES_ATTRSET_CHG
== nTmp
)
1046 SET_WRONG( nPos
, nPos
+ nLen
, false )
1047 SET_SCRIPT_INVAL( nPos
)
1052 case RES_OBJECTDYING
:
1055 case RES_PARATR_LINESPACING
:
1060 if( IsInSct() && !GetPrev() )
1062 SwSectionFrm
*pSect
= FindSctFrm();
1063 if( pSect
->ContainsAny() == this )
1064 pSect
->InvalidatePrt();
1067 // OD 09.01.2004 #i11859# - correction:
1068 // (1) Also invalidate next frame on next page/column.
1069 // (2) Skip empty sections and hidden paragraphs
1070 // Thus, use method <InvalidateNextPrtArea()>
1071 InvalidateNextPrtArea();
1076 case RES_TXTATR_FIELD
:
1078 nPos
= *((SwFmtFld
*)pNew
)->GetTxtFld()->GetStart();
1079 if( IsIdxInside( nPos
, 1 ) )
1084 // opt: invalidate aufs Window ?
1089 _InvalidateRange( SwCharRange( nPos
, 1 ) );
1091 bSetFldsDirty
= sal_True
;
1093 if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
1094 SET_WRONG( nPos
, nPos
+ 1, false )
1097 case RES_TXTATR_FTN
:
1099 nPos
= *((SwFmtFtn
*)pNew
)->GetTxtFtn()->GetStart();
1100 if( IsInFtn() || IsIdxInside( nPos
, 1 ) )
1101 Prepare( PREP_FTN
, ((SwFmtFtn
*)pNew
)->GetTxtFtn() );
1105 case RES_ATTRSET_CHG
:
1107 InvalidateLineNum();
1109 SwAttrSet
& rNewSet
= *((SwAttrSetChg
*)pNew
)->GetChgSet();
1110 const SfxPoolItem
* pItem
;
1112 MSHORT nCount
= rNewSet
.Count();
1114 if( SFX_ITEM_SET
== rNewSet
.GetItemState( RES_TXTATR_FTN
,
1115 sal_False
, &pItem
))
1117 nPos
= *((SwFmtFtn
*)pItem
)->GetTxtFtn()->GetStart();
1118 if( IsIdxInside( nPos
, 1 ) )
1119 Prepare( PREP_FTN
, pNew
);
1124 if( SFX_ITEM_SET
== rNewSet
.GetItemState( RES_TXTATR_FIELD
,
1125 sal_False
, &pItem
))
1127 nPos
= *((SwFmtFld
*)pItem
)->GetTxtFld()->GetStart();
1128 if( IsIdxInside( nPos
, 1 ) )
1130 const SfxPoolItem
& rOldItem
= ((SwAttrSetChg
*)pOld
)->
1131 GetChgSet()->Get( RES_TXTATR_FIELD
);
1132 if( pItem
== &rOldItem
)
1135 // opt: invalidate aufs Window ?
1140 _InvalidateRange( SwCharRange( nPos
, 1 ) );
1145 sal_Bool bLineSpace
= SFX_ITEM_SET
== rNewSet
.GetItemState(
1146 RES_PARATR_LINESPACING
, sal_False
),
1147 bRegister
= SFX_ITEM_SET
== rNewSet
.GetItemState(
1148 RES_PARATR_REGISTER
, sal_False
);
1149 if ( bLineSpace
|| bRegister
)
1151 Prepare( bRegister
? PREP_REGISTER
: PREP_ADJUST_FRM
);
1156 // OD 09.01.2004 #i11859# - correction:
1157 // (1) Also invalidate next frame on next page/column.
1158 // (2) Skip empty sections and hidden paragraphs
1159 // Thus, use method <InvalidateNextPrtArea()>
1160 InvalidateNextPrtArea();
1167 if( IsInSct() && !GetPrev() )
1169 SwSectionFrm
*pSect
= FindSctFrm();
1170 if( pSect
->ContainsAny() == this )
1171 pSect
->InvalidatePrt();
1177 if ( SFX_ITEM_SET
== rNewSet
.GetItemState( RES_PARATR_SPLIT
,
1182 Prepare( PREP_CLEAR
);
1188 if( SFX_ITEM_SET
== rNewSet
.GetItemState( RES_BACKGROUND
, sal_False
)
1189 && !IsFollow() && GetDrawObjs() )
1191 SwSortedObjs
*pObjs
= GetDrawObjs();
1192 for ( int i
= 0; GetDrawObjs() && i
< int(pObjs
->Count()); ++i
)
1194 SwAnchoredObject
* pAnchoredObj
= (*pObjs
)[MSHORT(i
)];
1195 if ( pAnchoredObj
->ISA(SwFlyFrm
) )
1197 SwFlyFrm
*pFly
= static_cast<SwFlyFrm
*>(pAnchoredObj
);
1198 if( !pFly
->IsFlyInCntFrm() )
1200 const SvxBrushItem
&rBack
=
1201 pFly
->GetAttrSet()->GetBackground();
1202 // OD 20.08.2002 #99657# #GetTransChg#
1203 // following condition determines, if the fly frame
1204 // "inherites" the background color of text frame.
1205 // This is the case, if fly frame background
1206 // color is "no fill"/"auto fill" and if the fly frame
1207 // has no background graphic.
1208 // Thus, check complete fly frame background
1209 // color and *not* only its transparency value
1210 if ( (rBack
.GetColor() == COL_TRANSPARENT
) &&
1211 //if( rBack.GetColor().GetTransparency() &&
1212 rBack
.GetGraphicPos() == GPOS_NONE
)
1214 pFly
->SetCompletePaint();
1215 pFly
->InvalidatePage();
1222 if ( SFX_ITEM_SET
==
1223 rNewSet
.GetItemState( RES_TXTATR_CHARFMT
, sal_False
) )
1225 SET_WRONG( 0, STRING_LEN
, false )
1226 SET_SCRIPT_INVAL( 0 )
1228 else if ( SFX_ITEM_SET
==
1229 rNewSet
.GetItemState( RES_CHRATR_LANGUAGE
, sal_False
) ||
1231 rNewSet
.GetItemState( RES_CHRATR_CJK_LANGUAGE
, sal_False
) ||
1233 rNewSet
.GetItemState( RES_CHRATR_CTL_LANGUAGE
, sal_False
) )
1234 SET_WRONG( 0, STRING_LEN
, false )
1235 else if ( SFX_ITEM_SET
==
1236 rNewSet
.GetItemState( RES_CHRATR_FONT
, sal_False
) ||
1238 rNewSet
.GetItemState( RES_CHRATR_CJK_FONT
, sal_False
) ||
1240 rNewSet
.GetItemState( RES_CHRATR_CTL_FONT
, sal_False
) )
1241 SET_SCRIPT_INVAL( 0 )
1242 else if ( SFX_ITEM_SET
==
1243 rNewSet
.GetItemState( RES_FRAMEDIR
, sal_False
) )
1245 SetDerivedR2L( sal_False
);
1247 // OD 09.12.2002 #105576# - Force complete paint due to existing
1257 Prepare( PREP_CLEAR
);
1263 SwAttrSetChg
aOldSet( *(SwAttrSetChg
*)pOld
);
1264 SwAttrSetChg
aNewSet( *(SwAttrSetChg
*)pNew
);
1268 aOldSet
.ClearItem( RES_TXTATR_FTN
);
1269 aNewSet
.ClearItem( RES_TXTATR_FTN
);
1273 aOldSet
.ClearItem( RES_TXTATR_FIELD
);
1274 aNewSet
.ClearItem( RES_TXTATR_FIELD
);
1276 if ( 0x04 & nClear
)
1280 aOldSet
.ClearItem( RES_PARATR_LINESPACING
);
1281 aNewSet
.ClearItem( RES_PARATR_LINESPACING
);
1285 aOldSet
.ClearItem( RES_PARATR_REGISTER
);
1286 aNewSet
.ClearItem( RES_PARATR_REGISTER
);
1289 if ( 0x08 & nClear
)
1291 aOldSet
.ClearItem( RES_PARATR_SPLIT
);
1292 aNewSet
.ClearItem( RES_PARATR_SPLIT
);
1294 SwCntntFrm::Modify( &aOldSet
, &aNewSet
);
1297 SwCntntFrm::Modify( pOld
, pNew
);
1300 // --> OD 2009-01-06 #i88069#
1303 GetShell()->InvalidateAccessibleParaAttrs( *this );
1309 /* Seit dem neuen Blocksatz muessen wir immer neu formatieren:
1310 case RES_PARATR_ADJUST:
1314 Prepare( PREP_CLEAR );
1319 // 6870: SwDocPosUpdate auswerten.
1320 case RES_DOCPOS_UPDATE
:
1324 const SwDocPosUpdate
*pDocPos
= (const SwDocPosUpdate
*)pOld
;
1325 if( pDocPos
->nDocPos
<= aFrm
.Top() )
1327 const SwFmtFld
*pFld
= (const SwFmtFld
*)pNew
;
1329 SwCharRange( *pFld
->GetTxtFld()->GetStart(), 1 ) );
1334 case RES_PARATR_SPLIT
:
1337 Prepare( PREP_CLEAR
);
1338 bSetFldsDirty
= sal_True
;
1341 SetDerivedR2L( sal_False
);
1346 Prepare( PREP_CLEAR
);
1350 //Wird z.B. bei HiddenPara mit 0 gerufen.
1352 if ( 0 != (pNxt
= FindNext()) )
1353 pNxt
->InvalidatePrt();
1359 GetNode()->getIDocumentFieldsAccess()->SetFieldsDirty( sal_True
, GetNode(), 1 );
1361 if ( bRecalcFtnFlag
)
1365 sal_Bool
SwTxtFrm::GetInfo( SfxPoolItem
&rHnt
) const
1367 if ( RES_VIRTPAGENUM_INFO
== rHnt
.Which() && IsInDocBody() && ! IsFollow() )
1369 SwVirtPageNumInfo
&rInfo
= (SwVirtPageNumInfo
&)rHnt
;
1370 const SwPageFrm
*pPage
= FindPageFrm();
1373 if ( pPage
== rInfo
.GetOrigPage() && !GetPrev() )
1375 //Das sollte er sein (kann allenfalls temporaer anders sein,
1376 // sollte uns das beunruhigen?)
1377 rInfo
.SetInfo( pPage
, this );
1380 if ( pPage
->GetPhyPageNum() < rInfo
.GetOrigPage()->GetPhyPageNum() &&
1381 (!rInfo
.GetPage() || pPage
->GetPhyPageNum() > rInfo
.GetPage()->GetPhyPageNum()))
1383 //Das koennte er sein.
1384 rInfo
.SetInfo( pPage
, this );
1391 /*************************************************************************
1392 * SwTxtFrm::PrepWidows()
1393 *************************************************************************/
1395 void SwTxtFrm::PrepWidows( const MSHORT nNeed
, sal_Bool bNotify
)
1397 ASSERT(GetFollow() && nNeed
, "+SwTxtFrm::Prepare: lost all friends");
1399 SwParaPortion
*pPara
= GetPara();
1402 pPara
->SetPrepWidows( sal_True
);
1404 // These two lines of code have been deleted for #102340#.
1405 // Obviously the widow control does not work if we have a
1406 // pMaster->pFollow->pFollow situation:
1408 // returnen oder nicht ist hier die Frage.
1409 // Ohne IsLocked() ist 5156 gefaehrlich,
1410 // ohne IsFollow() werden die Orphans unterdrueckt: 6968.
1411 // Abfrage auf IsLocked erst hier, weil das Flag gesetzt werden soll.
1412 // if( IsLocked() && IsFollow() )
1415 MSHORT nHave
= nNeed
;
1417 // Wir geben ein paar Zeilen ab und schrumpfen im CalcPreps()
1418 SWAP_IF_NOT_SWAPPED( this )
1420 SwTxtSizeInfo
aInf( this );
1421 SwTxtMargin
aLine( this, &aInf
);
1423 xub_StrLen nTmpLen
= aLine
.GetCurr()->GetLen();
1424 while( nHave
&& aLine
.PrevLine() )
1428 nTmpLen
= aLine
.GetCurr()->GetLen();
1430 // In dieser Ecke tummelten sich einige Bugs: 7513, 7606.
1431 // Wenn feststeht, dass Zeilen abgegeben werden koennen,
1432 // muss der Master darueber hinaus die Widow-Regel ueberpruefen.
1436 if( !IsFollow() ) //Nur ein Master entscheidet ueber Orphans
1438 const WidowsAndOrphans
aWidOrp( this );
1439 bSplit
= ( aLine
.GetLineNr() >= aWidOrp
.GetOrphansLines() &&
1440 aLine
.GetLineNr() >= aLine
.GetDropLines() );
1447 GetFollow()->SetOfst( aLine
.GetEnd() );
1448 aLine
.TruncLines( sal_True
);
1449 if( pPara
->IsFollowField() )
1450 GetFollow()->SetFieldFollow( sal_True
);
1462 /*************************************************************************
1464 *************************************************************************/
1466 sal_Bool
lcl_ErgoVadis( SwTxtFrm
* pFrm
, xub_StrLen
&rPos
, const PrepareHint ePrep
)
1468 const SwFtnInfo
&rFtnInfo
= pFrm
->GetNode()->GetDoc()->GetFtnInfo();
1469 if( ePrep
== PREP_ERGOSUM
)
1471 if( !rFtnInfo
.aErgoSum
.Len() )
1473 rPos
= pFrm
->GetOfst();
1477 if( !rFtnInfo
.aQuoVadis
.Len() )
1479 if( pFrm
->HasFollow() )
1480 rPos
= pFrm
->GetFollow()->GetOfst();
1482 rPos
= pFrm
->GetTxt().Len();
1484 --rPos
; // unser letztes Zeichen
1489 void SwTxtFrm::Prepare( const PrepareHint ePrep
, const void* pVoid
,
1492 SwFrmSwapper
aSwapper( this, sal_False
);
1494 #if OSL_DEBUG_LEVEL > 1
1495 const SwTwips nDbgY
= Frm().Top();
1503 case PREP_BOSS_CHGD
:
1504 SetInvalidVert( TRUE
); // Test
1505 case PREP_WIDOWS_ORPHANS
:
1507 case PREP_FTN_GONE
: return;
1509 case PREP_POS_CHGD
:
1511 // Auch in (spaltigen) Bereichen ist ein InvalidateSize notwendig,
1512 // damit formatiert wird und ggf. das bUndersized gesetzt wird.
1513 if( IsInFly() || IsInSct() )
1515 SwTwips nTmpBottom
= GetUpper()->Frm().Top() +
1516 GetUpper()->Prt().Bottom();
1517 if( nTmpBottom
< Frm().Bottom() )
1520 // Gibt es ueberhaupt Flys auf der Seite ?
1521 SwTxtFly
aTxtFly( this );
1522 if( aTxtFly
.IsOn() )
1524 // Ueberlappt irgendein Fly ?
1526 if ( aTxtFly
.IsOn() || IsUndersized() )
1529 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue())
1532 GETGRID( FindPageFrm() )
1533 if ( pGrid
&& GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1536 // --> OD 2004-07-16 #i28701# - consider anchored objects
1537 if ( GetDrawObjs() )
1548 if( !HasPara() && PREP_MUST_FIT
!= ePrep
)
1550 SetInvalidVert( TRUE
); // Test
1551 ASSERT( !IsLocked(), "SwTxtFrm::Prepare: three of a perfect pair" );
1559 //Objekt mit Locking aus dem Cache holen.
1560 SwTxtLineAccess
aAccess( this );
1561 SwParaPortion
*pPara
= aAccess
.GetPara();
1565 case PREP_MOVEFTN
: Frm().Height(0);
1570 case PREP_ADJUST_FRM
: pPara
->SetPrepAdjust( sal_True
);
1571 if( IsFtnNumFrm() != pPara
->IsFtnNum() ||
1574 InvalidateRange( SwCharRange( 0, 1 ), 1);
1575 if( GetOfst() && !IsFollow() )
1579 case PREP_MUST_FIT
: pPara
->SetPrepMustFit( sal_True
);
1581 case PREP_WIDOWS_ORPHANS
: pPara
->SetPrepAdjust( sal_True
);
1585 // MustFit ist staerker als alles anderes
1586 if( pPara
->IsPrepMustFit() )
1588 // Siehe Kommentar in WidowsAndOrphans::FindOrphans und CalcPreps()
1589 PrepWidows( *(const MSHORT
*)pVoid
, bNotify
);
1594 SwTxtFtn
*pFtn
= (SwTxtFtn
*)pVoid
;
1597 // Bin ich der erste TxtFrm einer Fussnote ?
1599 // Wir sind also ein TxtFrm der Fussnote, die
1600 // die Fussnotenzahl zur Anzeige bringen muss.
1601 // Oder den ErgoSum-Text...
1602 InvalidateRange( SwCharRange( 0, 1 ), 1);
1606 // Wir sind der letzte Ftn, jetzt muessten die
1607 // QuoVadis-Texte geupdated werden.
1608 const SwFtnInfo
&rFtnInfo
= GetNode()->GetDoc()->GetFtnInfo();
1609 if( !pPara
->UpdateQuoVadis( rFtnInfo
.aQuoVadis
) )
1611 xub_StrLen nPos
= pPara
->GetParLen();
1614 InvalidateRange( SwCharRange( nPos
, 1 ), 1);
1620 // Wir sind also der TxtFrm _mit_ der Fussnote
1621 const xub_StrLen nPos
= *pFtn
->GetStart();
1622 InvalidateRange( SwCharRange( nPos
, 1 ), 1);
1626 case PREP_BOSS_CHGD
:
1630 SetInvalidVert( FALSE
);
1631 BOOL bOld
= IsVertical();
1632 SetInvalidVert( TRUE
);
1633 if( bOld
!= IsVertical() )
1634 InvalidateRange( SwCharRange( GetOfst(), STRING_LEN
) );
1639 xub_StrLen nNxtOfst
= GetFollow()->GetOfst();
1642 InvalidateRange( SwCharRange( nNxtOfst
, 1 ), 1);
1647 if( lcl_ErgoVadis( this, nPos
, PREP_QUOVADIS
) )
1648 InvalidateRange( SwCharRange( nPos
, 1 ), 0 );
1649 if( lcl_ErgoVadis( this, nPos
, PREP_ERGOSUM
) )
1650 InvalidateRange( SwCharRange( nPos
, 1 ), 0 );
1652 // 4739: Wenn wir ein Seitennummernfeld besitzen, muessen wir
1653 // die Stellen invalidieren.
1654 SwpHints
*pHints
= GetTxtNode()->GetpSwpHints();
1657 const USHORT nSize
= pHints
->Count();
1658 const xub_StrLen nEnd
= GetFollow() ?
1659 GetFollow()->GetOfst() : STRING_LEN
;
1660 for ( USHORT i
= 0; i
< nSize
; ++i
)
1662 const SwTxtAttr
*pHt
= (*pHints
)[i
];
1663 const xub_StrLen nStart
= *pHt
->GetStart();
1664 if( nStart
>= GetOfst() )
1666 if( nStart
>= nEnd
)
1667 i
= nSize
; // fuehrt das Ende herbei
1670 // 4029: wenn wir zurueckfliessen und eine Ftn besitzen, so
1671 // fliesst die Ftn in jedem Fall auch mit. Damit sie nicht im
1672 // Weg steht, schicken wir uns ein ADJUST_FRM.
1673 // pVoid != 0 bedeutet MoveBwd()
1674 const MSHORT nWhich
= pHt
->Which();
1675 if( RES_TXTATR_FIELD
== nWhich
||
1676 (HasFtn() && pVoid
&& RES_TXTATR_FTN
== nWhich
))
1677 InvalidateRange( SwCharRange( nStart
, 1 ), 1 );
1682 // A new boss, a new chance for growing
1683 if( IsUndersized() )
1686 InvalidateRange( SwCharRange( GetOfst(), 1 ), 1);
1691 case PREP_POS_CHGD
:
1693 if ( GetValidPrtAreaFlag() )
1695 GETGRID( FindPageFrm() )
1696 if ( pGrid
&& GetTxtNode()->GetSwAttrSet().GetParaGrid().GetValue() )
1700 // Falls wir mit niemandem ueberlappen:
1701 // Ueberlappte irgendein Fly _vor_ der Positionsaenderung ?
1702 sal_Bool bFormat
= pPara
->HasFly();
1707 SwTwips nTmpBottom
= GetUpper()->Frm().Top() +
1708 GetUpper()->Prt().Bottom();
1709 if( nTmpBottom
< Frm().Bottom() )
1714 if ( GetDrawObjs() )
1716 const sal_uInt32 nCnt
= GetDrawObjs()->Count();
1717 for ( MSHORT i
= 0; i
< nCnt
; ++i
)
1719 SwAnchoredObject
* pAnchoredObj
= (*GetDrawObjs())[i
];
1720 // --> OD 2004-07-16 #i28701# - consider all
1721 // to-character anchored objects
1722 if ( pAnchoredObj
->GetFrmFmt().GetAnchor().GetAnchorId()
1732 // Gibt es ueberhaupt Flys auf der Seite ?
1733 SwTxtFly
aTxtFly( this );
1734 if( aTxtFly
.IsOn() )
1736 // Ueberlappt irgendein Fly ?
1738 bFormat
= aTxtFly
.IsOn() || IsUndersized();
1748 if( pPara
->GetRepaint()->HasArea() )
1757 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1758 Prepare( PREP_REGISTER
, 0, bNotify
);
1759 // Durch Positionsverschiebungen mit Ftns muessen die
1760 // Frames neu adjustiert werden.
1763 Prepare( PREP_ADJUST_FRM
, 0, bNotify
);
1767 return; // damit kein SetPrep() erfolgt.
1772 if( GetTxtNode()->GetSwAttrSet().GetRegister().GetValue() )
1774 pPara
->SetPrepAdjust( sal_True
);
1779 if ( 0 != ( pNxt
= GetIndNext() ) )
1781 pNxt
->_InvalidatePrt();
1782 if ( pNxt
->IsLayoutFrm() )
1783 pNxt
->InvalidatePage();
1788 case PREP_FTN_GONE
:
1790 // Wenn ein Follow uns ruft, weil eine Fussnote geloescht wird, muss unsere
1791 // letzte Zeile formatiert werden, damit ggf. die erste Zeile des Follows
1792 // hochrutschen kann, die extra auf die naechste Seite gerutscht war, um mit
1793 // der Fussnote zusammen zu sein, insbesondere bei spaltigen Bereichen.
1794 ASSERT( GetFollow(), "PREP_FTN_GONE darf nur vom Follow gerufen werden" );
1795 xub_StrLen nPos
= GetFollow()->GetOfst();
1796 if( IsFollow() && GetOfst() == nPos
) // falls wir gar keine Textmasse besitzen,
1797 FindMaster()->Prepare( PREP_FTN_GONE
); // rufen wir das Prepare unseres Masters
1799 --nPos
; // das Zeichen vor unserem Follow
1800 InvalidateRange( SwCharRange( nPos
, 1 ), 0 );
1807 if( lcl_ErgoVadis( this, nPos
, ePrep
) )
1808 InvalidateRange( SwCharRange( nPos
, 1 ), 0 );
1811 case PREP_FLY_ATTR_CHG
:
1815 xub_StrLen nWhere
= CalcFlyPos( (SwFrmFmt
*)pVoid
);
1816 ASSERT( STRING_LEN
!= nWhere
, "Prepare: Why me?" );
1817 InvalidateRange( SwCharRange( nWhere
, 1 ) );
1820 // else ... Laufe in den Default-Switch
1827 if( PREP_FLY_ARRIVE
== ePrep
|| PREP_FLY_LEAVE
== ePrep
)
1829 xub_StrLen nLen
= ( GetFollow() ? GetFollow()->GetOfst() :
1830 STRING_LEN
) - GetOfst();
1831 InvalidateRange( SwCharRange( GetOfst(), nLen
), 0 );
1836 if( pPara
->GetRepaint()->HasArea() )
1840 if( GetOfst() && !IsFollow() )
1847 return; // damit kein SetPrep() erfolgt.
1851 pPara
->SetPrep( sal_True
);
1854 /* -----------------11.02.99 17:56-------------------
1855 * Kleine Hilfsklasse mit folgender Funktion:
1856 * Sie soll eine Probeformatierung vorbereiten.
1857 * Der Frame wird in Groesse und Position angepasst, sein SwParaPortion zur Seite
1858 * gestellt und eine neue erzeugt, dazu wird formatiert mit gesetztem bTestFormat.
1859 * Im Dtor wird der TxtFrm wieder in seinen alten Zustand zurueckversetzt.
1861 * --------------------------------------------------*/
1866 SwParaPortion
*pOldPara
;
1867 SwRect aOldFrm
, aOldPrt
;
1869 SwTestFormat( SwTxtFrm
* pTxtFrm
, const SwFrm
* pPrv
, SwTwips nMaxHeight
);
1873 SwTestFormat::SwTestFormat( SwTxtFrm
* pTxtFrm
, const SwFrm
* pPre
, SwTwips nMaxHeight
)
1876 aOldFrm
= pFrm
->Frm();
1877 aOldPrt
= pFrm
->Prt();
1880 SwTwips nLower
= (pFrm
->*fnRect
->fnGetBottomMargin
)();
1882 pFrm
->Frm() = pFrm
->GetUpper()->Prt();
1883 pFrm
->Frm() += pFrm
->GetUpper()->Frm().Pos();
1885 (pFrm
->Frm().*fnRect
->fnSetHeight
)( nMaxHeight
);
1886 if( pFrm
->GetPrev() )
1887 (pFrm
->Frm().*fnRect
->fnSetPosY
)(
1888 (pFrm
->GetPrev()->Frm().*fnRect
->fnGetBottom
)() -
1889 ( bVert
? nMaxHeight
+ 1 : 0 ) );
1891 SwBorderAttrAccess
aAccess( SwFrm::GetCache(), pFrm
);
1892 const SwBorderAttrs
&rAttrs
= *aAccess
.Get();
1893 (pFrm
->Prt().*fnRect
->fnSetPosX
)( rAttrs
.CalcLeft( pFrm
) );
1897 SwTwips nUpper
= pFrm
->CalcUpperSpace( &rAttrs
, pPre
);
1898 (pFrm
->Prt().*fnRect
->fnSetPosY
)( nUpper
);
1900 (pFrm
->Prt().*fnRect
->fnSetHeight
)(
1901 Max( 0L , (pFrm
->Frm().*fnRect
->fnGetHeight
)() -
1902 (pFrm
->Prt().*fnRect
->fnGetTop
)() - nLower
) );
1903 (pFrm
->Prt().*fnRect
->fnSetWidth
)(
1904 (pFrm
->Frm().*fnRect
->fnGetWidth
)() -
1905 // OD 23.01.2003 #106895# - add 1st param to <SwBorderAttrs::CalcRight(..)>
1906 ( rAttrs
.CalcLeft( pFrm
) + rAttrs
.CalcRight( pFrm
) ) );
1907 pOldPara
= pFrm
->HasPara() ? pFrm
->GetPara() : NULL
;
1908 pFrm
->SetPara( new SwParaPortion(), sal_False
);
1910 ASSERT( ! pFrm
->IsSwapped(), "A frame is swapped before _Format" );
1912 if ( pFrm
->IsVertical() )
1913 pFrm
->SwapWidthAndHeight();
1915 SwTxtFormatInfo
aInf( pFrm
, sal_False
, sal_True
, sal_True
);
1916 SwTxtFormatter
aLine( pFrm
, &aInf
);
1918 pFrm
->_Format( aLine
, aInf
);
1920 if ( pFrm
->IsVertical() )
1921 pFrm
->SwapWidthAndHeight();
1923 ASSERT( ! pFrm
->IsSwapped(), "A frame is swapped after _Format" );
1926 SwTestFormat::~SwTestFormat()
1928 pFrm
->Frm() = aOldFrm
;
1929 pFrm
->Prt() = aOldPrt
;
1930 pFrm
->SetPara( pOldPara
);
1933 sal_Bool
SwTxtFrm::TestFormat( const SwFrm
* pPrv
, SwTwips
&rMaxHeight
, sal_Bool
&bSplit
)
1935 PROTOCOL_ENTER( this, PROT_TESTFORMAT
, 0, 0 )
1937 if( IsLocked() && GetUpper()->Prt().Width() <= 0 )
1940 SwTestFormat
aSave( this, pPrv
, rMaxHeight
);
1942 return SwTxtFrm::WouldFit( rMaxHeight
, bSplit
, sal_True
);
1946 /*************************************************************************
1947 * SwTxtFrm::WouldFit()
1948 *************************************************************************/
1950 /* SwTxtFrm::WouldFit()
1951 * sal_True: wenn ich aufspalten kann.
1952 * Es soll und braucht nicht neu formatiert werden.
1953 * Wir gehen davon aus, dass bereits formatiert wurde und dass
1954 * die Formatierungsdaten noch aktuell sind.
1955 * Wir gehen davon aus, dass die Framebreiten des evtl. Masters und
1956 * Follows gleich sind. Deswegen wird kein FindBreak() mit FindOrphans()
1958 * Die benoetigte Hoehe wird von nMaxHeight abgezogen!
1961 sal_Bool
SwTxtFrm::WouldFit( SwTwips
&rMaxHeight
, sal_Bool
&bSplit
, sal_Bool bTst
)
1963 ASSERT( ! IsVertical() || ! IsSwapped(),
1964 "SwTxtFrm::WouldFit with swapped frame" );
1970 //Kann gut sein, dass mir der IdleCollector mir die gecachten
1971 //Informationen entzogen hat.
1975 // OD 2004-05-24 #i27801# - correction: 'short cut' for empty paragraph
1976 // can *not* be applied, if test format is in progress. The test format doesn't
1977 // adjust the frame and the printing area - see method <SwTxtFrm::_Format(..)>,
1978 // which is called in <SwTxtFrm::TestFormat(..)>
1979 if ( IsEmpty() && !bTst
)
1982 SwTwips nHeight
= bVert
? Prt().SSize().Width() : Prt().SSize().Height();
1983 if( rMaxHeight
< nHeight
)
1987 rMaxHeight
-= nHeight
;
1992 // In sehr unguenstigen Faellen kann GetPara immer noch 0 sein.
1993 // Dann returnen wir sal_True, um auf der neuen Seite noch einmal
1994 // anformatiert zu werden.
1995 ASSERT( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" );
1996 if( !HasPara() || ( !(Frm().*fnRect
->fnGetHeight
)() && IsHiddenNow() ) )
1999 // Da das Orphan-Flag nur sehr fluechtig existiert, wird als zweite
2000 // Bedingung ueberprueft, ob die Rahmengroesse durch CalcPreps
2001 // auf riesengross gesetzt wird, um ein MoveFwd zu erzwingen.
2002 if( IsWidow() || ( bVert
?
2003 ( 0 == Frm().Left() ) :
2004 ( LONG_MAX
- 20000 < Frm().Bottom() ) ) )
2006 SetWidow(sal_False
);
2009 // Wenn wir hier durch eine Widow-Anforderung unseres Follows gelandet
2010 // sind, wird ueberprueft, ob es ueberhaupt einen Follow mit einer
2011 // echten Hoehe gibt, andernfalls (z.B. in neu angelegten SctFrms)
2012 // ignorieren wir das IsWidow() und pruefen doch noch, ob wir
2013 // genung Platz finden.
2014 if( ( ( ! bVert
&& LONG_MAX
- 20000 >= Frm().Bottom() ) ||
2015 ( bVert
&& 0 < Frm().Left() ) ) &&
2016 ( GetFollow()->IsVertical() ?
2017 !GetFollow()->Frm().Width() :
2018 !GetFollow()->Frm().Height() ) )
2020 SwTxtFrm
* pFoll
= GetFollow()->GetFollow();
2022 ( pFoll
->IsVertical() ?
2023 !pFoll
->Frm().Width() :
2024 !pFoll
->Frm().Height() ) )
2025 pFoll
= pFoll
->GetFollow();
2034 SWAP_IF_NOT_SWAPPED( this );
2036 SwTxtSizeInfo
aInf( this );
2037 SwTxtMargin
aLine( this, &aInf
);
2039 WidowsAndOrphans
aFrmBreak( this, rMaxHeight
, bSplit
);
2041 sal_Bool bRet
= sal_True
;
2044 // Ist Aufspalten ueberhaupt notwendig?
2045 if ( 0 != ( bSplit
= !aFrmBreak
.IsInside( aLine
) ) )
2046 bRet
= !aFrmBreak
.IsKeepAlways() && aFrmBreak
.WouldFit( aLine
, rMaxHeight
, bTst
);
2049 //Wir brauchen die Gesamthoehe inklusive der aktuellen Zeile
2053 rMaxHeight
-= aLine
.GetLineHeight();
2054 } while ( aLine
.Next() );
2063 /*************************************************************************
2064 * SwTxtFrm::GetParHeight()
2065 *************************************************************************/
2067 KSHORT
SwTxtFrm::GetParHeight() const
2069 ASSERT( ! IsVertical() || ! IsSwapped(),
2070 "SwTxtFrm::GetParHeight with swapped frame" )
2073 { // Fuer nichtleere Absaetze ist dies ein Sonderfall, da koennen wir
2074 // bei UnderSized ruhig nur 1 Twip mehr anfordern.
2075 KSHORT nRet
= (KSHORT
)Prt().SSize().Height();
2076 if( IsUndersized() )
2079 nRet
= (KSHORT
)EmptyHeight();
2086 // FME, OD 08.01.2004 #i11859# - refactoring and improve code
2087 const SwLineLayout
* pLineLayout
= GetPara();
2088 KSHORT nHeight
= pLineLayout
->GetRealHeight();
2089 if( GetOfst() && !IsFollow() ) // Ist dieser Absatz gescrollt? Dann ist unsere
2090 nHeight
*= 2; // bisherige Hoehe mind. eine Zeilenhoehe zu gering
2091 // OD 2004-03-04 #115793#
2092 while ( pLineLayout
&& pLineLayout
->GetNext() )
2094 pLineLayout
= pLineLayout
->GetNext();
2095 nHeight
= nHeight
+ pLineLayout
->GetRealHeight();
2102 /*************************************************************************
2103 * SwTxtFrm::GetFormatted()
2104 *************************************************************************/
2106 // returnt this _immer_ im formatierten Zustand!
2107 SwTxtFrm
* SwTxtFrm::GetFormatted( bool bForceQuickFormat
)
2109 SWAP_IF_SWAPPED( this )
2111 //Kann gut sein, dass mir der IdleCollector mir die gecachten
2112 //Informationen entzogen hat. Calc() ruft unser Format.
2113 //Nicht bei leeren Absaetzen!
2114 if( !HasPara() && !(IsValid() && IsEmpty()) )
2116 // Calc() muss gerufen werden, weil unsere Frameposition
2117 // nicht stimmen muss.
2118 const sal_Bool bFormat
= GetValidSizeFlag();
2120 // Es kann durchaus sein, dass Calc() das Format()
2121 // nicht anstiess (weil wir einst vom Idle-Zerstoerer
2122 // aufgefordert wurden unsere Formatinformationen wegzuschmeissen).
2123 // 6995: Optimierung mit FormatQuick()
2124 if( bFormat
&& !FormatQuick( bForceQuickFormat
) )
2133 /*************************************************************************
2134 * SwTxtFrm::CalcFitToContent()
2135 *************************************************************************/
2137 SwTwips
SwTxtFrm::CalcFitToContent()
2139 // --> FME 2004-07-16 #i31490#
2140 // If we are currently locked, we better return with a
2141 // fairly reasonable value:
2143 return Prt().Width();
2146 SwParaPortion
* pOldPara
= GetPara();
2147 SwParaPortion
*pDummy
= new SwParaPortion();
2148 SetPara( pDummy
, false );
2149 const SwPageFrm
* pPage
= FindPageFrm();
2151 const Point aOldFrmPos
= Frm().Pos();
2152 const SwTwips nOldFrmWidth
= Frm().Width();
2153 const SwTwips nOldPrtWidth
= Prt().Width();
2154 const SwTwips nPageWidth
= GetUpper()->IsVertical() ?
2155 pPage
->Prt().Height() :
2156 pPage
->Prt().Width();
2158 Frm().Width( nPageWidth
);
2159 Prt().Width( nPageWidth
);
2161 // --> FME 2004-07-19 #i25422# objects anchored as character in RTL
2162 if ( IsRightToLeft() )
2163 Frm().Pos().X() += nOldFrmWidth
- nPageWidth
;
2165 // --> FME 2004-07-16 #i31490#
2166 SwTxtFrmLocker
aLock( this );
2169 SwTxtFormatInfo
aInf( this, sal_False
, sal_True
, sal_True
);
2170 aInf
.SetIgnoreFly( sal_True
);
2171 SwTxtFormatter
aLine( this, &aInf
);
2172 SwHookOut
aHook( aInf
);
2174 // --> OD 2005-09-06 #i54031# - assure mininum of MINLAY twips.
2175 const SwTwips nMax
= Max( (SwTwips
)MINLAY
,
2176 aLine
._CalcFitToContent() + 1 );
2179 Frm().Width( nOldFrmWidth
);
2180 Prt().Width( nOldPrtWidth
);
2182 // --> FME 2004-07-19 #i25422# objects anchored as character in RTL
2183 if ( IsRightToLeft() )
2184 Frm().Pos() = aOldFrmPos
;
2187 SetPara( pOldPara
);
2192 /** simulate format for a list item paragraph, whose list level attributes
2193 are in LABEL_ALIGNMENT mode, in order to determine additional first
2194 line offset for the real text formatting due to the value of label
2195 adjustment attribute of the list level.
2197 OD 2008-01-31 #newlistlevelattrs#
2201 void SwTxtFrm::CalcAdditionalFirstLineOffset()
2206 // reset additional first line offset
2207 mnAdditionalFirstLineOffset
= 0;
2209 const SwTxtNode
* pTxtNode( GetTxtNode() );
2210 if ( pTxtNode
&& pTxtNode
->IsNumbered() && pTxtNode
->IsCountedInList() &&
2211 pTxtNode
->GetNumRule() )
2213 const SwNumFmt
& rNumFmt
=
2214 pTxtNode
->GetNumRule()->Get( static_cast<USHORT
>(pTxtNode
->GetActualListLevel()) );
2215 if ( rNumFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
2217 // keep current paragraph portion and apply dummy paragraph portion
2218 SwParaPortion
* pOldPara
= GetPara();
2219 SwParaPortion
*pDummy
= new SwParaPortion();
2220 SetPara( pDummy
, false );
2223 SwTxtFrmLocker
aLock( this );
2225 // simulate text formatting
2226 SwTxtFormatInfo
aInf( this, sal_False
, sal_True
, sal_True
);
2227 aInf
.SetIgnoreFly( sal_True
);
2228 SwTxtFormatter
aLine( this, &aInf
);
2229 SwHookOut
aHook( aInf
);
2230 aLine
._CalcFitToContent();
2232 // determine additional first line offset
2233 const SwLinePortion
* pFirstPortion
= aLine
.GetCurr()->GetFirstPortion();
2234 if ( pFirstPortion
->InNumberGrp() && !pFirstPortion
->IsFtnNumPortion() )
2236 SwTwips
nNumberPortionWidth( pFirstPortion
->Width() );
2238 const SwLinePortion
* pPortion
= pFirstPortion
->GetPortion();
2240 pPortion
->InNumberGrp() && !pPortion
->IsFtnNumPortion())
2242 nNumberPortionWidth
+= pPortion
->Width();
2243 pPortion
= pPortion
->GetPortion();
2246 if ( ( IsRightToLeft() &&
2247 rNumFmt
.GetNumAdjust() == SVX_ADJUST_LEFT
) ||
2248 ( !IsRightToLeft() &&
2249 rNumFmt
.GetNumAdjust() == SVX_ADJUST_RIGHT
) )
2251 mnAdditionalFirstLineOffset
= -nNumberPortionWidth
;
2253 else if ( rNumFmt
.GetNumAdjust() == SVX_ADJUST_CENTER
)
2255 mnAdditionalFirstLineOffset
= -(nNumberPortionWidth
/2);
2259 // restore paragraph portion
2260 SetPara( pOldPara
);
2265 /** determine height of last line for the calculation of the proportional line
2268 OD 08.01.2004 #i11859#
2269 OD 2004-03-17 #i11860# - method <GetHeightOfLastLineForPropLineSpacing()>
2270 replace by method <_CalcHeightOfLastLine()>. Height of last line will be
2271 stored in new member <mnHeightOfLastLine> and can be accessed via method
2272 <GetHeightOfLastLine()>
2273 OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
2274 in order to force the usage of the former algorithm to determine the
2275 height of the last line, which uses the font.
2279 void SwTxtFrm::_CalcHeightOfLastLine( const bool _bUseFont
)
2281 // --> OD 2006-11-13 #i71281#
2282 // invalidate printing area, if height of last line changes
2283 const SwTwips
mnOldHeightOfLastLine( mnHeightOfLastLine
);
2285 // determine output device
2286 ViewShell
* pVsh
= GetShell();
2287 ASSERT( pVsh
, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no ViewShell" );
2288 // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch
2289 // There could be no <ViewShell> instance in the case of loading a binary
2290 // StarOffice file format containing an embedded Writer document.
2295 OutputDevice
* pOut
= pVsh
->GetOut();
2296 const IDocumentSettingAccess
* pIDSA
= GetTxtNode()->getIDocumentSettingAccess();
2297 if ( !pIDSA
->get(IDocumentSettingAccess::BROWSE_MODE
) ||
2298 pVsh
->GetViewOptions()->IsPrtFormat() )
2300 pOut
= GetTxtNode()->getIDocumentDeviceAccess()->getReferenceDevice( true );
2302 ASSERT( pOut
, "<SwTxtFrm::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" );
2303 // --> OD 2007-07-02 #i78921# - make code robust, according to provided patch
2310 // determine height of last line
2312 if ( _bUseFont
|| pIDSA
->get(IDocumentSettingAccess::OLD_LINE_SPACING
) )
2314 // former determination of last line height for proprotional line
2315 // spacing - take height of font set at the paragraph
2316 SwFont
aFont( GetAttrSet(), pIDSA
);
2318 // Wir muessen dafuer sorgen, dass am OutputDevice der Font
2319 // korrekt restauriert wird, sonst droht ein Last!=Owner.
2322 SwFntObj
*pOldFont
= pLastFont
;
2324 aFont
.SetFntChg( sal_True
);
2325 aFont
.ChgPhysFnt( pVsh
, *pOut
);
2326 mnHeightOfLastLine
= aFont
.GetHeight( pVsh
, *pOut
);
2327 pLastFont
->Unlock();
2328 pLastFont
= pOldFont
;
2329 pLastFont
->SetDevFont( pVsh
, *pOut
);
2333 Font aOldFont
= pOut
->GetFont();
2334 aFont
.SetFntChg( sal_True
);
2335 aFont
.ChgPhysFnt( pVsh
, *pOut
);
2336 mnHeightOfLastLine
= aFont
.GetHeight( pVsh
, *pOut
);
2337 pLastFont
->Unlock();
2339 pOut
->SetFont( aOldFont
);
2344 // new determination of last line height - take actually height of last line
2345 // --> OD 2008-05-06 #i89000#
2346 // assure same results, if paragraph is undersized
2347 if ( IsUndersized() )
2349 mnHeightOfLastLine
= 0;
2353 bool bCalcHeightOfLastLine
= true;
2358 mnHeightOfLastLine
= EmptyHeight();
2359 bCalcHeightOfLastLine
= false;
2363 if ( bCalcHeightOfLastLine
)
2366 "<SwTxtFrm::_CalcHeightOfLastLine()> - missing paragraph portions." );
2367 const SwLineLayout
* pLineLayout
= GetPara();
2368 while ( pLineLayout
&& pLineLayout
->GetNext() )
2370 // iteration to last line
2371 pLineLayout
= pLineLayout
->GetNext();
2375 SwTwips nAscent
, nDescent
, nDummy1
, nDummy2
;
2376 // --> OD 2005-05-20 #i47162# - suppress consideration of
2377 // fly content portions and the line portion.
2378 pLineLayout
->MaxAscentDescent( nAscent
, nDescent
,
2382 // --> OD 2006-11-22 #i71281#
2383 // Suppress wrong invalidation of printing area, if method is
2384 // called recursive.
2385 // Thus, member <mnHeightOfLastLine> is only set directly, if
2386 // no recursive call is needed.
2387 // mnHeightOfLastLine = nAscent + nDescent;
2388 const SwTwips nNewHeightOfLastLine
= nAscent
+ nDescent
;
2389 // --> OD 2005-05-20 #i47162# - if last line only contains
2390 // fly content portions, <mnHeightOfLastLine> is zero.
2391 // In this case determine height of last line by the font
2392 if ( nNewHeightOfLastLine
== 0 )
2394 _CalcHeightOfLastLine( true );
2398 mnHeightOfLastLine
= nNewHeightOfLastLine
;
2407 // --> OD 2006-11-13 #i71281#
2408 // invalidate printing area, if height of last line changes
2409 if ( mnHeightOfLastLine
!= mnOldHeightOfLastLine
)
2416 /*************************************************************************
2417 * SwTxtFrm::GetLineSpace()
2418 *************************************************************************/
2419 // OD 07.01.2004 #i11859# - change return data type
2420 // add default parameter <_bNoPropLineSpacing> to control, if the
2421 // value of a proportional line spacing is returned or not
2422 // OD 07.01.2004 - trying to describe purpose of method:
2423 // Method returns the value of the inter line spacing for a text frame.
2424 // Such a value exists for proportional line spacings ("1,5 Lines",
2425 // "Double", "Proportional" and for leading line spacing ("Leading").
2426 // By parameter <_bNoPropLineSpace> (default value false) it can be
2427 // controlled, if the value of a proportional line spacing is returned.
2428 long SwTxtFrm::GetLineSpace( const bool _bNoPropLineSpace
) const
2432 const SwAttrSet
* pSet
= GetAttrSet();
2433 const SvxLineSpacingItem
&rSpace
= pSet
->GetLineSpacing();
2435 switch( rSpace
.GetInterLineSpaceRule() )
2437 case SVX_INTER_LINE_SPACE_PROP
:
2439 // OD 07.01.2004 #i11859#
2440 if ( _bNoPropLineSpace
)
2445 // OD 2004-03-17 #i11860# - use method <GetHeightOfLastLine()>
2446 nRet
= GetHeightOfLastLine();
2449 nTmp
*= rSpace
.GetPropLineSpace();
2458 case SVX_INTER_LINE_SPACE_FIX
:
2460 if ( rSpace
.GetInterLineSpace() > 0 )
2461 nRet
= rSpace
.GetInterLineSpace();
2470 /*************************************************************************
2471 * SwTxtFrm::FirstLineHeight()
2472 *************************************************************************/
2474 KSHORT
SwTxtFrm::FirstLineHeight() const
2478 if( IsEmpty() && IsValid() )
2479 return IsVertical() ? (KSHORT
)Prt().Width() : (KSHORT
)Prt().Height();
2482 const SwParaPortion
*pPara
= GetPara();
2486 return pPara
->Height();
2489 MSHORT
SwTxtFrm::GetLineCount( xub_StrLen nPos
)
2492 SwTxtFrm
*pFrm
= this;
2495 pFrm
->GetFormatted();
2496 if( !pFrm
->HasPara() )
2498 SwTxtSizeInfo
aInf( pFrm
);
2499 SwTxtMargin
aLine( pFrm
, &aInf
);
2500 if( STRING_LEN
== nPos
)
2503 aLine
.CharToLine( nPos
);
2504 nRet
= nRet
+ aLine
.GetLineNr();
2505 pFrm
= pFrm
->GetFollow();
2506 } while ( pFrm
&& pFrm
->GetOfst() <= nPos
);
2510 void SwTxtFrm::ChgThisLines()
2512 //not necassary to format here (GerFormatted etc.), because we have to come from there!
2515 const SwLineNumberInfo
&rInf
= GetNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo();
2516 if ( GetTxt().Len() && HasPara() )
2518 SwTxtSizeInfo
aInf( this );
2519 SwTxtMargin
aLine( this, &aInf
);
2520 if ( rInf
.IsCountBlankLines() )
2523 nNew
= (ULONG
)aLine
.GetLineNr();
2529 if( aLine
.GetCurr()->HasCntnt() )
2531 } while ( aLine
.NextLine() );
2534 else if ( rInf
.IsCountBlankLines() )
2537 if ( nNew
!= nThisLines
)
2539 if ( !IsInTab() && GetAttrSet()->GetLineNumber().IsCount() )
2541 nAllLines
-= nThisLines
;
2543 nAllLines
+= nThisLines
;
2544 SwFrm
*pNxt
= GetNextCntntFrm();
2545 while( pNxt
&& pNxt
->IsInTab() )
2547 if( 0 != (pNxt
= pNxt
->FindTabFrm()) )
2548 pNxt
= pNxt
->FindNextCnt();
2551 pNxt
->InvalidateLineNum();
2553 //Extend repaint to the bottom.
2556 SwRepaint
*pRepaint
= GetPara()->GetRepaint();
2557 pRepaint
->Bottom( Max( pRepaint
->Bottom(),
2558 Frm().Top()+Prt().Bottom()));
2561 else //Paragraphs which are not counted should not manipulate the AllLines.
2567 void SwTxtFrm::RecalcAllLines()
2571 const SwAttrSet
*pAttrSet
= GetAttrSet();
2575 const ULONG nOld
= GetAllLines();
2576 const SwFmtLineNumber
&rLineNum
= pAttrSet
->GetLineNumber();
2578 const bool bRestart
= GetTxtNode()->getIDocumentLineNumberAccess()->GetLineNumberInfo().IsRestartEachPage();
2580 if ( !IsFollow() && rLineNum
.GetStartValue() && rLineNum
.IsCount() )
2581 nNewNum
= rLineNum
.GetStartValue() - 1;
2582 //If it is a follow or not has not be considered if it is a restart at each page; the
2583 //restart should also take affekt at follows.
2584 else if ( bRestart
&& FindPageFrm()->FindFirstBodyCntnt() == this )
2590 SwCntntFrm
*pPrv
= GetPrevCntntFrm();
2592 (pPrv
->IsInTab() || pPrv
->IsInDocBody() != IsInDocBody()) )
2593 pPrv
= pPrv
->GetPrevCntntFrm();
2595 // --> FME 2007-06-22 #i78254# Restart line numbering at page change:
2596 // First body content may be in table!
2597 if ( bRestart
&& pPrv
&& pPrv
->FindPageFrm() != FindPageFrm() )
2601 nNewNum
= pPrv
? ((SwTxtFrm
*)pPrv
)->GetAllLines() : 0;
2603 if ( rLineNum
.IsCount() )
2604 nNewNum
+= GetThisLines();
2606 if ( nOld
!= nNewNum
)
2608 nAllLines
= nNewNum
;
2609 SwCntntFrm
*pNxt
= GetNextCntntFrm();
2611 (pNxt
->IsInTab() || pNxt
->IsInDocBody() != IsInDocBody()) )
2612 pNxt
= pNxt
->GetNextCntntFrm();
2615 if ( pNxt
->GetUpper() != GetUpper() )
2616 pNxt
->InvalidateLineNum();
2618 pNxt
->_InvalidateLineNum();
2624 void SwTxtFrm::VisitPortions( SwPortionHandler
& rPH
) const
2626 const SwParaPortion
* pPara
= GetPara();
2631 rPH
.Skip( GetOfst() );
2633 const SwLineLayout
* pLine
= pPara
;
2636 const SwLinePortion
* pPor
= pLine
->GetFirstPortion();
2639 pPor
->HandlePortion( rPH
);
2640 pPor
= pPor
->GetPortion();
2644 pLine
= pLine
->GetNext();
2652 /*************************************************************************
2653 * SwTxtFrm::GetScriptInfo()
2654 *************************************************************************/
2656 const SwScriptInfo
* SwTxtFrm::GetScriptInfo() const
2658 const SwParaPortion
* pPara
= GetPara();
2659 return pPara
? &pPara
->GetScriptInfo() : 0;
2662 /*************************************************************************
2663 * lcl_CalcFlyBasePos()
2664 * Helper function for SwTxtFrm::CalcBasePosForFly()
2665 *************************************************************************/
2667 SwTwips
lcl_CalcFlyBasePos( const SwTxtFrm
& rFrm
, SwRect aFlyRect
,
2671 SwTwips nRet
= rFrm
.IsRightToLeft() ?
2672 (rFrm
.Frm().*fnRect
->fnGetRight
)() :
2673 (rFrm
.Frm().*fnRect
->fnGetLeft
)();
2677 SwRect aRect
= rTxtFly
.GetFrm( aFlyRect
);
2678 if ( 0 != (aRect
.*fnRect
->fnGetWidth
)() )
2680 if ( rFrm
.IsRightToLeft() )
2682 if ( (aRect
.*fnRect
->fnGetRight
)() -
2683 (aFlyRect
.*fnRect
->fnGetRight
)() >= 0 )
2685 (aFlyRect
.*fnRect
->fnSetRight
)(
2686 (aRect
.*fnRect
->fnGetLeft
)() );
2687 nRet
= (aRect
.*fnRect
->fnGetLeft
)();
2694 if ( (aFlyRect
.*fnRect
->fnGetLeft
)() -
2695 (aRect
.*fnRect
->fnGetLeft
)() >= 0 )
2697 (aFlyRect
.*fnRect
->fnSetLeft
)(
2698 (aRect
.*fnRect
->fnGetRight
)() + 1 );
2699 nRet
= (aRect
.*fnRect
->fnGetRight
)();
2708 while ( (aFlyRect
.*fnRect
->fnGetWidth
)() > 0 );
2713 /*************************************************************************
2714 * SwTxtFrm::CalcBasePosForFly()
2715 *************************************************************************/
2717 void SwTxtFrm::CalcBaseOfstForFly()
2719 ASSERT( !IsVertical() || !IsSwapped(),
2720 "SwTxtFrm::CalcBasePosForFly with swapped frame!" )
2722 const SwNode
* pNode
= GetTxtNode();
2723 if ( !pNode
->getIDocumentSettingAccess()->get(IDocumentSettingAccess::ADD_FLY_OFFSETS
) )
2728 SwRect
aFlyRect( Frm().Pos() + Prt().Pos(), Prt().SSize() );
2730 // Get first 'real' line and adjust position and height of line rectangle
2731 // OD 08.09.2003 #110978#, #108749#, #110354# - correct behaviour,
2732 // if no 'real' line exists (empty paragraph with and without a dummy portion)
2734 SwTwips nTop
= (aFlyRect
.*fnRect
->fnGetTop
)();
2735 const SwLineLayout
* pLay
= GetPara();
2736 SwTwips nLineHeight
= 200;
2737 while( pLay
&& pLay
->IsDummy() && pLay
->GetNext() )
2739 nTop
+= pLay
->Height();
2740 pLay
= pLay
->GetNext();
2744 nLineHeight
= pLay
->Height();
2746 (aFlyRect
.*fnRect
->fnSetTopAndHeight
)( nTop
, nLineHeight
);
2749 SwTxtFly
aTxtFly( this );
2750 aTxtFly
.SetIgnoreCurrentFrame( sal_True
);
2751 aTxtFly
.SetIgnoreContour( sal_True
);
2752 // --> OD 2004-12-17 #118809# - ignore objects in page header|footer for
2753 // text frames not in page header|footer
2754 aTxtFly
.SetIgnoreObjsInHeaderFooter( sal_True
);
2756 SwTwips nRet1
= lcl_CalcFlyBasePos( *this, aFlyRect
, aTxtFly
);
2757 aTxtFly
.SetIgnoreCurrentFrame( sal_False
);
2758 SwTwips nRet2
= lcl_CalcFlyBasePos( *this, aFlyRect
, aTxtFly
);
2760 // make values relative to frame start position
2761 SwTwips nLeft
= IsRightToLeft() ?
2762 (Frm().*fnRect
->fnGetRight
)() :
2763 (Frm().*fnRect
->fnGetLeft
)();
2765 mnFlyAnchorOfst
= nRet1
- nLeft
;
2766 mnFlyAnchorOfstNoWrap
= nRet2
- nLeft
;