/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/ #ifndef INCLUDED_SW_SOURCE_CORE_INC_TXTFRM_HXX #define INCLUDED_SW_SOURCE_CORE_INC_TXTFRM_HXX
namespace com::sun::star::linguistic2 { class XHyphenatedWord; }
namespace sw::mark { class MarkBase; } namespace sw { enumclass ParagraphBreakMode; } class SwCharRange; class SwTextNode; class SwTextAttrEnd; class SwTextFormatter; class SwTextFormatInfo; class SwParaPortion; class WidowsAndOrphans; class SwTextFootnote; class SwInterHyphInfo; // Hyphenate() class SwCache; class SwFrameFormat; struct SwCursorMoveState; struct SwFillData; class SwPortionHandler; class SwScriptInfo; enumclass ExpandMode; class SwTextAttr; class SwWrtShell; class SwNode; class SwNodeIndex; class SwFlyAtContentFrame;
/// a clone of SwInterHyphInfo, but with TextFrameIndex instead of node index class SwInterHyphInfoTextFrame
{ private: /// output: hyphenated word
css::uno::Reference<css::linguistic2::XHyphenatedWord> m_xHyphWord; public: /// input: requested range to hyphenate
TextFrameIndex m_nStart;
TextFrameIndex m_nEnd; /// output: found word
TextFrameIndex m_nWordStart;
TextFrameIndex m_nWordLen;
/** * Describes a part of a single text node, which will be part of a text frame, * even when redlines are hidden at a layout level.
*/ struct Extent
{
SwTextNode * /*const logically, but need assignment for std::vector*/ pNode;
sal_Int32 nStart;
sal_Int32 nEnd;
Extent(SwTextNode *const p, sal_Int32 const s, sal_Int32 const e)
: pNode(p), nStart(s), nEnd(e)
{
assert(pNode);
assert(nStart != nEnd);
}
};
// warning: Existing must be used only once; a second use would delete the frame created by the first one... enumclass FrameMode { New, Existing };
std::unique_ptr<sw::MergedPara> CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode, FrameMode eMode);
SwTextFrame * MakeTextFrame(SwTextNode & rNode, SwFrame *, sw::FrameMode eMode);
/** * Decides if rTextNode has a numbering which has layout-level values (e.g. Arabic, but not * none or bullets).
*/ bool HasNumberingWhichNeedsLayoutUpdate(const SwTextNode& rTextNode);
} // namespace sw
/// Represents the visualization of a paragraph. Typical upper is an /// SwBodyFrame. The first text portion of the first line is az SwParaPortion. class SW_DLLPUBLIC SwTextFrame final : public SwContentFrame
{ friendclass SwTextIter; friendclass SwTestFormat; friendclass WidowsAndOrphans; friendclass TextFrameLockGuard; // May Lock()/Unlock() friendbool sw_ChangeOffset(SwTextFrame* pFrame, TextFrameIndex nNew);
/// SwLineLayout cache: the lines are not actually owned by the SwTextFrame /// but by this SwCache, so they will be deleted in large documents /// if there are too many of them, but the "valid" flags of the frame /// will still be set; GetFormatted() is the function that forces /// recreation of the SwLineLayout by Format() if necessary. static SwCache *s_pTextCache;
sal_Int32 mnAllLines :24; // Line count for the Paint (including nThisLines)
sal_Int32 mnThisLines :8; // Count of Lines of the Frame
// The x position for flys anchored at this paragraph. // These values are calculated in SwTextFrame::CalcBaseOfstForFly()
SwTwips mnFlyAnchorOfst; // The x position for wrap-through flys anchored at this paragraph.
SwTwips mnFlyAnchorOfstNoWrap; /// The y position for wrap-through flys anchored at this paragraph.
SwTwips mnFlyAnchorVertOfstNoWrap;
SwTwips mnFootnoteLine; // OD 2004-03-17 #i11860# - re-factoring of #i11859# // member for height of last line (value needed for proportional line spacing)
SwTwips mnHeightOfLastLine; // member for the additional first line offset, which is caused by the list // label alignment for list level position and space mode LABEL_ALIGNMENT. // This additional first line offset is used for the text formatting. // It is NOT used for the determination of printing area.
SwTwips mnAdditionalFirstLineOffset;
/// redline merge data
std::unique_ptr<sw::MergedPara> m_pMergedPara;
TextFrameIndex mnOffset; // Is the offset in the Content (character count)
TextFrameIndex mnNoHyphOffset; // Is the offset of the last line with disabled or limited hyphenation
sal_Int16 mnNoHyphEndZone; // size of end zone (-1 means disabled hyphenation)
sal_uInt16 mnCacheIndex; // Index into the cache, USHRT_MAX if there's definitely no fitting object in the cache
// Separates the Master and creates a Follow or adjusts the data in the Follow void AdjustFollow_( SwTextFormatter &rLine, TextFrameIndex nOffset,
TextFrameIndex nStrEnd, bool bDontJoin );
// Iterates all Lines and sets the line spacing using the attribute void CalcLineSpace();
// Only called in Format void AdjustFrame( const SwTwips nChgHeight, bool bHasToFit = false );
bool mbLocked : 1; // In the Format? bool mbWidow : 1; // Is our follow a Widow? bool mbJustWidow : 1; // Did we just request Widow flag on master? bool mbEmpty : 1; // Are we an empty paragraph? bool mbInFootnoteConnect : 1; // Is in Connect at the moment bool mbFootnote : 1; // Has at least one footnote bool mbRepaint : 1; // TextFrame: Repaint is ready to be fetched /// Contains rotated portions. bool mbHasRotatedPortions : 1; bool mbFieldFollow : 1; // Start with Field rest of the Master bool mbHasAnimation : 1; // Contains animated SwGrfNumPortion bool mbIsSwapped : 1; // during text formatting we swap the // width and height for vertical formatting // OD 14.03.2003 #i11760# - flag to control, if follow is formatted in // method <CalcFollow(..)>. // E.g., avoid formatting of follow, if method <SwLayoutFrame::FormatWidthCols(..)> // is running. bool mbFollowFormatAllowed : 1;
// Changes the Frame or not (cf. FlyCnt) bool GetModelPositionForViewPoint_(SwPosition *pPos, const Point &rPoint, constbool bChgFrame, SwCursorMoveState* = nullptr ) const; void FillCursorPos( SwFillData &rFill ) const;
// Format exactly one Line bool FormatLine( SwTextFormatter &rLine, constbool bPrev );
// In order to safe stack space, we split this method: // Format_ calls Format_ with parameters void FormatImpl( vcl::RenderContext* pRenderContext, SwParaPortion *pPara,
::std::vector<SwAnchoredObject *> & rIntersectingObjs); void Format_( SwTextFormatter &rLine, SwTextFormatInfo &rInf, constbool bAdjust = false ); void FormatOnceMore( SwTextFormatter &rLine, SwTextFormatInfo &rInf );
// Formats the Follow and ensures disposing on orphans bool CalcFollow(TextFrameIndex nTextOfst);
virtualvoid MakePos() override;
// Corrects the position from which we need to format static TextFrameIndex FindBrk(std::u16string_view aText, TextFrameIndex nStart,
TextFrameIndex nEnd);
void ChgThisLines(); // Must always be called if the Line count could have changed
// required for 'new' relative anchor position void CalcBaseOfstForFly();
/** method to determine height of last line, needed for proportional line spacing
OD 2004-03-17 #i11860# OD 2005-05-20 #i47162# - introduce new optional parameter <_bUseFont> in order to force the usage of the former algorithm to determine the height of the last line, which uses the font.
@param _bUseFont optional input parameter - boolean indicating, if the font has to be used to determine the height of the last line. default value: false
*/ void CalcHeightOfLastLine( constbool _bUseFont = false );
/** * This is public, as it needs to be called by some methods in order to save the Prepare * USE WITH CAUTION!
*/ void Init();
/// Is called by DoIdleJob_() and ExecSpellPopup()
SwRect AutoSpell_(SwTextNode &, sal_Int32);
/// Is called by DoIdleJob_()
SwRect SmartTagScan(SwTextNode &);
/// Is called by DoIdleJob_() void CollectAutoCmplWrds(SwTextNode &, sal_Int32);
/** * Returns the view rectangle for the rPos model position. The values are relative to the upper * left position of the page frame. * Additional information can be obtained by passing an SwCursorMoveState object. * Returns false if rPos > number of character is string
*/ virtualbool GetCharRect( SwRect& rRect, const SwPosition& rPos,
SwCursorMoveState* pCMS = nullptr, bool bAllowFarAway = true ) const override;
/// A slimmer version of GetCharRect for autopositioning Frames bool GetAutoPos( SwRect &, const SwPosition& ) const;
/** * Determine top of line for given position in the text frame * * OD 11.11.2003 #i22341# * Assumption: given position exists in the text frame or in a follow of it * OD 2004-02-02 - adjustment * Top of first paragraph line is the top of the paragraph. * OD 2004-03-18 #i11860# - Consider upper space amount considered for * previous frame and the page grid. * * @param _onTopOfLine * output parameter - top of line, if the given position is found in the * text frame. * * @param _rPos * input parameter - reference to the position in the text frame * * @return boolean indicating, if the top of line for the given position * has been determined or not.
*/ bool GetTopOfLine( SwTwips& _onTopOfLine, const SwPosition& _rPos ) const;
/** * In nOffset returns the offset of the char within the set * text buffer, which is closest to the position provided by * aPoint within the layout's SSize. * * @returns false if the SPoint is outside of the SSize else * returns true
*/ virtualbool GetModelPositionForViewPoint( SwPosition *, Point&,
SwCursorMoveState* = nullptr, bool bTestBackground = false ) const override;
/** * Makes sure that the Frame is not switched (e.g. switched for a * character-bound Frame)
*/ bool GetKeyCursorOfst(SwPosition *pPos, const Point &rPoint ) const
{ return GetModelPositionForViewPoint_( pPos, rPoint, false ); }
/** * Prepares the cursor position for a visual cursor move (BiDi). * The behaviour is different for insert and overwrite cursors
*/ void PrepareVisualMove( TextFrameIndex& nPos, sal_uInt8& nCursorLevel, bool& bRight, bool bInsertCursor );
/** * SwContentFrame: the shortcut for the Frames * If the void* casts wrongly, it's its own fault! * The void* must be checked for 0 in any case! * * return true if the Portion associated with this SwTextFrame was * potentially destroyed and replaced by Prepare
*/ virtualbool Prepare( const PrepareHint ePrep = PrepareHint::Clear, constvoid *pVoid = nullptr, bool bNotify = true ) override;
/** * nMaxHeight is the required height * bSplit indicates, that the paragraph has to be split * bTst indicates, that we are currently doing a test formatting
*/ virtualbool WouldFit(SwTwips &nMaxHeight, bool &bSplit, bool bTst, bool bMoveBwd) override;
/** * The WouldFit equivalent for temporarily rewired TextFrames * nMaxHeight returns the required size here too and bSplit * determines whether the paragraph needs to be split. * We pass the potential predecessor for the distance calculation
*/ bool TestFormat( const SwFrame* pPrv, SwTwips &nMaxHeight, bool &bSplit );
/** * We format a Line for interactive hyphenation * @return found
*/ bool Hyphenate(SwInterHyphInfoTextFrame & rInf); /// Is a hyphenated word? At selection, Point can be at the end of the word bool IsInHyphenatedWord(SwPaM *, bool bSelection) const;
/// Does the Frame have a local footnote (in this Frame or Follow)? #ifdef DBG_UTIL void CalcFootnoteFlag(TextFrameIndex nStop = TextFrameIndex(COMPLETE_STRING)); //For testing SplitFrame #else void CalcFootnoteFlag(); #endif
/** * Hides respectively shows objects, which are anchored at paragraph, * at/as a character of the paragraph, corresponding to the paragraph and * paragraph portion visibility.
*/ void HideAndShowObjects() override;
/** * If we're a Footnote that grows towards its reference ... * public, because it's needed by SwContentFrame::MakeAll
*/
SwTwips GetFootnoteLine( const SwTextFootnote *pFootnote ) const;
/// Find the page number of ErgoSum and QuoVadis
SwTextFrame *FindQuoVadisFrame();
/** * In case the SwLineLayout was cleared out of the s_pTextCache, recreate it * * #i29062# GetFormatted() can trigger a full formatting * of the paragraph, causing other layout frames to become invalid. This * has to be avoided during painting. Therefore we need to pass the * information that we are currently in the paint process.
*/
SwTextFrame* GetFormatted( bool bForceQuickFormat = false );
/// Will be moved soon void SetFootnote( constbool bNew ) { mbFootnote = bNew; }
/// Respect the Follows inlinebool IsInside(TextFrameIndex nPos) const;
/// Removes the Line information from the Cache but retains the entry itself void ClearPara(); /// Removes this frame completely from the Cache void RemoveFromCache();
/// Am I a FootnoteFrame, with a number at the start of the paragraph? bool IsFootnoteNumFrame() const
{ return IsInFootnote() && !GetIndPrev() && IsFootnoteNumFrame_(); }
/** * Simulates a formatting as if there were not right margin or Flys or other * obstacles and returns the width
*/
SwTwips CalcFitToContent();
/** * Simulate format for a list item paragraph, whose list level attributes * are in LABEL_ALIGNMENT mode, in order to determine additional first * line offset for the real text formatting due to the value of label * adjustment attribute of the list level.
*/ void CalcAdditionalFirstLineOffset();
/** * Returns the additional line spacing for the next paragraph * @param _bNoPropLineSpacing: control, whether the value of a * proportional line spacing is returned or not
*/
tools::Long GetLineSpace( constbool _bNoPropLineSpacing = false ) const;
/// Returns the first line height
SwTwips FirstLineHeight() const;
/// Rewires FlyInContentFrame, if nEnd > Index >= nStart void MoveFlyInCnt(SwTextFrame *pNew, TextFrameIndex nStart, TextFrameIndex nEnd);
/// Calculates the position of FlyInContentFrames
TextFrameIndex CalcFlyPos( SwFrameFormat const * pSearch );
/// Determines the start position and step size of the register bool FillRegister( SwTwips& rRegStart, sal_uInt16& rRegDiff );
/// Determines the line count
sal_Int32 GetLineCount(TextFrameIndex nPos);
/// For displaying the line numbers
sal_Int32 GetAllLines() const { return mnAllLines; }
sal_Int32 GetThisLines() const { return mnThisLines;} void RecalcAllLines();
/// Stops the animations within numberings void StopAnimation( const OutputDevice *pOut );
/// Visit all portions for Accessibility void VisitPortions( SwPortionHandler& rPH ) const;
/// Returns the script info stored at the paraportion const SwScriptInfo* GetScriptInfo() const;
SwScriptInfo* GetScriptInfo();
/// Swaps width and height of the text frame void SwapWidthAndHeight();
/** * Calculates the coordinates of a rectangle when switching from * horizontal to vertical layout
*/ void SwitchHorizontalToVertical( SwRect& rRect ) const;
/** * Calculates the coordinates of a point when switching from * horizontal to vertical layout
*/ void SwitchHorizontalToVertical( Point& rPoint ) const;
/** * Calculates the limit value when switching from * horizontal to vertical layout
*/
tools::Long SwitchHorizontalToVertical( tools::Long nLimit ) const;
/** * Calculates the coordinates of a rectangle when switching from * vertical to horizontal layout
*/ void SwitchVerticalToHorizontal( SwRect& rRect ) const;
/** * Calculates the coordinates of a point when switching from * vertical to horizontal layout
*/ void SwitchVerticalToHorizontal( Point& rPoint ) const;
/** * Calculates the a limit value when switching from * vertical to horizontal layout
*/
tools::Long SwitchVerticalToHorizontal( tools::Long nLimit ) const;
/** * Calculates the coordinates of a rectangle when switching from * LTR to RTL layout
*/ void SwitchLTRtoRTL( SwRect& rRect ) const;
/** * Calculates the coordinates of a point when switching from * LTR to RTL layout
*/ void SwitchLTRtoRTL( Point& rPoint ) const;
/** * Calculates the coordinates of a rectangle when switching from * RTL to LTR layout
*/ void SwitchRTLtoLTR( SwRect& rRect ) const { SwitchLTRtoRTL( rRect ); }
/** * Calculates the coordinates of a point when switching from * RTL to LTR layout
*/ void SwitchRTLtoLTR( Point& rPoint ) const { SwitchLTRtoRTL( rPoint ); };
/// This text frame may have a split fly frames anchored to it. Is any of them a frame that has /// a follow, i.e. not the last in a master -> follow 1 -> ... -> last follow chain?
SwFlyAtContentFrame* HasNonLastSplitFlyDrawObj() const;
/// This text frame has a follow and the text frame don't contain text. Additionally one split /// fly is anchored to the text frame. bool IsEmptyMasterWithSplitFly() const;
/// This text frame is not split, doesn't fit the upper, has a single split fly anchored to it /// with a negative vertical offset. Such frames may need explicit splitting. bool IsEmptyWithSplitFly() const;
//use this to protect a SwTextFrame for a given scope from getting merged with //its neighbour and thus deleted class TextFrameLockGuard
{ private:
SwTextFrame *m_pTextFrame; bool m_bOldLocked; public: //Lock pFrame for the lifetime of the Cut/Paste call, etc. to avoid //SwTextFrame::AdjustFollow_ removing the pFrame we're trying to Make
TextFrameLockGuard(SwFrame* pFrame)
{
m_pTextFrame = pFrame->IsTextFrame() ? static_cast<SwTextFrame*>(pFrame) : nullptr; if (m_pTextFrame)
{
m_bOldLocked = m_pTextFrame->IsLocked();
m_pTextFrame->Lock();
} else
{
m_bOldLocked = false;
}
}
~TextFrameLockGuard()
{ if (m_pTextFrame && !m_bOldLocked)
m_pTextFrame->Unlock();
}
};
/** * Helper class which can be used instead of the macros if a function * has too many returns
*/ class SwFrameSwapper
{ const SwTextFrame* pFrame; bool bUndo; public:
SwFrameSwapper( const SwTextFrame* pFrame, bool bSwapIfNotSwapped );
~SwFrameSwapper();
};
/** * Describes parts of multiple text nodes, which will form a text frame, even * when redlines are hidden at a layout level.
*/ struct MergedPara
{
sw::WriterMultiListener listener;
std::vector<Extent> extents; /// note: cannot be const currently to avoid UB because SwTextGuess::Guess /// const_casts it and modifies it (also, Update will modify it)
OUString mergedText; /// most paragraph properties are taken from the first non-empty node
SwTextNode * pParaPropsNode; /// except break attributes, those are taken from the first node
SwTextNode *const pFirstNode; /// mainly for sanity checks
SwTextNode const* pLastNode;
MergedPara(SwTextFrame & rFrame, std::vector<Extent>&& rExtents,
OUString aText,
SwTextNode *const pFirst,
SwTextNode const*const pLast)
: listener(rFrame), extents(std::move(rExtents)), mergedText(std::move(aText))
, pParaPropsNode(nullptr), pFirstNode(pFirst), pLastNode(pLast)
{
assert(pFirstNode);
assert(pLastNode);
}
};
/// iterate SwTextAttr in potentially merged text frame class MergedAttrIterBase
{ protected:
sw::MergedPara const*const m_pMerged;
SwTextNode const*const m_pNode;
size_t m_CurrentExtent;
size_t m_CurrentHint;
MergedAttrIterBase(SwTextFrame const& rFrame);
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.