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 .
20 #include <sal/config.h>
25 TextFrameIndex
SwTextMargin::GetTextStart() const
27 const OUString
&rText
= GetInfo().GetText();
28 const TextFrameIndex nEnd
= m_nStart
+ m_pCurr
->GetLen();
30 for (TextFrameIndex i
= m_nStart
; i
< nEnd
; ++i
)
32 const sal_Unicode aChar
= rText
[sal_Int32(i
)];
33 if( CH_TAB
!= aChar
&& ' ' != aChar
)
39 TextFrameIndex
SwTextMargin::GetTextEnd() const
41 const OUString
&rText
= GetInfo().GetText();
42 const TextFrameIndex nEnd
= m_nStart
+ m_pCurr
->GetLen();
43 for (TextFrameIndex i
= nEnd
- TextFrameIndex(1); i
>= m_nStart
; --i
)
45 const sal_Unicode aChar
= rText
[sal_Int32(i
)];
46 if( CH_TAB
!= aChar
&& CH_BREAK
!= aChar
&& ' ' != aChar
)
47 return i
+ TextFrameIndex(1);
52 // Does the paragraph fit into one line?
53 bool SwTextFrameInfo::IsOneLine() const
55 const SwLineLayout
*pLay
= m_pFrame
->GetPara();
59 // For follows false of course
60 if( m_pFrame
->GetFollow() )
63 pLay
= pLay
->GetNext();
68 pLay
= pLay
->GetNext();
73 // Is the line filled for X percent?
74 bool SwTextFrameInfo::IsFilled( const sal_uInt8 nPercent
) const
76 const SwLineLayout
*pLay
= m_pFrame
->GetPara();
80 tools::Long nWidth
= m_pFrame
->getFramePrintArea().Width();
83 return nWidth
<= pLay
->Width();
86 // Where does the text start (without whitespace)? (document global)
87 SwTwips
SwTextFrameInfo::GetLineStart( const SwTextCursor
&rLine
)
89 const TextFrameIndex nTextStart
= rLine
.GetTextStart();
90 if( rLine
.GetStart() == nTextStart
)
91 return rLine
.GetLineStart();
94 const_cast<SwTextCursor
&>(rLine
).GetCharRect( &aRect
, nTextStart
);
98 // Where does the text start (without whitespace)? (relative in the Frame)
99 SwTwips
SwTextFrameInfo::GetLineStart() const
101 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
102 SwTextCursor
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
103 return GetLineStart( aLine
) - m_pFrame
->getFrameArea().Left() - m_pFrame
->getFramePrintArea().Left();
106 // Calculates the character's position and returns the middle position
107 SwTwips
SwTextFrameInfo::GetCharPos(TextFrameIndex
const nChar
, bool bCenter
) const
109 SwRectFnSet
aRectFnSet(m_pFrame
);
110 SwFrameSwapper
aSwapper( m_pFrame
, true );
112 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
113 SwTextCursor
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
117 aLine
.GetCharRect( &aRect
, nChar
);
118 if ( aRectFnSet
.IsVert() )
119 m_pFrame
->SwitchHorizontalToVertical( aRect
);
121 nStt
= aRectFnSet
.GetLeft(aRect
);
124 return nStt
- aRectFnSet
.GetLeft(m_pFrame
->getFrameArea());
126 aLine
.GetCharRect( &aRect
, nChar
+ TextFrameIndex(1) );
127 if ( aRectFnSet
.IsVert() )
128 m_pFrame
->SwitchHorizontalToVertical( aRect
);
130 nNext
= aRectFnSet
.GetLeft(aRect
);
132 return (( nNext
+ nStt
) / 2 ) - aRectFnSet
.GetLeft(m_pFrame
->getFrameArea());
136 AddRange(std::vector
<std::pair
<TextFrameIndex
, TextFrameIndex
>> & rRanges
,
137 TextFrameIndex
const nPos
, TextFrameIndex
const nLen
)
139 assert(rRanges
.empty() || rRanges
.back().second
<= nPos
);
142 if (!rRanges
.empty() && nPos
== rRanges
.back().second
)
144 rRanges
.back().second
+= nLen
;
148 rRanges
.emplace_back(nPos
, nPos
+ nLen
);
153 // Accumulates the whitespace at line start and end in the vector
154 void SwTextFrameInfo::GetSpaces(
155 std::vector
<std::pair
<TextFrameIndex
, TextFrameIndex
>> & rRanges
,
156 bool const bWithLineBreak
) const
158 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
159 SwTextMargin
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
160 bool bFirstLine
= true;
163 if( aLine
.GetCurr()->GetLen() )
165 TextFrameIndex nPos
= aLine
.GetTextStart();
166 // Do NOT include the blanks/tabs from the first line
168 if( !bFirstLine
&& nPos
> aLine
.GetStart() )
169 AddRange( rRanges
, aLine
.GetStart(), nPos
- aLine
.GetStart() );
171 // Do NOT include the blanks/tabs from the last line
173 if( aLine
.GetNext() )
175 nPos
= aLine
.GetTextEnd();
177 if( nPos
< aLine
.GetEnd() )
179 TextFrameIndex
const nOff( !bWithLineBreak
&& CH_BREAK
==
180 aLine
.GetInfo().GetChar(aLine
.GetEnd() - TextFrameIndex(1))
182 AddRange( rRanges
, nPos
, aLine
.GetEnd() - nPos
- nOff
);
188 while( aLine
.Next() );
191 // Is there a bullet/symbol etc. at the text position?
192 // Fonts: CharSet, SYMBOL and DONTKNOW
193 bool SwTextFrameInfo::IsBullet(TextFrameIndex
const nTextStart
) const
195 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
196 SwTextMargin
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
197 aInf
.SetIdx( nTextStart
);
198 return aLine
.IsSymbol( nTextStart
);
201 // Get first line indent
202 // The precondition for a positive or negative first line indent:
203 // All lines (except for the first one) have the same left margin.
204 // We do not want to be so picky and work with a tolerance of TOLERANCE twips.
205 SwTwips
SwTextFrameInfo::GetFirstIndent() const
207 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
208 SwTextCursor
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
209 const SwTwips nFirst
= GetLineStart( aLine
);
210 const SwTwips TOLERANCE
= 20;
215 SwTwips nLeft
= GetLineStart( aLine
);
216 while( aLine
.Next() )
218 if( aLine
.GetCurr()->GetLen() )
220 const SwTwips nCurrLeft
= GetLineStart( aLine
);
221 if( nLeft
+ TOLERANCE
< nCurrLeft
||
222 nLeft
- TOLERANCE
> nCurrLeft
)
227 // At first we only return +1, -1 and 0
228 if( nLeft
== nFirst
)
237 sal_Int32
SwTextFrameInfo::GetBigIndent(TextFrameIndex
& rFndPos
,
238 const SwTextFrame
*pNextFrame
) const
240 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
241 SwTextCursor
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
242 SwTwips nNextIndent
= 0;
247 SwTextSizeInfo
aNxtInf( const_cast<SwTextFrame
*>(pNextFrame
) );
248 SwTextCursor
aNxtLine( const_cast<SwTextFrame
*>(pNextFrame
), &aNxtInf
);
249 nNextIndent
= GetLineStart( aNxtLine
);
256 nNextIndent
= GetLineStart( aLine
);
261 if( nNextIndent
<= GetLineStart( aLine
) )
264 const Point
aPoint( nNextIndent
, aLine
.Y() );
265 rFndPos
= aLine
.GetModelPositionForViewPoint( nullptr, aPoint
, false );
266 if (TextFrameIndex(1) >= rFndPos
)
269 // Is on front of a non-space
270 const OUString
& rText
= aInf
.GetText();
271 sal_Unicode aChar
= rText
[sal_Int32(rFndPos
)];
272 if( CH_TAB
== aChar
|| CH_BREAK
== aChar
|| ' ' == aChar
||
273 (( CH_TXTATR_BREAKWORD
== aChar
|| CH_TXTATR_INWORD
== aChar
) &&
274 aInf
.HasHint( rFndPos
) ) )
278 aChar
= rText
[sal_Int32(rFndPos
) - 1];
279 if( CH_TAB
!= aChar
&& CH_BREAK
!= aChar
&&
280 ( ( CH_TXTATR_BREAKWORD
!= aChar
&& CH_TXTATR_INWORD
!= aChar
) ||
281 !aInf
.HasHint(rFndPos
- TextFrameIndex(1))) &&
282 // More than two Blanks!
283 (' ' != aChar
|| ' ' != rText
[sal_Int32(rFndPos
) - 2]))
287 aLine
.GetCharRect( &aRect
, rFndPos
);
288 return static_cast<sal_Int32
>(aRect
.Left() - m_pFrame
->getFrameArea().Left() - m_pFrame
->getFramePrintArea().Left());
291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */