tdf#35361 Add a Quick Look plugins for .od* files on macOS
[LibreOffice.git] / sw / source / core / text / frminf.cxx
blob386f40942f5fd117966c3b997895c4fa359d45d4
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 .
20 #include <sal/config.h>
22 #include <frminf.hxx>
23 #include "itrtxt.hxx"
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 )
34 return i;
36 return nEnd;
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);
49 return m_nStart;
52 // Does the paragraph fit into one line?
53 bool SwTextFrameInfo::IsOneLine() const
55 const SwLineLayout *pLay = m_pFrame->GetPara();
56 if( !pLay )
57 return false;
59 // For follows false of course
60 if( m_pFrame->GetFollow() )
61 return false;
63 pLay = pLay->GetNext();
64 while( pLay )
66 if( pLay->GetLen() )
67 return false;
68 pLay = pLay->GetNext();
70 return true;
73 // Is the line filled for X percent?
74 bool SwTextFrameInfo::IsFilled( const sal_uInt8 nPercent ) const
76 const SwLineLayout *pLay = m_pFrame->GetPara();
77 if( !pLay )
78 return false;
80 tools::Long nWidth = m_pFrame->getFramePrintArea().Width();
81 nWidth *= nPercent;
82 nWidth /= 100;
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();
93 SwRect aRect;
94 const_cast<SwTextCursor&>(rLine).GetCharRect( &aRect, nTextStart );
95 return aRect.Left();
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 );
115 SwTwips nStt, nNext;
116 SwRect aRect;
117 aLine.GetCharRect( &aRect, nChar );
118 if ( aRectFnSet.IsVert() )
119 m_pFrame->SwitchHorizontalToVertical( aRect );
121 nStt = aRectFnSet.GetLeft(aRect);
123 if( !bCenter )
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());
135 static void
136 AddRange(std::vector<std::pair<TextFrameIndex, TextFrameIndex>> & rRanges,
137 TextFrameIndex const nPos, TextFrameIndex const nLen)
139 assert(rRanges.empty() || rRanges.back().second <= nPos);
140 if( nLen )
142 if (!rRanges.empty() && nPos == rRanges.back().second)
144 rRanges.back().second += nLen;
146 else
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;
161 do {
163 if( aLine.GetCurr()->GetLen() )
165 TextFrameIndex nPos = aLine.GetTextStart();
166 // Do NOT include the blanks/tabs from the first line
167 // in the selection
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
172 // in the selection
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))
182 ? 1 : 0 );
183 AddRange(rRanges, nEndPos, aLine.GetEnd() - nEndPos - nOff);
187 bFirstLine = false;
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;
213 if( !aLine.Next() )
214 return 0;
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 )
224 return 0;
228 // At first we only return +1, -1 and 0
229 if( nLeft == nFirst )
230 return 0;
232 if( nLeft > nFirst )
233 return -1;
235 return 1;
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;
245 if( pNextFrame )
247 // I'm a single line
248 SwTextSizeInfo aNxtInf( const_cast<SwTextFrame*>(pNextFrame) );
249 SwTextCursor aNxtLine( const_cast<SwTextFrame*>(pNextFrame), &aNxtInf );
250 nNextIndent = GetLineStart( aNxtLine );
252 else
254 // I'm multi-line
255 if( aLine.Next() )
257 nNextIndent = GetLineStart( aLine );
258 aLine.Prev();
262 if( nNextIndent <= GetLineStart( aLine ) )
263 return 0;
265 const Point aPoint( nNextIndent, aLine.Y() );
266 rFndPos = aLine.GetModelPositionForViewPoint( nullptr, aPoint, false );
267 if (TextFrameIndex(1) >= rFndPos)
268 return 0;
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 ) ) )
276 return 0;
278 // and after a space
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]))
285 return 0;
287 SwRect aRect;
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: */