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"
25 #include <nodeoffset.hxx>
32 namespace com::sun::star::linguistic2
{ class XHyphenatedWord
; }
34 namespace sw::mark
{ class IMark
; }
38 class SwTextFormatter
;
39 class SwTextFormatInfo
;
41 class WidowsAndOrphans
;
43 class SwInterHyphInfo
; // Hyphenate()
47 struct SwCursorMoveState
;
49 class SwPortionHandler
;
51 enum class ExpandMode
;
55 class SwFlyAtContentFrame
;
57 #define NON_PRINTING_CHARACTER_COLOR Color(0x26, 0x8b, 0xd2)
59 /// a clone of SwInterHyphInfo, but with TextFrameIndex instead of node index
60 class SwInterHyphInfoTextFrame
63 /// output: hyphenated word
64 css::uno::Reference
<css::linguistic2::XHyphenatedWord
> m_xHyphWord
;
66 /// input: requested range to hyphenate
67 TextFrameIndex m_nStart
;
68 TextFrameIndex m_nEnd
;
69 /// output: found word
70 TextFrameIndex m_nWordStart
;
71 TextFrameIndex m_nWordLen
;
73 SwInterHyphInfoTextFrame(SwTextFrame
const& rFrame
,
74 SwTextNode
const& rNode
, SwInterHyphInfo
const& rHyphInfo
);
75 void UpdateTextNodeHyphInfo(SwTextFrame
const& rFrame
,
76 SwTextNode
const& rNode
, SwInterHyphInfo
& o_rHyphInfo
);
78 void SetHyphWord(const css::uno::Reference
<css::linguistic2::XHyphenatedWord
> &xHW
)
87 * Describes a part of a single text node, which will be part of a text frame,
88 * even when redlines are hidden at a layout level.
92 SwTextNode
* /*const logically, but need assignment for std::vector*/ pNode
;
95 Extent(SwTextNode
*const p
, sal_Int32
const s
, sal_Int32
const e
)
96 : pNode(p
), nStart(s
), nEnd(e
)
99 assert(nStart
!= nEnd
);
106 std::pair
<SwTextNode
*, sal_Int32
> MapViewToModel(MergedPara
const&, TextFrameIndex nIndex
);
107 TextFrameIndex
MapModelToView(MergedPara
const&, SwTextNode
const* pNode
, sal_Int32 nIndex
);
109 // warning: Existing must be used only once; a second use would delete the frame created by the first one...
110 enum class FrameMode
{ New
, Existing
};
111 std::unique_ptr
<sw::MergedPara
> CheckParaRedlineMerge(SwTextFrame
& rFrame
, SwTextNode
& rTextNode
, FrameMode eMode
);
112 SwTextFrame
* MakeTextFrame(SwTextNode
& rNode
, SwFrame
*, sw::FrameMode eMode
);
114 bool FrameContainsNode(SwContentFrame
const& rFrame
, SwNodeOffset nNodeIndex
);
115 bool IsParaPropsNode(SwRootFrame
const& rLayout
, SwTextNode
const& rNode
);
116 SwTextNode
* GetParaPropsNode(SwRootFrame
const& rLayout
, SwNode
const& rNode
);
117 SwPosition
GetParaPropsPos(SwRootFrame
const& rLayout
, SwPosition
const& rPos
);
118 std::pair
<SwTextNode
*, SwTextNode
*>
119 GetFirstAndLastNode(SwRootFrame
const& rLayout
, SwNode
const& rPos
);
121 SwTextNode
const& GetAttrMerged(SfxItemSet
& rFormatSet
,
122 SwTextNode
const& rNode
, SwRootFrame
const* pLayout
);
124 void GotoPrevLayoutTextFrame(SwNodeIndex
& rIndex
, SwRootFrame
const* pLayout
);
125 void GotoNextLayoutTextFrame(SwNodeIndex
& rIndex
, SwRootFrame
const* pLayout
);
127 TextFrameIndex
UpdateMergedParaForDelete(MergedPara
& rMerged
,
129 SwTextNode
const& rNode
, sal_Int32 nIndex
, sal_Int32 nLen
);
131 void MoveMergedFlysAndFootnotes(std::vector
<SwTextFrame
*> const& rFrames
,
132 SwTextNode
const& rFirstNode
, SwTextNode
& rSecondNode
, bool);
134 void MoveDeletedPrevFrames(const SwTextNode
& rDeletedPrev
, SwTextNode
& rNode
);
135 enum class Recreate
{ No
, ThisNode
, Predecessor
};
136 void CheckResetRedlineMergeFlag(SwTextNode
& rNode
, Recreate eRecreateMerged
);
138 void UpdateFramesForAddDeleteRedline(SwDoc
& rDoc
, SwPaM
const& rPam
);
139 void UpdateFramesForRemoveDeleteRedline(SwDoc
& rDoc
, SwPaM
const& rPam
);
141 void AddRemoveFlysAnchoredToFrameStartingAtNode(
142 SwTextFrame
& rFrame
, SwTextNode
& rTextNode
,
143 std::set
<SwNodeOffset
> *pSkipped
);
145 OUString
GetExpandTextMerged(SwRootFrame
const* pLayout
,
146 SwTextNode
const& rNode
, bool bWithNumber
,
147 bool bWithSpacesForLevel
, ExpandMode i_mode
);
149 bool IsMarkHidden(SwRootFrame
const& rLayout
, ::sw::mark::IMark
const& rMark
);
150 bool IsMarkHintHidden(SwRootFrame
const& rLayout
,
151 SwTextNode
const& rNode
, SwTextAttrEnd
const& rHint
);
153 void RecreateStartTextFrames(SwTextNode
& rNode
);
155 sw::InsertText
MakeInsertText(SwTextNode
& rNode
, const sal_Int32 nPos
, const sal_Int32 nLen
);
158 * Decides if rTextNode has a numbering which has layout-level values (e.g. Arabic, but not
161 bool HasNumberingWhichNeedsLayoutUpdate(const SwTextNode
& rTextNode
);
165 /// Represents the visualization of a paragraph. Typical upper is an
166 /// SwBodyFrame. The first text portion of the first line is az SwParaPortion.
167 class SW_DLLPUBLIC SwTextFrame final
: public SwContentFrame
169 friend class SwTextIter
;
170 friend class SwTestFormat
;
171 friend class WidowsAndOrphans
;
172 friend class TextFrameLockGuard
; // May Lock()/Unlock()
173 friend bool sw_ChangeOffset(SwTextFrame
* pFrame
, TextFrameIndex nNew
);
175 /// SwLineLayout cache: the lines are not actually owned by the SwTextFrame
176 /// but by this SwCache, so they will be deleted in large documents
177 /// if there are too many of them, but the "valid" flags of the frame
178 /// will still be set; GetFormatted() is the function that forces
179 /// recreation of the SwLineLayout by Format() if necessary.
180 static SwCache
*s_pTextCache
;
181 static constexpr tools::Long nMinPrtLine
= 0; // This Line must not be underrun when printing
182 // Hack for table cells stretching multiple pages
184 sal_Int32 mnAllLines
:24; // Line count for the Paint (including nThisLines)
185 sal_Int32 mnThisLines
:8; // Count of Lines of the Frame
187 // The x position for flys anchored at this paragraph.
188 // These values are calculated in SwTextFrame::CalcBaseOfstForFly()
189 SwTwips mnFlyAnchorOfst
;
190 // The x position for wrap-through flys anchored at this paragraph.
191 SwTwips mnFlyAnchorOfstNoWrap
;
192 /// The y position for wrap-through flys anchored at this paragraph.
193 SwTwips mnFlyAnchorVertOfstNoWrap
;
194 SwTwips mnFootnoteLine
;
195 // OD 2004-03-17 #i11860# - re-factoring of #i11859#
196 // member for height of last line (value needed for proportional line spacing)
197 SwTwips mnHeightOfLastLine
;
198 // member for the additional first line offset, which is caused by the list
199 // label alignment for list level position and space mode LABEL_ALIGNMENT.
200 // This additional first line offset is used for the text formatting.
201 // It is NOT used for the determination of printing area.
202 SwTwips mnAdditionalFirstLineOffset
;
204 /// redline merge data
205 std::unique_ptr
<sw::MergedPara
> m_pMergedPara
;
207 TextFrameIndex mnOffset
; // Is the offset in the Content (character count)
209 sal_uInt16 mnCacheIndex
; // Index into the cache, USHRT_MAX if there's definitely no fitting object in the cache
211 // Separates the Master and creates a Follow or adjusts the data in the Follow
212 void AdjustFollow_( SwTextFormatter
&rLine
, TextFrameIndex nOffset
,
213 TextFrameIndex nStrEnd
, const sal_uInt8 nMode
);
215 // Iterates all Lines and sets the line spacing using the attribute
216 void CalcLineSpace();
218 // Only called in Format
219 void AdjustFrame( const SwTwips nChgHeight
, bool bHasToFit
= false );
221 // Evaluates the Preps in Format()
223 void PrepWidows( const sal_uInt16 nNeed
, bool bNotify
);
224 void InvalidateRange_( const SwCharRange
&, const tools::Long
= 0);
225 inline void InvalidateRange( const SwCharRange
&, const tools::Long
= 0);
227 // WidowsAndOrphans, AdjustFrame, AdjustFollow
228 void FormatAdjust( SwTextFormatter
&rLine
, WidowsAndOrphans
&rFrameBreak
,
229 TextFrameIndex nStrLen
, const bool bDummy
);
230 void ChangeOffset( SwTextFrame
* pFrame
, TextFrameIndex nNew
);
232 bool mbLocked
: 1; // In the Format?
233 bool mbWidow
: 1; // Is our follow a Widow?
234 bool mbJustWidow
: 1; // Did we just request Widow flag on master?
235 bool mbEmpty
: 1; // Are we an empty paragraph?
236 bool mbInFootnoteConnect
: 1; // Is in Connect at the moment
237 bool mbFootnote
: 1; // Has at least one footnote
238 bool mbRepaint
: 1; // TextFrame: Repaint is ready to be fetched
239 /// Contains rotated portions.
240 bool mbHasRotatedPortions
: 1;
241 bool mbFieldFollow
: 1; // Start with Field rest of the Master
242 bool mbHasAnimation
: 1; // Contains animated SwGrfNumPortion
243 bool mbIsSwapped
: 1; // during text formatting we swap the
244 // width and height for vertical formatting
245 // OD 14.03.2003 #i11760# - flag to control, if follow is formatted in
246 // method <CalcFollow(..)>.
247 // E.g., avoid formatting of follow, if method <SwLayoutFrame::FormatWidthCols(..)>
249 bool mbFollowFormatAllowed
: 1;
252 void Lock() { mbLocked
= true; }
253 void Unlock() { mbLocked
= false; }
254 void SetWidow( const bool bNew
) { mbWidow
= bNew
; }
255 void SetJustWidow( const bool bNew
) { mbJustWidow
= bNew
; }
256 void SetEmpty( const bool bNew
) { mbEmpty
= bNew
; }
257 void SetFieldFollow( const bool bNew
) { mbFieldFollow
= bNew
; }
259 bool IsIdxInside(TextFrameIndex nPos
, TextFrameIndex nLen
) const;
261 // Changes the Frame or not (cf. FlyCnt)
262 bool GetModelPositionForViewPoint_(SwPosition
*pPos
, const Point
&rPoint
,
263 const bool bChgFrame
, SwCursorMoveState
* = nullptr ) const;
264 void FillCursorPos( SwFillData
&rFill
) const;
266 // Format exactly one Line
267 bool FormatLine( SwTextFormatter
&rLine
, const bool bPrev
);
269 // In order to safe stack space, we split this method:
270 // Format_ calls Format_ with parameters
271 void FormatImpl( vcl::RenderContext
* pRenderContext
, SwParaPortion
*pPara
,
272 ::std::vector
<SwAnchoredObject
*> & rIntersectingObjs
);
273 void Format_( SwTextFormatter
&rLine
, SwTextFormatInfo
&rInf
,
274 const bool bAdjust
= false );
275 void FormatOnceMore( SwTextFormatter
&rLine
, SwTextFormatInfo
&rInf
);
277 // Formats the Follow and ensures disposing on orphans
278 bool CalcFollow(TextFrameIndex nTextOfst
);
280 virtual void MakePos() override
;
282 // Corrects the position from which we need to format
283 static TextFrameIndex
FindBrk(std::u16string_view aText
, TextFrameIndex nStart
,
284 TextFrameIndex nEnd
);
287 SwTwips
GetFootnoteFrameHeight_() const;
289 // Outsourced to CalcPreps
290 bool CalcPrepFootnoteAdjust();
292 // For Footnote and WidOrp: Forced validation
293 void ValidateFrame();
294 void ValidateBodyFrame();
296 bool GetDropRect_( SwRect
&rRect
) const;
298 void SetPara( SwParaPortion
*pNew
, bool bDelete
= true );
300 bool IsFootnoteNumFrame_() const;
302 // Refresh formatting information
303 bool FormatQuick( bool bForceQuickFormat
);
305 // Opt: Format empty paragraphs
307 SwTwips
EmptyHeight() const;
309 // Opt: Paint empty paragraphs
310 bool PaintEmpty( const SwRect
&, bool bCheck
) const;
312 void ChgThisLines(); // Must always be called if the Line count could have changed
314 // required for 'new' relative anchor position
315 void CalcBaseOfstForFly();
317 /** method to determine height of last line, needed for proportional line spacing
319 OD 2004-03-17 #i11860#
320 OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont>
321 in order to force the usage of the former algorithm to determine the
322 height of the last line, which uses the font.
325 optional input parameter - boolean indicating, if the font has to be
326 used to determine the height of the last line. default value: false
328 void CalcHeightOfLastLine( const bool _bUseFont
= false );
330 virtual void DestroyImpl() override
;
331 virtual ~SwTextFrame() override
;
333 void UpdateOutlineContentVisibilityButton(SwWrtShell
* pWrtSh
) const;
334 void PaintOutlineContentVisibilityButton() const;
336 void PaintParagraphStylesHighlighting() const;
338 virtual void SwClientNotify(SwModify
const& rModify
, SfxHint
const& rHint
) override
;
340 /// Like GetDrawObjs(), but limit to fly frames which are allowed to split.
341 std::vector
<SwFlyAtContentFrame
*> GetSplitFlyDrawObjs() const;
345 virtual const SvxFormatBreakItem
& GetBreakItem() const override
;
346 virtual const SwFormatPageDesc
& GetPageDescItem() const override
;
348 css::uno::Sequence
< css::style::TabStop
> GetTabStopInfo( SwTwips CurrentPos
) override
;
351 * This is public, as it needs to be called by some methods in order to save the Prepare
356 /// Is called by DoIdleJob_(), ExecSpellPopup() and UpDown()
357 SwRect
AutoSpell_(SwTextNode
&, sal_Int32
);
359 /// Is called by DoIdleJob_()
360 SwRect
SmartTagScan(SwTextNode
&);
362 /// Is called by DoIdleJob_()
363 void CollectAutoCmplWrds(SwTextNode
&, sal_Int32
);
366 * Returns the view rectangle for the rPos model position. The values are relative to the upper
367 * left position of the page frame.
368 * Additional information can be obtained by passing an SwCursorMoveState object.
369 * Returns false if rPos > number of character is string
371 virtual bool GetCharRect( SwRect
& rRect
, const SwPosition
& rPos
,
372 SwCursorMoveState
* pCMS
= nullptr, bool bAllowFarAway
= true ) const override
;
374 /// A slimmer version of GetCharRect for autopositioning Frames
375 bool GetAutoPos( SwRect
&, const SwPosition
& ) const;
378 * Determine top of line for given position in the text frame
380 * OD 11.11.2003 #i22341#
381 * Assumption: given position exists in the text frame or in a follow of it
382 * OD 2004-02-02 - adjustment
383 * Top of first paragraph line is the top of the paragraph.
384 * OD 2004-03-18 #i11860# - Consider upper space amount considered for
385 * previous frame and the page grid.
387 * @param _onTopOfLine
388 * output parameter - top of line, if the given position is found in the
392 * input parameter - reference to the position in the text frame
394 * @return boolean indicating, if the top of line for the given position
395 * has been determined or not.
397 bool GetTopOfLine( SwTwips
& _onTopOfLine
,
398 const SwPosition
& _rPos
) const;
400 virtual bool FillSelection( SwSelectionList
& rList
, const SwRect
& rRect
) const override
;
403 * In nOffset returns the offset of the char within the set
404 * text buffer, which is closest to the position provided by
405 * aPoint within the layout's SSize.
407 * @returns false if the SPoint is outside of the SSize else
410 virtual bool GetModelPositionForViewPoint( SwPosition
*, Point
&,
411 SwCursorMoveState
* = nullptr, bool bTestBackground
= false ) const override
;
414 * Makes sure that the Frame is not switched (e.g. switched for a
415 * character-bound Frame)
417 bool GetKeyCursorOfst(SwPosition
*pPos
, const Point
&rPoint
) const
418 { return GetModelPositionForViewPoint_( pPos
, rPoint
, false ); }
420 void PaintExtraData( const SwRect
& rRect
) const; /// Page number etc.
421 SwRect
GetPaintSwRect();
422 virtual void PaintSwFrame( vcl::RenderContext
& rRenderContext
, SwRect
const& ) const override
;
425 * Layout oriented cursor travelling:
426 * Left border, right border, previous Line, following Line,
427 * same horizontal position
429 virtual bool LeftMargin(SwPaM
*) const override
;
430 virtual bool RightMargin(SwPaM
*, bool bAPI
= false) const override
;
432 virtual bool UnitUp(SwPaM
*, const SwTwips nOffset
,
433 bool bSetInReadOnly
) const override
;
434 virtual bool UnitDown(SwPaM
*, const SwTwips nOffset
,
435 bool bSetInReadOnly
) const override
;
436 bool UnitUp_(SwPaM
*, const SwTwips nOffset
,
437 bool bSetInReadOnly
) const;
438 bool UnitDown_(SwPaM
*, const SwTwips nOffset
,
439 bool bSetInReadOnly
) const;
442 * Prepares the cursor position for a visual cursor move (BiDi).
443 * The behaviour is different for insert and overwrite cursors
445 void PrepareVisualMove( TextFrameIndex
& nPos
, sal_uInt8
& nCursorLevel
,
446 bool& bRight
, bool bInsertCursor
);
448 /// Methods to manage the FollowFrame
449 void SplitFrame(TextFrameIndex nTextPos
);
450 SwContentFrame
*JoinFrame();
451 TextFrameIndex
GetOffset() const { return mnOffset
; }
452 void SetOffset_(TextFrameIndex nNewOfst
);
453 inline void SetOffset (TextFrameIndex nNewOfst
);
454 void ManipOfst(TextFrameIndex
const nNewOfst
) { mnOffset
= nNewOfst
; }
455 SwTextFrame
*GetFrameAtPos ( const SwPosition
&rPos
);
456 inline const SwTextFrame
*GetFrameAtPos ( const SwPosition
&rPos
) const;
457 SwTextFrame
& GetFrameAtOfst(TextFrameIndex nOfst
);
458 /// If there's a Follow and we don't contain text ourselves
459 bool IsEmptyMaster() const
460 { return GetFollow() && !GetFollow()->GetOffset(); }
462 void SetMergedPara(std::unique_ptr
<sw::MergedPara
> p
);
463 sw::MergedPara
* GetMergedPara() { return m_pMergedPara
.get(); }
464 sw::MergedPara
const* GetMergedPara() const { return m_pMergedPara
.get(); }
466 /// Returns the text portion we want to edit (for inline see underneath)
467 const OUString
& GetText() const;
468 SwTextNode
const* GetTextNodeForParaProps() const;
469 SwTextNode
const* GetTextNodeForFirstText() const;
470 SwTextNode
* GetTextNodeFirst()
471 { return const_cast<SwTextNode
*>(const_cast<SwTextFrame
const*>(this)->GetTextNodeFirst()); };
472 SwTextNode
const* GetTextNodeFirst() const;
474 { return const_cast<SwDoc
&>(const_cast<SwTextFrame
const*>(this)->GetDoc()); }
475 SwDoc
const& GetDoc() const;
477 SwTextFrame(SwTextNode
* const, SwFrame
*, sw::FrameMode eMode
);
480 * SwContentFrame: the shortcut for the Frames
481 * If the void* casts wrongly, it's its own fault!
482 * The void* must be checked for 0 in any case!
484 * return true if the Portion associated with this SwTextFrame was
485 * potentially destroyed and replaced by Prepare
487 virtual bool Prepare( const PrepareHint ePrep
= PrepareHint::Clear
,
488 const void *pVoid
= nullptr, bool bNotify
= true ) override
;
491 * nMaxHeight is the required height
492 * bSplit indicates, that the paragraph has to be split
493 * bTst indicates, that we are currently doing a test formatting
495 virtual bool WouldFit(SwTwips
&nMaxHeight
, bool &bSplit
, bool bTst
, bool bMoveBwd
) override
;
498 * The WouldFit equivalent for temporarily rewired TextFrames
499 * nMaxHeight returns the required size here too and bSplit
500 * determines whether the paragraph needs to be split.
501 * We pass the potential predecessor for the distance calculation
503 bool TestFormat( const SwFrame
* pPrv
, SwTwips
&nMaxHeight
, bool &bSplit
);
506 * We format a Line for interactive hyphenation
509 bool Hyphenate(SwInterHyphInfoTextFrame
& rInf
);
512 inline SwTwips
GrowTst( const SwTwips nGrow
);
514 SwParaPortion
*GetPara();
515 inline const SwParaPortion
*GetPara() const;
516 inline bool HasPara() const;
517 bool HasPara_() const;
519 /// map position in potentially merged text frame to SwPosition
520 std::pair
<SwTextNode
*, sal_Int32
> MapViewToModel(TextFrameIndex nIndex
) const;
521 SwPosition
MapViewToModelPos(TextFrameIndex nIndex
) const;
522 TextFrameIndex
MapModelToView(SwTextNode
const* pNode
, sal_Int32 nIndex
) const;
523 TextFrameIndex
MapModelToViewPos(SwPosition
const& rPos
) const;
525 // If there are any hanging punctuation portions in the margin
526 // the offset will be returned.
527 SwTwips
HangingMargin() const;
529 /// Get the amount of lower margin of this frame we need to consider for fly portion purposes.
530 SwTwips
GetLowerMarginForFlyIntersect() const;
533 bool IsLocked() const { return mbLocked
; }
535 bool IsWidow() const { return mbWidow
; }
536 bool IsJustWidow() const { return mbJustWidow
; }
537 bool IsEmpty() const { return mbEmpty
; }
538 bool HasFootnote() const { return mbFootnote
; }
539 bool IsInFootnoteConnect()const { return mbInFootnoteConnect
;}
540 bool IsFieldFollow() const { return mbFieldFollow
;}
542 inline void SetRepaint() const;
543 inline void ResetRepaint() const;
544 bool HasRepaint() const { return mbRepaint
; }
545 void SetHasRotatedPortions(bool bHasRotatedPortions
);
546 bool GetHasRotatedPortions() const { return mbHasRotatedPortions
; }
547 void SetAnimation() const
548 { const_cast<SwTextFrame
*>(this)->mbHasAnimation
= true; }
549 bool HasAnimation() const { return mbHasAnimation
; }
551 bool IsSwapped() const { return mbIsSwapped
; }
553 /// Does the Frame have a local footnote (in this Frame or Follow)?
555 void CalcFootnoteFlag(TextFrameIndex nStop
= TextFrameIndex(COMPLETE_STRING
)); //For testing SplitFrame
557 void CalcFootnoteFlag();
561 virtual bool IsHiddenNow() const override
; // bHidden && pOut == pPrt
562 void HideHidden(); // Remove appendage if Hidden
563 void HideFootnotes(TextFrameIndex nStart
, TextFrameIndex nEnd
);
566 * Hides respectively shows objects, which are anchored at paragraph,
567 * at/as a character of the paragraph, corresponding to the paragraph and
568 * paragraph portion visibility.
570 void HideAndShowObjects();
573 void RemoveFootnote(TextFrameIndex nStart
,
574 TextFrameIndex nLen
= TextFrameIndex(COMPLETE_STRING
));
575 inline SwTwips
GetFootnoteFrameHeight() const;
576 SwTextFrame
*FindFootnoteRef( const SwTextFootnote
*pFootnote
);
577 const SwTextFrame
*FindFootnoteRef( const SwTextFootnote
*pFootnote
) const
578 { return const_cast<SwTextFrame
*>(this)->FindFootnoteRef( pFootnote
); }
579 void ConnectFootnote( SwTextFootnote
*pFootnote
, const SwTwips nDeadLine
);
582 * If we're a Footnote that grows towards its reference ...
583 * public, because it's needed by SwContentFrame::MakeAll
585 SwTwips
GetFootnoteLine( const SwTextFootnote
*pFootnote
) const;
587 TextFrameIndex
GetDropLen(TextFrameIndex nWishLen
) const;
589 LanguageType
GetLangOfChar(TextFrameIndex nIndex
, sal_uInt16 nScript
,
590 bool bNoChar
= false, bool bNoneIfNoHyphenation
= false ) const;
592 virtual void Format( vcl::RenderContext
* pRenderContext
, const SwBorderAttrs
*pAttrs
= nullptr ) override
;
593 virtual void CheckDirection( bool bVert
) override
;
595 /// Returns the sum of line height in pLine
596 SwTwips
GetParHeight() const;
598 inline SwTextFrame
*GetFollow();
599 inline const SwTextFrame
*GetFollow() const;
601 /// Find the page number of ErgoSum and QuoVadis
602 SwTextFrame
*FindQuoVadisFrame();
605 * In case the SwLineLayout was cleared out of the s_pTextCache, recreate it
607 * #i29062# GetFormatted() can trigger a full formatting
608 * of the paragraph, causing other layout frames to become invalid. This
609 * has to be avoided during painting. Therefore we need to pass the
610 * information that we are currently in the paint process.
612 SwTextFrame
* GetFormatted( bool bForceQuickFormat
= false );
614 /// Will be moved soon
615 void SetFootnote( const bool bNew
) { mbFootnote
= bNew
; }
617 /// Respect the Follows
618 inline bool IsInside(TextFrameIndex nPos
) const;
620 /// DropCaps and selections
621 bool GetDropRect( SwRect
&rRect
) const
622 { return HasPara() && GetDropRect_( rRect
); }
624 static SwCache
*GetTextCache() { return s_pTextCache
; }
625 static void SetTextCache( SwCache
*pNew
) { s_pTextCache
= pNew
; }
627 static tools::Long
GetMinPrtLine() { return nMinPrtLine
; }
629 sal_uInt16
GetCacheIdx() const { return mnCacheIndex
; }
630 void SetCacheIdx( const sal_uInt16 nNew
) { mnCacheIndex
= nNew
; }
632 /// Removes the Line information from the Cache but retains the entry itself
634 /// Removes this frame completely from the Cache
635 void RemoveFromCache();
637 /// Am I a FootnoteFrame, with a number at the start of the paragraph?
638 bool IsFootnoteNumFrame() const
639 { return IsInFootnote() && !GetIndPrev() && IsFootnoteNumFrame_(); }
642 * Simulates a formatting as if there were not right margin or Flys or other
643 * obstacles and returns the width
645 SwTwips
CalcFitToContent();
648 * Simulate format for a list item paragraph, whose list level attributes
649 * are in LABEL_ALIGNMENT mode, in order to determine additional first
650 * line offset for the real text formatting due to the value of label
651 * adjustment attribute of the list level.
653 void CalcAdditionalFirstLineOffset();
655 SwTwips
GetAdditionalFirstLineOffset() const
657 return mnAdditionalFirstLineOffset
;
661 * Returns the additional line spacing for the next paragraph
662 * @param _bNoPropLineSpacing: control, whether the value of a
663 * proportional line spacing is returned or not
665 tools::Long
GetLineSpace( const bool _bNoPropLineSpacing
= false ) const;
667 /// Returns the first line height
668 sal_uInt16
FirstLineHeight() const;
670 /// Rewires FlyInContentFrame, if nEnd > Index >= nStart
671 void MoveFlyInCnt(SwTextFrame
*pNew
, TextFrameIndex nStart
, TextFrameIndex nEnd
);
673 /// Calculates the position of FlyInContentFrames
674 TextFrameIndex
CalcFlyPos( SwFrameFormat
const * pSearch
);
676 /// Determines the start position and step size of the register
677 bool FillRegister( SwTwips
& rRegStart
, sal_uInt16
& rRegDiff
);
679 /// Determines the line count
680 sal_Int32
GetLineCount(TextFrameIndex nPos
);
682 /// For displaying the line numbers
683 sal_Int32
GetAllLines() const { return mnAllLines
; }
684 sal_Int32
GetThisLines() const { return mnThisLines
;}
685 void RecalcAllLines();
687 /// Stops the animations within numberings
688 void StopAnimation( const OutputDevice
*pOut
);
690 /// Visit all portions for Accessibility
691 void VisitPortions( SwPortionHandler
& rPH
) const;
693 /// Returns the script info stored at the paraportion
694 const SwScriptInfo
* GetScriptInfo() const;
696 /// Swaps width and height of the text frame
697 void SwapWidthAndHeight();
700 * Calculates the coordinates of a rectangle when switching from
701 * horizontal to vertical layout
703 void SwitchHorizontalToVertical( SwRect
& rRect
) const;
706 * Calculates the coordinates of a point when switching from
707 * horizontal to vertical layout
709 void SwitchHorizontalToVertical( Point
& rPoint
) const;
712 * Calculates the limit value when switching from
713 * horizontal to vertical layout
715 tools::Long
SwitchHorizontalToVertical( tools::Long nLimit
) const;
718 * Calculates the coordinates of a rectangle when switching from
719 * vertical to horizontal layout
721 void SwitchVerticalToHorizontal( SwRect
& rRect
) const;
724 * Calculates the coordinates of a point when switching from
725 * vertical to horizontal layout
727 void SwitchVerticalToHorizontal( Point
& rPoint
) const;
730 * Calculates the a limit value when switching from
731 * vertical to horizontal layout
733 tools::Long
SwitchVerticalToHorizontal( tools::Long nLimit
) const;
736 * Calculates the coordinates of a rectangle when switching from
739 void SwitchLTRtoRTL( SwRect
& rRect
) const;
742 * Calculates the coordinates of a point when switching from
745 void SwitchLTRtoRTL( Point
& rPoint
) const;
748 * Calculates the coordinates of a rectangle when switching from
751 void SwitchRTLtoLTR( SwRect
& rRect
) const { SwitchLTRtoRTL( rRect
); }
754 * Calculates the coordinates of a point when switching from
757 void SwitchRTLtoLTR( Point
& rPoint
) const { SwitchLTRtoRTL( rPoint
); };
759 bool FollowFormatAllowed() const
761 return mbFollowFormatAllowed
;
764 void AllowFollowFormat()
766 mbFollowFormatAllowed
= true;
769 void ForbidFollowFormat()
771 mbFollowFormatAllowed
= false;
774 SwTwips
GetBaseOffsetForFly( bool bIgnoreFlysAnchoredAtThisFrame
) const
776 return ( bIgnoreFlysAnchoredAtThisFrame
?
778 mnFlyAnchorOfstNoWrap
);
781 SwTwips
GetBaseVertOffsetForFly(bool bIgnoreFlysAnchoredAtThisFrame
) const;
783 SwTwips
GetHeightOfLastLine() const
785 return mnHeightOfLastLine
;
788 static void repaintTextFrames( const SwTextNode
& rNode
);
790 void RegisterToNode(SwTextNode
&, bool isForceNodeAsFirst
= false);
792 bool IsSymbolAt(TextFrameIndex
) const;
793 OUString
GetCurWord(SwPosition
const&) const;
794 sal_uInt16
GetScalingOfSelectedText(TextFrameIndex nStt
, TextFrameIndex nEnd
);
796 /// This text frame may have a split fly frames anchored to it. Is any of them a frame that has
797 /// a follow, i.e. not the last in a master -> follow 1 -> ... -> last follow chain?
798 SwFlyAtContentFrame
* HasNonLastSplitFlyDrawObj() const;
800 /// This text frame has a follow and the text frame don't contain text. Additionally one split
801 /// fly is anchored to the text frame.
802 bool IsEmptyMasterWithSplitFly() const;
804 /// This text frame is not split, doesn't fit the upper, has a single split fly anchored to it
805 /// with a negative vertical offset. Such frames may need explicit splitting.
806 bool IsEmptyWithSplitFly() const;
808 static SwView
* GetView();
810 void dumpAsXml(xmlTextWriterPtr writer
= nullptr) const override
;
811 void dumpAsXmlAttributes(xmlTextWriterPtr writer
) const override
;
814 //use this to protect a SwTextFrame for a given scope from getting merged with
815 //its neighbour and thus deleted
816 class TextFrameLockGuard
819 SwTextFrame
*m_pTextFrame
;
822 //Lock pFrame for the lifetime of the Cut/Paste call, etc. to avoid
823 //SwTextFrame::AdjustFollow_ removing the pFrame we're trying to Make
824 TextFrameLockGuard(SwFrame
* pFrame
)
826 m_pTextFrame
= pFrame
->IsTextFrame() ? static_cast<SwTextFrame
*>(pFrame
) : nullptr;
829 m_bOldLocked
= m_pTextFrame
->IsLocked();
830 m_pTextFrame
->Lock();
834 m_bOldLocked
= false;
838 ~TextFrameLockGuard()
840 if (m_pTextFrame
&& !m_bOldLocked
)
841 m_pTextFrame
->Unlock();
845 inline const SwParaPortion
*SwTextFrame::GetPara() const
847 return const_cast<SwTextFrame
*>(this)->GetPara();
850 inline bool SwTextFrame::HasPara() const
852 return mnCacheIndex
!=USHRT_MAX
&& HasPara_();
855 inline SwTwips
SwTextFrame::GrowTst( const SwTwips nGrow
)
857 return Grow( nGrow
, true );
860 inline bool SwTextFrame::IsInside(TextFrameIndex
const nPos
) const
863 if( nPos
< GetOffset() )
867 const SwTextFrame
*pFoll
= GetFollow();
868 if( pFoll
&& nPos
>= pFoll
->GetOffset() )
874 inline SwTwips
SwTextFrame::GetFootnoteFrameHeight() const
876 if( !IsFollow() && IsInFootnote() && HasPara() )
877 return GetFootnoteFrameHeight_();
882 inline const SwTextFrame
*SwTextFrame::GetFollow() const
884 return static_cast<const SwTextFrame
*>(SwContentFrame::GetFollow());
886 inline SwTextFrame
*SwTextFrame::GetFollow()
888 return static_cast<SwTextFrame
*>(SwContentFrame::GetFollow());
891 inline const SwTextFrame
*SwTextFrame::GetFrameAtPos( const SwPosition
&rPos
) const
893 return const_cast<SwTextFrame
*>(this)->GetFrameAtPos( rPos
);
896 inline void SwTextFrame::SetOffset(TextFrameIndex
const nNewOfst
)
898 if ( mnOffset
!= nNewOfst
)
899 SetOffset_( nNewOfst
);
902 inline void SwTextFrame::SetRepaint() const
904 const_cast<SwTextFrame
*>(this)->mbRepaint
= true;
906 inline void SwTextFrame::ResetRepaint() const
908 const_cast<SwTextFrame
*>(this)->mbRepaint
= false;
911 class TemporarySwap
{
913 explicit TemporarySwap(SwTextFrame
* frame
, bool swap
):
914 m_frame(frame
), m_undo(false)
916 if (m_frame
->IsVertical() && swap
) {
918 m_frame
->SwapWidthAndHeight();
924 m_frame
->SwapWidthAndHeight();
929 TemporarySwap(TemporarySwap
const &) = delete;
930 void operator =(TemporarySwap
const &) = delete;
932 SwTextFrame
* m_frame
;
936 class SwSwapIfSwapped
: private TemporarySwap
{
938 explicit SwSwapIfSwapped(SwTextFrame
* frame
):
939 TemporarySwap(frame
, frame
->IsSwapped()) {}
942 class SwSwapIfNotSwapped
: private TemporarySwap
{
944 explicit SwSwapIfNotSwapped(SwTextFrame
* frame
):
945 TemporarySwap(frame
, !frame
->IsSwapped()) {}
949 * Helper class which can be used instead of the macros if a function
950 * has too many returns
954 const SwTextFrame
* pFrame
;
957 SwFrameSwapper( const SwTextFrame
* pFrame
, bool bSwapIfNotSwapped
);
961 class SwLayoutModeModifier
963 const OutputDevice
& m_rOut
;
964 vcl::text::ComplexTextLayoutFlags m_nOldLayoutMode
;
966 SwLayoutModeModifier( const OutputDevice
& rOutp
);
967 ~SwLayoutModeModifier();
968 void Modify( bool bChgToRTL
);
972 class SwDigitModeModifier
974 const OutputDevice
& rOut
;
975 LanguageType nOldLanguageType
;
977 SwDigitModeModifier( const OutputDevice
& rOutp
, LanguageType eCurLang
);
978 ~SwDigitModeModifier();
984 * Describes parts of multiple text nodes, which will form a text frame, even
985 * when redlines are hidden at a layout level.
989 sw::WriterMultiListener listener
;
990 std::vector
<Extent
> extents
;
991 /// note: cannot be const currently to avoid UB because SwTextGuess::Guess
992 /// const_casts it and modifies it (also, Update will modify it)
994 /// most paragraph properties are taken from the first non-empty node
995 SwTextNode
* pParaPropsNode
;
996 /// except break attributes, those are taken from the first node
997 SwTextNode
*const pFirstNode
;
998 /// mainly for sanity checks
999 SwTextNode
const* pLastNode
;
1000 MergedPara(SwTextFrame
& rFrame
, std::vector
<Extent
>&& rExtents
,
1002 SwTextNode
*const pProps
, SwTextNode
*const pFirst
,
1003 SwTextNode
const*const pLast
)
1004 : listener(rFrame
), extents(std::move(rExtents
)), mergedText(std::move(aText
))
1005 , pParaPropsNode(pProps
), pFirstNode(pFirst
), pLastNode(pLast
)
1007 assert(pParaPropsNode
);
1013 /// iterate SwTextAttr in potentially merged text frame
1014 class MergedAttrIterBase
1017 sw::MergedPara
const*const m_pMerged
;
1018 SwTextNode
const*const m_pNode
;
1019 size_t m_CurrentExtent
;
1020 size_t m_CurrentHint
;
1021 MergedAttrIterBase(SwTextFrame
const& rFrame
);
1024 class MergedAttrIter
1025 : public MergedAttrIterBase
1028 MergedAttrIter(SwTextFrame
const& rFrame
) : MergedAttrIterBase(rFrame
) {}
1029 SwTextAttr
const* NextAttr(SwTextNode
const** ppNode
= nullptr);
1032 class MergedAttrIterByEnd
1035 std::vector
<std::pair
<SwTextNode
const*, SwTextAttr
const*>> m_Hints
;
1036 SwTextNode
const*const m_pNode
;
1037 size_t m_CurrentHint
;
1039 MergedAttrIterByEnd(SwTextFrame
const& rFrame
);
1040 SwTextAttr
const* NextAttr(SwTextNode
const*& rpNode
);
1044 class MergedAttrIterReverse
1045 : public MergedAttrIterBase
1048 MergedAttrIterReverse(SwTextFrame
const& rFrame
);
1049 SwTextAttr
const* PrevAttr(SwTextNode
const** ppNode
= nullptr);
1053 const SwTwips WIDOW_MAGIC
= (SAL_MAX_INT32
- 1)/2;
1059 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */