LibreOffice Module sw (master)  1
itrtxt.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 <ndtxt.hxx>
21 #include <txatbase.hxx>
22 #include <paratr.hxx>
23 #include <vcl/outdev.hxx>
25 
26 #include "pormulti.hxx"
27 #include <pagefrm.hxx>
28 #include <tgrditem.hxx>
29 #include "porfld.hxx"
30 
31 #include "itrtxt.hxx"
32 #include <txtfrm.hxx>
33 
35 {
36  assert(pNewFrame->GetPara());
37 
38  CtorInitAttrIter( *pNewFrame->GetTextNodeFirst(), pNewFrame->GetPara()->GetScriptInfo(), pNewFrame );
39 
40  SwTextNode const*const pNode = pNewFrame->GetTextNodeForParaProps();
41 
42  m_pFrame = pNewFrame;
43  m_pInf = pNewInf;
44  m_aLineInf.CtorInitLineInfo( pNode->GetSwAttrSet(), *pNode );
47 
48  // Order is important: only execute FillRegister if GetValue!=0
49  m_bRegisterOn = pNode->GetSwAttrSet().GetRegister().GetValue()
51 }
52 
54 {
58  m_bPrev = true;
59  m_pPrev = nullptr;
60  m_nLineNr = 1;
61 }
62 
63 void SwTextIter::CalcAscentAndHeight( sal_uInt16 &rAscent, sal_uInt16 &rHeight ) const
64 {
65  rHeight = GetLineHeight();
66  rAscent = m_pCurr->GetAscent() + rHeight - m_pCurr->Height();
67 }
68 
70 {
71  m_pPrev = nullptr;
72  m_bPrev = true;
74  if( m_pCurr == pLay )
75  return nullptr;
76  while( pLay->GetNext() != m_pCurr )
77  pLay = pLay->GetNext();
78  m_pPrev = pLay;
79  return m_pPrev;
80 }
81 
83 {
84  if(! m_bPrev)
85  GetPrev_();
86  return m_pPrev;
87 }
88 
90 {
91  if( !m_bPrev )
92  GetPrev_();
93  if( m_pPrev )
94  {
95  m_bPrev = false;
96  m_pCurr = m_pPrev;
98  m_nY = m_nY - GetLineHeight();
99  if( !m_pCurr->IsDummy() && !(--m_nLineNr) )
100  ++m_nLineNr;
101  return m_pCurr;
102  }
103  else
104  return nullptr;
105 }
106 
108 {
109  if(m_pCurr->GetNext())
110  {
111  m_pPrev = m_pCurr;
112  m_bPrev = true;
114  m_nY += GetLineHeight();
115  if( m_pCurr->GetLen() || ( m_nLineNr>1 && !m_pCurr->IsDummy() ) )
116  ++m_nLineNr;
117  m_pCurr = m_pCurr->GetNext();
118  return m_pCurr;
119  }
120  else
121  return nullptr;
122 }
123 
125 {
126  const SwLineLayout *pNext = Next();
127  while( pNext && pNext->IsDummy() && pNext->GetNext() )
128  {
129  pNext = Next();
130  }
131  return pNext;
132 }
133 
135 {
136  const SwLineLayout *pNext = m_pCurr->GetNext();
137  while( pNext && pNext->IsDummy() && pNext->GetNext() )
138  {
139  pNext = pNext->GetNext();
140  }
141  return pNext;
142 }
143 
145 {
146  const SwLineLayout *pRoot = m_pInf->GetParaPortion();
147  if( pRoot == m_pCurr )
148  return nullptr;
149  const SwLineLayout *pLay = pRoot;
150 
151  while( pLay->GetNext() != m_pCurr )
152  pLay = pLay->GetNext();
153 
154  if( pLay->IsDummy() )
155  {
156  const SwLineLayout *pTmp = pRoot;
157  pLay = pRoot->IsDummy() ? nullptr : pRoot;
158  while( pTmp->GetNext() != m_pCurr )
159  {
160  if( !pTmp->IsDummy() )
161  pLay = pTmp;
162  pTmp = pTmp->GetNext();
163  }
164  }
165 
166  // If nothing has changed, then there are only dummy's
167  return pLay;
168 }
169 
171 {
172  const SwLineLayout *pMyPrev = Prev();
173  if( !pMyPrev )
174  return nullptr;
175 
176  const SwLineLayout *pLast = pMyPrev;
177  while( pMyPrev && pMyPrev->IsDummy() )
178  {
179  pLast = pMyPrev;
180  pMyPrev = Prev();
181  }
182  return pMyPrev ? pMyPrev : pLast;
183 }
184 
186 {
187  while( Next() )
188  {
189  // nothing
190  }
191 }
192 
194 {
195  while( m_nStart + m_pCurr->GetLen() <= nChar && Next() )
196  ;
197  while( m_nStart > nChar && Prev() )
198  ;
199 }
200 
201 // 1170: takes into account ambiguities:
203 {
204  CharToLine( nPosition );
205  if( nPosition != m_nStart )
206  bRightMargin = false;
207  bool bPrevious = bRightMargin && m_pCurr->GetLen() && GetPrev() &&
208  GetPrev()->GetLen();
209  if (bPrevious && nPosition && CH_BREAK == GetInfo().GetChar(nPosition - TextFrameIndex(1)))
210  bPrevious = false;
211  return bPrevious ? PrevLine() : m_pCurr;
212 }
213 
215  const SwLinePortion* pPor,
216  sal_uInt16 nPorHeight, sal_uInt16 nPorAscent,
217  const bool bAutoToCentered ) const
218 {
219  if ( pPor )
220  {
221  nPorHeight = pPor->Height();
222  nPorAscent = pPor->GetAscent();
223  }
224 
225  sal_uInt16 nOfst = rLine.GetRealHeight() - rLine.Height();
226 
227  SwTextGridItem const*const pGrid(GetGridItem(m_pFrame->FindPageFrame()));
228 
229  if ( pGrid && GetInfo().SnapToGrid() && pGrid->IsSquaredMode() )
230  {
231  const sal_uInt16 nRubyHeight = pGrid->GetRubyHeight();
232  const bool bRubyTop = ! pGrid->GetRubyTextBelow();
233 
234  if ( GetInfo().IsMulti() )
235  // we are inside the GetCharRect recursion for multi portions
236  // we center the portion in its surrounding line
237  nOfst = ( m_pCurr->Height() - nPorHeight ) / 2 + nPorAscent;
238  else
239  {
240  // We have to take care for ruby portions.
241  // The ruby portion is NOT centered
242  nOfst = nOfst + nPorAscent;
243 
244  if ( ! pPor || ! pPor->IsMultiPortion() ||
245  ! static_cast<const SwMultiPortion*>(pPor)->IsRuby() )
246  {
247  // Portions which are bigger than on grid distance are
248  // centered inside the whole line.
249 
250  //for text refactor
251  const sal_uInt16 nLineNet = rLine.Height() - nRubyHeight;
252  //const sal_uInt16 nLineNet = ( nPorHeight > nGridWidth ) ?
253  // rLine.Height() - nRubyHeight :
254  // nGridWidth;
255  nOfst += ( nLineNet - nPorHeight ) / 2;
256  if ( bRubyTop )
257  nOfst += nRubyHeight;
258  }
259  }
260  }
261  else
262  {
263  switch ( GetLineInfo().GetVertAlign() ) {
265  nOfst = nOfst + nPorAscent;
266  break;
268  OSL_ENSURE( rLine.Height() >= nPorHeight, "Portion height > Line height");
269  nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
270  break;
272  nOfst += rLine.Height() - nPorHeight + nPorAscent;
273  break;
275  if ( bAutoToCentered || GetInfo().GetTextFrame()->IsVertical() )
276  {
277  // Vertical text has these cases to calculate the baseline:
278  // - Implicitly TB and RL: the origo is the top right corner, offset is the
279  // ascent.
280  // - (Implicitly TB and) LR: the origo is the top left corner, offset is the
281  // descent.
282  // - BT and LR: the origo is the bottom left corner, offset is the ascent.
283  if (GetInfo().GetTextFrame()->IsVertLR() && !GetInfo().GetTextFrame()->IsVertLRBT())
284  nOfst += rLine.Height() - ( rLine.Height() - nPorHeight ) / 2 - nPorAscent;
285  else
286  nOfst += ( rLine.Height() - nPorHeight ) / 2 + nPorAscent;
287  break;
288  }
289  [[fallthrough]];
291  // base line
292  nOfst = nOfst + rLine.GetAscent();
293  break;
294  }
295  }
296 
297  return nOfst;
298 }
299 
301 {
302  while( m_nY + GetLineHeight() <= y && Next() )
303  ;
304  while( m_nY > y && Prev() )
305  ;
306 }
307 
308 // Local helper function to check, if pCurr needs a field rest portion:
309 static bool lcl_NeedsFieldRest( const SwLineLayout* pCurr )
310 {
311  const SwLinePortion *pPor = pCurr->GetNextPortion();
312  bool bRet = false;
313  while( pPor && !bRet )
314  {
315  bRet = pPor->InFieldGrp() && static_cast<const SwFieldPortion*>(pPor)->HasFollow();
316  if( !pPor->GetNextPortion() || !pPor->GetNextPortion()->InFieldGrp() )
317  break;
318  pPor = pPor->GetNextPortion();
319  }
320  return bRet;
321 }
322 
323 void SwTextIter::TruncLines( bool bNoteFollow )
324 {
325  SwLineLayout *pDel = m_pCurr->GetNext();
326  TextFrameIndex const nEnd = m_nStart + m_pCurr->GetLen();
327 
328  if( pDel )
329  {
330  m_pCurr->SetNext( nullptr );
331  if (MaybeHasHints() && bNoteFollow)
332  {
335 
336  // bug 88534: wrong positioning of flys
337  SwTextFrame* pFollow = GetTextFrame()->GetFollow();
338  if ( pFollow && ! pFollow->IsLocked() &&
339  nEnd == pFollow->GetOffset() )
340  {
341  TextFrameIndex nRangeEnd = nEnd;
342  SwLineLayout* pLine = pDel;
343 
344  // determine range to be searched for flys anchored as characters
345  while ( pLine )
346  {
347  nRangeEnd = nRangeEnd + pLine->GetLen();
348  pLine = pLine->GetNext();
349  }
350 
351  // examine hints in range nEnd - (nEnd + nRangeChar)
352  SwTextNode const* pNode(nullptr);
354  for (SwTextAttr const* pHt = iter.NextAttr(&pNode); pHt; pHt = iter.NextAttr(&pNode))
355  {
356  if( RES_TXTATR_FLYCNT == pHt->Which() )
357  {
358  // check if hint is in our range
359  TextFrameIndex const nTmpPos(
360  GetTextFrame()->MapModelToView(pNode, pHt->GetStart()));
361  if ( nEnd <= nTmpPos && nTmpPos < nRangeEnd )
362  pFollow->InvalidateRange_(
363  SwCharRange( nTmpPos, nTmpPos ) );
364  }
365  }
366  }
367  }
368  delete pDel;
369  }
370  if( m_pCurr->IsDummy() &&
371  !m_pCurr->GetLen() &&
372  m_nStart < TextFrameIndex(GetTextFrame()->GetText().getLength()))
373  {
374  m_pCurr->SetRealHeight( 1 );
375  }
376  if (MaybeHasHints())
377  m_pFrame->RemoveFootnote( nEnd );
378 }
379 
380 void SwTextIter::CntHyphens( sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
381 {
382  nEndCnt = 0;
383  nMidCnt = 0;
384  if ( m_bPrev && m_pPrev && !m_pPrev->IsEndHyph() && !m_pPrev->IsMidHyph() )
385  return;
387  if( m_pCurr == pLay )
388  return;
389  while( pLay != m_pCurr )
390  {
391  if ( pLay->IsEndHyph() )
392  nEndCnt++;
393  else
394  nEndCnt = 0;
395  if ( pLay->IsMidHyph() )
396  nMidCnt++;
397  else
398  nMidCnt = 0;
399  pLay = pLay->GetNext();
400  }
401 }
402 
403 // Change current output device to formatting device, this has to be done before
404 // formatting.
406  pInf( &rInfo ),
407  pOut( rInfo.GetOut() ),
408  bOnWin( rInfo.OnWin() )
409 {
410  OSL_ENSURE( rInfo.GetRefDev(), "No reference device for text formatting" );
411 
412  // set new values
413  rInfo.SetOut( rInfo.GetRefDev() );
414  rInfo.SetOnWin( false );
415 }
416 
418 {
419  pInf->SetOut( pOut );
420  pInf->SetOnWin( bOnWin );
421 }
422 
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
~SwHookOut()
Definition: itrtxt.cxx:417
void CtorInitTextIter(SwTextFrame *pFrame, SwTextInfo *pInf)
Definition: itrtxt.cxx:34
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:151
bool MaybeHasHints() const
Definition: itratr.cxx:123
static bool bRightMargin
Definition: itrtxt.hxx:268
SwHookOut(SwTextSizeInfo &rInfo)
Definition: itrtxt.cxx:405
bool IsRest() const
Definition: porlay.hxx:119
sal_uInt16 Height() const
Definition: possiz.hxx:44
SwLineLayout * GetNext()
Definition: porlay.hxx:143
sal_uInt16 m_nLineNr
Definition: itrtxt.hxx:43
const SwLineLayout * NextLine()
Definition: itrtxt.cxx:124
void InvalidateRange_(const SwCharRange &, const long=0)
Definition: txtfrm.cxx:1678
bool m_bRegisterOn
Definition: itrtxt.hxx:45
const SwRect & getFramePrintArea() const
Definition: frame.hxx:178
void SetOnWin(const bool bNew)
Definition: inftxt.hxx:200
SwParaPortion * GetPara()
Definition: txtcache.cxx:89
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(57)
bool bOnWin
Definition: itrtxt.hxx:304
bool GetRubyTextBelow() const
Definition: tgrditem.hxx:85
long SwTwips
Definition: swtypes.hxx:49
void CharToLine(TextFrameIndex)
Definition: itrtxt.cxx:193
const SwLineLayout * Next()
Definition: itrtxt.cxx:107
void Pos(const Point &rNew)
Definition: swrect.hxx:169
SwLineInfo m_aLineInf
Definition: itrtxt.hxx:33
bool InFieldGrp() const
Definition: porlin.hxx:104
bool IsEndHyph() const
Definition: porlay.hxx:113
sal_uInt16 m_nRegDiff
Definition: itrtxt.hxx:42
SwTextAttr const * NextAttr(SwTextNode const **ppNode=nullptr)
Definition: txtfrm.cxx:85
void CtorInitAttrIter(SwTextNode &rTextNode, SwScriptInfo &rScrInf, SwTextFrame const *pFrame=nullptr)
Definition: redlnitr.cxx:383
const SwRect & getFrameArea() const
Definition: frame.hxx:177
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void CtorInitLineInfo(const SwAttrSet &rAttrSet, const SwTextNode &rTextNode)
Definition: inftxt.cxx:99
const SwLineLayout * GetNextLine() const
Definition: itrtxt.cxx:134
oslFileHandle & pOut
bool IsSquaredMode() const
Definition: tgrditem.hxx:104
vcl::RenderContext * GetRefDev()
Definition: inftxt.hxx:235
SwLineLayout * GetPrev_()
Definition: itrtxt.cxx:69
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:846
TextFrameIndex GetOffset() const
Definition: txtfrm.hxx:429
static bool lcl_NeedsFieldRest(const SwLineLayout *pCurr)
Definition: itrtxt.cxx:309
void CalcAscentAndHeight(sal_uInt16 &rAscent, sal_uInt16 &rHeight) const
Definition: itrtxt.cxx:63
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:448
void SetRealHeight(sal_uInt16 nNew)
Definition: porlay.hxx:152
bool m_bPrev
Definition: itrtxt.hxx:44
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1288
SwTextInfo * m_pInf
Definition: itrtxt.hxx:35
void Bottom()
Definition: itrtxt.cxx:185
sal_uInt16 AdjustBaseLine(const SwLineLayout &rLine, const SwLinePortion *pPor, sal_uInt16 nPorHeight=0, sal_uInt16 nAscent=0, const bool bAutoToCentered=false) const
Definition: itrtxt.cxx:214
bool IsDummy() const
Definition: porlay.hxx:135
const SwLineLayout * GetPrevLine()
Definition: itrtxt.cxx:144
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:78
const SwLineInfo & GetLineInfo() const
Definition: itrtxt.hxx:128
SwPageFrame * FindPageFrame()
Definition: frame.hxx:660
SwParaPortion * GetParaPortion()
Definition: inftxt.hxx:128
TextFrameIndex MapModelToView(MergedPara const &, SwTextNode const *pNode, sal_Int32 nIndex)
Definition: txtfrm.cxx:1170
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2539
void Init()
Definition: itrtxt.cxx:53
void TwipsToLine(const SwTwips)
Definition: itrtxt.cxx:300
const SwLineLayout * GetPrev()
Definition: itrtxt.cxx:82
SwTwips m_nFrameStart
Definition: itrtxt.hxx:38
sal_uInt16 GetLineHeight() const
Definition: itrtxt.hxx:116
void TruncLines(bool bNoteFollow=false)
Definition: itrtxt.cxx:323
bool IsLocked() const
Definition: txtfrm.hxx:508
bool FillRegister(SwTwips &rRegStart, sal_uInt16 &rRegDiff)
Determines the start position and step size of the register.
Definition: porrst.cxx:360
TextFrameIndex GetLen() const
Definition: porlin.hxx:74
bool IsMultiPortion() const
Definition: porlin.hxx:134
SwTextFrame * m_pFrame
Definition: itrtxt.hxx:34
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:50
const SwLineLayout * Prev()
Definition: itrtxt.cxx:89
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
TextFrameIndex m_nStart
Definition: itrtxt.hxx:41
bool IsMidHyph() const
Definition: porlay.hxx:115
void SetNext(SwLineLayout *pNew)
Definition: porlay.hxx:145
unsigned char sal_uInt8
SwTextSizeInfo * pInf
Definition: itrtxt.hxx:302
SwTextSizeInfo & GetInfo()
Definition: itrtxt.hxx:216
SwLineLayout * m_pPrev
Definition: itrtxt.hxx:37
const SwLineLayout * PrevLine()
Definition: itrtxt.cxx:170
SwScriptInfo & GetScriptInfo()
Definition: porlay.hxx:270
double getLength(const B2DPolygon &rCandidate)
void SetFollowField(const bool bNew)
Definition: porlay.hxx:292
SwTwips m_nY
Definition: itrtxt.hxx:39
void CntHyphens(sal_uInt8 &nEndCnt, sal_uInt8 &nMidCnt) const
Definition: itrtxt.cxx:380
sal_uInt16 GetRealHeight() const
Definition: porlay.hxx:153
void SetOut(OutputDevice *pNewOut)
Definition: inftxt.hxx:233
SwTextInfo & GetInfo()
Definition: itrtxt.hxx:96
const SwLineLayout * CharCursorToLine(TextFrameIndex const nPos)
Definition: itrtxt.cxx:202
SwTextFrame * GetTextFrame()
Definition: itrtxt.hxx:134
VclPtr< OutputDevice > pOut
Definition: itrtxt.hxx:303
SwLineLayout * m_pCurr
Definition: itrtxt.hxx:36
SwTwips m_nRegStart
Definition: itrtxt.hxx:40
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:72
SvxParaVertAlignItem::Align GetVertAlign() const
Definition: inftxt.hxx:92
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...
void RemoveFootnote(TextFrameIndex nStart, TextFrameIndex nLen=TextFrameIndex(COMPLETE_STRING))
Footnote.
Definition: txtftn.cxx:395
sal_uInt16 GetRubyHeight() const
Definition: tgrditem.hxx:78
sal_uInt16 & GetAscent()
Definition: porlin.hxx:77
TextFrameIndex GetTextStart() const
Definition: inftxt.hxx:130