LibreOffice Module sw (master)  1
frminf.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <o3tl/safeint.hxx>
23 
24 #include <frminf.hxx>
25 #include "itrtxt.hxx"
26 
28 {
29  const OUString &rText = GetInfo().GetText();
30  const TextFrameIndex nEnd = m_nStart + m_pCurr->GetLen();
31 
32  for (TextFrameIndex i = m_nStart; i < nEnd; ++i)
33  {
34  const sal_Unicode aChar = rText[sal_Int32(i)];
35  if( CH_TAB != aChar && ' ' != aChar )
36  return i;
37  }
38  return nEnd;
39 }
40 
42 {
43  const OUString &rText = GetInfo().GetText();
44  const TextFrameIndex nEnd = m_nStart + m_pCurr->GetLen();
45  for (TextFrameIndex i = nEnd - TextFrameIndex(1); i >= m_nStart; --i)
46  {
47  const sal_Unicode aChar = rText[sal_Int32(i)];
48  if( CH_TAB != aChar && CH_BREAK != aChar && ' ' != aChar )
49  return i + TextFrameIndex(1);
50  }
51  return m_nStart;
52 }
53 
54 // Does the paragraph fit into one line?
56 {
57  const SwLineLayout *pLay = m_pFrame->GetPara();
58  if( !pLay )
59  return false;
60 
61  // For follows false of course
62  if( m_pFrame->GetFollow() )
63  return false;
64 
65  pLay = pLay->GetNext();
66  while( pLay )
67  {
68  if( pLay->GetLen() )
69  return false;
70  pLay = pLay->GetNext();
71  }
72  return true;
73 }
74 
75 // Is the line filled for X percent?
76 bool SwTextFrameInfo::IsFilled( const sal_uInt8 nPercent ) const
77 {
78  const SwLineLayout *pLay = m_pFrame->GetPara();
79  if( !pLay )
80  return false;
81 
83  nWidth *= nPercent;
84  nWidth /= 100;
85  return o3tl::make_unsigned(nWidth) <= pLay->Width();
86 }
87 
88 // Where does the text start (without whitespace)? (document global)
90 {
91  const TextFrameIndex nTextStart = rLine.GetTextStart();
92  if( rLine.GetStart() == nTextStart )
93  return rLine.GetLineStart();
94 
95  SwRect aRect;
96  const_cast<SwTextCursor&>(rLine).GetCharRect( &aRect, nTextStart );
97  return aRect.Left();
98 }
99 
100 // Where does the text start (without whitespace)? (relative in the Frame)
102 {
103  SwTextSizeInfo aInf( const_cast<SwTextFrame*>(m_pFrame) );
104  SwTextCursor aLine( const_cast<SwTextFrame*>(m_pFrame), &aInf );
105  return GetLineStart( aLine ) - m_pFrame->getFrameArea().Left() - m_pFrame->getFramePrintArea().Left();
106 }
107 
108 // Calculates the character's position and returns the middle position
109 SwTwips SwTextFrameInfo::GetCharPos(TextFrameIndex const nChar, bool bCenter) const
110 {
111  SwRectFnSet aRectFnSet(m_pFrame);
112  SwFrameSwapper aSwapper( m_pFrame, true );
113 
114  SwTextSizeInfo aInf( const_cast<SwTextFrame*>(m_pFrame) );
115  SwTextCursor aLine( const_cast<SwTextFrame*>(m_pFrame), &aInf );
116 
117  SwTwips nStt, nNext;
118  SwRect aRect;
119  aLine.GetCharRect( &aRect, nChar );
120  if ( aRectFnSet.IsVert() )
122 
123  nStt = aRectFnSet.GetLeft(aRect);
124 
125  if( !bCenter )
126  return nStt - aRectFnSet.GetLeft(m_pFrame->getFrameArea());
127 
128  aLine.GetCharRect( &aRect, nChar + TextFrameIndex(1) );
129  if ( aRectFnSet.IsVert() )
131 
132  nNext = aRectFnSet.GetLeft(aRect);
133 
134  return (( nNext + nStt ) / 2 ) - aRectFnSet.GetLeft(m_pFrame->getFrameArea());
135 }
136 
137 static void
138 AddRange(std::vector<std::pair<TextFrameIndex, TextFrameIndex>> & rRanges,
139  TextFrameIndex const nPos, TextFrameIndex const nLen)
140 {
141  assert(rRanges.empty() || rRanges.back().second <= nPos);
142  if( nLen )
143  {
144  if (!rRanges.empty() && nPos == rRanges.back().second)
145  {
146  rRanges.back().second += nLen;
147  }
148  else
149  {
150  rRanges.emplace_back(nPos, nPos + nLen);
151  }
152  }
153 }
154 
155 // Accumulates the whitespace at line start and end in the vector
157  std::vector<std::pair<TextFrameIndex, TextFrameIndex>> & rRanges,
158  bool const bWithLineBreak) const
159 {
160  SwTextSizeInfo aInf( const_cast<SwTextFrame*>(m_pFrame) );
161  SwTextMargin aLine( const_cast<SwTextFrame*>(m_pFrame), &aInf );
162  bool bFirstLine = true;
163  do {
164 
165  if( aLine.GetCurr()->GetLen() )
166  {
167  TextFrameIndex nPos = aLine.GetTextStart();
168  // Do NOT include the blanks/tabs from the first line
169  // in the selection
170  if( !bFirstLine && nPos > aLine.GetStart() )
171  AddRange( rRanges, aLine.GetStart(), nPos - aLine.GetStart() );
172 
173  // Do NOT include the blanks/tabs from the last line
174  // in the selection
175  if( aLine.GetNext() )
176  {
177  nPos = aLine.GetTextEnd();
178 
179  if( nPos < aLine.GetEnd() )
180  {
181  TextFrameIndex const nOff( !bWithLineBreak && CH_BREAK ==
182  aLine.GetInfo().GetChar(aLine.GetEnd() - TextFrameIndex(1))
183  ? 1 : 0 );
184  AddRange( rRanges, nPos, aLine.GetEnd() - nPos - nOff );
185  }
186  }
187  }
188  bFirstLine = false;
189  }
190  while( aLine.Next() );
191 }
192 
193 // Is there a bullet/symbol etc. at the text position?
194 // Fonts: CharSet, SYMBOL and DONTKNOW
195 bool SwTextFrameInfo::IsBullet(TextFrameIndex const nTextStart) const
196 {
197  SwTextSizeInfo aInf( const_cast<SwTextFrame*>(m_pFrame) );
198  SwTextMargin aLine( const_cast<SwTextFrame*>(m_pFrame), &aInf );
199  aInf.SetIdx( nTextStart );
200  return aLine.IsSymbol( nTextStart );
201 }
202 
203 // Get first line indent
204 // The precondition for a positive or negative first line indent:
205 // All lines (except for the first one) have the same left margin.
206 // We do not want to be so picky and work with a tolerance of TOLERANCE twips.
208 {
209  SwTextSizeInfo aInf( const_cast<SwTextFrame*>(m_pFrame) );
210  SwTextCursor aLine( const_cast<SwTextFrame*>(m_pFrame), &aInf );
211  const SwTwips nFirst = GetLineStart( aLine );
212  const SwTwips TOLERANCE = 20;
213 
214  if( !aLine.Next() )
215  return 0;
216 
217  SwTwips nLeft = GetLineStart( aLine );
218  while( aLine.Next() )
219  {
220  if( aLine.GetCurr()->GetLen() )
221  {
222  const SwTwips nCurrLeft = GetLineStart( aLine );
223  if( nLeft + TOLERANCE < nCurrLeft ||
224  nLeft - TOLERANCE > nCurrLeft )
225  return 0;
226  }
227  }
228 
229  // At first we only return +1, -1 and 0
230  if( nLeft == nFirst )
231  return 0;
232 
233  if( nLeft > nFirst )
234  return -1;
235 
236  return 1;
237 }
238 
240  const SwTextFrame *pNextFrame ) const
241 {
242  SwTextSizeInfo aInf( const_cast<SwTextFrame*>(m_pFrame) );
243  SwTextCursor aLine( const_cast<SwTextFrame*>(m_pFrame), &aInf );
244  SwTwips nNextIndent = 0;
245 
246  if( pNextFrame )
247  {
248  // I'm a single line
249  SwTextSizeInfo aNxtInf( const_cast<SwTextFrame*>(pNextFrame) );
250  SwTextCursor aNxtLine( const_cast<SwTextFrame*>(pNextFrame), &aNxtInf );
251  nNextIndent = GetLineStart( aNxtLine );
252  }
253  else
254  {
255  // I'm multi-line
256  if( aLine.Next() )
257  {
258  nNextIndent = GetLineStart( aLine );
259  aLine.Prev();
260  }
261  }
262 
263  if( nNextIndent <= GetLineStart( aLine ) )
264  return 0;
265 
266  const Point aPoint( nNextIndent, aLine.Y() );
267  rFndPos = aLine.GetModelPositionForViewPoint( nullptr, aPoint, false );
268  if (TextFrameIndex(1) >= rFndPos)
269  return 0;
270 
271  // Is on front of a non-space
272  const OUString& rText = aInf.GetText();
273  sal_Unicode aChar = rText[sal_Int32(rFndPos)];
274  if( CH_TAB == aChar || CH_BREAK == aChar || ' ' == aChar ||
275  (( CH_TXTATR_BREAKWORD == aChar || CH_TXTATR_INWORD == aChar ) &&
276  aInf.HasHint( rFndPos ) ) )
277  return 0;
278 
279  // and after a space
280  aChar = rText[sal_Int32(rFndPos) - 1];
281  if( CH_TAB != aChar && CH_BREAK != aChar &&
282  ( ( CH_TXTATR_BREAKWORD != aChar && CH_TXTATR_INWORD != aChar ) ||
283  !aInf.HasHint(rFndPos - TextFrameIndex(1))) &&
284  // More than two Blanks!
285  (' ' != aChar || ' ' != rText[sal_Int32(rFndPos) - 2]))
286  return 0;
287 
288  SwRect aRect;
289  aLine.GetCharRect( &aRect, rFndPos );
290  return static_cast<sal_Int32>(aRect.Left() - m_pFrame->getFrameArea().Left() - m_pFrame->getFramePrintArea().Left());
291 }
292 
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
TextFrameIndex GetModelPositionForViewPoint(SwPosition *pPos, const Point &rPoint, bool bChgNode, SwCursorMoveState *=nullptr) const
Definition: itrcrsr.cxx:1289
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:151
SwLineLayout * GetNext()
Definition: porlay.hxx:160
TextFrameIndex GetStart() const
Definition: itrtxt.hxx:88
void Left(const tools::Long nLeft)
Definition: swrect.hxx:195
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:471
long Long
const SwRect & getFramePrintArea() const
Definition: frame.hxx:179
SwParaPortion * GetPara()
Definition: txtcache.cxx:89
bool IsVert() const
Definition: frame.hxx:1348
const SwLineLayout * Next()
Definition: itrtxt.cxx:107
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
bool HasHint(TextFrameIndex nPos) const
Definition: inftxt.cxx:474
SwTwips Y() const
Definition: itrtxt.hxx:90
sal_Int32 GetBigIndent(TextFrameIndex &rFndPos, const SwTextFrame *pNextFrame) const
Definition: frminf.cxx:239
TextFrameIndex GetTextEnd() const
Definition: frminf.cxx:41
SwTwips GetLineStart() const
Definition: frminf.cxx:101
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:169
sal_uInt16 sal_Unicode
bool IsBullet(TextFrameIndex nTextPos) const
Definition: frminf.cxx:195
#define CH_TXTATR_INWORD
Definition: hintids.hxx:170
const SwRect & getFrameArea() const
Definition: frame.hxx:178
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
sal_Unicode GetChar(TextFrameIndex const nPos) const
Definition: inftxt.hxx:240
bool IsFilled(const sal_uInt8 nPercent) const
Definition: frminf.cxx:76
void Width(tools::Long nNew)
Definition: swrect.hxx:187
tools::Long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1360
SwTwips GetFirstIndent() const
Definition: frminf.cxx:207
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:846
SwTwips GetLineStart() const
Definition: itrcrsr.cxx:376
int i
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:79
bool IsOneLine() const
Definition: frminf.cxx:55
const sal_Unicode CH_TAB
Definition: swfont.hxx:44
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:912
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
TextFrameIndex GetTextStart() const
Definition: frminf.cxx:27
TextFrameIndex GetLen() const
Definition: porlin.hxx:74
tools::Long SwTwips
Definition: swtypes.hxx:49
const OUString & GetText() const
Definition: inftxt.hxx:239
const SwLineLayout * Prev()
Definition: itrtxt.cxx:89
TextFrameIndex m_nStart
Definition: itrtxt.hxx:41
static void AddRange(std::vector< std::pair< TextFrameIndex, TextFrameIndex >> &rRanges, TextFrameIndex const nPos, TextFrameIndex const nLen)
Definition: frminf.cxx:138
unsigned char sal_uInt8
void GetCharRect(SwRect *, TextFrameIndex, SwCursorMoveState *=nullptr, const tools::Long nMax=0)
Definition: itrcrsr.cxx:1178
SwTextSizeInfo & GetInfo()
Definition: itrtxt.hxx:216
sal_uInt16 Width() const
Definition: possiz.hxx:52
void GetSpaces(std::vector< std::pair< TextFrameIndex, TextFrameIndex >> &, bool bWithLineBreak) const
Definition: frminf.cxx:156
const SwLineLayout * GetNext() const
Definition: itrtxt.hxx:84
SwTwips GetCharPos(TextFrameIndex nChar, bool bCenter=true) const
Definition: frminf.cxx:109
const SwLineLayout * GetCurr() const
Definition: itrtxt.hxx:83
bool IsSymbol(TextFrameIndex nPos)
Definition: itratr.cxx:177
SwLineLayout * m_pCurr
Definition: itrtxt.hxx:36
TextFrameIndex GetEnd() const
Definition: itrtxt.hxx:89
const SwTextFrame * m_pFrame
Definition: frminf.hxx:34
void SetIdx(const TextFrameIndex nNew)
Definition: inftxt.hxx:272
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
sal_uInt16 nPos