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 .
19 #ifndef INCLUDED_SW_SOURCE_CORE_INC_TXTFRM_HXX
20 #define INCLUDED_SW_SOURCE_CORE_INC_TXTFRM_HXX
22 #include <com/sun/star/uno/Sequence.hxx>
24 #include "TextFrameIndex.hxx"
28 namespace com::sun::star::linguistic2
{ class XHyphenatedWord
; }
30 namespace sw::mark
{ class IMark
; }
34 class SwTextFormatter
;
35 class SwTextFormatInfo
;
37 class WidowsAndOrphans
;
39 class SwInterHyphInfo
; // Hyphenate()
43 struct SwCursorMoveState
;
45 class SwPortionHandler
;
47 enum class ExpandMode
;
50 #define NON_PRINTING_CHARACTER_COLOR Color(0x26, 0x8b, 0xd2)
52 /// a clone of SwInterHyphInfo, but with TextFrameIndex instead of node index
53 class SwInterHyphInfoTextFrame
56 /// output: hyphenated word
57 css::uno::Reference
<css::linguistic2::XHyphenatedWord
> m_xHyphWord
;
59 /// input: requested range to hyphenate
60 TextFrameIndex m_nStart
;
61 TextFrameIndex m_nEnd
;
62 /// output: found word
63 TextFrameIndex m_nWordStart
;
64 TextFrameIndex m_nWordLen
;
66 SwInterHyphInfoTextFrame(SwTextFrame
const& rFrame
,
67 SwTextNode
const& rNode
, SwInterHyphInfo
const& rHyphInfo
);
68 void UpdateTextNodeHyphInfo(SwTextFrame
const& rFrame
,
69 SwTextNode
const& rNode
, SwInterHyphInfo
& o_rHyphInfo
);
71 void SetHyphWord(const css::uno::Reference
<css::linguistic2::XHyphenatedWord
> &xHW
)
80 * Describes a part of a single text node, which will be part of a text frame,
81 * even when redlines are hidden at a layout level.
85 SwTextNode
* /*const logically, but need assignment for std::vector*/ pNode
;
88 Extent(SwTextNode
*const p
, sal_Int32
const s
, sal_Int32
const e
)
89 : pNode(p
), nStart(s
), nEnd(e
)
92 assert(nStart
!= nEnd
);
98 std::pair
<SwTextNode
*, sal_Int32
> MapViewToModel(MergedPara
const&, TextFrameIndex nIndex
);
99 TextFrameIndex
MapModelToView(MergedPara
const&, SwTextNode
const* pNode
, sal_Int32 nIndex
);
101 // warning: Existing must be used only once; a second use would delete the frame created by the first one...
102 enum class FrameMode
{ New
, Existing
};
103 std::unique_ptr
<sw::MergedPara
> CheckParaRedlineMerge(SwTextFrame
& rFrame
, SwTextNode
& rTextNode
, FrameMode eMode
);
104 SwTextFrame
* MakeTextFrame(SwTextNode
& rNode
, SwFrame
*, sw::FrameMode eMode
);
106 bool FrameContainsNode(SwContentFrame
const& rFrame
, sal_uLong nNodeIndex
);
107 bool IsParaPropsNode(SwRootFrame
const& rLayout
, SwTextNode
const& rNode
);
108 SwTextNode
* GetParaPropsNode(SwRootFrame
const& rLayout
, SwNodeIndex
const& rNode
);
109 SwPosition
GetParaPropsPos(SwRootFrame
const& rLayout
, SwPosition
const& rPos
);
110 std::pair
<SwTextNode
*, SwTextNode
*>
111 GetFirstAndLastNode(SwRootFrame
const& rLayout
, SwNodeIndex
const& rPos
);
113 SwTextNode
const& GetAttrMerged(SfxItemSet
& rFormatSet
,
114 SwTextNode
const& rNode
, SwRootFrame
const* pLayout
);
116 void GotoPrevLayoutTextFrame(SwNodeIndex
& rIndex
, SwRootFrame
const* pLayout
);
117 void GotoNextLayoutTextFrame(SwNodeIndex
& rIndex
, SwRootFrame
const* pLayout
);
119 TextFrameIndex
UpdateMergedParaForDelete(MergedPara
& rMerged
,
121 SwTextNode
const& rNode
, sal_Int32 nIndex
, sal_Int32 nLen
);
123 void MoveMergedFlysAndFootnotes(std::vector
<SwTextFrame
*> const& rFrames
,
124 SwTextNode
const& rFirstNode
, SwTextNode
& rSecondNode
, bool);
126 void MoveDeletedPrevFrames(const SwTextNode
& rDeletedPrev
, SwTextNode
& rNode
);
127 enum class Recreate
{ No
, ThisNode
, Predecessor
};
128 void CheckResetRedlineMergeFlag(SwTextNode
& rNode
, Recreate eRecreateMerged
);
130 void UpdateFramesForAddDeleteRedline(SwDoc
& rDoc
, SwPaM
const& rPam
);
131 void UpdateFramesForRemoveDeleteRedline(SwDoc
& rDoc
, SwPaM
const& rPam
);
133 void AddRemoveFlysAnchoredToFrameStartingAtNode(
134 SwTextFrame
& rFrame
, SwTextNode
& rTextNode
,
135 std::set
<sal_uLong
> *pSkipped
);
137 OUString
GetExpandTextMerged(SwRootFrame
const* pLayout
,
138 SwTextNode
const& rNode
, bool bWithNumber
,
139 bool bWithSpacesForLevel
, ExpandMode i_mode
);
141 bool IsMarkHidden(SwRootFrame
const& rLayout
, ::sw::mark::IMark
const& rMark
);
142 bool IsMarkHintHidden(SwRootFrame
const& rLayout
,
143 SwTextNode
const& rNode
, SwTextAttrEnd
const& rHint
);
145 void RecreateStartTextFrames(SwTextNode
& rNode
);
149 /// Represents the visualization of a paragraph. Typical upper is an
150 /// SwBodyFrame. The first text portion of the first line is az SwParaPortion.
151 class SW_DLLPUBLIC SwTextFrame
: public SwContentFrame
153 friend class SwTextIter
;
154 friend class SwTestFormat
;
155 friend class WidowsAndOrphans
;
156 friend class TextFrameLockGuard
; // May Lock()/Unlock()
157 friend bool sw_ChangeOffset(SwTextFrame
* pFrame
, TextFrameIndex nNew
);
159 /// SwLineLayout cache: the lines are not actually owned by the SwTextFrame
160 /// but by this SwCache, so they will be deleted in large documents
161 /// if there are too many of them, but the "valid" flags of the frame
162 /// will still be set; GetFormatted() is the function that forces
163 /// recreation of the SwLineLayout by Format() if necessary.
164 static SwCache
*s_pTextCache
;
165 static constexpr tools::Long nMinPrtLine
= 0; // This Line must not be underrun when printing
166 // Hack for table cells stretching multiple pages
168 sal_uLong mnAllLines
:24; // Line count for the Paint (including nThisLines)
169 sal_uLong mnThisLines
:8; // Count of Lines of the Frame
171 // The x position for flys anchored at this paragraph.
172 // These values are calculated in SwTextFrame::CalcBaseOfstForFly()
173 SwTwips mnFlyAnchorOfst
;
174 // The x position for wrap-through flys anchored at this paragraph.
175 SwTwips mnFlyAnchorOfstNoWrap
;
176 /// The y position for wrap-through flys anchored at this paragraph.
177 SwTwips mnFlyAnchorVertOfstNoWrap
;
178 SwTwips mnFootnoteLine
;
179 // OD 2004-03-17 #i11860# - re-factoring of #i11859#
180 // member for height of last line (value needed for proportional line spacing)
181 SwTwips mnHeightOfLastLine
;
182 // member for the additional first line offset, which is caused by the list
183 // label alignment for list level position and space mode LABEL_ALIGNMENT.
184 // This additional first line offset is used for the text formatting.
185 // It is NOT used for the determination of printing area.
186 SwTwips mnAdditionalFirstLineOffset
;
188 /// redline merge data
189 std::unique_ptr
<sw::MergedPara
> m_pMergedPara
;
191 TextFrameIndex mnOffset
; // Is the offset in the Content (character count)
193 sal_uInt16 mnCacheIndex
; // Index into the cache, USHRT_MAX if there's definitely no fitting object in the cache
195 // Separates the Master and creates a Follow or adjusts the data in the Follow
196 void AdjustFollow_( SwTextFormatter
&rLine
, TextFrameIndex nOffset
,
197 TextFrameIndex nStrEnd
, const sal_uInt8 nMode
);
199 // Iterates all Lines and sets the line spacing using the attribute
200 void CalcLineSpace();
202 // Only called in Format
203 void AdjustFrame( const SwTwips nChgHeight
, bool bHasToFit
= false );
205 // Evaluates the Preps in Format()
207 void PrepWidows( const sal_uInt16 nNeed
, bool bNotify
);
208 void InvalidateRange_( const SwCharRange
&, const tools::Long
= 0);
209 inline void InvalidateRange( const SwCharRange
&, const tools::Long
= 0);
211 // WidowsAndOrphans, AdjustFrame, AdjustFollow
212 void FormatAdjust( SwTextFormatter
&rLine
, WidowsAndOrphans
&rFrameBreak
,
213 TextFrameIndex nStrLen
, const bool bDummy
);
214 void ChangeOffset( SwTextFrame
* pFrame
, TextFrameIndex nNew
);
216 bool mbLocked
: 1; // In the Format?
217 bool mbWidow
: 1; // Is our follow a Widow?
218 bool mbJustWidow
: 1; // Did we just request Widow flag on master?
219 bool mbEmpty
: 1; // Are we an empty paragraph?
220 bool mbInFootnoteConnect
: 1; // Is in Connect at the moment
221 bool mbFootnote
: 1; // Has at least one footnote
222 bool mbRepaint
: 1; // TextFrame: Repaint is ready to be fetched
223 /// Contains rotated portions.
224 bool mbHasRotatedPortions
: 1;
225 bool mbFieldFollow
: 1; // Start with Field rest of the Master
226 bool mbHasAnimation
: 1; // Contains animated SwGrfNumPortion
227 bool mbIsSwapped
: 1; // during text formatting we swap the
228 // width and height for vertical formatting
229 // OD 14.03.2003 #i11760# - flag to control, if follow is formatted in
230 // method <CalcFollow(..)>.
231 // E.g., avoid formatting of follow, if method <SwLayoutFrame::FormatWidthCols(..)>
233 bool mbFollowFormatAllowed
: 1;
236 void Lock() { mbLocked
= true; }
237 void Unlock() { mbLocked
= false; }
238 void SetWidow( const bool bNew
) { mbWidow
= bNew
; }
239 void SetJustWidow( const bool bNew
) { mbJustWidow
= bNew
; }
240 void SetEmpty( const bool bNew
) { mbEmpty
= bNew
; }
241 void SetFieldFollow( const bool bNew
) { mbFieldFollow
= bNew
; }
243 bool IsIdxInside(TextFrameIndex nPos
, TextFrameIndex nLen
) const;
245 // Changes the Frame or not (cf. FlyCnt)
246 bool GetModelPositionForViewPoint_(SwPosition
*pPos
, const Point
&rPoint
,
247 const bool bChgFrame
, SwCursorMoveState
* = nullptr ) const;
248 void FillCursorPos( SwFillData
&rFill
) const;
250 // Format exactly one Line
251 bool FormatLine( SwTextFormatter
&rLine
, const bool bPrev
);
253 // In order to safe stack space, we split this method:
254 // Format_ calls Format_ with parameters
255 void Format_( vcl::RenderContext
* pRenderContext
, SwParaPortion
*pPara
);
256 void Format_( SwTextFormatter
&rLine
, SwTextFormatInfo
&rInf
,
257 const bool bAdjust
= false );
258 void FormatOnceMore( SwTextFormatter
&rLine
, SwTextFormatInfo
&rInf
);
260 // Formats the Follow and ensures disposing on orphans
261 bool CalcFollow(TextFrameIndex nTextOfst
);
263 virtual void MakePos() override
;
265 // Corrects the position from which we need to format
266 static TextFrameIndex
FindBrk(const OUString
&rText
, TextFrameIndex nStart
,
267 TextFrameIndex nEnd
);
270 SwTwips
GetFootnoteFrameHeight_() const;
272 // Outsourced to CalcPreps
273 bool CalcPrepFootnoteAdjust();
275 // For Footnote and WidOrp: Forced validation
276 void ValidateFrame();
277 void ValidateBodyFrame();
279 bool GetDropRect_( SwRect
&rRect
) const;
281 void SetPara( SwParaPortion
*pNew
, bool bDelete
= true );
283 bool IsFootnoteNumFrame_() const;
285 // Refresh formatting information
286 bool FormatQuick( bool bForceQuickFormat
);
288 // Opt: Format empty paragraphs
290 SwTwips
EmptyHeight() const;
292 // Opt: Paint empty paragraphs
293 bool PaintEmpty( const SwRect
&, bool bCheck
) const;
295 void ChgThisLines(); // Must always be called if the Line count could have changed
297 // required for 'new' relative anchor position
298 void CalcBaseOfstForFly();
300 /** method to determine height of last line, needed for proportional line spacing
302 OD 2004-03-17 #i11860#
303 OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
304 in order to force the usage of the former algorithm to determine the
305 height of the last line, which uses the font.
308 optional input parameter - boolean indicating, if the font has to be
309 used to determine the height of the last line. default value: false
311 void CalcHeightOfLastLine( const bool _bUseFont
= false );
313 virtual void DestroyImpl() override
;
314 virtual ~SwTextFrame() override
;
317 virtual void SwClientNotify(SwModify
const& rModify
, SfxHint
const& rHint
) override
;
321 virtual const SvxFormatBreakItem
& GetBreakItem() const override
;
322 virtual const SwFormatPageDesc
& GetPageDescItem() const override
;
324 css::uno::Sequence
< css::style::TabStop
> GetTabStopInfo( SwTwips CurrentPos
) override
;
327 * This is public, as it needs to be called by some methods in order to save the Prepare
332 /// Is called by DoIdleJob_() and ExecSpellPopup()
333 SwRect
AutoSpell_(SwTextNode
&, sal_Int32
);
335 /// Is called by DoIdleJob_()
336 SwRect
SmartTagScan(SwTextNode
&);
338 /// Is called by DoIdleJob_()
339 void CollectAutoCmplWrds(SwTextNode
&, sal_Int32
);
342 * Returns the screen position of rPos. The values are relative to the upper
343 * left position of the page frame.
344 * Additional information can be obtained by passing an SwCursorMoveState object.
345 * Returns false if rPos > number of character is string
347 virtual bool GetCharRect( SwRect
& rRect
, const SwPosition
& rPos
,
348 SwCursorMoveState
* pCMS
= nullptr, bool bAllowFarAway
= true ) const override
;
350 /// A slimmer version of GetCharRect for autopositioning Frames
351 bool GetAutoPos( SwRect
&, const SwPosition
& ) const;
354 * Determine top of line for given position in the text frame
356 * OD 11.11.2003 #i22341#
357 * Assumption: given position exists in the text frame or in a follow of it
358 * OD 2004-02-02 - adjustment
359 * Top of first paragraph line is the top of the paragraph.
360 * OD 2004-03-18 #i11860# - Consider upper space amount considered for
361 * previous frame and the page grid.
363 * @param _onTopOfLine
364 * output parameter - top of line, if the given position is found in the
368 * input parameter - reference to the position in the text frame
370 * @return boolean indicating, if the top of line for the given position
371 * has been determined or not.
373 bool GetTopOfLine( SwTwips
& _onTopOfLine
,
374 const SwPosition
& _rPos
) const;
376 virtual bool FillSelection( SwSelectionList
& rList
, const SwRect
& rRect
) const override
;
379 * In nOffset returns the offset of the char within the set
380 * text buffer, which is closest to the position provided by
381 * aPoint within the layout's SSize.
383 * @returns false if the SPoint is outside of the SSize else
386 virtual bool GetModelPositionForViewPoint( SwPosition
*, Point
&,
387 SwCursorMoveState
* = nullptr, bool bTestBackground
= false ) const override
;
390 * Makes sure that the Frame is not switched (e.g. switched for a
391 * character-bound Frame)
393 bool GetKeyCursorOfst(SwPosition
*pPos
, const Point
&rPoint
) const
394 { return GetModelPositionForViewPoint_( pPos
, rPoint
, false ); }
396 void PaintExtraData( const SwRect
& rRect
) const; /// Page number etc.
397 SwRect
GetPaintSwRect();
398 virtual void PaintSwFrame( vcl::RenderContext
& rRenderContext
, SwRect
const&,
399 SwPrintData
const*const pPrintData
= nullptr ) const override
;
400 virtual bool GetInfo( SfxPoolItem
& ) const override
;
403 * Layout oriented cursor travelling:
404 * Left border, right border, previous Line, following Line,
405 * same horizontal position
407 virtual bool LeftMargin(SwPaM
*) const override
;
408 virtual bool RightMargin(SwPaM
*, bool bAPI
= false) const override
;
410 virtual bool UnitUp(SwPaM
*, const SwTwips nOffset
,
411 bool bSetInReadOnly
) const override
;
412 virtual bool UnitDown(SwPaM
*, const SwTwips nOffset
,
413 bool bSetInReadOnly
) const override
;
414 bool UnitUp_(SwPaM
*, const SwTwips nOffset
,
415 bool bSetInReadOnly
) const;
416 bool UnitDown_(SwPaM
*, const SwTwips nOffset
,
417 bool bSetInReadOnly
) const;
420 * Prepares the cursor position for a visual cursor move (BiDi).
421 * The behaviour is different for insert and overwrite cursors
423 void PrepareVisualMove( TextFrameIndex
& nPos
, sal_uInt8
& nCursorLevel
,
424 bool& bRight
, bool bInsertCursor
);
426 /// Methods to manage the FollowFrame
427 void SplitFrame(TextFrameIndex nTextPos
);
428 SwContentFrame
*JoinFrame();
429 TextFrameIndex
GetOffset() const { return mnOffset
; }
430 void SetOffset_(TextFrameIndex nNewOfst
);
431 inline void SetOffset (TextFrameIndex nNewOfst
);
432 void ManipOfst(TextFrameIndex
const nNewOfst
) { mnOffset
= nNewOfst
; }
433 SwTextFrame
*GetFrameAtPos ( const SwPosition
&rPos
);
434 inline const SwTextFrame
*GetFrameAtPos ( const SwPosition
&rPos
) const;
435 SwTextFrame
& GetFrameAtOfst(TextFrameIndex nOfst
);
436 /// If there's a Follow and we don't contain text ourselves
437 bool IsEmptyMaster() const
438 { return GetFollow() && !GetFollow()->GetOffset(); }
440 void SetMergedPara(std::unique_ptr
<sw::MergedPara
> p
);
441 sw::MergedPara
* GetMergedPara() { return m_pMergedPara
.get(); }
442 sw::MergedPara
const* GetMergedPara() const { return m_pMergedPara
.get(); }
444 /// Returns the text portion we want to edit (for inline see underneath)
445 const OUString
& GetText() const;
446 SwTextNode
const* GetTextNodeForParaProps() const;
447 SwTextNode
const* GetTextNodeForFirstText() const;
448 SwTextNode
* GetTextNodeFirst()
449 { return const_cast<SwTextNode
*>(const_cast<SwTextFrame
const*>(this)->GetTextNodeFirst()); };
450 SwTextNode
const* GetTextNodeFirst() const;
452 { return const_cast<SwDoc
&>(const_cast<SwTextFrame
const*>(this)->GetDoc()); }
453 SwDoc
const& GetDoc() const;
455 SwTextFrame(SwTextNode
* const, SwFrame
*, sw::FrameMode eMode
);
458 * SwContentFrame: the shortcut for the Frames
459 * If the void* casts wrongly, it's its own fault!
460 * The void* must be checked for 0 in any case!
462 * return true if the Portion associated with this SwTextFrame was
463 * potentially destroyed and replaced by Prepare
465 virtual bool Prepare( const PrepareHint ePrep
= PrepareHint::Clear
,
466 const void *pVoid
= nullptr, bool bNotify
= true ) override
;
469 * nMaxHeight is the required height
470 * bSplit indicates, that the paragraph has to be split
471 * bTst indicates, that we are currently doing a test formatting
473 virtual bool WouldFit( SwTwips
&nMaxHeight
, bool &bSplit
, bool bTst
) override
;
476 * The WouldFit equivalent for temporarily rewired TextFrames
477 * nMaxHeight returns the required size here too and bSplit
478 * determines whether the paragraph needs to be split.
479 * We pass the potential predecessor for the distance calculation
481 bool TestFormat( const SwFrame
* pPrv
, SwTwips
&nMaxHeight
, bool &bSplit
);
484 * We format a Line for interactive hyphenation
487 bool Hyphenate(SwInterHyphInfoTextFrame
& rInf
);
490 inline SwTwips
GrowTst( const SwTwips nGrow
);
492 SwParaPortion
*GetPara();
493 inline const SwParaPortion
*GetPara() const;
494 inline bool HasPara() const;
495 bool HasPara_() const;
497 /// map position in potentially merged text frame to SwPosition
498 std::pair
<SwTextNode
*, sal_Int32
> MapViewToModel(TextFrameIndex nIndex
) const;
499 SwPosition
MapViewToModelPos(TextFrameIndex nIndex
) const;
500 TextFrameIndex
MapModelToView(SwTextNode
const* pNode
, sal_Int32 nIndex
) const;
501 TextFrameIndex
MapModelToViewPos(SwPosition
const& rPos
) const;
503 // If there are any hanging punctuation portions in the margin
504 // the offset will be returned.
505 SwTwips
HangingMargin() const;
508 bool IsLocked() const { return mbLocked
; }
510 bool IsWidow() const { return mbWidow
; }
511 bool IsJustWidow() const { return mbJustWidow
; }
512 bool IsEmpty() const { return mbEmpty
; }
513 bool HasFootnote() const { return mbFootnote
; }
514 bool IsInFootnoteConnect()const { return mbInFootnoteConnect
;}
515 bool IsFieldFollow() const { return mbFieldFollow
;}
517 inline void SetRepaint() const;
518 inline void ResetRepaint() const;
519 bool HasRepaint() const { return mbRepaint
; }
520 void SetHasRotatedPortions(bool bHasRotatedPortions
);
521 bool GetHasRotatedPortions() const { return mbHasRotatedPortions
; }
522 void SetAnimation() const
523 { const_cast<SwTextFrame
*>(this)->mbHasAnimation
= true; }
524 bool HasAnimation() const { return mbHasAnimation
; }
526 bool IsSwapped() const { return mbIsSwapped
; }
528 /// Does the Frame have a local footnote (in this Frame or Follow)?
530 void CalcFootnoteFlag(TextFrameIndex nStop
= TextFrameIndex(COMPLETE_STRING
)); //For testing SplitFrame
532 void CalcFootnoteFlag();
536 bool IsHiddenNow() const; // bHidden && pOut == pPrt
537 void HideHidden(); // Remove appendage if Hidden
538 void HideFootnotes(TextFrameIndex nStart
, TextFrameIndex nEnd
);
541 * Hides respectively shows objects, which are anchored at paragraph,
542 * at/as a character of the paragraph, corresponding to the paragraph and
543 * paragraph portion visibility.
545 void HideAndShowObjects();
548 void RemoveFootnote(TextFrameIndex nStart
,
549 TextFrameIndex nLen
= TextFrameIndex(COMPLETE_STRING
));
550 inline SwTwips
GetFootnoteFrameHeight() const;
551 SwTextFrame
*FindFootnoteRef( const SwTextFootnote
*pFootnote
);
552 const SwTextFrame
*FindFootnoteRef( const SwTextFootnote
*pFootnote
) const
553 { return const_cast<SwTextFrame
*>(this)->FindFootnoteRef( pFootnote
); }
554 void ConnectFootnote( SwTextFootnote
*pFootnote
, const SwTwips nDeadLine
);
557 * If we're a Footnote that grows towards its reference ...
558 * public, because it's needed by SwContentFrame::MakeAll
560 SwTwips
GetFootnoteLine( const SwTextFootnote
*pFootnote
) const;
562 TextFrameIndex
GetDropLen(TextFrameIndex nWishLen
) const;
564 LanguageType
GetLangOfChar(TextFrameIndex nIndex
, sal_uInt16 nScript
,
565 bool bNoChar
= false) const;
567 virtual void Format( vcl::RenderContext
* pRenderContext
, const SwBorderAttrs
*pAttrs
= nullptr ) override
;
568 virtual void CheckDirection( bool bVert
) override
;
570 /// Returns the sum of line height in pLine
571 sal_uInt16
GetParHeight() const;
573 inline SwTextFrame
*GetFollow();
574 inline const SwTextFrame
*GetFollow() const;
576 /// Find the page number of ErgoSum and QuoVadis
577 SwTextFrame
*FindQuoVadisFrame();
580 * In case the SwLineLayout was cleared out of the s_pTextCache, recreate it
582 * #i29062# GetFormatted() can trigger a full formatting
583 * of the paragraph, causing other layout frames to become invalid. This
584 * has to be avoided during painting. Therefore we need to pass the
585 * information that we are currently in the paint process.
587 SwTextFrame
* GetFormatted( bool bForceQuickFormat
= false );
589 /// Will be moved soon
590 void SetFootnote( const bool bNew
) { mbFootnote
= bNew
; }
592 /// Respect the Follows
593 inline bool IsInside(TextFrameIndex nPos
) const;
595 /// DropCaps and selections
596 bool GetDropRect( SwRect
&rRect
) const
597 { return HasPara() && GetDropRect_( rRect
); }
599 static SwCache
*GetTextCache() { return s_pTextCache
; }
600 static void SetTextCache( SwCache
*pNew
) { s_pTextCache
= pNew
; }
602 static tools::Long
GetMinPrtLine() { return nMinPrtLine
; }
604 sal_uInt16
GetCacheIdx() const { return mnCacheIndex
; }
605 void SetCacheIdx( const sal_uInt16 nNew
) { mnCacheIndex
= nNew
; }
607 /// Removes the Line information from the Cache but retains the entry itself
609 /// Removes this frame completely from the Cache
610 void RemoveFromCache();
612 /// Am I a FootnoteFrame, with a number at the start of the paragraph?
613 bool IsFootnoteNumFrame() const
614 { return IsInFootnote() && !GetIndPrev() && IsFootnoteNumFrame_(); }
617 * Simulates a formatting as if there were not right margin or Flys or other
618 * obstacles and returns the width
620 SwTwips
CalcFitToContent();
623 * Simulate format for a list item paragraph, whose list level attributes
624 * are in LABEL_ALIGNMENT mode, in order to determine additional first
625 * line offset for the real text formatting due to the value of label
626 * adjustment attribute of the list level.
628 void CalcAdditionalFirstLineOffset();
630 SwTwips
GetAdditionalFirstLineOffset() const
632 return mnAdditionalFirstLineOffset
;
636 * Returns the additional line spacing for the next paragraph
637 * @param _bNoPropLineSpacing: control, whether the value of a
638 * proportional line spacing is returned or not
640 tools::Long
GetLineSpace( const bool _bNoPropLineSpacing
= false ) const;
642 /// Returns the first line height
643 sal_uInt16
FirstLineHeight() const;
645 /// Rewires FlyInContentFrame, if nEnd > Index >= nStart
646 void MoveFlyInCnt(SwTextFrame
*pNew
, TextFrameIndex nStart
, TextFrameIndex nEnd
);
648 /// Calculates the position of FlyInContentFrames
649 TextFrameIndex
CalcFlyPos( SwFrameFormat
const * pSearch
);
651 /// Determines the start position and step size of the register
652 bool FillRegister( SwTwips
& rRegStart
, sal_uInt16
& rRegDiff
);
654 /// Determines the line count
655 sal_uInt16
GetLineCount(TextFrameIndex nPos
);
657 /// For displaying the line numbers
658 sal_uLong
GetAllLines() const { return mnAllLines
; }
659 sal_uLong
GetThisLines() const { return mnThisLines
;}
660 void RecalcAllLines();
662 /// Stops the animations within numberings
663 void StopAnimation( const OutputDevice
*pOut
);
665 /// Visit all portions for Accessibility
666 void VisitPortions( SwPortionHandler
& rPH
) const;
668 /// Returns the script info stored at the paraportion
669 const SwScriptInfo
* GetScriptInfo() const;
671 /// Swaps width and height of the text frame
672 void SwapWidthAndHeight();
675 * Calculates the coordinates of a rectangle when switching from
676 * horizontal to vertical layout
678 void SwitchHorizontalToVertical( SwRect
& rRect
) const;
681 * Calculates the coordinates of a point when switching from
682 * horizontal to vertical layout
684 void SwitchHorizontalToVertical( Point
& rPoint
) const;
687 * Calculates the limit value when switching from
688 * horizontal to vertical layout
690 tools::Long
SwitchHorizontalToVertical( tools::Long nLimit
) const;
693 * Calculates the coordinates of a rectangle when switching from
694 * vertical to horizontal layout
696 void SwitchVerticalToHorizontal( SwRect
& rRect
) const;
699 * Calculates the coordinates of a point when switching from
700 * vertical to horizontal layout
702 void SwitchVerticalToHorizontal( Point
& rPoint
) const;
705 * Calculates the a limit value when switching from
706 * vertical to horizontal layout
708 tools::Long
SwitchVerticalToHorizontal( tools::Long nLimit
) const;
711 * Calculates the coordinates of a rectangle when switching from
714 void SwitchLTRtoRTL( SwRect
& rRect
) const;
717 * Calculates the coordinates of a point when switching from
720 void SwitchLTRtoRTL( Point
& rPoint
) const;
723 * Calculates the coordinates of a rectangle when switching from
726 void SwitchRTLtoLTR( SwRect
& rRect
) const { SwitchLTRtoRTL( rRect
); }
729 * Calculates the coordinates of a point when switching from
732 void SwitchRTLtoLTR( Point
& rPoint
) const { SwitchLTRtoRTL( rPoint
); };
734 bool FollowFormatAllowed() const
736 return mbFollowFormatAllowed
;
739 void AllowFollowFormat()
741 mbFollowFormatAllowed
= true;
744 void ForbidFollowFormat()
746 mbFollowFormatAllowed
= false;
749 SwTwips
GetBaseOffsetForFly( bool bIgnoreFlysAnchoredAtThisFrame
) const
751 return ( bIgnoreFlysAnchoredAtThisFrame
?
753 mnFlyAnchorOfstNoWrap
);
756 SwTwips
GetBaseVertOffsetForFly(bool bIgnoreFlysAnchoredAtThisFrame
) const;
758 SwTwips
GetHeightOfLastLine() const
760 return mnHeightOfLastLine
;
763 static void repaintTextFrames( const SwTextNode
& rNode
);
765 void RegisterToNode(SwTextNode
&, bool isForceNodeAsFirst
= false);
767 bool IsSymbolAt(TextFrameIndex
) const;
768 OUString
GetCurWord(SwPosition
const&) const;
769 sal_uInt16
GetScalingOfSelectedText(TextFrameIndex nStt
, TextFrameIndex nEnd
);
771 virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer
) const override
;
774 //use this to protect a SwTextFrame for a given scope from getting merged with
775 //its neighbour and thus deleted
776 class TextFrameLockGuard
779 SwTextFrame
*m_pTextFrame
;
782 //Lock pFrame for the lifetime of the Cut/Paste call, etc. to avoid
783 //SwTextFrame::AdjustFollow_ removing the pFrame we're trying to Make
784 TextFrameLockGuard(SwFrame
* pFrame
)
786 m_pTextFrame
= pFrame
->IsTextFrame() ? static_cast<SwTextFrame
*>(pFrame
) : nullptr;
789 m_bOldLocked
= m_pTextFrame
->IsLocked();
790 m_pTextFrame
->Lock();
794 m_bOldLocked
= false;
798 ~TextFrameLockGuard()
800 if (m_pTextFrame
&& !m_bOldLocked
)
801 m_pTextFrame
->Unlock();
805 inline const SwParaPortion
*SwTextFrame::GetPara() const
807 return const_cast<SwTextFrame
*>(this)->GetPara();
810 inline bool SwTextFrame::HasPara() const
812 return mnCacheIndex
!=USHRT_MAX
&& HasPara_();
815 inline SwTwips
SwTextFrame::GrowTst( const SwTwips nGrow
)
817 return Grow( nGrow
, true );
820 inline bool SwTextFrame::IsInside(TextFrameIndex
const nPos
) const
823 if( nPos
< GetOffset() )
827 const SwTextFrame
*pFoll
= GetFollow();
828 if( pFoll
&& nPos
>= pFoll
->GetOffset() )
834 inline SwTwips
SwTextFrame::GetFootnoteFrameHeight() const
836 if( !IsFollow() && IsInFootnote() && HasPara() )
837 return GetFootnoteFrameHeight_();
842 inline const SwTextFrame
*SwTextFrame::GetFollow() const
844 return static_cast<const SwTextFrame
*>(SwContentFrame::GetFollow());
846 inline SwTextFrame
*SwTextFrame::GetFollow()
848 return static_cast<SwTextFrame
*>(SwContentFrame::GetFollow());
851 inline const SwTextFrame
*SwTextFrame::GetFrameAtPos( const SwPosition
&rPos
) const
853 return const_cast<SwTextFrame
*>(this)->GetFrameAtPos( rPos
);
856 inline void SwTextFrame::SetOffset(TextFrameIndex
const nNewOfst
)
858 if ( mnOffset
!= nNewOfst
)
859 SetOffset_( nNewOfst
);
862 inline void SwTextFrame::SetRepaint() const
864 const_cast<SwTextFrame
*>(this)->mbRepaint
= true;
866 inline void SwTextFrame::ResetRepaint() const
868 const_cast<SwTextFrame
*>(this)->mbRepaint
= false;
871 class TemporarySwap
{
873 explicit TemporarySwap(SwTextFrame
* frame
, bool swap
):
874 m_frame(frame
), m_undo(false)
876 if (m_frame
->IsVertical() && swap
) {
878 m_frame
->SwapWidthAndHeight();
884 m_frame
->SwapWidthAndHeight();
889 TemporarySwap(TemporarySwap
const &) = delete;
890 void operator =(TemporarySwap
const &) = delete;
892 SwTextFrame
* m_frame
;
896 class SwSwapIfSwapped
: private TemporarySwap
{
898 explicit SwSwapIfSwapped(SwTextFrame
* frame
):
899 TemporarySwap(frame
, frame
->IsSwapped()) {}
902 class SwSwapIfNotSwapped
: private TemporarySwap
{
904 explicit SwSwapIfNotSwapped(SwTextFrame
* frame
):
905 TemporarySwap(frame
, !frame
->IsSwapped()) {}
909 * Helper class which can be used instead of the macros if a function
910 * has too many returns
914 const SwTextFrame
* pFrame
;
917 SwFrameSwapper( const SwTextFrame
* pFrame
, bool bSwapIfNotSwapped
);
921 class SwLayoutModeModifier
923 const OutputDevice
& m_rOut
;
924 ComplexTextLayoutFlags m_nOldLayoutMode
;
926 SwLayoutModeModifier( const OutputDevice
& rOutp
);
927 ~SwLayoutModeModifier();
928 void Modify( bool bChgToRTL
);
932 class SwDigitModeModifier
934 const OutputDevice
& rOut
;
935 LanguageType nOldLanguageType
;
937 SwDigitModeModifier( const OutputDevice
& rOutp
, LanguageType eCurLang
);
938 ~SwDigitModeModifier();
944 * Describes parts of multiple text nodes, which will form a text frame, even
945 * when redlines are hidden at a layout level.
949 sw::WriterMultiListener listener
;
950 std::vector
<Extent
> extents
;
951 /// note: cannot be const currently to avoid UB because SwTextGuess::Guess
952 /// const_casts it and modifies it (also, Update will modify it)
954 /// most paragraph properties are taken from the first non-empty node
955 SwTextNode
* pParaPropsNode
;
956 /// except break attributes, those are taken from the first node
957 SwTextNode
*const pFirstNode
;
958 /// mainly for sanity checks
959 SwTextNode
const* pLastNode
;
960 MergedPara(SwTextFrame
& rFrame
, std::vector
<Extent
>&& rExtents
,
961 OUString
const& rText
,
962 SwTextNode
*const pProps
, SwTextNode
*const pFirst
,
963 SwTextNode
const*const pLast
)
964 : listener(rFrame
), extents(std::move(rExtents
)), mergedText(rText
)
965 , pParaPropsNode(pProps
), pFirstNode(pFirst
), pLastNode(pLast
)
967 assert(pParaPropsNode
);
973 /// iterate SwTextAttr in potentially merged text frame
974 class MergedAttrIterBase
977 #if BOOST_VERSION < 105600
978 sw::MergedPara
const* m_pMerged
;
979 SwTextNode
const* m_pNode
;
981 sw::MergedPara
const*const m_pMerged
;
982 SwTextNode
const*const m_pNode
;
984 size_t m_CurrentExtent
;
985 size_t m_CurrentHint
;
986 MergedAttrIterBase(SwTextFrame
const& rFrame
);
990 : public MergedAttrIterBase
993 MergedAttrIter(SwTextFrame
const& rFrame
) : MergedAttrIterBase(rFrame
) {}
994 SwTextAttr
const* NextAttr(SwTextNode
const** ppNode
= nullptr);
997 class MergedAttrIterByEnd
1000 std::vector
<std::pair
<SwTextNode
const*, SwTextAttr
const*>> m_Hints
;
1001 SwTextNode
const*const m_pNode
;
1002 size_t m_CurrentHint
;
1004 MergedAttrIterByEnd(SwTextFrame
const& rFrame
);
1005 SwTextAttr
const* NextAttr(SwTextNode
const*& rpNode
);
1009 class MergedAttrIterReverse
1010 : public MergedAttrIterBase
1013 MergedAttrIterReverse(SwTextFrame
const& rFrame
);
1014 SwTextAttr
const* PrevAttr(SwTextNode
const** ppNode
= nullptr);
1018 const SwTwips WIDOW_MAGIC
= (SAL_MAX_INT32
- 1)/2;
1024 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */