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 TextFrameIndex
const nEndPos
{aLine
.GetTextEnd()};
177 // if only whitespace in line, nEndPos < nPos !
178 if (nPos
< nEndPos
&& nEndPos
< aLine
.GetEnd())
180 TextFrameIndex
const nOff( !bWithLineBreak
&& CH_BREAK
==
181 aLine
.GetInfo().GetChar(aLine
.GetEnd() - TextFrameIndex(1))
183 AddRange(rRanges
, nEndPos
, aLine
.GetEnd() - nEndPos
- nOff
);
189 while( aLine
.Next() );
192 // Is there a bullet/symbol etc. at the text position?
193 // Fonts: CharSet, SYMBOL and DONTKNOW
194 bool SwTextFrameInfo::IsBullet(TextFrameIndex
const nTextStart
) const
196 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
197 SwTextMargin
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
198 aInf
.SetIdx( nTextStart
);
199 return aLine
.IsSymbol( nTextStart
);
202 // Get first line indent
203 // The precondition for a positive or negative first line indent:
204 // All lines (except for the first one) have the same left margin.
205 // We do not want to be so picky and work with a tolerance of TOLERANCE twips.
206 SwTwips
SwTextFrameInfo::GetFirstIndent() const
208 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
209 SwTextCursor
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
210 const SwTwips nFirst
= GetLineStart( aLine
);
211 const SwTwips TOLERANCE
= 20;
216 SwTwips nLeft
= GetLineStart( aLine
);
217 while( aLine
.Next() )
219 if( aLine
.GetCurr()->GetLen() )
221 const SwTwips nCurrLeft
= GetLineStart( aLine
);
222 if( nLeft
+ TOLERANCE
< nCurrLeft
||
223 nLeft
- TOLERANCE
> nCurrLeft
)
228 // At first we only return +1, -1 and 0
229 if( nLeft
== nFirst
)
238 sal_Int32
SwTextFrameInfo::GetBigIndent(TextFrameIndex
& rFndPos
,
239 const SwTextFrame
*pNextFrame
) const
241 SwTextSizeInfo
aInf( const_cast<SwTextFrame
*>(m_pFrame
) );
242 SwTextCursor
aLine( const_cast<SwTextFrame
*>(m_pFrame
), &aInf
);
243 SwTwips nNextIndent
= 0;
248 SwTextSizeInfo
aNxtInf( const_cast<SwTextFrame
*>(pNextFrame
) );
249 SwTextCursor
aNxtLine( const_cast<SwTextFrame
*>(pNextFrame
), &aNxtInf
);
250 nNextIndent
= GetLineStart( aNxtLine
);
257 nNextIndent
= GetLineStart( aLine
);
262 if( nNextIndent
<= GetLineStart( aLine
) )
265 const Point
aPoint( nNextIndent
, aLine
.Y() );
266 rFndPos
= aLine
.GetModelPositionForViewPoint( nullptr, aPoint
, false );
267 if (TextFrameIndex(1) >= rFndPos
)
270 // Is on front of a non-space
271 const OUString
& rText
= aInf
.GetText();
272 sal_Unicode aChar
= rText
[sal_Int32(rFndPos
)];
273 if( CH_TAB
== aChar
|| CH_BREAK
== aChar
|| ' ' == aChar
||
274 (( CH_TXTATR_BREAKWORD
== aChar
|| CH_TXTATR_INWORD
== aChar
) &&
275 aInf
.HasHint( rFndPos
) ) )
279 aChar
= rText
[sal_Int32(rFndPos
) - 1];
280 if( CH_TAB
!= aChar
&& CH_BREAK
!= aChar
&&
281 ( ( CH_TXTATR_BREAKWORD
!= aChar
&& CH_TXTATR_INWORD
!= aChar
) ||
282 !aInf
.HasHint(rFndPos
- TextFrameIndex(1))) &&
283 // More than two Blanks!
284 (' ' != aChar
|| ' ' != rText
[sal_Int32(rFndPos
) - 2]))
288 aLine
.GetCharRect( &aRect
, rFndPos
);
289 return static_cast<sal_Int32
>(aRect
.Left() - m_pFrame
->getFrameArea().Left() - m_pFrame
->getFramePrintArea().Left());
292 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */