Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / inc / txtfrm.hxx
blob6deba9f6104fc6aa245ae9176c3b27ca4641348a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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>
23 #include "cntfrm.hxx"
24 #include "TextFrameIndex.hxx"
25 #include <nodeoffset.hxx>
27 #include <set>
28 #include <utility>
30 #include <view.hxx>
32 namespace com::sun::star::linguistic2 { class XHyphenatedWord; }
34 namespace sw::mark { class IMark; }
35 class SwCharRange;
36 class SwTextNode;
37 class SwTextAttrEnd;
38 class SwTextFormatter;
39 class SwTextFormatInfo;
40 class SwParaPortion;
41 class WidowsAndOrphans;
42 class SwTextFootnote;
43 class SwInterHyphInfo; // Hyphenate()
44 class SwCache;
45 class SwBorderAttrs;
46 class SwFrameFormat;
47 struct SwCursorMoveState;
48 struct SwFillData;
49 class SwPortionHandler;
50 class SwScriptInfo;
51 enum class ExpandMode;
52 class SwTextAttr;
53 class SwWrtShell;
54 class SwNode;
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
62 private:
63 /// output: hyphenated word
64 css::uno::Reference<css::linguistic2::XHyphenatedWord> m_xHyphWord;
65 public:
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)
80 m_xHyphWord = xHW;
84 namespace sw {
86 /**
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.
90 struct Extent
92 SwTextNode * /*const logically, but need assignment for std::vector*/ pNode;
93 sal_Int32 nStart;
94 sal_Int32 nEnd;
95 Extent(SwTextNode *const p, sal_Int32 const s, sal_Int32 const e)
96 : pNode(p), nStart(s), nEnd(e)
98 assert(pNode);
99 assert(nStart != nEnd);
103 struct MergedPara;
104 class InsertText;
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,
128 bool isRealDelete,
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
159 * none or bullets).
161 bool HasNumberingWhichNeedsLayoutUpdate(const SwTextNode& rTextNode);
163 } // namespace sw
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()
222 bool CalcPreps();
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(..)>
248 // is running.
249 bool mbFollowFormatAllowed : 1;
251 void ResetPreps();
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);
286 // inline branch
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
306 bool FormatEmpty();
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.
324 @param _bUseFont
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;
343 public:
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
352 * USE WITH CAUTION!
354 void Init();
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
389 * text frame.
391 * @param _rPos
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
408 * returns true
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&,
423 SwPrintData const*const pPrintData = nullptr ) const override;
424 virtual bool GetInfo( SfxPoolItem & ) const override;
427 * Layout oriented cursor travelling:
428 * Left border, right border, previous Line, following Line,
429 * same horizontal position
431 virtual bool LeftMargin(SwPaM *) const override;
432 virtual bool RightMargin(SwPaM *, bool bAPI = false) const override;
434 virtual bool UnitUp(SwPaM *, const SwTwips nOffset,
435 bool bSetInReadOnly ) const override;
436 virtual bool UnitDown(SwPaM *, const SwTwips nOffset,
437 bool bSetInReadOnly ) const override;
438 bool UnitUp_(SwPaM *, const SwTwips nOffset,
439 bool bSetInReadOnly ) const;
440 bool UnitDown_(SwPaM *, const SwTwips nOffset,
441 bool bSetInReadOnly ) const;
444 * Prepares the cursor position for a visual cursor move (BiDi).
445 * The behaviour is different for insert and overwrite cursors
447 void PrepareVisualMove( TextFrameIndex& nPos, sal_uInt8& nCursorLevel,
448 bool& bRight, bool bInsertCursor );
450 /// Methods to manage the FollowFrame
451 void SplitFrame(TextFrameIndex nTextPos);
452 SwContentFrame *JoinFrame();
453 TextFrameIndex GetOffset() const { return mnOffset; }
454 void SetOffset_(TextFrameIndex nNewOfst);
455 inline void SetOffset (TextFrameIndex nNewOfst);
456 void ManipOfst(TextFrameIndex const nNewOfst) { mnOffset = nNewOfst; }
457 SwTextFrame *GetFrameAtPos ( const SwPosition &rPos);
458 inline const SwTextFrame *GetFrameAtPos ( const SwPosition &rPos) const;
459 SwTextFrame& GetFrameAtOfst(TextFrameIndex nOfst);
460 /// If there's a Follow and we don't contain text ourselves
461 bool IsEmptyMaster() const
462 { return GetFollow() && !GetFollow()->GetOffset(); }
464 void SetMergedPara(std::unique_ptr<sw::MergedPara> p);
465 sw::MergedPara * GetMergedPara() { return m_pMergedPara.get(); }
466 sw::MergedPara const* GetMergedPara() const { return m_pMergedPara.get(); }
468 /// Returns the text portion we want to edit (for inline see underneath)
469 const OUString& GetText() const;
470 SwTextNode const* GetTextNodeForParaProps() const;
471 SwTextNode const* GetTextNodeForFirstText() const;
472 SwTextNode * GetTextNodeFirst()
473 { return const_cast<SwTextNode*>(const_cast<SwTextFrame const*>(this)->GetTextNodeFirst()); };
474 SwTextNode const* GetTextNodeFirst() const;
475 SwDoc & GetDoc()
476 { return const_cast<SwDoc &>(const_cast<SwTextFrame const*>(this)->GetDoc()); }
477 SwDoc const& GetDoc() const;
479 SwTextFrame(SwTextNode * const, SwFrame*, sw::FrameMode eMode);
482 * SwContentFrame: the shortcut for the Frames
483 * If the void* casts wrongly, it's its own fault!
484 * The void* must be checked for 0 in any case!
486 * return true if the Portion associated with this SwTextFrame was
487 * potentially destroyed and replaced by Prepare
489 virtual bool Prepare( const PrepareHint ePrep = PrepareHint::Clear,
490 const void *pVoid = nullptr, bool bNotify = true ) override;
493 * nMaxHeight is the required height
494 * bSplit indicates, that the paragraph has to be split
495 * bTst indicates, that we are currently doing a test formatting
497 virtual bool WouldFit(SwTwips &nMaxHeight, bool &bSplit, bool bTst, bool bMoveBwd) override;
500 * The WouldFit equivalent for temporarily rewired TextFrames
501 * nMaxHeight returns the required size here too and bSplit
502 * determines whether the paragraph needs to be split.
503 * We pass the potential predecessor for the distance calculation
505 bool TestFormat( const SwFrame* pPrv, SwTwips &nMaxHeight, bool &bSplit );
508 * We format a Line for interactive hyphenation
509 * @return found
511 bool Hyphenate(SwInterHyphInfoTextFrame & rInf);
513 /// Test grow
514 inline SwTwips GrowTst( const SwTwips nGrow );
516 SwParaPortion *GetPara();
517 inline const SwParaPortion *GetPara() const;
518 inline bool HasPara() const;
519 bool HasPara_() const;
521 /// map position in potentially merged text frame to SwPosition
522 std::pair<SwTextNode*, sal_Int32> MapViewToModel(TextFrameIndex nIndex) const;
523 SwPosition MapViewToModelPos(TextFrameIndex nIndex) const;
524 TextFrameIndex MapModelToView(SwTextNode const* pNode, sal_Int32 nIndex) const;
525 TextFrameIndex MapModelToViewPos(SwPosition const& rPos) const;
527 // If there are any hanging punctuation portions in the margin
528 // the offset will be returned.
529 SwTwips HangingMargin() const;
531 /// Get the amount of lower margin of this frame we need to consider for fly portion purposes.
532 SwTwips GetLowerMarginForFlyIntersect() const;
534 // Locking
535 bool IsLocked() const { return mbLocked; }
537 bool IsWidow() const { return mbWidow; }
538 bool IsJustWidow() const { return mbJustWidow; }
539 bool IsEmpty() const { return mbEmpty; }
540 bool HasFootnote() const { return mbFootnote; }
541 bool IsInFootnoteConnect()const { return mbInFootnoteConnect;}
542 bool IsFieldFollow() const { return mbFieldFollow;}
544 inline void SetRepaint() const;
545 inline void ResetRepaint() const;
546 bool HasRepaint() const { return mbRepaint; }
547 void SetHasRotatedPortions(bool bHasRotatedPortions);
548 bool GetHasRotatedPortions() const { return mbHasRotatedPortions; }
549 void SetAnimation() const
550 { const_cast<SwTextFrame*>(this)->mbHasAnimation = true; }
551 bool HasAnimation() const { return mbHasAnimation; }
553 bool IsSwapped() const { return mbIsSwapped; }
555 /// Does the Frame have a local footnote (in this Frame or Follow)?
556 #ifdef DBG_UTIL
557 void CalcFootnoteFlag(TextFrameIndex nStop = TextFrameIndex(COMPLETE_STRING)); //For testing SplitFrame
558 #else
559 void CalcFootnoteFlag();
560 #endif
562 /// Hidden
563 bool IsHiddenNow() const; // bHidden && pOut == pPrt
564 void HideHidden(); // Remove appendage if Hidden
565 void HideFootnotes(TextFrameIndex nStart, TextFrameIndex nEnd);
568 * Hides respectively shows objects, which are anchored at paragraph,
569 * at/as a character of the paragraph, corresponding to the paragraph and
570 * paragraph portion visibility.
572 void HideAndShowObjects();
574 /// Footnote
575 void RemoveFootnote(TextFrameIndex nStart,
576 TextFrameIndex nLen = TextFrameIndex(COMPLETE_STRING));
577 inline SwTwips GetFootnoteFrameHeight() const;
578 SwTextFrame *FindFootnoteRef( const SwTextFootnote *pFootnote );
579 const SwTextFrame *FindFootnoteRef( const SwTextFootnote *pFootnote ) const
580 { return const_cast<SwTextFrame *>(this)->FindFootnoteRef( pFootnote ); }
581 void ConnectFootnote( SwTextFootnote *pFootnote, const SwTwips nDeadLine );
584 * If we're a Footnote that grows towards its reference ...
585 * public, because it's needed by SwContentFrame::MakeAll
587 SwTwips GetFootnoteLine( const SwTextFootnote *pFootnote ) const;
589 TextFrameIndex GetDropLen(TextFrameIndex nWishLen) const;
591 LanguageType GetLangOfChar(TextFrameIndex nIndex, sal_uInt16 nScript,
592 bool bNoChar = false) const;
594 virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ) override;
595 virtual void CheckDirection( bool bVert ) override;
597 /// Returns the sum of line height in pLine
598 SwTwips GetParHeight() const;
600 inline SwTextFrame *GetFollow();
601 inline const SwTextFrame *GetFollow() const;
603 /// Find the page number of ErgoSum and QuoVadis
604 SwTextFrame *FindQuoVadisFrame();
607 * In case the SwLineLayout was cleared out of the s_pTextCache, recreate it
609 * #i29062# GetFormatted() can trigger a full formatting
610 * of the paragraph, causing other layout frames to become invalid. This
611 * has to be avoided during painting. Therefore we need to pass the
612 * information that we are currently in the paint process.
614 SwTextFrame* GetFormatted( bool bForceQuickFormat = false );
616 /// Will be moved soon
617 void SetFootnote( const bool bNew ) { mbFootnote = bNew; }
619 /// Respect the Follows
620 inline bool IsInside(TextFrameIndex nPos) const;
622 /// DropCaps and selections
623 bool GetDropRect( SwRect &rRect ) const
624 { return HasPara() && GetDropRect_( rRect ); }
626 static SwCache *GetTextCache() { return s_pTextCache; }
627 static void SetTextCache( SwCache *pNew ) { s_pTextCache = pNew; }
629 static tools::Long GetMinPrtLine() { return nMinPrtLine; }
631 sal_uInt16 GetCacheIdx() const { return mnCacheIndex; }
632 void SetCacheIdx( const sal_uInt16 nNew ) { mnCacheIndex = nNew; }
634 /// Removes the Line information from the Cache but retains the entry itself
635 void ClearPara();
636 /// Removes this frame completely from the Cache
637 void RemoveFromCache();
639 /// Am I a FootnoteFrame, with a number at the start of the paragraph?
640 bool IsFootnoteNumFrame() const
641 { return IsInFootnote() && !GetIndPrev() && IsFootnoteNumFrame_(); }
644 * Simulates a formatting as if there were not right margin or Flys or other
645 * obstacles and returns the width
647 SwTwips CalcFitToContent();
650 * Simulate format for a list item paragraph, whose list level attributes
651 * are in LABEL_ALIGNMENT mode, in order to determine additional first
652 * line offset for the real text formatting due to the value of label
653 * adjustment attribute of the list level.
655 void CalcAdditionalFirstLineOffset();
657 SwTwips GetAdditionalFirstLineOffset() const
659 return mnAdditionalFirstLineOffset;
663 * Returns the additional line spacing for the next paragraph
664 * @param _bNoPropLineSpacing: control, whether the value of a
665 * proportional line spacing is returned or not
667 tools::Long GetLineSpace( const bool _bNoPropLineSpacing = false ) const;
669 /// Returns the first line height
670 sal_uInt16 FirstLineHeight() const;
672 /// Rewires FlyInContentFrame, if nEnd > Index >= nStart
673 void MoveFlyInCnt(SwTextFrame *pNew, TextFrameIndex nStart, TextFrameIndex nEnd);
675 /// Calculates the position of FlyInContentFrames
676 TextFrameIndex CalcFlyPos( SwFrameFormat const * pSearch );
678 /// Determines the start position and step size of the register
679 bool FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff );
681 /// Determines the line count
682 sal_Int32 GetLineCount(TextFrameIndex nPos);
684 /// For displaying the line numbers
685 sal_Int32 GetAllLines() const { return mnAllLines; }
686 sal_Int32 GetThisLines() const { return mnThisLines;}
687 void RecalcAllLines();
689 /// Stops the animations within numberings
690 void StopAnimation( const OutputDevice *pOut );
692 /// Visit all portions for Accessibility
693 void VisitPortions( SwPortionHandler& rPH ) const;
695 /// Returns the script info stored at the paraportion
696 const SwScriptInfo* GetScriptInfo() const;
698 /// Swaps width and height of the text frame
699 void SwapWidthAndHeight();
702 * Calculates the coordinates of a rectangle when switching from
703 * horizontal to vertical layout
705 void SwitchHorizontalToVertical( SwRect& rRect ) const;
708 * Calculates the coordinates of a point when switching from
709 * horizontal to vertical layout
711 void SwitchHorizontalToVertical( Point& rPoint ) const;
714 * Calculates the limit value when switching from
715 * horizontal to vertical layout
717 tools::Long SwitchHorizontalToVertical( tools::Long nLimit ) const;
720 * Calculates the coordinates of a rectangle when switching from
721 * vertical to horizontal layout
723 void SwitchVerticalToHorizontal( SwRect& rRect ) const;
726 * Calculates the coordinates of a point when switching from
727 * vertical to horizontal layout
729 void SwitchVerticalToHorizontal( Point& rPoint ) const;
732 * Calculates the a limit value when switching from
733 * vertical to horizontal layout
735 tools::Long SwitchVerticalToHorizontal( tools::Long nLimit ) const;
738 * Calculates the coordinates of a rectangle when switching from
739 * LTR to RTL layout
741 void SwitchLTRtoRTL( SwRect& rRect ) const;
744 * Calculates the coordinates of a point when switching from
745 * LTR to RTL layout
747 void SwitchLTRtoRTL( Point& rPoint ) const;
750 * Calculates the coordinates of a rectangle when switching from
751 * RTL to LTR layout
753 void SwitchRTLtoLTR( SwRect& rRect ) const { SwitchLTRtoRTL( rRect ); }
756 * Calculates the coordinates of a point when switching from
757 * RTL to LTR layout
759 void SwitchRTLtoLTR( Point& rPoint ) const { SwitchLTRtoRTL( rPoint ); };
761 bool FollowFormatAllowed() const
763 return mbFollowFormatAllowed;
766 void AllowFollowFormat()
768 mbFollowFormatAllowed = true;
771 void ForbidFollowFormat()
773 mbFollowFormatAllowed = false;
776 SwTwips GetBaseOffsetForFly( bool bIgnoreFlysAnchoredAtThisFrame ) const
778 return ( bIgnoreFlysAnchoredAtThisFrame ?
779 mnFlyAnchorOfst :
780 mnFlyAnchorOfstNoWrap );
783 SwTwips GetBaseVertOffsetForFly(bool bIgnoreFlysAnchoredAtThisFrame) const;
785 SwTwips GetHeightOfLastLine() const
787 return mnHeightOfLastLine;
790 static void repaintTextFrames( const SwTextNode& rNode );
792 void RegisterToNode(SwTextNode &, bool isForceNodeAsFirst = false);
794 bool IsSymbolAt(TextFrameIndex) const;
795 OUString GetCurWord(SwPosition const&) const;
796 sal_uInt16 GetScalingOfSelectedText(TextFrameIndex nStt, TextFrameIndex nEnd);
798 /// This text frame may have a split fly frames anchored to it. Is any of them a frame that has
799 /// a follow, i.e. not the last in a master -> follow 1 -> ... -> last follow chain?
800 SwFlyAtContentFrame* HasNonLastSplitFlyDrawObj() const;
802 /// This text frame has a follow and the text frame don't contain text. Additionally one split
803 /// fly is anchored to the text frame.
804 bool IsEmptyMasterWithSplitFly() const;
806 /// This text frame is not split, doesn't fit the upper, has a single split fly anchored to it
807 /// with a negative vertical offset. Such frames may need explicit splitting.
808 bool IsEmptyWithSplitFly() const;
810 static SwView* GetView();
812 virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override;
815 //use this to protect a SwTextFrame for a given scope from getting merged with
816 //its neighbour and thus deleted
817 class TextFrameLockGuard
819 private:
820 SwTextFrame *m_pTextFrame;
821 bool m_bOldLocked;
822 public:
823 //Lock pFrame for the lifetime of the Cut/Paste call, etc. to avoid
824 //SwTextFrame::AdjustFollow_ removing the pFrame we're trying to Make
825 TextFrameLockGuard(SwFrame* pFrame)
827 m_pTextFrame = pFrame->IsTextFrame() ? static_cast<SwTextFrame*>(pFrame) : nullptr;
828 if (m_pTextFrame)
830 m_bOldLocked = m_pTextFrame->IsLocked();
831 m_pTextFrame->Lock();
833 else
835 m_bOldLocked = false;
839 ~TextFrameLockGuard()
841 if (m_pTextFrame && !m_bOldLocked)
842 m_pTextFrame->Unlock();
846 inline const SwParaPortion *SwTextFrame::GetPara() const
848 return const_cast<SwTextFrame*>(this)->GetPara();
851 inline bool SwTextFrame::HasPara() const
853 return mnCacheIndex!=USHRT_MAX && HasPara_();
856 inline SwTwips SwTextFrame::GrowTst( const SwTwips nGrow )
858 return Grow( nGrow, true );
861 inline bool SwTextFrame::IsInside(TextFrameIndex const nPos) const
863 bool bRet = true;
864 if( nPos < GetOffset() )
865 bRet = false;
866 else
868 const SwTextFrame *pFoll = GetFollow();
869 if( pFoll && nPos >= pFoll->GetOffset() )
870 bRet = false;
872 return bRet;
875 inline SwTwips SwTextFrame::GetFootnoteFrameHeight() const
877 if( !IsFollow() && IsInFootnote() && HasPara() )
878 return GetFootnoteFrameHeight_();
879 else
880 return 0;
883 inline const SwTextFrame *SwTextFrame::GetFollow() const
885 return static_cast<const SwTextFrame*>(SwContentFrame::GetFollow());
887 inline SwTextFrame *SwTextFrame::GetFollow()
889 return static_cast<SwTextFrame*>(SwContentFrame::GetFollow());
892 inline const SwTextFrame *SwTextFrame::GetFrameAtPos( const SwPosition &rPos) const
894 return const_cast<SwTextFrame*>(this)->GetFrameAtPos( rPos );
897 inline void SwTextFrame::SetOffset(TextFrameIndex const nNewOfst)
899 if ( mnOffset != nNewOfst )
900 SetOffset_( nNewOfst );
903 inline void SwTextFrame::SetRepaint() const
905 const_cast<SwTextFrame*>(this)->mbRepaint = true;
907 inline void SwTextFrame::ResetRepaint() const
909 const_cast<SwTextFrame*>(this)->mbRepaint = false;
912 class TemporarySwap {
913 protected:
914 explicit TemporarySwap(SwTextFrame * frame, bool swap):
915 m_frame(frame), m_undo(false)
917 if (m_frame->IsVertical() && swap) {
918 m_undo = true;
919 m_frame->SwapWidthAndHeight();
923 ~TemporarySwap() {
924 if (m_undo) {
925 m_frame->SwapWidthAndHeight();
929 private:
930 TemporarySwap(TemporarySwap const &) = delete;
931 void operator =(TemporarySwap const &) = delete;
933 SwTextFrame * m_frame;
934 bool m_undo;
937 class SwSwapIfSwapped: private TemporarySwap {
938 public:
939 explicit SwSwapIfSwapped(SwTextFrame* frame):
940 TemporarySwap(frame, frame->IsSwapped()) {}
943 class SwSwapIfNotSwapped: private TemporarySwap {
944 public:
945 explicit SwSwapIfNotSwapped(SwTextFrame* frame):
946 TemporarySwap(frame, !frame->IsSwapped()) {}
950 * Helper class which can be used instead of the macros if a function
951 * has too many returns
953 class SwFrameSwapper
955 const SwTextFrame* pFrame;
956 bool bUndo;
957 public:
958 SwFrameSwapper( const SwTextFrame* pFrame, bool bSwapIfNotSwapped );
959 ~SwFrameSwapper();
962 class SwLayoutModeModifier
964 const OutputDevice& m_rOut;
965 vcl::text::ComplexTextLayoutFlags m_nOldLayoutMode;
966 public:
967 SwLayoutModeModifier( const OutputDevice& rOutp );
968 ~SwLayoutModeModifier();
969 void Modify( bool bChgToRTL );
970 void SetAuto();
973 class SwDigitModeModifier
975 const OutputDevice& rOut;
976 LanguageType nOldLanguageType;
977 public:
978 SwDigitModeModifier( const OutputDevice& rOutp, LanguageType eCurLang );
979 ~SwDigitModeModifier();
982 namespace sw {
985 * Describes parts of multiple text nodes, which will form a text frame, even
986 * when redlines are hidden at a layout level.
988 struct MergedPara
990 sw::WriterMultiListener listener;
991 std::vector<Extent> extents;
992 /// note: cannot be const currently to avoid UB because SwTextGuess::Guess
993 /// const_casts it and modifies it (also, Update will modify it)
994 OUString mergedText;
995 /// most paragraph properties are taken from the first non-empty node
996 SwTextNode * pParaPropsNode;
997 /// except break attributes, those are taken from the first node
998 SwTextNode *const pFirstNode;
999 /// mainly for sanity checks
1000 SwTextNode const* pLastNode;
1001 MergedPara(SwTextFrame & rFrame, std::vector<Extent>&& rExtents,
1002 OUString aText,
1003 SwTextNode *const pProps, SwTextNode *const pFirst,
1004 SwTextNode const*const pLast)
1005 : listener(rFrame), extents(std::move(rExtents)), mergedText(std::move(aText))
1006 , pParaPropsNode(pProps), pFirstNode(pFirst), pLastNode(pLast)
1008 assert(pParaPropsNode);
1009 assert(pFirstNode);
1010 assert(pLastNode);
1014 /// iterate SwTextAttr in potentially merged text frame
1015 class MergedAttrIterBase
1017 protected:
1018 sw::MergedPara const*const m_pMerged;
1019 SwTextNode const*const m_pNode;
1020 size_t m_CurrentExtent;
1021 size_t m_CurrentHint;
1022 MergedAttrIterBase(SwTextFrame const& rFrame);
1025 class MergedAttrIter
1026 : public MergedAttrIterBase
1028 public:
1029 MergedAttrIter(SwTextFrame const& rFrame) : MergedAttrIterBase(rFrame) {}
1030 SwTextAttr const* NextAttr(SwTextNode const** ppNode = nullptr);
1033 class MergedAttrIterByEnd
1035 private:
1036 std::vector<std::pair<SwTextNode const*, SwTextAttr const*>> m_Hints;
1037 SwTextNode const*const m_pNode;
1038 size_t m_CurrentHint;
1039 public:
1040 MergedAttrIterByEnd(SwTextFrame const& rFrame);
1041 SwTextAttr const* NextAttr(SwTextNode const*& rpNode);
1042 void PrevAttr();
1045 class MergedAttrIterReverse
1046 : public MergedAttrIterBase
1048 public:
1049 MergedAttrIterReverse(SwTextFrame const& rFrame);
1050 SwTextAttr const* PrevAttr(SwTextNode const** ppNode = nullptr);
1054 const SwTwips WIDOW_MAGIC = (SAL_MAX_INT32 - 1)/2;
1056 } // namespace sw
1058 #endif
1060 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */