LibreOffice Module sw (master)  1
txtfrm.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 <hintids.hxx>
21 #include <hints.hxx>
22 #include <svl/ctloptions.hxx>
23 #include <sfx2/printer.hxx>
24 #include <sfx2/sfxuno.hxx>
25 #include <editeng/langitem.hxx>
26 #include <editeng/lspcitem.hxx>
27 #include <editeng/lrspitem.hxx>
28 #include <editeng/ulspitem.hxx>
29 #include <editeng/brushitem.hxx>
30 #include <editeng/pgrditem.hxx>
31 #include <editeng/rsiditem.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <swmodule.hxx>
34 #include <SwSmartTagMgr.hxx>
35 #include <doc.hxx>
39 #include <rootfrm.hxx>
40 #include <pagefrm.hxx>
41 #include <viewsh.hxx>
42 #include <pam.hxx>
43 #include <ndtxt.hxx>
44 #include <txtatr.hxx>
45 #include <paratr.hxx>
46 #include <viewopt.hxx>
47 #include <dflyobj.hxx>
48 #include <flyfrm.hxx>
49 #include <tabfrm.hxx>
50 #include <frmatr.hxx>
51 #include <frmtool.hxx>
52 #include <pagedesc.hxx>
53 #include <tgrditem.hxx>
54 #include <dbg_lay.hxx>
55 #include <fmtfld.hxx>
56 #include <fmtftn.hxx>
57 #include <txtfld.hxx>
58 #include <txtftn.hxx>
59 #include <charatr.hxx>
60 #include <ftninfo.hxx>
61 #include <fmtline.hxx>
62 #include <txtfrm.hxx>
63 #include <notxtfrm.hxx>
64 #include <sectfrm.hxx>
65 #include "itrform2.hxx"
66 #include "widorp.hxx"
67 #include "txtcache.hxx"
68 #include <fntcache.hxx>
69 #include <SwGrammarMarkUp.hxx>
70 #include <lineinfo.hxx>
71 #include <SwPortionHandler.hxx>
72 #include <dcontact.hxx>
73 #include <sortedobjs.hxx>
74 #include <txtflcnt.hxx>
75 #include <fmtflcnt.hxx>
76 #include <fmtcntnt.hxx>
77 #include <numrule.hxx>
78 #include <swtable.hxx>
79 #include <fldupde.hxx>
80 #include <docufld.hxx>
81 #include <IGrammarContact.hxx>
82 #include <calbck.hxx>
83 #include <ftnidx.hxx>
84 #include <ftnfrm.hxx>
85 
86 
87 namespace sw {
88 
90  : m_pMerged(rFrame.GetMergedPara())
91  , m_pNode(m_pMerged ? nullptr : rFrame.GetTextNodeFirst())
92  , m_CurrentExtent(0)
93  , m_CurrentHint(0)
94  {
95  }
96 
98  {
99  if (m_pMerged)
100  {
101  while (m_CurrentExtent < m_pMerged->extents.size())
102  {
103  sw::Extent const& rExtent(m_pMerged->extents[m_CurrentExtent]);
104  if (SwpHints const*const pHints = rExtent.pNode->GetpSwpHints())
105  {
106  while (m_CurrentHint < pHints->Count())
107  {
108  SwTextAttr *const pHint(pHints->Get(m_CurrentHint));
109  if (rExtent.nEnd < pHint->GetStart()
110  // <= if it has no end or isn't empty
111  || (rExtent.nEnd == pHint->GetStart()
112  && (!pHint->GetEnd()
113  || *pHint->GetEnd() != pHint->GetStart())))
114  {
115  break;
116  }
117  ++m_CurrentHint;
118  if (rExtent.nStart <= pHint->GetStart())
119  {
120  if (ppNode)
121  {
122  *ppNode = rExtent.pNode;
123  }
124  return pHint;
125  }
126  }
127  }
128  ++m_CurrentExtent;
129  if (m_CurrentExtent < m_pMerged->extents.size() &&
130  rExtent.pNode != m_pMerged->extents[m_CurrentExtent].pNode)
131  {
132  m_CurrentHint = 0; // reset
133  }
134  }
135  return nullptr;
136  }
137  else
138  {
139  SwpHints const*const pHints(m_pNode->GetpSwpHints());
140  if (pHints)
141  {
142  if (m_CurrentHint < pHints->Count())
143  {
144  SwTextAttr const*const pHint(pHints->Get(m_CurrentHint));
145  ++m_CurrentHint;
146  if (ppNode)
147  {
148  *ppNode = m_pNode;
149  }
150  return pHint;
151  }
152  }
153  return nullptr;
154  }
155  }
156 
158  : m_pNode(rFrame.GetMergedPara() ? nullptr : rFrame.GetTextNodeFirst())
159  , m_CurrentHint(0)
160  {
161  if (!m_pNode)
162  {
163  MergedAttrIterReverse iter(rFrame);
164  SwTextNode const* pNode(nullptr);
165  while (SwTextAttr const* pHint = iter.PrevAttr(&pNode))
166  {
167  m_Hints.emplace_back(pNode, pHint);
168  }
169  }
170  }
171 
173  {
174  if (m_pNode)
175  {
176  SwpHints const*const pHints(m_pNode->GetpSwpHints());
177  if (pHints)
178  {
179  if (m_CurrentHint < pHints->Count())
180  {
181  SwTextAttr const*const pHint(
182  pHints->GetSortedByEnd(m_CurrentHint));
183  ++m_CurrentHint;
184  rpNode = m_pNode;
185  return pHint;
186  }
187  }
188  return nullptr;
189  }
190  else
191  {
192  if (m_CurrentHint < m_Hints.size())
193  {
194  auto const ret = m_Hints[m_Hints.size() - m_CurrentHint - 1];
195  ++m_CurrentHint;
196  rpNode = ret.first;
197  return ret.second;
198  }
199  return nullptr;
200  }
201  }
202 
204  {
205  assert(0 < m_CurrentHint); // should only rewind as far as 0
206  --m_CurrentHint;
207  }
208 
210  : MergedAttrIterBase(rFrame)
211  {
212  if (m_pMerged)
213  {
215  SwpHints const*const pHints(0 < m_CurrentExtent
216  ? m_pMerged->extents[m_CurrentExtent-1].pNode->GetpSwpHints()
217  : nullptr);
218  if (pHints)
219  {
220  pHints->SortIfNeedBe();
221  m_CurrentHint = pHints->Count();
222  }
223  }
224  else
225  {
226  if (SwpHints const*const pHints = m_pNode->GetpSwpHints())
227  {
228  pHints->SortIfNeedBe();
229  m_CurrentHint = pHints->Count();
230  }
231  }
232  }
233 
235  {
236  if (m_pMerged)
237  {
238  while (0 < m_CurrentExtent)
239  {
240  sw::Extent const& rExtent(m_pMerged->extents[m_CurrentExtent-1]);
241  if (SwpHints const*const pHints = rExtent.pNode->GetpSwpHints())
242  {
243  while (0 < m_CurrentHint)
244  {
245  SwTextAttr *const pHint(
246  pHints->GetSortedByEnd(m_CurrentHint - 1));
247  if (pHint->GetAnyEnd() < rExtent.nStart
248  // <= if it has end and isn't empty
249  || (pHint->GetEnd()
250  && *pHint->GetEnd() != pHint->GetStart()
251  && *pHint->GetEnd() == rExtent.nStart))
252  {
253  break;
254  }
255  --m_CurrentHint;
256  if (pHint->GetAnyEnd() <= rExtent.nEnd)
257  {
258  if (ppNode)
259  {
260  *ppNode = rExtent.pNode;
261  }
262  return pHint;
263  }
264  }
265  }
266  --m_CurrentExtent;
267  if (0 < m_CurrentExtent &&
268  rExtent.pNode != m_pMerged->extents[m_CurrentExtent-1].pNode)
269  {
270  SwpHints const*const pHints(
271  m_pMerged->extents[m_CurrentExtent-1].pNode->GetpSwpHints());
272  m_CurrentHint = pHints ? pHints->Count() : 0; // reset
273  if (pHints)
274  pHints->SortIfNeedBe();
275  }
276  }
277  return nullptr;
278  }
279  else
280  {
281  SwpHints const*const pHints(m_pNode->GetpSwpHints());
282  if (pHints && 0 < m_CurrentHint)
283  {
284  SwTextAttr const*const pHint(pHints->GetSortedByEnd(m_CurrentHint - 1));
285  --m_CurrentHint;
286  if (ppNode)
287  {
288  *ppNode = m_pNode;
289  }
290  return pHint;
291  }
292  return nullptr;
293  }
294  }
295 
296  bool FrameContainsNode(SwContentFrame const& rFrame, sal_uLong const nNodeIndex)
297  {
298  if (rFrame.IsTextFrame())
299  {
300  SwTextFrame const& rTextFrame(static_cast<SwTextFrame const&>(rFrame));
301  if (sw::MergedPara const*const pMerged = rTextFrame.GetMergedPara())
302  {
303  sal_uLong const nFirst(pMerged->pFirstNode->GetIndex());
304  sal_uLong const nLast(pMerged->pLastNode->GetIndex());
305  return (nFirst <= nNodeIndex && nNodeIndex <= nLast);
306  }
307  else
308  {
309  return rTextFrame.GetTextNodeFirst()->GetIndex() == nNodeIndex;
310  }
311  }
312  else
313  {
314  assert(rFrame.IsNoTextFrame());
315  return static_cast<SwNoTextFrame const&>(rFrame).GetNode()->GetIndex() == nNodeIndex;
316  }
317  }
318 
319  bool IsParaPropsNode(SwRootFrame const& rLayout, SwTextNode const& rNode)
320  {
321  if (rLayout.IsHideRedlines())
322  {
323  if (SwTextFrame const*const pFrame = static_cast<SwTextFrame*>(rNode.getLayoutFrame(&rLayout)))
324  {
325  sw::MergedPara const*const pMerged(pFrame->GetMergedPara());
326  if (pMerged && pMerged->pParaPropsNode != &rNode)
327  {
328  return false;
329  }
330  }
331  }
332  return true;
333  }
334 
335  SwTextNode *
336  GetParaPropsNode(SwRootFrame const& rLayout, SwNodeIndex const& rPos)
337  {
338  SwTextNode *const pTextNode(rPos.GetNode().GetTextNode());
339  if (pTextNode && !sw::IsParaPropsNode(rLayout, *pTextNode))
340  {
341  return static_cast<SwTextFrame*>(pTextNode->getLayoutFrame(&rLayout))->GetMergedPara()->pParaPropsNode;
342  }
343  else
344  {
345  return pTextNode;
346  }
347  }
348 
349  SwPosition
350  GetParaPropsPos(SwRootFrame const& rLayout, SwPosition const& rPos)
351  {
352  SwPosition pos(rPos);
353  SwTextNode const*const pNode(pos.nNode.GetNode().GetTextNode());
354  if (pNode)
355  {
356  pos.nNode = *sw::GetParaPropsNode(rLayout, *pNode);
357  pos.nContent.Assign(pos.nNode.GetNode().GetContentNode(), 0);
358  }
359  return pos;
360  }
361 
362  std::pair<SwTextNode *, SwTextNode *>
363  GetFirstAndLastNode(SwRootFrame const& rLayout, SwNodeIndex const& rPos)
364  {
365  SwTextNode *const pTextNode(rPos.GetNode().GetTextNode());
366  if (pTextNode && rLayout.IsHideRedlines())
367  {
368  if (SwTextFrame const*const pFrame = static_cast<SwTextFrame*>(pTextNode->getLayoutFrame(&rLayout)))
369  {
370  if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara())
371  {
372  return std::make_pair(pMerged->pFirstNode, const_cast<SwTextNode*>(pMerged->pLastNode));
373  }
374  }
375  }
376  return std::make_pair(pTextNode, pTextNode);
377  }
378 
379  SwTextNode const& GetAttrMerged(SfxItemSet & rFormatSet,
380  SwTextNode const& rNode, SwRootFrame const*const pLayout)
381  {
382  rNode.SwContentNode::GetAttr(rFormatSet);
383  if (pLayout && pLayout->IsHideRedlines())
384  {
385  auto pFrame = static_cast<SwTextFrame*>(rNode.getLayoutFrame(pLayout));
386  if (sw::MergedPara const*const pMerged = pFrame ? pFrame->GetMergedPara() : nullptr)
387  {
388  if (pMerged->pFirstNode != &rNode)
389  {
390  rFormatSet.ClearItem(RES_PAGEDESC);
391  rFormatSet.ClearItem(RES_BREAK);
392  static_assert(RES_PAGEDESC + 1 == sal_uInt16(RES_BREAK),
393  "first-node items must be adjacent");
394  SfxItemSet firstSet(*rFormatSet.GetPool(),
396  pMerged->pFirstNode->SwContentNode::GetAttr(firstSet);
397  rFormatSet.Put(firstSet);
398 
399  }
400  if (pMerged->pParaPropsNode != &rNode)
401  {
402  for (sal_uInt16 i = RES_PARATR_BEGIN; i != RES_FRMATR_END; ++i)
403  {
404  if (i != RES_PAGEDESC && i != RES_BREAK)
405  {
406  rFormatSet.ClearItem(i);
407  }
408  }
409  for (sal_uInt16 i = XATTR_FILL_FIRST; i <= XATTR_FILL_LAST; ++i)
410  {
411  rFormatSet.ClearItem(i);
412  }
413  SfxItemSet propsSet(*rFormatSet.GetPool(),
417  pMerged->pParaPropsNode->SwContentNode::GetAttr(propsSet);
418  rFormatSet.Put(propsSet);
419  return *pMerged->pParaPropsNode;
420  }
421  // keep all the CHRATR/UNKNOWNATR anyway...
422  }
423  }
424  return rNode;
425  }
426 
427 } // namespace sw
428 
431 {
432  {
434 
435  if ( ! mbIsSwapped )
436  {
437  const long nPrtOfstX = aPrt.Pos().X();
438  aPrt.Pos().setX( aPrt.Pos().Y() );
439 
440  if( IsVertLR() )
441  {
442  aPrt.Pos().setY( nPrtOfstX );
443  }
444  else
445  {
446  aPrt.Pos().setY( getFrameArea().Width() - ( nPrtOfstX + aPrt.Width() ) );
447  }
448  }
449  else
450  {
451  const long nPrtOfstY = aPrt.Pos().Y();
452  aPrt.Pos().setY( aPrt.Pos().X() );
453 
454  if( IsVertLR() )
455  {
456  aPrt.Pos().setX( nPrtOfstY );
457  }
458  else
459  {
460  aPrt.Pos().setX( getFrameArea().Height() - ( nPrtOfstY + aPrt.Height() ) );
461  }
462  }
463 
464  const long nPrtWidth = aPrt.Width();
465  aPrt.Width( aPrt.Height() );
466  aPrt.Height( nPrtWidth );
467  }
468 
469  {
470  const long nFrameWidth = getFrameArea().Width();
472  aFrm.Width( aFrm.Height() );
473  aFrm.Height( nFrameWidth );
474  }
475 
477 }
478 
484 {
485  // calc offset inside frame
486  long nOfstX, nOfstY;
487  if ( IsVertLR() )
488  {
489  if (IsVertLRBT())
490  {
491  // X and Y offsets here mean the position of the point that will be the top left corner
492  // after the switch.
493  nOfstX = rRect.Left() + rRect.Width() - getFrameArea().Left();
494  nOfstY = rRect.Top() - getFrameArea().Top();
495  }
496  else
497  {
498  nOfstX = rRect.Left() - getFrameArea().Left();
499  nOfstY = rRect.Top() - getFrameArea().Top();
500  }
501  }
502  else
503  {
504  nOfstX = rRect.Left() - getFrameArea().Left();
505  nOfstY = rRect.Top() + rRect.Height() - getFrameArea().Top();
506  }
507 
508  const long nWidth = rRect.Width();
509  const long nHeight = rRect.Height();
510 
511  if ( IsVertLR() )
512  {
513  rRect.Left(getFrameArea().Left() + nOfstY);
514  }
515  else
516  {
517  if ( mbIsSwapped )
518  rRect.Left( getFrameArea().Left() + getFrameArea().Height() - nOfstY );
519  else
520  // frame is rotated
521  rRect.Left( getFrameArea().Left() + getFrameArea().Width() - nOfstY );
522  }
523 
524  if (IsVertLRBT())
525  {
526  if (mbIsSwapped)
527  rRect.Top(getFrameArea().Top() + getFrameArea().Width() - nOfstX);
528  else
529  rRect.Top(getFrameArea().Top() + getFrameArea().Height() - nOfstX);
530  }
531  else
532  rRect.Top(getFrameArea().Top() + nOfstX);
533  rRect.Width( nHeight );
534  rRect.Height( nWidth );
535 }
536 
542 {
543  if (IsVertLRBT())
544  {
545  // The horizontal origo is the top left corner, the LRBT origo is the
546  // bottom left corner. Finally x and y has to be swapped.
547  SAL_WARN_IF(!mbIsSwapped, "sw.core",
548  "SwTextFrame::SwitchHorizontalToVertical, IsVertLRBT, not swapped");
549  Point aPoint(rPoint);
550  rPoint.setX(getFrameArea().Left() + (aPoint.Y() - getFrameArea().Top()));
551  // This would be bottom - x delta, but bottom is top + height, finally
552  // width (and not height), as it's swapped.
553  rPoint.setY(getFrameArea().Top() + getFrameArea().Width()
554  - (aPoint.X() - getFrameArea().Left()));
555  return;
556  }
557 
558  // calc offset inside frame
559  const long nOfstX = rPoint.X() - getFrameArea().Left();
560  const long nOfstY = rPoint.Y() - getFrameArea().Top();
561  if ( IsVertLR() )
562  rPoint.setX( getFrameArea().Left() + nOfstY );
563  else
564  {
565  if ( mbIsSwapped )
566  rPoint.setX( getFrameArea().Left() + getFrameArea().Height() - nOfstY );
567  else
568  // calc rotated coords
569  rPoint.setX( getFrameArea().Left() + getFrameArea().Width() - nOfstY );
570  }
571 
572  rPoint.setY( getFrameArea().Top() + nOfstX );
573 }
574 
580 {
581  Point aTmp( 0, nLimit );
583  return aTmp.X();
584 }
585 
591 {
592  long nOfstX;
593 
594  // calc offset inside frame
595  if ( IsVertLR() )
596  nOfstX = rRect.Left() - getFrameArea().Left();
597  else
598  {
599  if ( mbIsSwapped )
600  nOfstX = getFrameArea().Left() + getFrameArea().Height() - ( rRect.Left() + rRect.Width() );
601  else
602  nOfstX = getFrameArea().Left() + getFrameArea().Width() - ( rRect.Left() + rRect.Width() );
603  }
604 
605  long nOfstY;
606  if (IsVertLRBT())
607  {
608  // Note that mbIsSwapped only affects the frame area, not rRect, so rRect.Height() is used
609  // here unconditionally.
610  if (mbIsSwapped)
611  nOfstY = getFrameArea().Top() + getFrameArea().Width() - (rRect.Top() + rRect.Height());
612  else
613  nOfstY = getFrameArea().Top() + getFrameArea().Height() - (rRect.Top() + rRect.Height());
614  }
615  else
616  nOfstY = rRect.Top() - getFrameArea().Top();
617  const long nWidth = rRect.Height();
618  const long nHeight = rRect.Width();
619 
620  // calc rotated coords
621  rRect.Left( getFrameArea().Left() + nOfstY );
622  rRect.Top( getFrameArea().Top() + nOfstX );
623  rRect.Width( nWidth );
624  rRect.Height( nHeight );
625 }
626 
632 {
633  long nOfstX;
634 
635  // calc offset inside frame
636  if ( IsVertLR() )
637  // X offset is Y - left.
638  nOfstX = rPoint.X() - getFrameArea().Left();
639  else
640  {
641  // X offset is right - X.
642  if ( mbIsSwapped )
643  nOfstX = getFrameArea().Left() + getFrameArea().Height() - rPoint.X();
644  else
645  nOfstX = getFrameArea().Left() + getFrameArea().Width() - rPoint.X();
646  }
647 
648  long nOfstY;
649  if (IsVertLRBT())
650  {
651  // Y offset is bottom - Y.
652  if (mbIsSwapped)
653  nOfstY = getFrameArea().Top() + getFrameArea().Width() - rPoint.Y();
654  else
655  nOfstY = getFrameArea().Top() + getFrameArea().Height() - rPoint.Y();
656  }
657  else
658  // Y offset is Y - top.
659  nOfstY = rPoint.Y() - getFrameArea().Top();
660 
661  // calc rotated coords
662  rPoint.setX( getFrameArea().Left() + nOfstY );
663  rPoint.setY( getFrameArea().Top() + nOfstX );
664 }
665 
671 {
672  Point aTmp( nLimit, 0 );
674  return aTmp.Y();
675 }
676 
677 SwFrameSwapper::SwFrameSwapper( const SwTextFrame* pTextFrame, bool bSwapIfNotSwapped )
678  : pFrame( pTextFrame ), bUndo( false )
679 {
680  if (pFrame->IsVertical() && bSwapIfNotSwapped != pFrame->IsSwapped())
681  {
682  bUndo = true;
683  const_cast<SwTextFrame*>(pFrame)->SwapWidthAndHeight();
684  }
685 }
686 
688 {
689  if ( bUndo )
690  const_cast<SwTextFrame*>(pFrame)->SwapWidthAndHeight();
691 }
692 
694 {
695  SwSwapIfNotSwapped swap(const_cast<SwTextFrame *>(this));
696 
697  long nWidth = rRect.Width();
698  rRect.Left( 2 * ( getFrameArea().Left() + getFramePrintArea().Left() ) +
699  getFramePrintArea().Width() - rRect.Right() - 1 );
700 
701  rRect.Width( nWidth );
702 }
703 
704 void SwTextFrame::SwitchLTRtoRTL( Point& rPoint ) const
705 {
706  SwSwapIfNotSwapped swap(const_cast<SwTextFrame *>(this));
707 
708  rPoint.setX( 2 * ( getFrameArea().Left() + getFramePrintArea().Left() ) + getFramePrintArea().Width() - rPoint.X() - 1 );
709 }
710 
712  m_rOut( rOutp ), m_nOldLayoutMode( rOutp.GetLayoutMode() )
713 {
714 }
715 
717 {
718  const_cast<OutputDevice&>(m_rOut).SetLayoutMode( m_nOldLayoutMode );
719 }
720 
721 void SwLayoutModeModifier::Modify( bool bChgToRTL )
722 {
723  const_cast<OutputDevice&>(m_rOut).SetLayoutMode( bChgToRTL ?
724  ComplexTextLayoutFlags::BiDiStrong | ComplexTextLayoutFlags::BiDiRtl :
725  ComplexTextLayoutFlags::BiDiStrong );
726 }
727 
729 {
730  const ComplexTextLayoutFlags nNewLayoutMode = m_nOldLayoutMode & ~ComplexTextLayoutFlags::BiDiStrong;
731  const_cast<OutputDevice&>(m_rOut).SetLayoutMode( nNewLayoutMode );
732 }
733 
735  rOut( rOutp ), nOldLanguageType( rOutp.GetDigitLanguage() )
736 {
737  LanguageType eLang = eCurLang;
739  eLang = LANGUAGE_ENGLISH_US;
740  else
741  {
742  const SvtCTLOptions::TextNumerals nTextNumerals = SW_MOD()->GetCTLOptions().GetCTLTextNumerals();
743 
744  if ( SvtCTLOptions::NUMERALS_HINDI == nTextNumerals )
746  else if ( SvtCTLOptions::NUMERALS_ARABIC == nTextNumerals )
747  eLang = LANGUAGE_ENGLISH;
748  else if ( SvtCTLOptions::NUMERALS_SYSTEM == nTextNumerals )
749  eLang = ::GetAppLanguage();
750  }
751 
752  const_cast<OutputDevice&>(rOut).SetDigitLanguage( eLang );
753 }
754 
756 {
757  const_cast<OutputDevice&>(rOut).SetDigitLanguage( nOldLanguageType );
758 }
759 
761 {
762  OSL_ENSURE( !IsLocked(), "+SwTextFrame::Init: this is locked." );
763  if( !IsLocked() )
764  {
765  ClearPara();
766  ResetBlinkPor();
767  // set flags directly to save a ResetPreps call,
768  // and thereby an unnecessary GetPara call
769  // don't set bOrphan, bLocked or bWait to false!
770  // bOrphan = bFlag7 = bFlag8 = false;
771  }
772 }
773 
775  sw::FrameMode const eMode)
776  : SwContentFrame( pNode, pSib )
777  , mnAllLines( 0 )
778  , mnThisLines( 0 )
779  , mnFlyAnchorOfst( 0 )
780  , mnFlyAnchorOfstNoWrap( 0 )
781  , mnFlyAnchorVertOfstNoWrap( 0 )
782  , mnFootnoteLine( 0 )
783  , mnHeightOfLastLine( 0 )
784  , mnAdditionalFirstLineOffset( 0 )
785  , mnOffset( 0 )
786  , mnCacheIndex( USHRT_MAX )
787  , mbLocked( false )
788  , mbWidow( false )
789  , mbJustWidow( false )
790  , mbEmpty( false )
791  , mbInFootnoteConnect( false )
792  , mbFootnote( false )
793  , mbRepaint( false )
794  , mbHasBlinkPortions( false )
795  , mbFieldFollow( false )
796  , mbHasAnimation( false )
797  , mbIsSwapped( false )
798  , mbFollowFormatAllowed( true )
799 {
801  // note: this may call SwClientNotify if it's in a list so do it last
802  // note: this may change this->pRegisteredIn to m_pMergedPara->listeners
803  m_pMergedPara = CheckParaRedlineMerge(*this, *pNode, eMode);
804 }
805 
806 namespace sw {
807 
808 SwTextFrame * MakeTextFrame(SwTextNode & rNode, SwFrame *const pSibling,
809  sw::FrameMode const eMode)
810 {
811  return new SwTextFrame(&rNode, pSibling, eMode);
812 }
813 
815  SwRootFrame const& rLayout, SwTextNode const& rTextNode,
816  std::vector<std::pair<sal_Int32, sal_Int32>> const*const pExtents)
817 {
818  if (pExtents && pExtents->empty())
819  {
820  return; // nothing to do
821  }
822  const SwFootnoteIdxs &rFootnoteIdxs = rTextNode.GetDoc()->GetFootnoteIdxs();
823  size_t nPos = 0;
824  sal_uLong const nIndex = rTextNode.GetIndex();
825  rFootnoteIdxs.SeekEntry( rTextNode, &nPos );
826  if (nPos < rFootnoteIdxs.size())
827  {
828  while (nPos && &rTextNode == &(rFootnoteIdxs[ nPos ]->GetTextNode()))
829  --nPos;
830  if (nPos || &rTextNode != &(rFootnoteIdxs[ nPos ]->GetTextNode()))
831  ++nPos;
832  }
833  size_t iter(0);
834  for ( ; nPos < rFootnoteIdxs.size(); ++nPos)
835  {
836  SwTextFootnote* pTextFootnote = rFootnoteIdxs[ nPos ];
837  if (pTextFootnote->GetTextNode().GetIndex() > nIndex)
838  break;
839  if (pExtents)
840  {
841  while ((*pExtents)[iter].second <= pTextFootnote->GetStart())
842  {
843  ++iter;
844  if (iter == pExtents->size())
845  {
846  return;
847  }
848  }
849  if (pTextFootnote->GetStart() < (*pExtents)[iter].first)
850  {
851  continue;
852  }
853  }
854  pTextFootnote->DelFrames(&rLayout);
855  }
856 }
857 
858 } // namespace sw
859 
861 {
862  // Remove associated SwParaPortion from s_pTextCache
863  ClearPara();
864 
865  assert(!GetDoc().IsInDtor()); // this shouldn't be happening with ViewShell owning layout
866  if (!GetDoc().IsInDtor() && HasFootnote())
867  {
868  if (m_pMergedPara)
869  {
870  SwTextNode const* pNode(nullptr);
871  for (auto const& e : m_pMergedPara->extents)
872  {
873  if (e.pNode != pNode)
874  {
875  pNode = e.pNode;
876  // sw_redlinehide: not sure if it's necessary to check
877  // if the nodes are still alive here, which would require
878  // accessing WriterMultiListener::m_vDepends
879  sw::RemoveFootnotesForNode(*getRootFrame(), *pNode, nullptr);
880  }
881  }
882  }
883  else
884  {
885  SwTextNode *const pNode(static_cast<SwTextNode*>(GetDep()));
886  if (pNode)
887  {
888  sw::RemoveFootnotesForNode(*getRootFrame(), *pNode, nullptr);
889  }
890  }
891  }
892 
894 }
895 
897 {
898  RemoveFromCache();
899 }
900 
901 namespace sw {
902 
903 // 1. if real insert => correct nStart/nEnd for full nLen
904 // 2. if rl un-delete => do not correct nStart/nEnd but just include un-deleted
906  bool const isRealInsert,
907  SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
908 {
909  assert(!isRealInsert || nLen); // can 0 happen? yes, for redline in empty node
910  assert(nIndex <= rNode.Len());
911  assert(nIndex + nLen <= rNode.Len());
912  assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
913  if (!nLen)
914  {
915  return TextFrameIndex(0);
916  }
917  OUStringBuffer text(rMerged.mergedText);
918  sal_Int32 nTFIndex(0); // index used for insertion at the end
919  sal_Int32 nInserted(0);
920  bool bInserted(false);
921  bool bFoundNode(false);
922  auto itInsert(rMerged.extents.end());
923  for (auto it = rMerged.extents.begin(); it != rMerged.extents.end(); ++it)
924  {
925  if (it->pNode == &rNode)
926  {
927  if (isRealInsert)
928  {
929  bFoundNode = true;
930  if (it->nStart <= nIndex && nIndex <= it->nEnd)
931  { // note: this can happen only once
932  text.insert(nTFIndex + (nIndex - it->nStart),
933  rNode.GetText().copy(nIndex, nLen));
934  it->nEnd += nLen;
935  nInserted = nLen;
936  assert(!bInserted);
937  bInserted = true;
938  }
939  else if (nIndex < it->nStart)
940  {
941  if (itInsert == rMerged.extents.end())
942  {
943  itInsert = it;
944  }
945  it->nStart += nLen;
946  it->nEnd += nLen;
947  }
948  }
949  else
950  {
951  assert(it == rMerged.extents.begin() || (it-1)->pNode != &rNode || (it-1)->nEnd < nIndex);
952  if (nIndex + nLen < it->nStart)
953  {
954  itInsert = it;
955  break;
956  }
957  if (nIndex < it->nStart)
958  {
959  text.insert(nTFIndex,
960  rNode.GetText().copy(nIndex, it->nStart - nIndex));
961  nInserted += it->nStart - nIndex;
962  it->nStart = nIndex;
963  bInserted = true;
964  }
965  assert(it->nStart <= nIndex);
966  if (nIndex <= it->nEnd)
967  {
968  nTFIndex += it->nEnd - it->nStart;
969  while (it->nEnd < nIndex + nLen)
970  {
971  auto *const pNext(
972  (it+1) != rMerged.extents.end() && (it+1)->pNode == it->pNode
973  ? &*(it+1)
974  : nullptr);
975  if (pNext && pNext->nStart <= nIndex + nLen)
976  {
977  text.insert(nTFIndex,
978  rNode.GetText().copy(it->nEnd, pNext->nStart - it->nEnd));
979  nTFIndex += pNext->nStart - it->nEnd;
980  nInserted += pNext->nStart - it->nEnd;
981  pNext->nStart = it->nStart;
982  it = rMerged.extents.erase(it);
983  }
984  else
985  {
986  text.insert(nTFIndex,
987  rNode.GetText().copy(it->nEnd, nIndex + nLen - it->nEnd));
988  nTFIndex += nIndex + nLen - it->nEnd;
989  nInserted += nIndex + nLen - it->nEnd;
990  it->nEnd = nIndex + nLen;
991  }
992  }
993  bInserted = true;
994  break;
995  }
996  }
997  }
998  else if (rNode.GetIndex() < it->pNode->GetIndex() || bFoundNode)
999  {
1000  if (itInsert == rMerged.extents.end())
1001  {
1002  itInsert = it;
1003  }
1004  break;
1005  }
1006  if (itInsert == rMerged.extents.end())
1007  {
1008  nTFIndex += it->nEnd - it->nStart;
1009  }
1010  }
1011 // assert((bFoundNode || rMerged.extents.empty()) && "text node not found - why is it sending hints to us");
1012  if (!bInserted)
1013  { // must be in a gap
1014  rMerged.extents.emplace(itInsert, const_cast<SwTextNode*>(&rNode), nIndex, nIndex + nLen);
1015  text.insert(nTFIndex, rNode.GetText().copy(nIndex, nLen));
1016  nInserted = nLen;
1017  if (rMerged.extents.size() == 1 // also if it was empty!
1018  || rMerged.pParaPropsNode->GetIndex() < rNode.GetIndex())
1019  { // text inserted after current para-props node
1021  rMerged.pParaPropsNode = &const_cast<SwTextNode&>(rNode);
1022  rMerged.pParaPropsNode->AddToListRLHidden();
1023  }
1024  }
1025  rMerged.mergedText = text.makeStringAndClear();
1026  return TextFrameIndex(nInserted);
1027 }
1028 
1029 // 1. if real delete => correct nStart/nEnd for full nLen
1030 // 2. if rl delete => do not correct nStart/nEnd but just exclude deleted
1032  bool const isRealDelete,
1033  SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 const nLen)
1034 {
1035  assert(nIndex <= rNode.Len());
1036  assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
1037  OUStringBuffer text(rMerged.mergedText);
1038  sal_Int32 nTFIndex(0);
1039  sal_Int32 nToDelete(nLen);
1040  sal_Int32 nDeleted(0);
1041  size_t nFoundNode(0);
1042  size_t nErased(0);
1043  auto it = rMerged.extents.begin();
1044  for (; it != rMerged.extents.end(); )
1045  {
1046  bool bErase(false);
1047  if (it->pNode == &rNode)
1048  {
1049  ++nFoundNode;
1050  if (nIndex + nToDelete < it->nStart)
1051  {
1052  nToDelete = 0;
1053  if (!isRealDelete)
1054  {
1055  break;
1056  }
1057  it->nStart -= nLen;
1058  it->nEnd -= nLen;
1059  }
1060  else
1061  {
1062  if (nIndex < it->nStart)
1063  {
1064  // do not adjust nIndex into the text frame index space!
1065  nToDelete -= it->nStart - nIndex;
1066  nIndex = it->nStart;
1067  // note: continue with the if check below, no else!
1068  }
1069  if (it->nStart <= nIndex && nIndex < it->nEnd)
1070  {
1071  sal_Int32 const nDeleteHere(nIndex + nToDelete <= it->nEnd
1072  ? nToDelete
1073  : it->nEnd - nIndex);
1074  text.remove(nTFIndex + (nIndex - it->nStart), nDeleteHere);
1075  bErase = nDeleteHere == it->nEnd - it->nStart;
1076  if (bErase)
1077  {
1078  ++nErased;
1079  assert(it->nStart == nIndex);
1080  it = rMerged.extents.erase(it);
1081  }
1082  else if (isRealDelete)
1083  { // adjust for deleted text
1084  it->nStart -= (nLen - nToDelete);
1085  it->nEnd -= (nLen - nToDelete + nDeleteHere);
1086  if (it != rMerged.extents.begin()
1087  && (it-1)->pNode == &rNode
1088  && (it-1)->nEnd == it->nStart)
1089  { // merge adjacent extents
1090  nTFIndex += it->nEnd - it->nStart;
1091  (it-1)->nEnd = it->nEnd;
1092  it = rMerged.extents.erase(it);
1093  bErase = true; // skip increment
1094  }
1095  }
1096  else
1097  { // exclude text marked as deleted
1098  if (nIndex + nDeleteHere == it->nEnd)
1099  {
1100  it->nEnd -= nDeleteHere;
1101  }
1102  else
1103  {
1104  if (nIndex == it->nStart)
1105  {
1106  it->nStart += nDeleteHere;
1107  }
1108  else
1109  {
1110  sal_Int32 const nOldEnd(it->nEnd);
1111  it->nEnd = nIndex;
1112  it = rMerged.extents.emplace(it+1,
1113  it->pNode, nIndex + nDeleteHere, nOldEnd);
1114  }
1115  assert(nDeleteHere == nToDelete);
1116  }
1117  }
1118  nDeleted += nDeleteHere;
1119  nToDelete -= nDeleteHere;
1120  nIndex += nDeleteHere;
1121  if (!isRealDelete && nToDelete == 0)
1122  {
1123  break;
1124  }
1125  }
1126  }
1127  }
1128  else if (nFoundNode != 0)
1129  {
1130  break;
1131  }
1132  if (!bErase)
1133  {
1134  nTFIndex += it->nEnd - it->nStart;
1135  ++it;
1136  }
1137  }
1138 // assert(nFoundNode != 0 && "text node not found - why is it sending hints to us");
1139  assert(nIndex <= rNode.Len() + nLen);
1140  // if there's a remaining deletion, it must be in gap at the end of the node
1141 // can't do: might be last one in node was erased assert(nLen == 0 || rMerged.empty() || (it-1)->nEnd <= nIndex);
1142  // note: if first node gets deleted then that must call DelFrames as
1143  // pFirstNode is never updated
1144  if (nErased && nErased == nFoundNode)
1145  { // all visible text from node was erased
1146 #if 1
1147  if (rMerged.pParaPropsNode == &rNode)
1148  {
1150  rMerged.pParaPropsNode = rMerged.extents.empty()
1151  ? const_cast<SwTextNode*>(rMerged.pLastNode)
1152  : rMerged.extents.front().pNode;
1153  rMerged.pParaPropsNode->AddToListRLHidden();
1154  }
1155 #endif
1156 // NOPE must listen on all non-hidden nodes; particularly on pLastNode rMerged.listener.EndListening(&const_cast<SwTextNode&>(rNode));
1157  }
1158  rMerged.mergedText = text.makeStringAndClear();
1159  return TextFrameIndex(nDeleted);
1160 }
1161 
1162 std::pair<SwTextNode*, sal_Int32>
1163 MapViewToModel(MergedPara const& rMerged, TextFrameIndex const i_nIndex)
1164 {
1165  sal_Int32 nIndex(i_nIndex);
1166  sw::Extent const* pExtent(nullptr);
1167  for (const auto& rExt : rMerged.extents)
1168  {
1169  pExtent = &rExt;
1170  if (nIndex < (pExtent->nEnd - pExtent->nStart))
1171  {
1172  return std::make_pair(pExtent->pNode, pExtent->nStart + nIndex);
1173  }
1174  nIndex = nIndex - (pExtent->nEnd - pExtent->nStart);
1175  }
1176  assert(nIndex == 0 && "view index out of bounds");
1177  return pExtent
1178  ? std::make_pair(pExtent->pNode, pExtent->nEnd) //1-past-the-end index
1179  : std::make_pair(rMerged.pFirstNode, sal_Int32(0));
1180 }
1181 
1182 TextFrameIndex MapModelToView(MergedPara const& rMerged, SwTextNode const*const pNode, sal_Int32 const nIndex)
1183 {
1184  assert(rMerged.pFirstNode->GetIndex() <= pNode->GetIndex()
1185  && pNode->GetIndex() <= rMerged.pLastNode->GetIndex());
1186  sal_Int32 nRet(0);
1187  bool bFoundNode(false);
1188  for (auto const& e : rMerged.extents)
1189  {
1190  if (pNode->GetIndex() < e.pNode->GetIndex())
1191  {
1192  return TextFrameIndex(nRet);
1193  }
1194  if (e.pNode == pNode)
1195  {
1196  if (e.nStart <= nIndex && nIndex <= e.nEnd)
1197  {
1198  return TextFrameIndex(nRet + (nIndex - e.nStart));
1199  }
1200  else if (nIndex < e.nStart)
1201  {
1202  // in gap before this extent => map to 0 here TODO???
1203  return TextFrameIndex(nRet);
1204  }
1205  bFoundNode = true;
1206  }
1207  else if (bFoundNode)
1208  {
1209  break;
1210  }
1211  nRet += e.nEnd - e.nStart;
1212  }
1213  if (bFoundNode)
1214  {
1215  // must be in a gap at the end of the node
1216  assert(nIndex <= pNode->Len());
1217  return TextFrameIndex(nRet);
1218  }
1219  else if (rMerged.extents.empty())
1220  {
1221  assert(nIndex <= pNode->Len());
1222  return TextFrameIndex(0);
1223  }
1224  return TextFrameIndex(rMerged.mergedText.getLength());
1225 }
1226 
1227 } // namespace sw
1228 
1229 std::pair<SwTextNode*, sal_Int32>
1231 {
1232 //nope assert(GetPara());
1233  sw::MergedPara const*const pMerged(GetMergedPara());
1234  if (pMerged)
1235  {
1236  return sw::MapViewToModel(*pMerged, nIndex);
1237  }
1238  else
1239  {
1240  return std::make_pair(static_cast<SwTextNode*>(const_cast<SwModify*>(
1241  SwFrame::GetDep())), sal_Int32(nIndex));
1242  }
1243 }
1244 
1246 {
1247  std::pair<SwTextNode*, sal_Int32> const ret(MapViewToModel(nIndex));
1248  return SwPosition(*ret.first, ret.second);
1249 }
1250 
1251 TextFrameIndex SwTextFrame::MapModelToView(SwTextNode const*const pNode, sal_Int32 const nIndex) const
1252 {
1253 //nope assert(GetPara());
1254  sw::MergedPara const*const pMerged(GetMergedPara());
1255  if (pMerged)
1256  {
1257  return sw::MapModelToView(*pMerged, pNode, nIndex);
1258  }
1259  else
1260  {
1261  assert(static_cast<SwTextNode*>(const_cast<SwModify*>(SwFrame::GetDep())) == pNode);
1262  return TextFrameIndex(nIndex);
1263  }
1264 }
1265 
1267 {
1268  SwTextNode const*const pNode(rPos.nNode.GetNode().GetTextNode());
1269  sal_Int32 const nIndex(rPos.nContent.GetIndex());
1270  return MapModelToView(pNode, nIndex);
1271 }
1272 
1273 void SwTextFrame::SetMergedPara(std::unique_ptr<sw::MergedPara> p)
1274 {
1275  SwTextNode *const pFirst(m_pMergedPara ? m_pMergedPara->pFirstNode : nullptr);
1276  m_pMergedPara = std::move(p);
1277  if (pFirst)
1278  {
1279  if (m_pMergedPara)
1280  {
1281  assert(pFirst == m_pMergedPara->pFirstNode);
1282  }
1283  else
1284  {
1285  pFirst->Add(this); // must register at node again
1286  }
1287  }
1288 }
1289 
1290 const OUString& SwTextFrame::GetText() const
1291 {
1292 //nope assert(GetPara());
1293  sw::MergedPara const*const pMerged(GetMergedPara());
1294  if (pMerged)
1295  return pMerged->mergedText;
1296  else
1297  return static_cast<SwTextNode const*>(SwFrame::GetDep())->GetText();
1298 }
1299 
1301 {
1302  // FIXME can GetPara be 0 ? yes... this is needed in SwContentNotify::SwContentNotify() which is called before any formatting is started
1303 //nope assert(GetPara());
1304  sw::MergedPara const*const pMerged(GetMergedPara());
1305  if (pMerged)
1306  {
1307 // assert(pMerged->pFirstNode == pMerged->pParaPropsNode); // surprising news!
1308  return pMerged->pParaPropsNode;
1309  }
1310  else
1311  return static_cast<SwTextNode const*>(SwFrame::GetDep());
1312 }
1313 
1315 {
1316  sw::MergedPara const*const pMerged(GetMergedPara());
1317  if (pMerged)
1318  return pMerged->extents.empty()
1319  ? pMerged->pFirstNode
1320  : pMerged->extents.front().pNode;
1321  else
1322  return static_cast<SwTextNode const*>(SwFrame::GetDep());
1323 }
1324 
1326 {
1327 //nope assert(GetPara());
1328  sw::MergedPara const*const pMerged(GetMergedPara());
1329  if (pMerged)
1330  return pMerged->pFirstNode;
1331  else
1332  return static_cast<SwTextNode const*>(SwFrame::GetDep());
1333 }
1334 
1336 {
1337  return *GetTextNodeFirst()->GetDoc();
1338 }
1339 
1341  sal_uInt16 const nScript, bool const bNoChar) const
1342 {
1343  // a single character can be mapped uniquely!
1344  std::pair<SwTextNode const*, sal_Int32> const pos(MapViewToModel(nIndex));
1345  return pos.first->GetLang(pos.second, bNoChar ? 0 : 1, nScript);
1346 }
1347 
1349 {
1350  if ( GetCacheIdx() != USHRT_MAX )
1351  {
1352  if (SwParaPortion *pPara = GetPara())
1353  pPara->ResetPreps();
1354  }
1355 }
1356 
1358 {
1359  SwFrameSwapper aSwapper( this, true );
1360 
1361  if( !getFrameArea().Width() && isFrameAreaDefinitionValid() && GetUpper()->isFrameAreaDefinitionValid() ) // invalid when stack overflows (StackHack)!
1362  {
1363 // OSL_FAIL( "SwTextFrame::IsHiddenNow: thin frame" );
1364  return true;
1365  }
1366 
1367  bool bHiddenCharsHidePara(false);
1368  bool bHiddenParaField(false);
1369  if (m_pMergedPara)
1370  {
1371  TextFrameIndex nHiddenStart(COMPLETE_STRING);
1372  TextFrameIndex nHiddenEnd(0);
1373  if (auto const pScriptInfo = GetScriptInfo())
1374  {
1375  pScriptInfo->GetBoundsOfHiddenRange(TextFrameIndex(0),
1376  nHiddenStart, nHiddenEnd);
1377  }
1378  else // ParaPortion is created in Format, but this is called earlier
1379  {
1380  SwScriptInfo aInfo;
1381  aInfo.InitScriptInfo(*m_pMergedPara->pFirstNode, m_pMergedPara.get(), IsRightToLeft());
1383  nHiddenStart, nHiddenEnd);
1384  }
1385  if (TextFrameIndex(0) == nHiddenStart &&
1386  TextFrameIndex(GetText().getLength()) <= nHiddenEnd)
1387  {
1388  bHiddenCharsHidePara = true;
1389  }
1390  sw::MergedAttrIter iter(*this);
1391  SwTextNode const* pNode(nullptr);
1392  int nNewResultWeight = 0;
1393  for (SwTextAttr const* pHint = iter.NextAttr(&pNode); pHint; pHint = iter.NextAttr(&pNode))
1394  {
1395  if (pHint->Which() == RES_TXTATR_FIELD)
1396  {
1397  // see also SwpHints::CalcHiddenParaField()
1398  const SwFormatField& rField = pHint->GetFormatField();
1399  int nCurWeight = pNode->FieldCanHideParaWeight(rField.GetField()->GetTyp()->Which());
1400  if (nCurWeight > nNewResultWeight)
1401  {
1402  nNewResultWeight = nCurWeight;
1403  bHiddenParaField = pNode->FieldHidesPara(*rField.GetField());
1404  }
1405  else if (nCurWeight == nNewResultWeight && bHiddenParaField)
1406  {
1407  // Currently, for both supported hiding types (HiddenPara, Database), "Don't hide"
1408  // takes precedence - i.e., if there's a "Don't hide" field of that weight, we only
1409  // care about fields of higher weight.
1410  bHiddenParaField = pNode->FieldHidesPara(*rField.GetField());
1411  }
1412  }
1413  }
1414  }
1415  else
1416  {
1417  bHiddenCharsHidePara = static_cast<SwTextNode const*>(SwFrame::GetDep())->HasHiddenCharAttribute( true );
1418  bHiddenParaField = static_cast<SwTextNode const*>(SwFrame::GetDep())->IsHiddenByParaField();
1419  }
1420  const SwViewShell* pVsh = getRootFrame()->GetCurrShell();
1421 
1422  if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
1423  {
1424 
1425  if (
1426  ( bHiddenParaField &&
1427  ( !pVsh->GetViewOptions()->IsShowHiddenPara() &&
1428  !pVsh->GetViewOptions()->IsFieldName() ) ) ||
1429  ( bHiddenCharsHidePara &&
1430  !pVsh->GetViewOptions()->IsShowHiddenChar() ) )
1431  {
1432  return true;
1433  }
1434  }
1435 
1436  return false;
1437 }
1438 
1441 {
1442  OSL_ENSURE( !GetFollow() && IsHiddenNow(),
1443  "HideHidden on visible frame of hidden frame has follow" );
1444 
1447 
1448  // format information is obsolete
1449  ClearPara();
1450 }
1451 
1453 {
1454  SwPageFrame *pPage = nullptr;
1455  sw::MergedAttrIter iter(*this);
1456  SwTextNode const* pNode(nullptr);
1457  for (SwTextAttr const* pHt = iter.NextAttr(&pNode); pHt; pHt = iter.NextAttr(&pNode))
1458  {
1459  if (pHt->Which() == RES_TXTATR_FTN)
1460  {
1461  TextFrameIndex const nIdx(MapModelToView(pNode, pHt->GetStart()));
1462  if (nEnd < nIdx)
1463  break;
1464  if (nStart <= nIdx)
1465  {
1466  if (!pPage)
1467  pPage = FindPageFrame();
1468  pPage->RemoveFootnote( this, static_cast<const SwTextFootnote*>(pHt) );
1469  }
1470  }
1471  }
1472 }
1473 
1483 bool sw_HideObj( const SwTextFrame& _rFrame,
1484  const RndStdIds _eAnchorType,
1485  SwPosition const& rAnchorPos,
1486  SwAnchoredObject* _pAnchoredObj )
1487 {
1488  bool bRet( true );
1489 
1490  if (_eAnchorType == RndStdIds::FLY_AT_CHAR)
1491  {
1492  const IDocumentSettingAccess *const pIDSA = &_rFrame.GetDoc().getIDocumentSettingAccess();
1497  _rFrame.IsInDocBody() && !_rFrame.FindNextCnt() )
1498  {
1499  SwTextNode const& rNode(*rAnchorPos.nNode.GetNode().GetTextNode());
1500  assert(FrameContainsNode(_rFrame, rNode.GetIndex()));
1501  sal_Int32 const nObjAnchorPos(rAnchorPos.nContent.GetIndex());
1502  const sal_Unicode cAnchorChar = nObjAnchorPos < rNode.Len()
1503  ? rNode.GetText()[nObjAnchorPos]
1504  : 0;
1505  if (cAnchorChar == CH_TXTATR_BREAKWORD)
1506  {
1507  const SwTextAttr* const pHint(
1508  rNode.GetTextAttrForCharAt(nObjAnchorPos, RES_TXTATR_FLYCNT));
1509  if ( pHint )
1510  {
1511  const SwFrameFormat* pFrameFormat =
1512  static_cast<const SwTextFlyCnt*>(pHint)->GetFlyCnt().GetFrameFormat();
1513  if ( pFrameFormat->Which() == RES_FLYFRMFMT )
1514  {
1515  SwNodeIndex nContentIndex = *(pFrameFormat->GetContent().GetContentIdx());
1516  ++nContentIndex;
1517  if ( nContentIndex.GetNode().IsNoTextNode() )
1518  {
1519  bRet = false;
1520  // set needed data structure values for object positioning
1521  SwRectFnSet aRectFnSet(&_rFrame);
1522  SwRect aLastCharRect( _rFrame.getFrameArea() );
1523  aRectFnSet.SetWidth( aLastCharRect, 1 );
1524  _pAnchoredObj->maLastCharRect = aLastCharRect;
1525  _pAnchoredObj->mnLastTopOfLine = aRectFnSet.GetTop(aLastCharRect);
1526  }
1527  }
1528  }
1529  }
1530  }
1531  }
1532 
1533  return bRet;
1534 }
1535 
1547 {
1548  if ( GetDrawObjs() )
1549  {
1550  if ( IsHiddenNow() )
1551  {
1552  // complete paragraph is hidden. Thus, hide all objects
1553  for (SwAnchoredObject* i : *GetDrawObjs())
1554  {
1555  SdrObject* pObj = i->DrawObj();
1556  SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
1557  // under certain conditions
1558  const RndStdIds eAnchorType( pContact->GetAnchorId() );
1559  if ((eAnchorType != RndStdIds::FLY_AT_CHAR) ||
1560  sw_HideObj(*this, eAnchorType, pContact->GetContentAnchor(),
1561  i ))
1562  {
1563  pContact->MoveObjToInvisibleLayer( pObj );
1564  }
1565  }
1566  }
1567  else
1568  {
1569  // paragraph is visible, but can contain hidden text portion.
1570  // first we check if objects are allowed to be hidden:
1571  const SwViewShell* pVsh = getRootFrame()->GetCurrShell();
1572  const bool bShouldBeHidden = !pVsh || !pVsh->GetWin() ||
1573  !pVsh->GetViewOptions()->IsShowHiddenChar();
1574 
1575  // Thus, show all objects, which are anchored at paragraph and
1576  // hide/show objects, which are anchored at/as character, according
1577  // to the visibility of the anchor character.
1578  for (SwAnchoredObject* i : *GetDrawObjs())
1579  {
1580  SdrObject* pObj = i->DrawObj();
1581  SwContact* pContact = static_cast<SwContact*>(pObj->GetUserCall());
1582  // Determine anchor type only once
1583  const RndStdIds eAnchorType( pContact->GetAnchorId() );
1584 
1585  if (eAnchorType == RndStdIds::FLY_AT_PARA)
1586  {
1587  pContact->MoveObjToVisibleLayer( pObj );
1588  }
1589  else if ((eAnchorType == RndStdIds::FLY_AT_CHAR) ||
1590  (eAnchorType == RndStdIds::FLY_AS_CHAR))
1591  {
1592  sal_Int32 nHiddenStart;
1593  sal_Int32 nHiddenEnd;
1594  const SwPosition& rAnchor = pContact->GetContentAnchor();
1596  *rAnchor.nNode.GetNode().GetTextNode(),
1597  rAnchor.nContent.GetIndex(), nHiddenStart, nHiddenEnd);
1598  // Under certain conditions
1599  if ( nHiddenStart != COMPLETE_STRING && bShouldBeHidden &&
1600  sw_HideObj(*this, eAnchorType, rAnchor, i))
1601  {
1602  pContact->MoveObjToInvisibleLayer( pObj );
1603  }
1604  else
1605  pContact->MoveObjToVisibleLayer( pObj );
1606  }
1607  else
1608  {
1609  OSL_FAIL( "<SwTextFrame::HideAndShowObjects()> - object not anchored at/inside paragraph!?" );
1610  }
1611  }
1612  }
1613  }
1614 
1615  if (IsFollow())
1616  {
1617  SwTextFrame *pMaster = FindMaster();
1618  OSL_ENSURE(pMaster, "SwTextFrame without master");
1619  if (pMaster)
1620  pMaster->HideAndShowObjects();
1621  }
1622 }
1623 
1630 TextFrameIndex SwTextFrame::FindBrk(const OUString &rText,
1631  const TextFrameIndex nStart,
1632  const TextFrameIndex nEnd)
1633 {
1634  sal_Int32 nFound = sal_Int32(nStart);
1635  const sal_Int32 nEndLine = std::min(sal_Int32(nEnd), rText.getLength() - 1);
1636 
1637  // Skip all leading blanks.
1638  while( nFound <= nEndLine && ' ' == rText[nFound] )
1639  {
1640  nFound++;
1641  }
1642 
1643  // A tricky situation with the TextAttr-Dummy-character (in this case "$"):
1644  // "Dr.$Meyer" at the beginning of the second line. Typing a blank after that
1645  // doesn't result in the word moving into first line, even though that would work.
1646  // For this reason we don't skip the dummy char.
1647  while( nFound <= nEndLine && ' ' != rText[nFound] )
1648  {
1649  nFound++;
1650  }
1651 
1652  return TextFrameIndex(nFound);
1653 }
1654 
1655 bool SwTextFrame::IsIdxInside(TextFrameIndex const nPos, TextFrameIndex const nLen) const
1656 {
1657 // Silence over-eager warning emitted at least by GCC trunk towards 6:
1658 #if defined __GNUC__ && !defined __clang__
1659 #pragma GCC diagnostic push
1660 #pragma GCC diagnostic ignored "-Wstrict-overflow"
1661 #endif
1662  if (nLen != TextFrameIndex(COMPLETE_STRING) && GetOfst() > nPos + nLen) // the range preceded us
1663 #if defined __GNUC__ && !defined __clang__
1664 #pragma GCC diagnostic pop
1665 #endif
1666  return false;
1667 
1668  if( !GetFollow() ) // the range doesn't precede us,
1669  return true; // nobody follows us.
1670 
1671  TextFrameIndex const nMax = GetFollow()->GetOfst();
1672 
1673  // either the range overlap or our text has been deleted
1674  // sw_redlinehide: GetText() should be okay here because it has already
1675  // been updated in the INS/DEL hint case
1676  if (nMax > nPos || nMax > TextFrameIndex(GetText().getLength()))
1677  return true;
1678 
1679  // changes made in the first line of a follow can modify the master
1680  const SwParaPortion* pPara = GetFollow()->GetPara();
1681  return pPara && ( nPos <= nMax + pPara->GetLen() );
1682 }
1683 
1684 inline void SwTextFrame::InvalidateRange(const SwCharRange &aRange, const long nD)
1685 {
1686  if ( IsIdxInside( aRange.Start(), aRange.Len() ) )
1687  InvalidateRange_( aRange, nD );
1688 }
1689 
1690 void SwTextFrame::InvalidateRange_( const SwCharRange &aRange, const long nD)
1691 {
1692  if ( !HasPara() )
1693  { InvalidateSize();
1694  return;
1695  }
1696 
1697  SetWidow( false );
1698  SwParaPortion *pPara = GetPara();
1699 
1700  bool bInv = false;
1701  if( 0 != nD )
1702  {
1703  // In nDelta the differences between old and new
1704  // linelengths are being added, that's why it's negative
1705  // if chars have been added and positive, if chars have
1706  // deleted
1707  pPara->GetDelta() += nD;
1708  bInv = true;
1709  }
1710  SwCharRange &rReformat = pPara->GetReformat();
1711  if(aRange != rReformat) {
1712  if (TextFrameIndex(COMPLETE_STRING) == rReformat.Len())
1713  rReformat = aRange;
1714  else
1715  rReformat += aRange;
1716  bInv = true;
1717  }
1718  if(bInv)
1719  {
1720  InvalidateSize();
1721  }
1722 }
1723 
1725 {
1726  OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
1727  "SwTextFrame::CalcLineSpace with swapped frame!" );
1728 
1729  if( IsLocked() || !HasPara() )
1730  return;
1731 
1732  if( GetDrawObjs() ||
1733  GetTextNodeForParaProps()->GetSwAttrSet().GetLRSpace().IsAutoFirst())
1734  {
1735  Init();
1736  return;
1737  }
1738 
1739  SwParaPortion *const pPara(GetPara());
1740  assert(pPara);
1741  if (pPara->IsFixLineHeight())
1742  {
1743  Init();
1744  return;
1745  }
1746 
1747  Size aNewSize( getFramePrintArea().SSize() );
1748 
1749  SwTextFormatInfo aInf( getRootFrame()->GetCurrShell()->GetOut(), this );
1750  SwTextFormatter aLine( this, &aInf );
1751  if( aLine.GetDropLines() )
1752  {
1753  Init();
1754  return;
1755  }
1756 
1757  aLine.Top();
1758  aLine.RecalcRealHeight();
1759 
1760  aNewSize.setHeight( (aLine.Y() - getFrameArea().Top()) + aLine.GetLineHeight() );
1761 
1762  SwTwips nDelta = aNewSize.Height() - getFramePrintArea().Height();
1763  // Underflow with free-flying frames
1764  if( aInf.GetTextFly().IsOn() )
1765  {
1766  SwRect aTmpFrame( getFrameArea() );
1767  if( nDelta < 0 )
1768  aTmpFrame.Height( getFramePrintArea().Height() );
1769  else
1770  aTmpFrame.Height( aNewSize.Height() );
1771  if( aInf.GetTextFly().Relax( aTmpFrame ) )
1772  {
1773  Init();
1774  return;
1775  }
1776  }
1777 
1778  if( nDelta )
1779  {
1780  SwTextFrameBreak aBreak( this );
1781  if( GetFollow() || aBreak.IsBreakNow( aLine ) )
1782  {
1783  // if there is a Follow() or if we need to break here, reformat
1784  Init();
1785  }
1786  else
1787  {
1788  // everything is business as usual...
1789  pPara->SetPrepAdjust();
1790  pPara->SetPrep();
1791  }
1792  }
1793 }
1794 
1795 static void lcl_SetWrong( SwTextFrame& rFrame, SwTextNode const& rNode,
1796  sal_Int32 const nPos, sal_Int32 const nCnt, bool const bMove)
1797 {
1798  if ( !rFrame.IsFollow() )
1799  {
1800  SwTextNode* pTextNode = const_cast<SwTextNode*>(&rNode);
1801  IGrammarContact* pGrammarContact = getGrammarContact( *pTextNode );
1802  SwGrammarMarkUp* pWrongGrammar = pGrammarContact ?
1803  pGrammarContact->getGrammarCheck( *pTextNode, false ) :
1804  pTextNode->GetGrammarCheck();
1805  bool bGrammarProxy = pWrongGrammar != pTextNode->GetGrammarCheck();
1806  if( bMove )
1807  {
1808  if( pTextNode->GetWrong() )
1809  pTextNode->GetWrong()->Move( nPos, nCnt );
1810  if( pWrongGrammar )
1811  pWrongGrammar->MoveGrammar( nPos, nCnt );
1812  if( bGrammarProxy && pTextNode->GetGrammarCheck() )
1813  pTextNode->GetGrammarCheck()->MoveGrammar( nPos, nCnt );
1814  if( pTextNode->GetSmartTags() )
1815  pTextNode->GetSmartTags()->Move( nPos, nCnt );
1816  }
1817  else
1818  {
1819  if( pTextNode->GetWrong() )
1820  pTextNode->GetWrong()->Invalidate( nPos, nCnt );
1821  if( pWrongGrammar )
1822  pWrongGrammar->Invalidate( nPos, nCnt );
1823  if( pTextNode->GetSmartTags() )
1824  pTextNode->GetSmartTags()->Invalidate( nPos, nCnt );
1825  }
1826  const sal_Int32 nEnd = nPos + (nCnt > 0 ? nCnt : 1 );
1827  if ( !pTextNode->GetWrong() && !pTextNode->IsWrongDirty() )
1828  {
1829  pTextNode->SetWrong( new SwWrongList( WRONGLIST_SPELL ) );
1830  pTextNode->GetWrong()->SetInvalid( nPos, nEnd );
1831  }
1832  if ( !pTextNode->GetSmartTags() && !pTextNode->IsSmartTagDirty() )
1833  {
1834  pTextNode->SetSmartTags( new SwWrongList( WRONGLIST_SMARTTAG ) );
1835  pTextNode->GetSmartTags()->SetInvalid( nPos, nEnd );
1836  }
1838  pTextNode->SetGrammarCheckDirty( true );
1839  pTextNode->SetWordCountDirty( true );
1840  pTextNode->SetAutoCompleteWordDirty( true );
1841  pTextNode->SetSmartTagDirty( true );
1842  }
1843 
1844  SwRootFrame *pRootFrame = rFrame.getRootFrame();
1845  if (pRootFrame)
1846  {
1847  pRootFrame->SetNeedGrammarCheck( true );
1848  }
1849 
1850  SwPageFrame *pPage = rFrame.FindPageFrame();
1851  if( pPage )
1852  {
1853  pPage->InvalidateSpelling();
1854  pPage->InvalidateAutoCompleteWords();
1855  pPage->InvalidateWordCount();
1856  pPage->InvalidateSmartTags();
1857  }
1858 }
1859 
1860 static void lcl_SetScriptInval(SwTextFrame& rFrame, TextFrameIndex const nPos)
1861 {
1862  if( rFrame.GetPara() )
1863  rFrame.GetPara()->GetScriptInfo().SetInvalidityA( nPos );
1864 }
1865 
1866 // note: SwClientNotify will be called once for every frame => just fix own Ofst
1867 static void lcl_ModifyOfst(SwTextFrame & rFrame,
1868  TextFrameIndex const nPos, TextFrameIndex const nLen,
1869  TextFrameIndex (* op)(TextFrameIndex const&, TextFrameIndex const&))
1870 {
1871  assert(nLen != TextFrameIndex(COMPLETE_STRING));
1872  if (rFrame.IsFollow() && nPos < rFrame.GetOfst())
1873  {
1874  rFrame.ManipOfst( std::max(nPos, op(rFrame.GetOfst(), nLen)) );
1875  assert(sal_Int32(rFrame.GetOfst()) <= rFrame.GetText().getLength());
1876  }
1877 }
1878 
1879 namespace {
1880 
1881 void UpdateMergedParaForMove(sw::MergedPara & rMerged,
1882  SwTextFrame & rTextFrame,
1883  bool & o_rbRecalcFootnoteFlag,
1884  SwTextNode const& rDestNode,
1885  SwTextNode const& rNode,
1886  sal_Int32 const nDestStart,
1887  sal_Int32 const nSourceStart,
1888  sal_Int32 const nLen)
1889 {
1890  std::vector<std::pair<sal_Int32, sal_Int32>> deleted;
1891  sal_Int32 const nSourceEnd(nSourceStart + nLen);
1892  sal_Int32 nLastEnd(0);
1893  for (const auto& rExt : rMerged.extents)
1894  {
1895  if (rExt.pNode == &rNode)
1896  {
1897  sal_Int32 const nStart(std::max(nLastEnd, nSourceStart));
1898  sal_Int32 const nEnd(std::min(rExt.nStart, nSourceEnd));
1899  if (nStart < nEnd)
1900  {
1901  deleted.emplace_back(nStart, nEnd);
1902  }
1903  nLastEnd = rExt.nEnd;
1904  if (nSourceEnd <= rExt.nEnd)
1905  {
1906  break;
1907  }
1908  }
1909  else if (rNode.GetIndex() < rExt.pNode->GetIndex())
1910  {
1911  break;
1912  }
1913  }
1914  if (nLastEnd != rNode.Len()) // without nLen, string yet to be removed
1915  {
1916  assert(rNode.Len() == 0 || nLastEnd < nSourceEnd);
1917  if (nLastEnd < nSourceEnd)
1918  {
1919  deleted.emplace_back(std::max(nLastEnd, nSourceStart), nSourceEnd);
1920  }
1921  }
1922  if (!deleted.empty())
1923  {
1924  o_rbRecalcFootnoteFlag = true;
1925  for (auto const& it : deleted)
1926  {
1927  sal_Int32 const nStart(it.first - nSourceStart + nDestStart);
1928  TextFrameIndex const nDeleted = UpdateMergedParaForDelete(rMerged, false,
1929  rDestNode, nStart, it.second - it.first);
1930 //FIXME asserts valid for join - but if called from split, the new node isn't there yet and it will be added later... assert(nDeleted);
1931 // assert(nDeleted == it.second - it.first);
1932  if(nDeleted)
1933  {
1934  // InvalidateRange/lcl_SetScriptInval was called sufficiently for SwInsText
1935  lcl_SetWrong(rTextFrame, rDestNode, nStart, it.first - it.second, false);
1936  TextFrameIndex const nIndex(sw::MapModelToView(rMerged, &rDestNode, nStart));
1937  lcl_ModifyOfst(rTextFrame, nIndex, nDeleted, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>);
1938  }
1939  }
1940  }
1941 }
1942 
1943 } // namespace
1944 
1949 static bool isA11yRelevantAttribute(sal_uInt16 nWhich)
1950 {
1951  return nWhich != RES_CHRATR_RSID;
1952 }
1953 
1954 static bool hasA11yRelevantAttribute( const std::vector<sal_uInt16>& rWhichFmtAttr )
1955 {
1956  for( sal_uInt16 nWhich : rWhichFmtAttr )
1957  if ( isA11yRelevantAttribute( nWhich ) )
1958  return true;
1959 
1960  return false;
1961 }
1962 
1963 // Note: for now this overrides SwClient::SwClientNotify; the intermediary
1964 // classes still override SwClient::Modify, which should continue to work
1965 // as their implementation of SwClientNotify is SwClient's which calls Modify.
1966 // Therefore we also don't need to call SwClient::SwClientNotify(rModify, rHint)
1967 // because that's all it does, and this implementation calls
1968 // SwContentFrame::Modify() when appropriate.
1969 void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
1970 {
1971  SfxPoolItem const* pOld(nullptr);
1972  SfxPoolItem const* pNew(nullptr);
1973  sw::MoveText const* pMoveText(nullptr);
1974  sw::RedlineDelText const* pRedlineDelText(nullptr);
1975  sw::RedlineUnDelText const* pRedlineUnDelText(nullptr);
1976 
1977  if (auto const pHint = dynamic_cast<sw::LegacyModifyHint const*>(&rHint))
1978  {
1979  pOld = pHint->m_pOld;
1980  pNew = pHint->m_pNew;
1981  }
1982  else if (auto const pHt = dynamic_cast<sw::MoveText const*>(&rHint))
1983  {
1984  pMoveText = pHt;
1985  }
1986  else if (auto const pHynt = dynamic_cast<sw::RedlineDelText const*>(&rHint))
1987  {
1988  pRedlineDelText = pHynt;
1989  }
1990  else if (auto const pHnt = dynamic_cast<sw::RedlineUnDelText const*>(&rHint))
1991  {
1992  pRedlineUnDelText = pHnt;
1993  }
1994  else
1995  {
1996  assert(!"unexpected hint");
1997  }
1998 
1999  if (m_pMergedPara)
2000  {
2001  assert(m_pMergedPara->listener.IsListeningTo(&rModify));
2002  }
2003 
2004  SwTextNode const& rNode(static_cast<SwTextNode const&>(rModify));
2005  const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
2006 
2007  // modifications concerning frame attributes are processed by the base class
2008  if( IsInRange( aFrameFormatSetRange, nWhich ) || RES_FMT_CHG == nWhich )
2009  {
2010  if (m_pMergedPara)
2011  { // ignore item set changes that don't apply
2012  SwTextNode const*const pAttrNode(
2013  (nWhich == RES_PAGEDESC || nWhich == RES_BREAK)
2014  ? m_pMergedPara->pFirstNode
2015  : m_pMergedPara->pParaPropsNode);
2016  if (pAttrNode != &rModify)
2017  {
2018  return;
2019  }
2020  }
2021  SwContentFrame::Modify( pOld, pNew );
2022  if( nWhich == RES_FMT_CHG && getRootFrame()->GetCurrShell() )
2023  {
2024  // collection has changed
2025  Prepare();
2026  InvalidatePrt_();
2027  lcl_SetWrong( *this, rNode, 0, COMPLETE_STRING, false );
2028  SetDerivedR2L( false );
2029  CheckDirChange();
2030  // Force complete paint due to existing indents.
2031  SetCompletePaint();
2033  }
2034  return;
2035  }
2036 
2037  if (m_pMergedPara && m_pMergedPara->pParaPropsNode != &rModify)
2038  {
2039  if (isPARATR(nWhich) || isPARATR_LIST(nWhich)) // FRMATR handled above
2040  {
2041  return; // ignore it
2042  }
2043  }
2044 
2045  Broadcast(SfxHint()); // notify SwAccessibleParagraph
2046 
2047  // while locked ignore all modifications
2048  if( IsLocked() )
2049  return;
2050 
2051  // save stack
2052  // warning: one has to ensure that all variables are set
2053  TextFrameIndex nPos;
2054  TextFrameIndex nLen;
2055  bool bSetFieldsDirty = false;
2056  bool bRecalcFootnoteFlag = false;
2057 
2058  if (pRedlineDelText)
2059  {
2060  if (m_pMergedPara)
2061  {
2062  sal_Int32 const nNPos = pRedlineDelText->nStart;
2063  sal_Int32 const nNLen = pRedlineDelText->nLen;
2064  nPos = MapModelToView(&rNode, nNPos);
2065  // update merged before doing anything else
2066  nLen = UpdateMergedParaForDelete(*m_pMergedPara, false, rNode, nNPos, nNLen);
2067  const sal_Int32 m = -nNLen;
2068  if (nLen && IsIdxInside(nPos, nLen))
2069  {
2070  InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), m );
2071  }
2072  lcl_SetWrong( *this, rNode, nNPos, m, false );
2073  if (nLen)
2074  {
2075  lcl_SetScriptInval( *this, nPos );
2076  bSetFieldsDirty = bRecalcFootnoteFlag = true;
2077  lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>);
2078  }
2079  }
2080  }
2081  else if (pRedlineUnDelText)
2082  {
2083  if (m_pMergedPara)
2084  {
2085  sal_Int32 const nNPos = pRedlineUnDelText->nStart;
2086  sal_Int32 const nNLen = pRedlineUnDelText->nLen;
2087  nPos = MapModelToView(&rNode, nNPos);
2088  nLen = UpdateMergedParaForInsert(*m_pMergedPara, false, rNode, nNPos, nNLen);
2089  if (IsIdxInside(nPos, nLen))
2090  {
2091  if (!nLen)
2092  {
2093  // Refresh NumPortions even when line is empty!
2094  if (nPos)
2095  InvalidateSize();
2096  else
2097  Prepare();
2098  }
2099  else
2100  InvalidateRange_( SwCharRange( nPos, nLen ), nNLen );
2101  }
2102  lcl_SetWrong( *this, rNode, nNPos, nNLen, false );
2103  lcl_SetScriptInval( *this, nPos );
2104  bSetFieldsDirty = true;
2105  lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator+<sal_Int32, Tag_TextFrameIndex>);
2106  }
2107  }
2108  else if (pMoveText)
2109  {
2110  if (m_pMergedPara
2111  && m_pMergedPara->pFirstNode->GetIndex() <= pMoveText->pDestNode->GetIndex()
2112  && pMoveText->pDestNode->GetIndex() <= m_pMergedPara->pLastNode->GetIndex())
2113  { // if it's not 2 nodes in merged frame, assume the target node doesn't have frames at all
2114  assert(std::abs(static_cast<long>(rNode.GetIndex()) - static_cast<long>(pMoveText->pDestNode->GetIndex())) == 1);
2115  UpdateMergedParaForMove(*m_pMergedPara,
2116  *this,
2117  bRecalcFootnoteFlag,
2118  *pMoveText->pDestNode, rNode,
2119  pMoveText->nDestStart,
2120  pMoveText->nSourceStart,
2121  pMoveText->nLen);
2122  }
2123  else
2124  {
2125  // there is a situation where this is okay: from JoinNext, which will then call CheckResetRedlineMergeFlag, which will then create merged from scratch for this frame
2126  // assert(!m_pMergedPara || !getRootFrame()->IsHideRedlines() || !pMoveText->pDestNode->getLayoutFrame(getRootFrame()));
2127  }
2128  }
2129  else switch (nWhich)
2130  {
2131  case RES_LINENUMBER:
2132  {
2133  assert(false); // should have been forwarded to SwContentFrame
2135  }
2136  break;
2137  case RES_INS_TXT:
2138  {
2139  sal_Int32 const nNPos = static_cast<const SwInsText*>(pNew)->nPos;
2140  sal_Int32 const nNLen = static_cast<const SwInsText*>(pNew)->nLen;
2141  nPos = MapModelToView(&rNode, nNPos);
2142  nLen = TextFrameIndex(nNLen);
2143  if (m_pMergedPara)
2144  {
2145  UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, nNPos, nNLen);
2146  }
2147  if( IsIdxInside( nPos, nLen ) )
2148  {
2149  if( !nLen )
2150  {
2151  // Refresh NumPortions even when line is empty!
2152  if( nPos )
2153  InvalidateSize();
2154  else
2155  Prepare();
2156  }
2157  else
2158  InvalidateRange_( SwCharRange( nPos, nLen ), nNLen );
2159  }
2160  lcl_SetWrong( *this, rNode, nNPos, nNLen, true );
2161  lcl_SetScriptInval( *this, nPos );
2162  bSetFieldsDirty = true;
2163  lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator+<sal_Int32, Tag_TextFrameIndex>);
2164  }
2165  break;
2166  case RES_DEL_CHR:
2167  {
2168  sal_Int32 const nNPos = static_cast<const SwDelChr*>(pNew)->nPos;
2169  nPos = MapModelToView(&rNode, nNPos);
2170  if (m_pMergedPara)
2171  {
2172  nLen = UpdateMergedParaForDelete(*m_pMergedPara, true, rNode, nNPos, 1);
2173  }
2174  else
2175  {
2176  nLen = TextFrameIndex(1);
2177  }
2178  lcl_SetWrong( *this, rNode, nNPos, -1, true );
2179  if (nLen)
2180  {
2181  InvalidateRange( SwCharRange(nPos, nLen), -1 );
2182  lcl_SetScriptInval( *this, nPos );
2183  bSetFieldsDirty = bRecalcFootnoteFlag = true;
2184  lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>);
2185  }
2186  }
2187  break;
2188  case RES_DEL_TXT:
2189  {
2190  sal_Int32 const nNPos = static_cast<const SwDelText*>(pNew)->nStart;
2191  sal_Int32 const nNLen = static_cast<const SwDelText*>(pNew)->nLen;
2192  nPos = MapModelToView(&rNode, nNPos);
2193  if (m_pMergedPara)
2194  { // update merged before doing anything else
2195  nLen = UpdateMergedParaForDelete(*m_pMergedPara, true, rNode, nNPos, nNLen);
2196  }
2197  else
2198  {
2199  nLen = TextFrameIndex(nNLen);
2200  }
2201  const sal_Int32 m = -nNLen;
2202  if ((!m_pMergedPara || nLen) && IsIdxInside(nPos, nLen))
2203  {
2204  if( !nLen )
2205  InvalidateSize();
2206  else
2207  InvalidateRange( SwCharRange(nPos, TextFrameIndex(1)), m );
2208  }
2209  lcl_SetWrong( *this, rNode, nNPos, m, true );
2210  if (nLen)
2211  {
2212  lcl_SetScriptInval( *this, nPos );
2213  bSetFieldsDirty = bRecalcFootnoteFlag = true;
2214  lcl_ModifyOfst(*this, nPos, nLen, &o3tl::operator-<sal_Int32, Tag_TextFrameIndex>);
2215  }
2216  }
2217  break;
2218  case RES_UPDATE_ATTR:
2219  {
2220  const SwUpdateAttr* pNewUpdate = static_cast<const SwUpdateAttr*>(pNew);
2221 
2222  sal_Int32 const nNPos = pNewUpdate->getStart();
2223  sal_Int32 const nNLen = pNewUpdate->getEnd() - nNPos;
2224  nPos = MapModelToView(&rNode, nNPos);
2225  nLen = MapModelToView(&rNode, nNPos + nNLen) - nPos;
2226  if( IsIdxInside( nPos, nLen ) )
2227  {
2228  // We need to reformat anyways, even if the invalidated
2229  // range is empty.
2230  // E.g.: empty line, set 14 pt!
2231 
2232  // FootnoteNumbers need to be formatted
2233  if( !nLen )
2234  nLen = TextFrameIndex(1);
2235 
2236  InvalidateRange_( SwCharRange( nPos, nLen) );
2237  const sal_uInt16 nTmp = pNewUpdate->getWhichAttr();
2238 
2239  if( ! nTmp || RES_TXTATR_CHARFMT == nTmp || RES_TXTATR_INETFMT == nTmp || RES_TXTATR_AUTOFMT == nTmp ||
2240  RES_FMT_CHG == nTmp || RES_ATTRSET_CHG == nTmp )
2241  {
2242  lcl_SetWrong( *this, rNode, nNPos, nNPos + nNLen, false );
2243  lcl_SetScriptInval( *this, nPos );
2244  }
2245  }
2246 
2247  if( isA11yRelevantAttribute( pNewUpdate->getWhichAttr() ) &&
2248  hasA11yRelevantAttribute( pNewUpdate->getFmtAttrs() ) )
2249  {
2250  SwViewShell* pViewSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
2251  if ( pViewSh )
2252  {
2253  pViewSh->InvalidateAccessibleParaAttrs( *this );
2254  }
2255  }
2256  }
2257  break;
2258  case RES_OBJECTDYING:
2259  break;
2260 
2262  {
2263  CalcLineSpace();
2264  InvalidateSize();
2265  InvalidatePrt_();
2266  if( IsInSct() && !GetPrev() )
2267  {
2268  SwSectionFrame *pSect = FindSctFrame();
2269  if( pSect->ContainsAny() == this )
2270  pSect->InvalidatePrt();
2271  }
2272 
2273  // i#11859
2274  // (1) Also invalidate next frame on next page/column.
2275  // (2) Skip empty sections and hidden paragraphs
2276  // Thus, use method <InvalidateNextPrtArea()>
2278 
2279  SetCompletePaint();
2280  }
2281  break;
2282 
2283  case RES_TXTATR_FIELD:
2284  case RES_TXTATR_ANNOTATION:
2285  {
2286  sal_Int32 const nNPos = static_cast<const SwFormatField*>(pNew)->GetTextField()->GetStart();
2287  nPos = MapModelToView(&rNode, nNPos);
2288  if (IsIdxInside(nPos, TextFrameIndex(1)))
2289  {
2290  if( pNew == pOld )
2291  {
2292  // only repaint
2293  // opt: invalidate window?
2294  InvalidatePage();
2295  SetCompletePaint();
2296  }
2297  else
2299  }
2300  bSetFieldsDirty = true;
2301  // ST2
2302  if ( SwSmartTagMgr::Get().IsSmartTagsEnabled() )
2303  lcl_SetWrong( *this, rNode, nNPos, nNPos + 1, false );
2304  }
2305  break;
2306 
2307  case RES_TXTATR_FTN :
2308  {
2309  if (!IsInFootnote())
2310  { // the hint may be sent from the anchor node, or from a
2311  // node in the footnote; the anchor index is only valid in the
2312  // anchor node!
2313  assert(&rNode == &static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote()->GetTextNode());
2314  nPos = MapModelToView(&rNode,
2315  static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote()->GetStart());
2316  }
2317 #ifdef _MSC_VER
2318  else nPos = TextFrameIndex(42); // shut up MSVC 2017 spurious warning C4701
2319 #endif
2320  if (IsInFootnote() || IsIdxInside(nPos, TextFrameIndex(1)))
2321  Prepare( PREP_FTN, static_cast<const SwFormatFootnote*>(pNew)->GetTextFootnote() );
2322  break;
2323  }
2324 
2325  case RES_ATTRSET_CHG:
2326  {
2328 
2329  const SwAttrSet& rNewSet = *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet();
2330  const SfxPoolItem* pItem = nullptr;
2331  int nClear = 0;
2332  sal_uInt16 nCount = rNewSet.Count();
2333 
2334  if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FTN, false, &pItem ))
2335  {
2336  nPos = MapModelToView(&rNode,
2337  static_cast<const SwFormatFootnote*>(pItem)->GetTextFootnote()->GetStart());
2338  if (IsIdxInside(nPos, TextFrameIndex(1)))
2339  Prepare( PREP_FTN, pNew );
2340  nClear = 0x01;
2341  --nCount;
2342  }
2343 
2344  if( SfxItemState::SET == rNewSet.GetItemState( RES_TXTATR_FIELD, false, &pItem ))
2345  {
2346  nPos = MapModelToView(&rNode,
2347  static_cast<const SwFormatField*>(pItem)->GetTextField()->GetStart());
2348  if (IsIdxInside(nPos, TextFrameIndex(1)))
2349  {
2350  const SfxPoolItem* pOldItem = pOld ?
2351  &(static_cast<const SwAttrSetChg*>(pOld)->GetChgSet()->Get(RES_TXTATR_FIELD)) : nullptr;
2352  if( pItem == pOldItem )
2353  {
2354  InvalidatePage();
2355  SetCompletePaint();
2356  }
2357  else
2359  }
2360  nClear |= 0x02;
2361  --nCount;
2362  }
2363  bool bLineSpace = SfxItemState::SET == rNewSet.GetItemState(
2364  RES_PARATR_LINESPACING, false ),
2365  bRegister = SfxItemState::SET == rNewSet.GetItemState(
2366  RES_PARATR_REGISTER, false );
2367  if ( bLineSpace || bRegister )
2368  {
2369  if (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
2370  {
2371  Prepare( bRegister ? PREP_REGISTER : PREP_ADJUST_FRM );
2372  CalcLineSpace();
2373  InvalidateSize();
2374  InvalidatePrt_();
2375 
2376  // i#11859
2377  // (1) Also invalidate next frame on next page/column.
2378  // (2) Skip empty sections and hidden paragraphs
2379  // Thus, use method <InvalidateNextPrtArea()>
2381 
2382  SetCompletePaint();
2383  }
2384  nClear |= 0x04;
2385  if ( bLineSpace )
2386  {
2387  --nCount;
2388  if ((!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
2389  && IsInSct() && !GetPrev())
2390  {
2391  SwSectionFrame *pSect = FindSctFrame();
2392  if( pSect->ContainsAny() == this )
2393  pSect->InvalidatePrt();
2394  }
2395  }
2396  if ( bRegister )
2397  --nCount;
2398  }
2399  if ( SfxItemState::SET == rNewSet.GetItemState( RES_PARATR_SPLIT,
2400  false ))
2401  {
2402  if (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
2403  {
2404  if (GetPrev())
2405  CheckKeep();
2406  Prepare();
2407  InvalidateSize();
2408  }
2409  nClear |= 0x08;
2410  --nCount;
2411  }
2412 
2413  if( SfxItemState::SET == rNewSet.GetItemState( RES_BACKGROUND, false)
2414  && (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify)
2415  && !IsFollow() && GetDrawObjs() )
2416  {
2417  SwSortedObjs *pObjs = GetDrawObjs();
2418  for ( size_t i = 0; GetDrawObjs() && i < pObjs->size(); ++i )
2419  {
2420  SwAnchoredObject* pAnchoredObj = (*pObjs)[i];
2421  if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr )
2422  {
2423  SwFlyFrame *pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
2424  if( !pFly->IsFlyInContentFrame() )
2425  {
2426  const SvxBrushItem &rBack =
2427  pFly->GetAttrSet()->GetBackground();
2428  // #GetTransChg#
2429  // following condition determines, if the fly frame
2430  // "inherites" the background color of text frame.
2431  // This is the case, if fly frame background
2432  // color is "no fill"/"auto fill" and if the fly frame
2433  // has no background graphic.
2434  // Thus, check complete fly frame background
2435  // color and *not* only its transparency value
2436  if ( (rBack.GetColor() == COL_TRANSPARENT) &&
2437  rBack.GetGraphicPos() == GPOS_NONE )
2438  {
2439  pFly->SetCompletePaint();
2440  pFly->InvalidatePage();
2441  }
2442  }
2443  }
2444  }
2445  }
2446 
2447  if ( SfxItemState::SET ==
2448  rNewSet.GetItemState( RES_TXTATR_CHARFMT, false ) )
2449  {
2450  lcl_SetWrong( *this, rNode, 0, COMPLETE_STRING, false );
2451  lcl_SetScriptInval( *this, TextFrameIndex(0) );
2452  }
2453  else if ( SfxItemState::SET ==
2454  rNewSet.GetItemState( RES_CHRATR_LANGUAGE, false ) ||
2455  SfxItemState::SET ==
2456  rNewSet.GetItemState( RES_CHRATR_CJK_LANGUAGE, false ) ||
2457  SfxItemState::SET ==
2458  rNewSet.GetItemState( RES_CHRATR_CTL_LANGUAGE, false ) )
2459  lcl_SetWrong( *this, rNode, 0, COMPLETE_STRING, false );
2460  else if ( SfxItemState::SET ==
2461  rNewSet.GetItemState( RES_CHRATR_FONT, false ) ||
2462  SfxItemState::SET ==
2463  rNewSet.GetItemState( RES_CHRATR_CJK_FONT, false ) ||
2464  SfxItemState::SET ==
2465  rNewSet.GetItemState( RES_CHRATR_CTL_FONT, false ) )
2466  lcl_SetScriptInval( *this, TextFrameIndex(0) );
2467  else if ( SfxItemState::SET ==
2468  rNewSet.GetItemState( RES_FRAMEDIR, false )
2469  && (!m_pMergedPara || m_pMergedPara->pParaPropsNode == &rModify))
2470  {
2471  SetDerivedR2L( false );
2472  CheckDirChange();
2473  // Force complete paint due to existing indents.
2474  SetCompletePaint();
2475  }
2476 
2477  if( nCount )
2478  {
2479  if( getRootFrame()->GetCurrShell() )
2480  {
2481  Prepare();
2482  InvalidatePrt_();
2483  }
2484 
2485  if (nClear || (m_pMergedPara &&
2486  (m_pMergedPara->pParaPropsNode != &rModify ||
2487  m_pMergedPara->pFirstNode != &rModify)))
2488  {
2489  assert(pOld);
2490  SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) );
2491  SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) );
2492 
2493  if (m_pMergedPara && m_pMergedPara->pParaPropsNode != &rModify)
2494  {
2495  for (sal_uInt16 i = RES_PARATR_BEGIN; i != RES_FRMATR_END; ++i)
2496  {
2497  if (i != RES_BREAK && i != RES_PAGEDESC)
2498  {
2499  aOldSet.ClearItem(i);
2500  aNewSet.ClearItem(i);
2501  }
2502  }
2503  for (sal_uInt16 i = XATTR_FILL_FIRST; i <= XATTR_FILL_LAST; ++i)
2504  {
2505  aOldSet.ClearItem(i);
2506  aNewSet.ClearItem(i);
2507  }
2508  }
2509  if (m_pMergedPara && m_pMergedPara->pFirstNode != &rModify)
2510  {
2511  aOldSet.ClearItem(RES_BREAK);
2512  aNewSet.ClearItem(RES_BREAK);
2513  aOldSet.ClearItem(RES_PAGEDESC);
2514  aNewSet.ClearItem(RES_PAGEDESC);
2515  }
2516 
2517  if( 0x01 & nClear )
2518  {
2519  aOldSet.ClearItem( RES_TXTATR_FTN );
2520  aNewSet.ClearItem( RES_TXTATR_FTN );
2521  }
2522  if( 0x02 & nClear )
2523  {
2524  aOldSet.ClearItem( RES_TXTATR_FIELD );
2525  aNewSet.ClearItem( RES_TXTATR_FIELD );
2526  }
2527  if ( 0x04 & nClear )
2528  {
2529  if ( bLineSpace )
2530  {
2531  aOldSet.ClearItem( RES_PARATR_LINESPACING );
2532  aNewSet.ClearItem( RES_PARATR_LINESPACING );
2533  }
2534  if ( bRegister )
2535  {
2536  aOldSet.ClearItem( RES_PARATR_REGISTER );
2537  aNewSet.ClearItem( RES_PARATR_REGISTER );
2538  }
2539  }
2540  if ( 0x08 & nClear )
2541  {
2542  aOldSet.ClearItem( RES_PARATR_SPLIT );
2543  aNewSet.ClearItem( RES_PARATR_SPLIT );
2544  }
2545  if (aOldSet.Count() || aNewSet.Count())
2546  {
2547  SwContentFrame::Modify( &aOldSet, &aNewSet );
2548  }
2549  }
2550  else
2551  SwContentFrame::Modify( pOld, pNew );
2552  }
2553 
2554  if (isA11yRelevantAttribute(nWhich))
2555  {
2556  SwViewShell* pViewSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
2557  if ( pViewSh )
2558  {
2559  pViewSh->InvalidateAccessibleParaAttrs( *this );
2560  }
2561  }
2562  }
2563  break;
2564 
2565  // Process SwDocPosUpdate
2566  case RES_DOCPOS_UPDATE:
2567  {
2568  if( pOld && pNew )
2569  {
2570  const SwDocPosUpdate *pDocPos = static_cast<const SwDocPosUpdate*>(pOld);
2571  if( pDocPos->nDocPos <= getFrameArea().Top() )
2572  {
2573  const SwFormatField *pField = static_cast<const SwFormatField *>(pNew);
2574  TextFrameIndex const nIndex(MapModelToView(&rNode,
2575  pField->GetTextField()->GetStart()));
2577  }
2578  }
2579  break;
2580  }
2581  case RES_PARATR_SPLIT:
2582  if ( GetPrev() )
2583  CheckKeep();
2584  Prepare();
2585  bSetFieldsDirty = true;
2586  break;
2587  case RES_FRAMEDIR :
2588  assert(false); // should have been forwarded to SwContentFrame
2589  SetDerivedR2L( false );
2590  CheckDirChange();
2591  break;
2592  default:
2593  {
2594  Prepare();
2595  InvalidatePrt_();
2596  if ( !nWhich )
2597  {
2598  // is called by e. g. HiddenPara with 0
2599  SwFrame *pNxt;
2600  if ( nullptr != (pNxt = FindNext()) )
2601  pNxt->InvalidatePrt();
2602  }
2603  }
2604  } // switch
2605 
2606  if( bSetFieldsDirty )
2607  GetDoc().getIDocumentFieldsAccess().SetFieldsDirty( true, &rNode, 1 );
2608 
2609  if ( bRecalcFootnoteFlag )
2610  CalcFootnoteFlag();
2611 }
2612 
2613 bool SwTextFrame::GetInfo( SfxPoolItem &rHint ) const
2614 {
2615  if ( RES_VIRTPAGENUM_INFO == rHint.Which() && IsInDocBody() && ! IsFollow() )
2616  {
2617  SwVirtPageNumInfo &rInfo = static_cast<SwVirtPageNumInfo&>(rHint);
2618  const SwPageFrame *pPage = FindPageFrame();
2619  if ( pPage )
2620  {
2621  if ( pPage == rInfo.GetOrigPage() && !GetPrev() )
2622  {
2623  // this should be the one
2624  // (could only differ temporarily; is that disturbing?)
2625  rInfo.SetInfo( pPage, this );
2626  return false;
2627  }
2628  if ( pPage->GetPhyPageNum() < rInfo.GetOrigPage()->GetPhyPageNum() &&
2629  (!rInfo.GetPage() || pPage->GetPhyPageNum() > rInfo.GetPage()->GetPhyPageNum()))
2630  {
2631  // this could be the one
2632  rInfo.SetInfo( pPage, this );
2633  }
2634  }
2635  }
2636  return true;
2637 }
2638 
2639 void SwTextFrame::PrepWidows( const sal_uInt16 nNeed, bool bNotify )
2640 {
2641  OSL_ENSURE(GetFollow() && nNeed, "+SwTextFrame::Prepare: lost all friends");
2642 
2643  SwParaPortion *pPara = GetPara();
2644  if ( !pPara )
2645  return;
2646  pPara->SetPrepWidows();
2647 
2648  sal_uInt16 nHave = nNeed;
2649 
2650  // We yield a few lines and shrink in CalcPreps()
2651  SwSwapIfNotSwapped swap( this );
2652 
2653  SwTextSizeInfo aInf( this );
2654  SwTextMargin aLine( this, &aInf );
2655  aLine.Bottom();
2656  TextFrameIndex nTmpLen = aLine.GetCurr()->GetLen();
2657  while( nHave && aLine.PrevLine() )
2658  {
2659  if( nTmpLen )
2660  --nHave;
2661  nTmpLen = aLine.GetCurr()->GetLen();
2662  }
2663 
2664  // If it's certain that we can yield lines, the Master needs
2665  // to check the widow rule
2666  if( !nHave )
2667  {
2668  bool bSplit = true;
2669  if( !IsFollow() ) // only a master decides about orphans
2670  {
2671  const WidowsAndOrphans aWidOrp( this );
2672  bSplit = ( aLine.GetLineNr() >= aWidOrp.GetOrphansLines() &&
2673  aLine.GetLineNr() >= aLine.GetDropLines() );
2674  }
2675 
2676  if( bSplit )
2677  {
2678  GetFollow()->SetOfst( aLine.GetEnd() );
2679  aLine.TruncLines( true );
2680  if( pPara->IsFollowField() )
2681  GetFollow()->SetFieldFollow( true );
2682  }
2683  }
2684  if ( bNotify )
2685  {
2686  InvalidateSize_();
2687  InvalidatePage();
2688  }
2689 }
2690 
2691 static bool lcl_ErgoVadis(SwTextFrame* pFrame, TextFrameIndex & rPos, const PrepareHint ePrep)
2692 {
2693  const SwFootnoteInfo &rFootnoteInfo = pFrame->GetDoc().GetFootnoteInfo();
2694  if( ePrep == PREP_ERGOSUM )
2695  {
2696  if( rFootnoteInfo.aErgoSum.isEmpty() )
2697  return false;
2698  rPos = pFrame->GetOfst();
2699  }
2700  else
2701  {
2702  if( rFootnoteInfo.aQuoVadis.isEmpty() )
2703  return false;
2704  if( pFrame->HasFollow() )
2705  rPos = pFrame->GetFollow()->GetOfst();
2706  else
2707  rPos = TextFrameIndex(pFrame->GetText().getLength());
2708  if( rPos )
2709  --rPos; // our last character
2710  }
2711  return true;
2712 }
2713 
2714 // Silence over-eager warning emitted at least by GCC 5.3.1
2715 #if defined __GNUC__ && !defined __clang__
2716 # pragma GCC diagnostic push
2717 # pragma GCC diagnostic ignored "-Wstrict-overflow"
2718 #endif
2719 bool SwTextFrame::Prepare( const PrepareHint ePrep, const void* pVoid,
2720  bool bNotify )
2721 {
2722  bool bParaPossiblyInvalid = false;
2723 
2724  SwFrameSwapper aSwapper( this, false );
2725 
2726  if ( IsEmpty() )
2727  {
2728  switch ( ePrep )
2729  {
2730  case PREP_BOSS_CHGD:
2731  SetInvalidVert( true ); // Test
2732  [[fallthrough]];
2733  case PREP_WIDOWS_ORPHANS:
2734  case PREP_WIDOWS:
2735  case PREP_FTN_GONE : return bParaPossiblyInvalid;
2736 
2737  case PREP_POS_CHGD :
2738  {
2739  // We also need an InvalidateSize for Areas (with and without columns),
2740  // so that we format and bUndersized is set (if needed)
2741  if( IsInFly() || IsInSct() )
2742  {
2743  SwTwips nTmpBottom = GetUpper()->getFrameArea().Top() +
2745  if( nTmpBottom < getFrameArea().Bottom() )
2746  break;
2747  }
2748  // Are there any free-flying frames on this page?
2749  SwTextFly aTextFly( this );
2750  if( aTextFly.IsOn() )
2751  {
2752  // Does any free-flying frame overlap?
2753  if ( aTextFly.Relax() || IsUndersized() )
2754  break;
2755  }
2757  break;
2758 
2759  SwTextGridItem const*const pGrid(GetGridItem(FindPageFrame()));
2760  if (pGrid && GetTextNodeForParaProps()->GetSwAttrSet().GetParaGrid().GetValue())
2761  break;
2762 
2763  // i#28701 - consider anchored objects
2764  if ( GetDrawObjs() )
2765  break;
2766 
2767  return bParaPossiblyInvalid;
2768  }
2769  default:
2770  break;
2771  }
2772  }
2773 
2774  if( !HasPara() && PREP_MUST_FIT != ePrep )
2775  {
2776  SetInvalidVert( true ); // Test
2777  OSL_ENSURE( !IsLocked(), "SwTextFrame::Prepare: three of a perfect pair" );
2778  if ( bNotify )
2779  InvalidateSize();
2780  else
2781  InvalidateSize_();
2782  return bParaPossiblyInvalid;
2783  }
2784 
2785  // Get object from cache while locking
2786  SwTextLineAccess aAccess( this );
2787  SwParaPortion *pPara = aAccess.GetPara();
2788 
2789  switch( ePrep )
2790  {
2791  case PREP_MOVEFTN :
2792  {
2794  aFrm.Height(0);
2795  }
2796 
2797  {
2799  aPrt.Height(0);
2800  }
2801 
2802  InvalidatePrt_();
2803  InvalidateSize_();
2804  [[fallthrough]];
2805  case PREP_ADJUST_FRM :
2806  pPara->SetPrepAdjust();
2807  if( IsFootnoteNumFrame() != pPara->IsFootnoteNum() ||
2808  IsUndersized() )
2809  {
2811  if( GetOfst() && !IsFollow() )
2813  }
2814  break;
2815  case PREP_MUST_FIT :
2816  pPara->SetPrepMustFit(true);
2817  [[fallthrough]];
2818  case PREP_WIDOWS_ORPHANS :
2819  pPara->SetPrepAdjust();
2820  break;
2821  case PREP_WIDOWS :
2822  // MustFit is stronger than anything else
2823  if( pPara->IsPrepMustFit() )
2824  return bParaPossiblyInvalid;
2825  // see comment in WidowsAndOrphans::FindOrphans and CalcPreps()
2826  PrepWidows( *static_cast<const sal_uInt16 *>(pVoid), bNotify );
2827  break;
2828 
2829  case PREP_FTN :
2830  {
2831  SwTextFootnote const *pFootnote = static_cast<SwTextFootnote const *>(pVoid);
2832  if( IsInFootnote() )
2833  {
2834  // Am I the first TextFrame of a footnote?
2835  if( !GetPrev() )
2836  // So we're a TextFrame of the footnote, which has
2837  // to display the footnote number or the ErgoSum text
2839 
2840  if( !GetNext() )
2841  {
2842  // We're the last Footnote; we need to update the
2843  // QuoVadis texts now
2844  const SwFootnoteInfo &rFootnoteInfo = GetDoc().GetFootnoteInfo();
2845  if( !pPara->UpdateQuoVadis( rFootnoteInfo.aQuoVadis ) )
2846  {
2847  TextFrameIndex nPos = pPara->GetParLen();
2848  if( nPos )
2849  --nPos;
2851  }
2852  }
2853  }
2854  else
2855  {
2856  // We are the TextFrame _with_ the footnote
2857  TextFrameIndex const nPos = MapModelToView(
2858  &pFootnote->GetTextNode(), pFootnote->GetStart());
2860  }
2861  break;
2862  }
2863  case PREP_BOSS_CHGD :
2864  {
2865  // Test
2866  {
2867  SetInvalidVert( false );
2868  bool bOld = IsVertical();
2869  SetInvalidVert( true );
2870  if( bOld != IsVertical() )
2872  }
2873 
2874  if( HasFollow() )
2875  {
2876  TextFrameIndex nNxtOfst = GetFollow()->GetOfst();
2877  if( nNxtOfst )
2878  --nNxtOfst;
2879  InvalidateRange(SwCharRange( nNxtOfst, TextFrameIndex(1)), 1);
2880  }
2881  if( IsInFootnote() )
2882  {
2883  TextFrameIndex nPos;
2884  if( lcl_ErgoVadis( this, nPos, PREP_QUOVADIS ) )
2886  if( lcl_ErgoVadis( this, nPos, PREP_ERGOSUM ) )
2888  }
2889  // If we have a page number field, we must invalidate those spots
2890  SwTextNode const* pNode(nullptr);
2891  sw::MergedAttrIter iter(*this);
2892  TextFrameIndex const nEnd = GetFollow()
2894  for (SwTextAttr const* pHt = iter.NextAttr(&pNode); pHt; pHt = iter.NextAttr(&pNode))
2895  {
2896  TextFrameIndex const nStart(MapModelToView(pNode, pHt->GetStart()));
2897  if (nStart >= GetOfst())
2898  {
2899  if (nStart >= nEnd)
2900  break;
2901 
2902  // If we're flowing back and own a Footnote, the Footnote also flows
2903  // with us. So that it doesn't obstruct us, we send ourselves
2904  // an ADJUST_FRM.
2905  // pVoid != 0 means MoveBwd()
2906  const sal_uInt16 nWhich = pHt->Which();
2907  if (RES_TXTATR_FIELD == nWhich ||
2908  (HasFootnote() && pVoid && RES_TXTATR_FTN == nWhich))
2909  InvalidateRange(SwCharRange(nStart, TextFrameIndex(1)), 1);
2910  }
2911  }
2912  // A new boss, a new chance for growing
2913  if( IsUndersized() )
2914  {
2915  InvalidateSize_();
2917  }
2918  break;
2919  }
2920 
2921  case PREP_POS_CHGD :
2922  {
2923  if ( isFramePrintAreaValid() )
2924  {
2925  SwTextGridItem const*const pGrid(GetGridItem(FindPageFrame()));
2926  if (pGrid && GetTextNodeForParaProps()->GetSwAttrSet().GetParaGrid().GetValue())
2927  InvalidatePrt();
2928  }
2929 
2930  // If we don't overlap with anybody:
2931  // did any free-flying frame overlapped _before_ the position change?
2932  bool bFormat = pPara->HasFly();
2933  if( !bFormat )
2934  {
2935  if( IsInFly() )
2936  {
2937  SwTwips nTmpBottom = GetUpper()->getFrameArea().Top() +
2939  if( nTmpBottom < getFrameArea().Bottom() )
2940  bFormat = true;
2941  }
2942  if( !bFormat )
2943  {
2944  if ( GetDrawObjs() )
2945  {
2946  const size_t nCnt = GetDrawObjs()->size();
2947  for ( size_t i = 0; i < nCnt; ++i )
2948  {
2949  SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
2950  // i#28701 - consider all
2951  // to-character anchored objects
2952  if ( pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId()
2953  == RndStdIds::FLY_AT_CHAR )
2954  {
2955  bFormat = true;
2956  break;
2957  }
2958  }
2959  }
2960  if( !bFormat )
2961  {
2962  // Are there any free-flying frames on this page?
2963  SwTextFly aTextFly( this );
2964  if( aTextFly.IsOn() )
2965  {
2966  // Does any free-flying frame overlap?
2967  bFormat = aTextFly.Relax() || IsUndersized();
2968  }
2969  }
2970  }
2971  }
2972 
2973  if( bFormat )
2974  {
2975  if( !IsLocked() )
2976  {
2977  if( pPara->GetRepaint().HasArea() )
2978  SetCompletePaint();
2979  Init();
2980  pPara = nullptr;
2981  InvalidateSize_();
2982  }
2983  }
2984  else
2985  {
2986  if (GetTextNodeForParaProps()->GetSwAttrSet().GetRegister().GetValue())
2987  bParaPossiblyInvalid = Prepare( PREP_REGISTER, nullptr, bNotify );
2988  // The Frames need to be readjusted, which caused by changes
2989  // in position
2990  else if( HasFootnote() )
2991  {
2992  bParaPossiblyInvalid = Prepare( PREP_ADJUST_FRM, nullptr, bNotify );
2993  InvalidateSize_();
2994  }
2995  else
2996  return bParaPossiblyInvalid; // So that there's no SetPrep()
2997 
2998  if (bParaPossiblyInvalid)
2999  {
3000  // It's possible that pPara was deleted above; retrieve it again
3001  pPara = aAccess.GetPara();
3002  }
3003 
3004  }
3005  break;
3006  }
3007  case PREP_REGISTER:
3008  if (GetTextNodeForParaProps()->GetSwAttrSet().GetRegister().GetValue())
3009  {
3010  pPara->SetPrepAdjust();
3011  CalcLineSpace();
3012 
3013  // It's possible that pPara was deleted above; retrieve it again
3014  bParaPossiblyInvalid = true;
3015  pPara = aAccess.GetPara();
3016 
3017  InvalidateSize();
3018  InvalidatePrt_();
3019  SwFrame* pNxt;
3020  if ( nullptr != ( pNxt = GetIndNext() ) )
3021  {
3022  pNxt->InvalidatePrt_();
3023  if ( pNxt->IsLayoutFrame() )
3024  pNxt->InvalidatePage();
3025  }
3026  SetCompletePaint();
3027  }
3028  break;
3029  case PREP_FTN_GONE :
3030  {
3031  // If a Follow is calling us, because a footnote is being deleted, our last
3032  // line has to be formatted, so that the first line of the Follow can flow up.
3033  // Which had flowed to the next page to be together with the footnote (this is
3034  // especially true for areas with columns)
3035  OSL_ENSURE( GetFollow(), "PREP_FTN_GONE may only be called by Follow" );
3036  TextFrameIndex nPos = GetFollow()->GetOfst();
3037  if( IsFollow() && GetOfst() == nPos ) // If we don't have a mass of text, we call our
3038  FindMaster()->Prepare( PREP_FTN_GONE ); // Master's Prepare
3039  if( nPos )
3040  --nPos; // The char preceding our Follow
3042  return bParaPossiblyInvalid;
3043  }
3044  case PREP_ERGOSUM:
3045  case PREP_QUOVADIS:
3046  {
3047  TextFrameIndex nPos;
3048  if( lcl_ErgoVadis( this, nPos, ePrep ) )
3050  }
3051  break;
3052  case PREP_FLY_ATTR_CHG:
3053  {
3054  if( pVoid )
3055  {
3056  TextFrameIndex const nWhere = CalcFlyPos( static_cast<SwFrameFormat const *>(pVoid) );
3057  OSL_ENSURE( TextFrameIndex(COMPLETE_STRING) != nWhere, "Prepare: Why me?" );
3059  return bParaPossiblyInvalid;
3060  }
3061  [[fallthrough]]; // else: continue with default case block
3062  }
3063  case PREP_CLEAR:
3064  default:
3065  {
3066  if( IsLocked() )
3067  {
3068  if( PREP_FLY_ARRIVE == ePrep || PREP_FLY_LEAVE == ePrep )
3069  {
3070  TextFrameIndex const nLen = (GetFollow()
3071  ? GetFollow()->GetOfst()
3073  - GetOfst();
3074  InvalidateRange( SwCharRange( GetOfst(), nLen ) );
3075  }
3076  }
3077  else
3078  {
3079  if( pPara->GetRepaint().HasArea() )
3080  SetCompletePaint();
3081  Init();
3082  pPara = nullptr;
3083  if( GetOfst() && !IsFollow() )
3084  SetOfst_( TextFrameIndex(0) );
3085  if ( bNotify )
3086  InvalidateSize();
3087  else
3088  InvalidateSize_();
3089  }
3090  return bParaPossiblyInvalid; // no SetPrep() happened
3091  }
3092  }
3093  if( pPara )
3094  {
3095  pPara->SetPrep();
3096  }
3097 
3098  return bParaPossiblyInvalid;
3099 }
3100 #if defined __GNUC__ && !defined __clang__
3101 # pragma GCC diagnostic pop
3102 #endif
3103 
3113 {
3117 public:
3118  SwTestFormat( SwTextFrame* pTextFrame, const SwFrame* pPrv, SwTwips nMaxHeight );
3119  ~SwTestFormat();
3120 };
3121 
3122 SwTestFormat::SwTestFormat( SwTextFrame* pTextFrame, const SwFrame* pPre, SwTwips nMaxHeight )
3123  : pFrame( pTextFrame )
3124 {
3127 
3128  SwRectFnSet aRectFnSet(pFrame);
3129  SwTwips nLower = aRectFnSet.GetBottomMargin(*pFrame);
3130 
3131  {
3132  // indeed, here the GetUpper()->getFramePrintArea() gets copied and manipulated
3135  aFrm += pFrame->GetUpper()->getFrameArea().Pos();
3136  aRectFnSet.SetHeight( aFrm, nMaxHeight );
3137 
3138  if( pFrame->GetPrev() )
3139  {
3140  aRectFnSet.SetPosY(
3141  aFrm,
3142  aRectFnSet.GetBottom(pFrame->GetPrev()->getFrameArea()) - ( aRectFnSet.IsVert() ? nMaxHeight + 1 : 0 ) );
3143  }
3144  }
3145 
3147  const SwBorderAttrs &rAttrs = *aAccess.Get();
3148 
3149  {
3151  aRectFnSet.SetPosX(aPrt, rAttrs.CalcLeft( pFrame ) );
3152  }
3153 
3154  if( pPre )
3155  {
3156  SwTwips nUpper = pFrame->CalcUpperSpace( &rAttrs, pPre );
3158  aRectFnSet.SetPosY(aPrt, nUpper );
3159  }
3160 
3161  {
3163  aRectFnSet.SetHeight( aPrt, std::max( 0L , aRectFnSet.GetHeight(pFrame->getFrameArea()) - aRectFnSet.GetTop(aPrt) - nLower ) );
3164  aRectFnSet.SetWidth( aPrt, aRectFnSet.GetWidth(pFrame->getFrameArea()) - ( rAttrs.CalcLeft( pFrame ) + rAttrs.CalcRight( pFrame ) ) );
3165  }
3166 
3167  pOldPara = pFrame->HasPara() ? pFrame->GetPara() : nullptr;
3168  pFrame->SetPara( new SwParaPortion(), false );
3169  OSL_ENSURE( ! pFrame->IsSwapped(), "A frame is swapped before Format_" );
3170 
3171  if ( pFrame->IsVertical() )
3173 
3174  SwTextFormatInfo aInf( pFrame->getRootFrame()->GetCurrShell()->GetOut(), pFrame, false, true, true );
3175  SwTextFormatter aLine( pFrame, &aInf );
3176 
3177  pFrame->Format_( aLine, aInf );
3178 
3179  if ( pFrame->IsVertical() )
3181 
3182  OSL_ENSURE( ! pFrame->IsSwapped(), "A frame is swapped after Format_" );
3183 }
3184 
3186 {
3187  {
3189  aFrm.setSwRect(aOldFrame);
3190  }
3191 
3192  {
3194  aPrt.setSwRect(aOldPrt);
3195  }
3196 
3197  pFrame->SetPara( pOldPara );
3198 }
3199 
3200 bool SwTextFrame::TestFormat( const SwFrame* pPrv, SwTwips &rMaxHeight, bool &bSplit )
3201 {
3203 
3204  if( IsLocked() && GetUpper()->getFramePrintArea().Width() <= 0 )
3205  return false;
3206 
3207  SwTestFormat aSave( this, pPrv, rMaxHeight );
3208 
3209  return SwTextFrame::WouldFit( rMaxHeight, bSplit, true );
3210 }
3211 
3224 bool SwTextFrame::WouldFit( SwTwips &rMaxHeight, bool &bSplit, bool bTst )
3225 {
3226  OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
3227  "SwTextFrame::WouldFit with swapped frame" );
3228  SwRectFnSet aRectFnSet(this);
3229 
3230  if( IsLocked() )
3231  return false;
3232 
3233  // it can happen that the IdleCollector removed the cached information
3234  if( !IsEmpty() )
3235  GetFormatted();
3236 
3237  // i#27801 - correction: 'short cut' for empty paragraph
3238  // can *not* be applied, if test format is in progress. The test format doesn't
3239  // adjust the frame and the printing area - see method <SwTextFrame::Format_(..)>,
3240  // which is called in <SwTextFrame::TestFormat(..)>
3241  if ( IsEmpty() && !bTst )
3242  {
3243  bSplit = false;
3244  SwTwips nHeight = aRectFnSet.IsVert() ? getFramePrintArea().SSize().Width() : getFramePrintArea().SSize().Height();
3245  if( rMaxHeight < nHeight )
3246  return false;
3247  else
3248  {
3249  rMaxHeight -= nHeight;
3250  return true;
3251  }
3252  }
3253 
3254  // GetPara can still be 0 in edge cases
3255  // We return true in order to be reformatted on the new Page
3256  OSL_ENSURE( HasPara() || IsHiddenNow(), "WouldFit: GetFormatted() and then !HasPara()" );
3257  if( !HasPara() || ( !aRectFnSet.GetHeight(getFrameArea()) && IsHiddenNow() ) )
3258  return true;
3259 
3260  // Because the Orphan flag only exists for a short moment, we also check
3261  // whether the Framesize is set to very huge by CalcPreps, in order to
3262  // force a MoveFwd
3263  if( IsWidow() || ( aRectFnSet.IsVert() ?
3264  ( 0 == getFrameArea().Left() ) :
3265  ( LONG_MAX - 20000 < getFrameArea().Bottom() ) ) )
3266  {
3267  SetWidow(false);
3268  if ( GetFollow() )
3269  {
3270  // If we've ended up here due to a Widow request by our Follow, we check
3271  // whether there's a Follow with a real height at all.
3272  // Else (e.g. for newly created SctFrames) we ignore the IsWidow() and
3273  // still check if we can find enough room
3274  if( ( ( ! aRectFnSet.IsVert() && LONG_MAX - 20000 >= getFrameArea().Bottom() ) ||
3275  ( aRectFnSet.IsVert() && 0 < getFrameArea().Left() ) ) &&
3276  ( GetFollow()->IsVertical() ?
3277  !GetFollow()->getFrameArea().Width() :
3278  !GetFollow()->getFrameArea().Height() ) )
3279  {
3280  SwTextFrame* pFoll = GetFollow()->GetFollow();
3281  while( pFoll &&
3282  ( pFoll->IsVertical() ?
3283  !pFoll->getFrameArea().Width() :
3284  !pFoll->getFrameArea().Height() ) )
3285  pFoll = pFoll->GetFollow();
3286  if( pFoll )
3287  return false;
3288  }
3289  else
3290  return false;
3291  }
3292  }
3293 
3294  SwSwapIfNotSwapped swap( this );
3295 
3296  SwTextSizeInfo aInf( this );
3297  SwTextMargin aLine( this, &aInf );
3298 
3299  WidowsAndOrphans aFrameBreak( this, rMaxHeight, bSplit );
3300 
3301  bool bRet = true;
3302 
3303  aLine.Bottom();
3304  // is breaking necessary?
3305  bSplit = !aFrameBreak.IsInside( aLine );
3306  if ( bSplit )
3307  bRet = !aFrameBreak.IsKeepAlways() && aFrameBreak.WouldFit( aLine, rMaxHeight, bTst );
3308  else
3309  {
3310  // we need the total height including the current line
3311  aLine.Top();
3312  do
3313  {
3314  rMaxHeight -= aLine.GetLineHeight();
3315  } while ( aLine.Next() );
3316  }
3317 
3318  return bRet;
3319 }
3320 
3321 sal_uInt16 SwTextFrame::GetParHeight() const
3322 {
3323  OSL_ENSURE( ! IsVertical() || ! IsSwapped(),
3324  "SwTextFrame::GetParHeight with swapped frame" );
3325 
3326  if( !HasPara() )
3327  { // For non-empty paragraphs this is a special case
3328  // For UnderSized we can simply just ask 1 Twip more
3329  sal_uInt16 nRet = static_cast<sal_uInt16>(getFramePrintArea().SSize().Height());
3330  if( IsUndersized() )
3331  {
3332  if( IsEmpty() || GetText().isEmpty() )
3333  nRet = static_cast<sal_uInt16>(EmptyHeight());
3334  else
3335  ++nRet;
3336  }
3337  return nRet;
3338  }
3339 
3340  // TODO: Refactor and improve code
3341  const SwLineLayout* pLineLayout = GetPara();
3342  sal_uInt16 nHeight = pLineLayout ? pLineLayout->GetRealHeight() : 0;
3343 
3344  // Is this paragraph scrolled? Our height until now is at least
3345  // one line height too low then
3346  if( GetOfst() && !IsFollow() )
3347  nHeight *= 2;
3348 
3349  while ( pLineLayout && pLineLayout->GetNext() )
3350  {
3351  pLineLayout = pLineLayout->GetNext();
3352  nHeight = nHeight + pLineLayout->GetRealHeight();
3353  }
3354 
3355  return nHeight;
3356 }
3357 
3361 SwTextFrame* SwTextFrame::GetFormatted( bool bForceQuickFormat )
3362 {
3363  vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
3364  SwSwapIfSwapped swap( this );
3365 
3366  // In case the SwLineLayout was cleared out of the s_pTextCache, recreate it
3367  // Not for empty paragraphs
3368  if( !HasPara() && !(isFrameAreaDefinitionValid() && IsEmpty()) )
3369  {
3370  // Calc() must be called, because frame position can be wrong
3371  const bool bFormat = isFrameAreaSizeValid();
3372  Calc(pRenderContext); // calls Format() if invalid
3373 
3374  // If the flags were valid (hence bFormat=true), Calc did nothing,
3375  // so Format() must be called manually in order to recreate
3376  // the SwLineLayout that has been deleted from the
3377  // SwTextFrame::s_pTextCache (hence !HasPara() above).
3378  // Optimization with FormatQuick()
3379  if( bFormat && !FormatQuick( bForceQuickFormat ) )
3380  Format(getRootFrame()->GetCurrShell()->GetOut());
3381  }
3382 
3383  return this;
3384 }
3385 
3387 {
3388  // i#31490
3389  // If we are currently locked, we better return with a
3390  // fairly reasonable value:
3391  if ( IsLocked() )
3392  return getFramePrintArea().Width();
3393 
3394  SwParaPortion* pOldPara = GetPara();
3395  SwParaPortion *pDummy = new SwParaPortion();
3396  SetPara( pDummy, false );
3397  const SwPageFrame* pPage = FindPageFrame();
3398 
3399  const Point aOldFramePos = getFrameArea().Pos();
3400  const SwTwips nOldFrameWidth = getFrameArea().Width();
3401  const SwTwips nOldPrtWidth = getFramePrintArea().Width();
3402  const SwTwips nPageWidth = GetUpper()->IsVertical() ?
3403  pPage->getFramePrintArea().Height() :
3404  pPage->getFramePrintArea().Width();
3405 
3406  {
3408  aFrm.Width( nPageWidth );
3409  }
3410 
3411  {
3413  aPrt.Width( nPageWidth );
3414  }
3415 
3416  // i#25422 objects anchored as character in RTL
3417  if ( IsRightToLeft() )
3418  {
3420  aFrm.Pos().AdjustX(nOldFrameWidth - nPageWidth );
3421  }
3422 
3423  TextFrameLockGuard aLock( this );
3424 
3425  SwTextFormatInfo aInf( getRootFrame()->GetCurrShell()->GetOut(), this, false, true, true );
3426  aInf.SetIgnoreFly( true );
3427  SwTextFormatter aLine( this, &aInf );
3428  SwHookOut aHook( aInf );
3429 
3430  // i#54031 - assure minimum of MINLAY twips.
3431  const SwTwips nMax = std::max( SwTwips(MINLAY), aLine.CalcFitToContent_() + 1 );
3432 
3433  {
3435  aFrm.Width( nOldFrameWidth );
3436 
3437  // i#25422 objects anchored as character in RTL
3438  if ( IsRightToLeft() )
3439  {
3440  aFrm.Pos() = aOldFramePos;
3441  }
3442  }
3443 
3444  {
3446  aPrt.Width( nOldPrtWidth );
3447  }
3448 
3449  SetPara( pOldPara );
3450 
3451  return nMax;
3452 }
3453 
3461 {
3462  if ( IsLocked() )
3463  return;
3464 
3465  // reset additional first line offset
3467 
3468  const SwTextNode* pTextNode( GetTextNodeForParaProps() );
3469  // sw_redlinehide: check that pParaPropsNode is the correct one
3470  assert(pTextNode->IsNumbered(getRootFrame()) == pTextNode->IsNumbered(nullptr));
3471  if (pTextNode->IsNumbered(getRootFrame()) &&
3472  pTextNode->IsCountedInList() && pTextNode->GetNumRule())
3473  {
3474  int nListLevel = pTextNode->GetActualListLevel();
3475 
3476  if (nListLevel < 0)
3477  nListLevel = 0;
3478 
3479  if (nListLevel >= MAXLEVEL)
3480  nListLevel = MAXLEVEL - 1;
3481 
3482  const SwNumFormat& rNumFormat =
3483  pTextNode->GetNumRule()->Get( static_cast<sal_uInt16>(nListLevel) );
3485  {
3486  // keep current paragraph portion and apply dummy paragraph portion
3487  SwParaPortion* pOldPara = GetPara();
3488  SwParaPortion *pDummy = new SwParaPortion();
3489  SetPara( pDummy, false );
3490 
3491  // lock paragraph
3492  TextFrameLockGuard aLock( this );
3493 
3494  // simulate text formatting
3495  SwTextFormatInfo aInf( getRootFrame()->GetCurrShell()->GetOut(), this, false, true, true );
3496  aInf.SetIgnoreFly( true );
3497  SwTextFormatter aLine( this, &aInf );
3498  SwHookOut aHook( aInf );
3499  aLine.CalcFitToContent_();
3500 
3501  // determine additional first line offset
3502  const SwLinePortion* pFirstPortion = aLine.GetCurr()->GetFirstPortion();
3503  if ( pFirstPortion->InNumberGrp() && !pFirstPortion->IsFootnoteNumPortion() )
3504  {
3505  SwTwips nNumberPortionWidth( pFirstPortion->Width() );
3506 
3507  const SwLinePortion* pPortion = pFirstPortion->GetNextPortion();
3508  while ( pPortion &&
3509  pPortion->InNumberGrp() && !pPortion->IsFootnoteNumPortion())
3510  {
3511  nNumberPortionWidth += pPortion->Width();
3512  pPortion = pPortion->GetNextPortion();
3513  }
3514 
3515  if ( ( IsRightToLeft() &&
3516  rNumFormat.GetNumAdjust() == SvxAdjust::Left ) ||
3517  ( !IsRightToLeft() &&
3518  rNumFormat.GetNumAdjust() == SvxAdjust::Right ) )
3519  {
3520  mnAdditionalFirstLineOffset = -nNumberPortionWidth;
3521  }
3522  else if ( rNumFormat.GetNumAdjust() == SvxAdjust::Center )
3523  {
3524  mnAdditionalFirstLineOffset = -(nNumberPortionWidth/2);
3525  }
3526  }
3527 
3528  // restore paragraph portion
3529  SetPara( pOldPara );
3530  }
3531  }
3532 }
3533 
3546 void SwTextFrame::CalcHeightOfLastLine( const bool _bUseFont )
3547 {
3548  // i#71281
3549  // Invalidate printing area, if height of last line changes
3550  const SwTwips nOldHeightOfLastLine( mnHeightOfLastLine );
3551 
3552  // determine output device
3553  SwViewShell* pVsh = getRootFrame()->GetCurrShell();
3554  OSL_ENSURE( pVsh, "<SwTextFrame::_GetHeightOfLastLineForPropLineSpacing()> - no SwViewShell" );
3555 
3556  // i#78921
3557  // There could be no <SwViewShell> instance in the case of loading a binary
3558  // StarOffice file format containing an embedded Writer document.
3559  if ( !pVsh )
3560  {
3561  return;
3562  }
3563  OutputDevice* pOut = pVsh->GetOut();
3564  const IDocumentSettingAccess *const pIDSA = &GetDoc().getIDocumentSettingAccess();
3565  if ( !pVsh->GetViewOptions()->getBrowseMode() ||
3566  pVsh->GetViewOptions()->IsPrtFormat() )
3567  {
3569  }
3570  OSL_ENSURE( pOut, "<SwTextFrame::_GetHeightOfLastLineForPropLineSpacing()> - no OutputDevice" );
3571 
3572  if ( !pOut )
3573  {
3574  return;
3575  }
3576 
3577  // determine height of last line
3578  if ( _bUseFont || pIDSA->get(DocumentSettingId::OLD_LINE_SPACING ) )
3579  {
3580  // former determination of last line height for proportional line
3581  // spacing - take height of font set at the paragraph
3582  // FIXME actually... must the font match across all nodes?
3583  SwFont aFont( &GetTextNodeForParaProps()->GetSwAttrSet(), pIDSA );
3584 
3585  // we must ensure that the font is restored correctly on the OutputDevice
3586  // otherwise Last!=Owner could occur
3587  if ( pLastFont )
3588  {
3589  SwFntObj *pOldFont = pLastFont;
3590  pLastFont = nullptr;
3591  aFont.SetFntChg( true );
3592  aFont.ChgPhysFnt( pVsh, *pOut );
3593  mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
3594  assert(pLastFont && "coverity[var_deref_model] - pLastFont should be set in SwSubFont::ChgFnt");
3595  pLastFont->Unlock();
3596  pLastFont = pOldFont;
3597  pLastFont->SetDevFont( pVsh, *pOut );
3598  }
3599  else
3600  {
3601  vcl::Font aOldFont = pOut->GetFont();
3602  aFont.SetFntChg( true );
3603  aFont.ChgPhysFnt( pVsh, *pOut );
3604  mnHeightOfLastLine = aFont.GetHeight( pVsh, *pOut );
3605  assert(pLastFont && "coverity[var_deref_model] - pLastFont should be set in SwSubFont::ChgFnt");
3606  pLastFont->Unlock();
3607  pLastFont = nullptr;
3608  pOut->SetFont( aOldFont );
3609  }
3610  }
3611  else
3612  {
3613  // new determination of last line height - take actually height of last line
3614  // i#89000
3615  // assure same results, if paragraph is undersized
3616  if ( IsUndersized() )
3617  {
3618  mnHeightOfLastLine = 0;
3619  }
3620  else
3621  {
3622  bool bCalcHeightOfLastLine = true;
3623  if ( ( !HasPara() && IsEmpty( ) ) || GetText().isEmpty() )
3624  {
3626  bCalcHeightOfLastLine = false;
3627  }
3628 
3629  if ( bCalcHeightOfLastLine )
3630  {
3631  OSL_ENSURE( HasPara(),
3632  "<SwTextFrame::CalcHeightOfLastLine()> - missing paragraph portions." );
3633  const SwLineLayout* pLineLayout = GetPara();
3634  while ( pLineLayout && pLineLayout->GetNext() )
3635  {
3636  // iteration to last line
3637  pLineLayout = pLineLayout->GetNext();
3638  }
3639  if ( pLineLayout )
3640  {
3641  SwTwips nAscent, nDescent, nDummy1, nDummy2;
3642  // i#47162 - suppress consideration of
3643  // fly content portions and the line portion.
3644  pLineLayout->MaxAscentDescent( nAscent, nDescent,
3645  nDummy1, nDummy2,
3646  nullptr, true );
3647  // i#71281
3648  // Suppress wrong invalidation of printing area, if method is
3649  // called recursive.
3650  // Thus, member <mnHeightOfLastLine> is only set directly, if
3651  // no recursive call is needed.
3652  const SwTwips nNewHeightOfLastLine = nAscent + nDescent;
3653  // i#47162 - if last line only contains
3654  // fly content portions, <mnHeightOfLastLine> is zero.
3655  // In this case determine height of last line by the font
3656  if ( nNewHeightOfLastLine == 0 )
3657  {
3658  CalcHeightOfLastLine( true );
3659  }
3660  else
3661  {
3662  mnHeightOfLastLine = nNewHeightOfLastLine;
3663  }
3664  }
3665  }
3666  }
3667  }
3668  // i#71281
3669  // invalidate printing area, if height of last line changes
3670  if ( mnHeightOfLastLine != nOldHeightOfLastLine )
3671  {
3672  InvalidatePrt();
3673  }
3674 }
3675 
3685 long SwTextFrame::GetLineSpace( const bool _bNoPropLineSpace ) const
3686 {
3687  long nRet = 0;
3688 
3690 
3691  switch( rSpace.GetInterLineSpaceRule() )
3692  {
3693  case SvxInterLineSpaceRule::Prop:
3694  {
3695  if ( _bNoPropLineSpace )
3696  {
3697  break;
3698  }
3699 
3700  // i#11860 - adjust spacing implementation for object positioning
3701  // - compatibility to MS Word
3702  nRet = GetHeightOfLastLine();
3703 
3704  long nTmp = nRet;
3705  nTmp *= rSpace.GetPropLineSpace();
3706  nTmp /= 100;
3707  nTmp -= nRet;
3708  if ( nTmp > 0 )
3709  nRet = nTmp;
3710  else
3711  nRet = 0;
3712  }
3713  break;
3714  case SvxInterLineSpaceRule::Fix:
3715  {
3716  if ( rSpace.GetInterLineSpace() > 0 )
3717  nRet = rSpace.GetInterLineSpace();
3718  }
3719  break;
3720  default:
3721  break;
3722  }
3723  return nRet;
3724 }
3725 
3727 {
3728  if ( !HasPara() )
3729  {
3730  if( IsEmpty() && isFrameAreaDefinitionValid() )
3731  return IsVertical() ? static_cast<sal_uInt16>(getFramePrintArea().Width()) : static_cast<sal_uInt16>(getFramePrintArea().Height());
3732  return USHRT_MAX;
3733  }
3734  const SwParaPortion *pPara = GetPara();
3735  if ( !pPara )
3736  return USHRT_MAX;
3737 
3738  return pPara->Height();
3739 }
3740 
3742 {
3743  sal_uInt16 nRet = 0;
3744  SwTextFrame *pFrame = this;
3745  do
3746  {
3747  pFrame->GetFormatted();
3748  if( !pFrame->HasPara() )
3749  break;
3750  SwTextSizeInfo aInf( pFrame );
3751  SwTextMargin aLine( pFrame, &aInf );
3752  if (TextFrameIndex(COMPLETE_STRING) == nPos)
3753  aLine.Bottom();
3754  else
3755  aLine.CharToLine( nPos );
3756  nRet = nRet + aLine.GetLineNr();
3757  pFrame = pFrame->GetFollow();
3758  } while ( pFrame && pFrame->GetOfst() <= nPos );
3759  return nRet;
3760 }
3761 
3763 {
3764  // not necessary to format here (GetFormatted etc.), because we have to come from there!
3765  sal_uLong nNew = 0;
3766  const SwLineNumberInfo &rInf = GetDoc().GetLineNumberInfo();
3767  if ( !GetText().isEmpty() && HasPara() )
3768  {
3769  SwTextSizeInfo aInf( this );
3770  SwTextMargin aLine( this, &aInf );
3771  if ( rInf.IsCountBlankLines() )
3772  {
3773  aLine.Bottom();
3774  nNew = static_cast<sal_uLong>(aLine.GetLineNr());
3775  }
3776  else
3777  {
3778  do
3779  {
3780  if( aLine.GetCurr()->HasContent() )
3781  ++nNew;
3782  } while ( aLine.NextLine() );
3783  }
3784  }
3785  else if ( rInf.IsCountBlankLines() )
3786  nNew = 1;
3787 
3788  if ( nNew != mnThisLines )
3789  {
3791  {
3793  mnThisLines = nNew;
3795  SwFrame *pNxt = GetNextContentFrame();
3796  while( pNxt && pNxt->IsInTab() )
3797  {
3798  if( nullptr != (pNxt = pNxt->FindTabFrame()) )
3799  pNxt = pNxt->FindNextCnt();
3800  }
3801  if( pNxt )
3802  pNxt->InvalidateLineNum();
3803 
3804  // Extend repaint to the bottom.
3805  if ( HasPara() )
3806  {
3807  SwRepaint& rRepaint = GetPara()->GetRepaint();
3808  rRepaint.Bottom( std::max( rRepaint.Bottom(),
3810  }
3811  }
3812  else // Paragraphs which are not counted should not manipulate the AllLines.
3813  mnThisLines = nNew;
3814  }
3815 }
3816 
3818 {
3819  ValidateLineNum();
3820 
3821  if ( !IsInTab() )
3822  {
3823  const sal_uLong nOld = GetAllLines();
3825  sal_uLong nNewNum;
3826  const bool bRestart = GetDoc().GetLineNumberInfo().IsRestartEachPage();
3827 
3828  if ( !IsFollow() && rLineNum.GetStartValue() && rLineNum.IsCount() )
3829  nNewNum = rLineNum.GetStartValue() - 1;
3830  // If it is a follow or not has not be considered if it is a restart at each page; the
3831  // restart should also take effect at follows.
3832  else if ( bRestart && FindPageFrame()->FindFirstBodyContent() == this )
3833  {
3834  nNewNum = 0;
3835  }
3836  else
3837  {
3839  while ( pPrv &&
3840  (pPrv->IsInTab() || pPrv->IsInDocBody() != IsInDocBody()) )
3841  pPrv = pPrv->GetPrevContentFrame();
3842 
3843  // i#78254 Restart line numbering at page change
3844  // First body content may be in table!
3845  if ( bRestart && pPrv && pPrv->FindPageFrame() != FindPageFrame() )
3846  pPrv = nullptr;
3847 
3848  nNewNum = pPrv ? static_cast<SwTextFrame*>(pPrv)->GetAllLines() : 0;
3849  }
3850  if ( rLineNum.IsCount() )
3851  nNewNum += GetThisLines();
3852 
3853  if ( nOld != nNewNum )
3854  {
3855  mnAllLines = nNewNum;
3857  while ( pNxt &&
3858  (pNxt->IsInTab() || pNxt->IsInDocBody() != IsInDocBody()) )
3859  pNxt = pNxt->GetNextContentFrame();
3860  if ( pNxt )
3861  {
3862  if ( pNxt->GetUpper() != GetUpper() )
3863  pNxt->InvalidateLineNum();
3864  else
3865  pNxt->InvalidateLineNum_();
3866  }
3867  }
3868  }
3869 }
3870 
3872 {
3873  const SwParaPortion* pPara = isFrameAreaDefinitionValid() ? GetPara() : nullptr;
3874 
3875  if (pPara)
3876  {
3877  if ( IsFollow() )
3878  rPH.Skip( GetOfst() );
3879 
3880  const SwLineLayout* pLine = pPara;
3881  while ( pLine )
3882  {
3883  const SwLinePortion* pPor = pLine->GetFirstPortion();
3884  while ( pPor )
3885  {
3886  pPor->HandlePortion( rPH );
3887  pPor = pPor->GetNextPortion();
3888  }
3889 
3890  rPH.LineBreak(pLine->Width());
3891  pLine = pLine->GetNext();
3892  }
3893  }
3894 
3895  rPH.Finish();
3896 }
3897 
3899 {
3900  const SwParaPortion* pPara = GetPara();
3901  return pPara ? &pPara->GetScriptInfo() : nullptr;
3902 }
3903 
3907 static SwTwips lcl_CalcFlyBasePos( const SwTextFrame& rFrame, SwRect aFlyRect,
3908  SwTextFly const & rTextFly )
3909 {
3910  SwRectFnSet aRectFnSet(&rFrame);
3911  SwTwips nRet = rFrame.IsRightToLeft() ?
3912  aRectFnSet.GetRight(rFrame.getFrameArea()) :
3913  aRectFnSet.GetLeft(rFrame.getFrameArea());
3914 
3915  do
3916  {
3917  SwRect aRect = rTextFly.GetFrame( aFlyRect );
3918  if ( 0 != aRectFnSet.GetWidth(aRect) )
3919  {
3920  if ( rFrame.IsRightToLeft() )
3921  {
3922  if ( aRectFnSet.GetRight(aRect) -
3923  aRectFnSet.GetRight(aFlyRect) >= 0 )
3924  {
3925  aRectFnSet.SetRight(
3926 aFlyRect, aRectFnSet.GetLeft(aRect) );
3927  nRet = aRectFnSet.GetLeft(aRect);
3928  }
3929  else
3930  break;
3931  }
3932  else
3933  {
3934  if ( aRectFnSet.GetLeft(aFlyRect) -
3935  aRectFnSet.GetLeft(aRect) >= 0 )
3936  {
3937  aRectFnSet.SetLeft(
3938 aFlyRect, aRectFnSet.GetRight(aRect) + 1 );
3939  nRet = aRectFnSet.GetRight(aRect);
3940  }
3941  else
3942  break;
3943  }
3944  }
3945  else
3946  break;
3947  }
3948  while ( aRectFnSet.GetWidth(aFlyRect) > 0 );
3949 
3950  return nRet;
3951 }
3952 
3954 {
3955  OSL_ENSURE( !IsVertical() || !IsSwapped(),
3956  "SwTextFrame::CalcBasePosForFly with swapped frame!" );
3957 
3958  if (!GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_FLY_OFFSETS))
3959  return;
3960 
3961  SwRectFnSet aRectFnSet(this);
3962 
3963  SwRect aFlyRect( getFrameArea().Pos() + getFramePrintArea().Pos(), getFramePrintArea().SSize() );
3964 
3965  // Get first 'real' line and adjust position and height of line rectangle.
3966  // Correct behaviour if no 'real' line exists
3967  // (empty paragraph with and without a dummy portion)
3968  SwTwips nFlyAnchorVertOfstNoWrap = 0;
3969  {
3970  SwTwips nTop = aRectFnSet.GetTop(aFlyRect);
3971  const SwLineLayout* pLay = GetPara();
3972  SwTwips nLineHeight = 200;
3973  while( pLay && pLay->IsDummy() && pLay->GetNext() )
3974  {
3975  nTop += pLay->Height();
3976  nFlyAnchorVertOfstNoWrap += pLay->Height();
3977  pLay = pLay->GetNext();
3978  }
3979  if ( pLay )
3980  {
3981  nLineHeight = pLay->Height();
3982  }
3983  aRectFnSet.SetTopAndHeight( aFlyRect, nTop, nLineHeight );
3984  }
3985 
3986  SwTextFly aTextFly( this );
3987  aTextFly.SetIgnoreCurrentFrame( true );
3988  aTextFly.SetIgnoreContour( true );
3989  // ignore objects in page header|footer for
3990  // text frames not in page header|footer
3991  aTextFly.SetIgnoreObjsInHeaderFooter( true );
3992  SwTwips nRet1 = lcl_CalcFlyBasePos( *this, aFlyRect, aTextFly );
3993  aTextFly.SetIgnoreCurrentFrame( false );
3994  SwTwips nRet2 = lcl_CalcFlyBasePos( *this, aFlyRect, aTextFly );
3995 
3996  // make values relative to frame start position
3997  SwTwips nLeft = IsRightToLeft() ?
3998  aRectFnSet.GetRight(getFrameArea()) :
3999  aRectFnSet.GetLeft(getFrameArea());
4000 
4001  mnFlyAnchorOfst = nRet1 - nLeft;
4002  mnFlyAnchorOfstNoWrap = nRet2 - nLeft;
4003 
4004  if (!GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS))
4005  return;
4006 
4007  if (mnFlyAnchorOfstNoWrap > 0)
4008  mnFlyAnchorVertOfstNoWrap = nFlyAnchorVertOfstNoWrap;
4009 }
4010 
4011 SwTwips SwTextFrame::GetBaseVertOffsetForFly(bool bIgnoreFlysAnchoredAtThisFrame) const
4012 {
4013  return bIgnoreFlysAnchoredAtThisFrame ? 0 : mnFlyAnchorVertOfstNoWrap;
4014 }
4015 
4020 {
4022  for( const SwTextFrame *pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
4023  {
4024  SwRect aRec( pFrame->GetPaintArea() );
4025  const SwRootFrame *pRootFrame = pFrame->getRootFrame();
4026  SwViewShell *pCurShell = pRootFrame ? pRootFrame->GetCurrShell() : nullptr;
4027  if( pCurShell )
4028  pCurShell->InvalidateWindows( aRec );
4029  }
4030 }
4031 
4032 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void HideHidden()
Removes Textfrm's attachments, when it's hidden.
Definition: txtfrm.cxx:1440
void SetWordCountDirty(bool bNew) const
Definition: txtedt.cxx:2222
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:341
bool GetValue() const
sal_uInt16 GetParHeight() const
Returns the sum of line height in pLine.
Definition: txtfrm.cxx:3321
SwFntObj * pLastFont
Definition: fntcache.cxx:70
void CalcAdditionalFirstLineOffset()
Simulate format for a list item paragraph, whose list level attributes are in LABEL_ALIGNMENT mode...
Definition: txtfrm.cxx:3460
void Init()
This is public, as it needs to be called by some methods in order to save the Prepare USE WITH CAUTIO...
Definition: txtfrm.cxx:760
bool HasContent() const
Definition: porlay.hxx:123
Base class for the following contact objects (frame + draw objects).
Definition: dcontact.hxx:66
Base class of the Writer layout elements.
Definition: frame.hxx:295
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
void SwitchVerticalToHorizontal(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from vertical to horizontal layout...
Definition: txtfrm.cxx:590
bool IsFootnoteNum() const
Definition: porlay.hxx:298
void SetTopAndHeight(SwRect &rRect, long nTop, long nHeight) const
Definition: frame.hxx:1404
SwTwips GetBaseVertOffsetForFly(bool bIgnoreFlysAnchoredAtThisFrame) const
Definition: txtfrm.cxx:4011
sal_uLong GetIndex() const
Definition: node.hxx:282
void Add(SwClient *pDepend)
Definition: calbck.cxx:217
bool IsFollow() const
Definition: flowfrm.hxx:166
sal_Int32 const nStart
Definition: hints.hxx:115
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:543
sal_uInt16 GetPropLineSpace() const
void SetIgnoreCurrentFrame(bool bNew)
Definition: txtfly.hxx:361
SwTwips EmptyHeight() const
Definition: porrst.cxx:207
sal_uInt16 GetLineNr() const
Definition: itrtxt.hxx:87
LanguageType const nOldLanguageType
Definition: txtfrm.hxx:942
Marks a position in the document model.
Definition: pam.hxx:35
SwTextNode const & GetAttrMerged(SfxItemSet &rFormatSet, SwTextNode const &rNode, SwRootFrame const *pLayout)
Definition: txtfrm.cxx:379
void SetPrepAdjust()
Definition: porlay.hxx:290
#define RES_CHRATR_CJK_LANGUAGE
Definition: hintids.hxx:93
SwContentFrame * GetNextContentFrame() const
Definition: cntfrm.hxx:98
const SwField * GetField() const
Definition: fmtfld.hxx:70
static SwTwips lcl_CalcFlyBasePos(const SwTextFrame &rFrame, SwRect aFlyRect, SwTextFly const &rTextFly)
Helper function for SwTextFrame::CalcBasePosForFly()
Definition: txtfrm.cxx:3907
SwContentNode * GetNode(SwPaM &rPam, bool &rbFirst, SwMoveFnCollection const &fnMove, bool const bInReadOnly, SwRootFrame const *const i_pLayout)
This function returns the next node in direction of search.
Definition: pam.cxx:758
bool IsInDocBody() const
Definition: frame.hxx:919
const SwPageFrame * GetOrigPage() const
Definition: hints.hxx:272
bool IsInFly() const
Definition: frame.hxx:937
sal_Int32 nSourceStart
Definition: hints.hxx:105
#define LANGUAGE_ARABIC_SAUDI_ARABIA
SwRect aOldPrt
Definition: txtfrm.cxx:3116
bool IsInSct() const
Definition: frame.hxx:943
LanguageType GetLangOfChar(TextFrameIndex nIndex, sal_uInt16 nScript, bool bNoChar=false) const
Definition: txtfrm.cxx:1340
SwDigitModeModifier(const OutputDevice &rOutp, LanguageType eCurLang)
Definition: txtfrm.cxx:734
const OutputDevice & rOut
Definition: txtfrm.hxx:941
#define RES_ATTRSET_CHG
Definition: hintids.hxx:287
const SwLineNumberInfo & GetLineNumberInfo() const
Definition: lineinfo.cxx:49
sal_uInt16 Height() const
Definition: possiz.hxx:44
#define RES_CHRATR_LANGUAGE
Definition: hintids.hxx:79
#define LANGUAGE_ENGLISH_US
SwLineLayout * GetNext()
Definition: porlay.hxx:143
const OUString & GetText() const
Definition: ndtxt.hxx:210
bool IsSwapped() const
Definition: txtfrm.hxx:524
const SvxBrushItem & GetBackground(bool=true) const
Definition: frmatr.hxx:58
#define RES_INS_TXT
Definition: hintids.hxx:288
bool IsWrongDirty() const
Definition: txtedt.cxx:2248
const SwLineLayout * NextLine()
Definition: itrtxt.cxx:125
bool InNumberGrp() const
Definition: porlin.hxx:102
bool FieldHidesPara(const SwField &rField) const
Definition: ndtxt.hxx:715
long & GetDelta()
Definition: porlay.hxx:268
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:218
std::string GetValue
bool HasPara() const
Definition: txtfrm.hxx:808
IDocumentDeviceAccess const & getIDocumentDeviceAccess() const
Definition: doc.cxx:237
void CalcBaseOfstForFly()
Definition: txtfrm.cxx:3953
void InvalidateAccessibleParaAttrs(const SwTextFrame &rTextFrame)
invalidate attributes for paragraphs and paragraph's characters
Definition: viewsh.cxx:2453
void Move(sal_Int32 nPos, sal_Int32 nDiff)
Change all values after the given position.
Definition: wrong.cxx:266
#define RES_DEL_CHR
Definition: hintids.hxx:289
long Height() const
SwNodeIndex nNode
Definition: pam.hxx:37
GPOS_NONE
virtual SwGrammarMarkUp * getGrammarCheck(SwTextNode &rTextNode, bool bCreate)=0
getGrammarCheck checks if the given text node is blocked by the current cursor if not...
void SetCompletePaint() const
Definition: frame.hxx:970
SwParaPortion * GetPara()
Definition: txtcache.cxx:49
bool IsInFootnote() const
Definition: frame.hxx:925
SwModify * GetDep()
use these so we can grep for SwFrame's GetRegisteredIn accesses beware that SwTextFrame may return sw...
Definition: frame.hxx:457
void SwitchHorizontalToVertical(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from horizontal to vertical layout...
Definition: txtfrm.cxx:483
void InvalidateRange_(const SwCharRange &, const long=0)
Definition: txtfrm.cxx:1690
static void repaintTextFrames(const SwTextNode &rNode)
Repaint all text frames of the given text node.
Definition: txtfrm.cxx:4019
void SetNeedGrammarCheck(bool bVal)
Definition: rootfrm.hxx:260
void setSwRect(const SwRect &rNew)
Definition: frame.hxx:194
void SetDerivedR2L(bool bNew)
Definition: frame.hxx:610
SwTwips CalcFitToContent()
Simulates a formatting as if there were not right margin or Flys or other obstacles and returns the w...
Definition: txtfrm.cxx:3386
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:284
sal_uIntPtr sal_uLong
#define RES_FRAMEDIR
Definition: hintids.hxx:227
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
virtual bool GetInfo(SfxPoolItem &) const override
Definition: txtfrm.cxx:2613
void InvalidateLineNum_()
Definition: frame.hxx:773
The SwPortionHandler interface implements a visitor for the layout engine's text portions.
#define MINLAY
Definition: swtypes.hxx:66
void SetInvalidityA(const TextFrameIndex nPos)
Definition: scriptinfo.hxx:108
SwRect aOldFrame
Definition: txtfrm.cxx:3116
SwTextFrame(SwTextNode *const, SwFrame *, sw::FrameMode eMode)
Definition: txtfrm.cxx:774
static SwCache & GetCache()
Definition: frame.hxx:500
long GetLineSpace(const bool _bNoPropLineSpacing=false) const
Returns the additional line spacing for the next paragraph.
Definition: txtfrm.cxx:3685
SwTextNode const * GetTextNodeForFirstText() const
Definition: txtfrm.cxx:1314
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:438
The purpose of this class is to be the universal interface between formatting/text output and the pos...
Definition: txtfly.hxx:119
void SetPosX(SwRect &rRect, long nNew) const
Definition: frame.hxx:1376
#define RES_FRMATR_END
Definition: hintids.hxx:238
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1147
void InvalidateSize_()
Definition: frame.hxx:749
Definition: doc.hxx:185
TElementType * Next()
Definition: calbck.hxx:373
bool HasFollow() const
Definition: flowfrm.hxx:165
SwParaPortion * GetPara()
Definition: txtcache.cxx:89
void Height(long nNew)
Definition: swrect.hxx:189
SwTextAttr const * PrevAttr(SwTextNode const **ppNode=nullptr)
Definition: txtfrm.cxx:234
void SetIgnoreFly(const bool bNew)
Definition: inftxt.hxx:576
long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1354
TextFrameIndex GetOfst() const
Definition: txtfrm.hxx:426
#define RES_CHRATR_FONT
Definition: hintids.hxx:76
SwNode & GetNode() const
Definition: ndindex.hxx:119
long SwTwips
Definition: swtypes.hxx:49
void CharToLine(TextFrameIndex)
Definition: itrtxt.cxx:194
#define RES_PARATR_REGISTER
Definition: hintids.hxx:170
void Format_(vcl::RenderContext *pRenderContext, SwParaPortion *pPara)
Definition: frmform.cxx:1687
bool IsVert() const
Definition: frame.hxx:1343
sal_Int32 nStart
Definition: hints.hxx:125
const SwLineLayout * Next()
Definition: itrtxt.cxx:109
bool IsSmartTagDirty() const
Definition: txtedt.cxx:2274
void HideAndShowObjects()
Hides respectively shows objects, which are anchored at paragraph, at/as a character of the paragraph...
Definition: txtfrm.cxx:1546
void Pos(const Point &rNew)
Definition: swrect.hxx:167
bool WouldFit(SwTextMargin &rLine, SwTwips &rMaxHeight, bool bTest)
Definition: widorp.cxx:478
Dialog to specify the properties of date form field.
SwFrame * FindNext()
Definition: frame.hxx:1117
#define RES_CHRATR_CJK_FONT
Definition: hintids.hxx:91
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1787
void MaxAscentDescent(SwTwips &_orAscent, SwTwips &_orDescent, SwTwips &_orObjAscent, SwTwips &_orObjDescent, const SwLinePortion *_pDontConsiderPortion=nullptr, const bool _bNoFlyCntPorAndLinePor=false) const
determine ascent and descent for positioning of as-character anchored object
Definition: porlay.cxx:609
bool IsKeepAlways() const
Definition: widorp.hxx:38
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
#define RES_TXTATR_CHARFMT
Definition: hintids.hxx:143
long CalcRight(const SwFrame *pCaller) const
Definition: frmtool.cxx:2107
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1290
#define RES_PARATR_SPLIT
Definition: hintids.hxx:164
bool IsShowHiddenPara() const
Definition: viewopt.hxx:358
bool IsCountBlankLines() const
Definition: lineinfo.hxx:83
void SetSmartTags(SwWrongList *pNew, bool bDelete=true)
Definition: txtedt.cxx:2197
SwTwips Y() const
Definition: itrtxt.hxx:90
#define RES_DOCPOS_UPDATE
Definition: hintids.hxx:293
void SetGrammarCheckDirty(bool bNew) const
Definition: txtedt.cxx:2253
The root element of a Writer document layout.
Definition: rootfrm.hxx:79
SwTextNode * pNode
Definition: txtfrm.hxx:85
Collection of SwLineLayout instances, represents the paragraph text in Writer layout.
Definition: porlay.hxx:229
sal_uInt16 GetOrphansLines() const
Definition: widorp.hxx:61
void SetPara(SwParaPortion *pNew, bool bDelete=true)
Definition: txtcache.cxx:128
const SwTwips nDocPos
Definition: hints.hxx:186
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4097
void ValidateLineNum()
Definition: frame.hxx:738
bool TestFormat(const SwFrame *pPrv, SwTwips &nMaxHeight, bool &bSplit)
The WouldFit equivalent for temporarily rewired TextFrames nMaxHeight returns the required size here ...
Definition: txtfrm.cxx:3200
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:167
TextFrameIndex & Start()
Definition: porlay.hxx:45
SwTextAttr const * NextAttr(SwTextNode const **ppNode=nullptr)
Definition: txtfrm.cxx:97
void CalcFootnoteFlag(TextFrameIndex nStop=TextFrameIndex(COMPLETE_STRING))
Does the Frame have a local footnote (in this Frame or Follow)?
Definition: txtftn.cxx:90
void SetPosY(SwRect &rRect, long nNew) const
Definition: frame.hxx:1377
void CheckDirChange()
checks the layout direction and invalidates the lower frames recursively, if necessary.
Definition: ssfrm.cxx:190
bool IsVertLRBT() const
Definition: frame.hxx:959
virtual void Finish()=0
end of paragraph.
bool FormatQuick(bool bForceQuickFormat)
Definition: frmform.cxx:1962
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:190
bool IsHiddenNow() const
Hidden.
Definition: txtfrm.cxx:1357
void CalcLineSpace()
Definition: txtfrm.cxx:1724
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:356
long CalcLeft(const SwFrame *pCaller) const
Definition: frmtool.cxx:2155
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:43
sal_Int32 nDestStart
Definition: hints.hxx:104
SwRect GetFrame(const SwRect &rPortion) const
Definition: txtfly.hxx:356
#define RES_UPDATE_ATTR
Definition: hintids.hxx:291
const SwRegisterItem & GetRegister(bool=true) const
Definition: paratr.hxx:184
bool IsFieldName() const
Definition: viewopt.hxx:252
SwTwips CalcUpperSpace(const SwBorderAttrs *pAttrs=nullptr, const SwFrame *pPr=nullptr, const bool _bConsiderGrid=true) const
method to determine the upper space hold by the frame
Definition: flowfrm.cxx:1391
IGrammarContact * getGrammarContact(const SwTextNode &rTextNode)
getGrammarContact() delivers the grammar contact of the document (for a given textnode) ...
Definition: docnew.cxx:774
sal_uInt16 sal_Unicode
constexpr::Color COL_TRANSPARENT(0xFF, 0xFF, 0xFF, 0xFF)
void InvalidateNextPrtArea()
method to invalidate printing area of next frame #i11859#
Definition: findfrm.cxx:1279
wrapper class for the positioning of Writer fly frames and drawing objects
std::vector< std::pair< SwTextNode const *, SwTextAttr const * > > m_Hints
Definition: txtfrm.hxx:1007
bool IsRestartEachPage() const
Definition: lineinfo.hxx:89
sal_uLong mnAllLines
Definition: txtfrm.hxx:166
sal_Int32 getEnd() const
Definition: hints.hxx:150
const SwScriptInfo * GetScriptInfo() const
Returns the script info stored at the paraportion.
Definition: txtfrm.cxx:3898
SvxGraphicPosition GetGraphicPos() const
void RemoveFromListRLHidden()
Definition: ndtxt.cxx:4332
void SortIfNeedBe() const
Trigger the sorting if necessary.
Definition: ndhints.hxx:176
const SwPageFrame * GetPage() const
Definition: hints.hxx:271
void Top(const long nTop)
Definition: swrect.hxx:202
new delete redline is created
Definition: hints.hxx:112
#define XATTR_FILL_LAST
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:175
void setX(long nX)
const SwTextField * GetTextField() const
Definition: fmtfld.hxx:88
bool getBrowseMode() const
Definition: viewopt.hxx:433
#define XATTR_FILL_FIRST
const vcl::Font & GetFont() const
sal_uLong GetThisLines() const
Definition: txtfrm.hxx:657
bool IsInTab() const
Definition: frame.hxx:931
std::unique_ptr< sw::MergedPara > CheckParaRedlineMerge(SwTextFrame &rFrame, SwTextNode &rTextNode, FrameMode eMode)
Definition: redlnitr.cxx:54
void ResetBlinkPor() const
Definition: txtfrm.hxx:873
void SetInfo(const SwPageFrame *pPg, const SwFrame *pF)
Definition: hints.hxx:274
sal_Int32 nEnd
Definition: txtfrm.hxx:87
static bool IsFuzzing()
SwTestFormat(SwTextFrame *pTextFrame, const SwFrame *pPrv, SwTwips nMaxHeight)
Definition: txtfrm.cxx:3122
long GetBottomMargin(const SwFrame &rFrame) const
Definition: frame.hxx:1380
bool IsTextFrame() const
Definition: frame.hxx:1210
sal_uInt16 GetCacheIdx() const
Definition: txtfrm.hxx:602
sal_Int32 GetStart() const
Definition: txatbase.hxx:82
void SetFntChg(const bool bNew)
Definition: swfont.hxx:208
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
TextFrameIndex UpdateMergedParaForDelete(MergedPara &rMerged, bool isRealDelete, SwTextNode const &rNode, sal_Int32 nIndex, sal_Int32 nLen)
Definition: txtfrm.cxx:1031
void InitScriptInfo(const SwTextNode &rNode, sw::MergedPara const *pMerged, bool bRTL)
Definition: porlay.cxx:743
bool HasFly() const
Definition: porlay.hxx:281
const SwTextFrame * pFrame
Definition: txtfrm.hxx:921
const OutputDevice & m_rOut
Definition: txtfrm.hxx:930
virtual bool SetFieldsDirty(bool b, const SwNode *pChk, sal_uLong nLen)=0
bool IsInRange(const sal_uInt16 *pRange, const sal_uInt16 nId)
check if ID is in range of attribute set IDs
Definition: swatrset.cxx:458
sal_uLong mnThisLines
Definition: txtfrm.hxx:167
virtual ~SwTextFrame() override
Definition: txtfrm.cxx:896
virtual void LineBreak(sal_Int32 nWidth)=0
line break.
sal_uLong GetStartValue() const
Definition: fmtline.hxx:57
Describes parts of multiple text nodes, which will form a text frame, even when redlines are hidden a...
Definition: txtfrm.hxx:954
#define RES_PARATR_BEGIN
Definition: hintids.hxx:161
SwContentFrame * GetPrevContentFrame() const
Definition: cntfrm.hxx:106
long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1355
long GetRight(const SwRect &rRect) const
Definition: frame.hxx:1356
void Right(const long nRight)
Definition: swrect.hxx:198
void ChgPhysFnt(SwViewShell const *pSh, OutputDevice &rOut)
Definition: swfont.cxx:972
void setY(long nY)
void SetWrongDirty(WrongState eNew) const
Definition: txtedt.cxx:2235
bool IsFlyInContentFrame() const
Definition: flyfrm.hxx:193
size_type size() const
sal_Int32 getStart() const
Definition: hints.hxx:145
void SetOfst_(TextFrameIndex nNewOfst)
Definition: frmform.cxx:763
virtual void MoveObjToVisibleLayer(SdrObject *_pDrawObj)
method to move drawing object to corresponding visible layer
Definition: dcontact.cxx:207
virtual bool Prepare(const PrepareHint ePrep=PREP_CLEAR, const void *pVoid=nullptr, bool bNotify=true) override
SwContentFrame: the shortcut for the Frames If the void* casts wrongly, it's its own fault! The void*...
Definition: txtfrm.cxx:2719
static void lcl_ModifyOfst(SwTextFrame &rFrame, TextFrameIndex const nPos, TextFrameIndex const nLen, TextFrameIndex(*op)(TextFrameIndex const &, TextFrameIndex const &))
Definition: txtfrm.cxx:1867
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:844
const SwAttrSet * GetAttrSet() const
WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for SwTextFrame, use GetBreakItem()/GetPageDescItem() instead.
Definition: findfrm.cxx:674
FrameMode
Definition: txtfrm.hxx:102
void SetIgnoreObjsInHeaderFooter(const bool bNew)
Definition: txtfly.hxx:371
std::vector< Extent > extents
Definition: txtfrm.hxx:957
bool IsFollowField() const
Definition: porlay.hxx:293
static bool isA11yRelevantAttribute(sal_uInt16 nWhich)
Related: fdo#56031 filter out attribute changes that don't matter for humans/a11y to stop flooding th...
Definition: txtfrm.cxx:1949
#define RES_BACKGROUND
Definition: hintids.hxx:212
void MoveGrammar(sal_Int32 nPos, sal_Int32 nDiff)
void PrepWidows(const sal_uInt16 nNeed, bool bNotify)
Definition: txtfrm.cxx:2639
const Color & GetColor() const
#define RES_FLYFRMFMT
Definition: hintids.hxx:276
void SetHeight(SwRect &rRect, long nNew) const
Definition: frame.hxx:1367
bool IsEmpty() const
Definition: txtfrm.hxx:509
void ResetPreps()
Definition: txtfrm.cxx:1348
Describes a part of a single text node, which will be part of a text frame, even when redlines are hi...
Definition: txtfrm.hxx:83
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:445
void SetInvalidVert(bool bNew)
Definition: frame.hxx:608
bool FrameContainsNode(SwContentFrame const &rFrame, sal_uLong nNodeIndex)
Definition: txtfrm.cxx:296
bool IsInDtor() const
Definition: frame.hxx:868
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1300
void InvalidateAutoCompleteWords() const
Definition: pagefrm.hxx:376
SwTwips mnFlyAnchorOfst
Definition: txtfrm.hxx:171
delete redline is removed
Definition: hints.hxx:122
void SetIgnoreContour(bool bNew)
Definition: txtfly.hxx:366
SwTextFootnote * SeekEntry(const SwNodeIndex &rIdx, size_t *pPos=nullptr) const
Definition: ftnidx.cxx:409
bool IsFootnoteNumPortion() const
Definition: porlin.hxx:119
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
Style of a layout element.
Definition: frmfmt.hxx:57
bool IsWidow() const
Definition: txtfrm.hxx:507
SwTwips CalcFitToContent_()
Definition: itrform2.cxx:1916
PrepareHint
Definition: swtypes.hxx:204
void Bottom()
Definition: itrtxt.cxx:186
void SetWidth(SwRect &rRect, long nNew) const
Definition: frame.hxx:1366
TextFrameIndex MapModelToViewPos(SwPosition const &rPos) const
Definition: txtfrm.cxx:1266
#define SW_MOD()
Definition: swmodule.hxx:256
void InvalidateLineNum()
Definition: frame.hxx:1026
bool IsDummy() const
Definition: porlay.hxx:135
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void InvalidatePrt()
Definition: frame.hxx:1012
void InvalidateSpelling() const
Definition: pagefrm.hxx:367
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
#define RES_CHRATR_CTL_FONT
Definition: hintids.hxx:96
void SetSmartTagDirty(bool bNew) const
Definition: txtedt.cxx:2266
ComplexTextLayoutFlags const m_nOldLayoutMode
Definition: txtfrm.hxx:931
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:78
#define RES_DEL_TXT
Definition: hintids.hxx:290
bool IsInside(SwTextMargin const &rLine) const
BP 18.6.93: Widows.
Definition: widorp.cxx:104
void Top()
Definition: itrtxt.hxx:99
SwFrame * GetIndNext()
Definition: frame.hxx:705
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
static SwSmartTagMgr & Get()
#define RES_TXTATR_FTN
Definition: hintids.hxx:153
size_t size() const
Definition: sortedobjs.cxx:42
SwTextFly & GetTextFly()
Definition: inftxt.hxx:390
ComplexTextLayoutFlags
SwPageFrame * FindPageFrame()
Definition: frame.hxx:658
sal_uLong GetAllLines() const
For displaying the line numbers.
Definition: txtfrm.hxx:656
Helper class which can be used instead of the macros if a function has too many returns.
Definition: txtfrm.hxx:919
SwCharRange & GetReformat()
Definition: porlay.hxx:266
RndStdIds GetAnchorId() const
Definition: dcontact.hxx:145
void RecalcRealHeight()
Definition: itrform2.cxx:1678
Count
TextFrameIndex MapModelToView(MergedPara const &, SwTextNode const *pNode, sal_Int32 nIndex)
Definition: txtfrm.cxx:1182
SwContentFrame * FindNextCnt(const bool _bInSameFootnote=false)
Definition: findfrm.cxx:190
TElementType * First()
Definition: calbck.hxx:342
SwTextGridItem const * GetGridItem(SwPageFrame const *const)
Definition: pagechg.cxx:2514
int i
void ManipOfst(TextFrameIndex const nNewOfst)
Definition: txtfrm.hxx:429
SwContentNode * GetContentNode()
Definition: node.hxx:615
void InvalidatePage(const SwPageFrame *pPage=nullptr) const
Invalidates the page in which the Frame is currently placed.
Definition: wsfrm.cxx:597
SwLinePortion * GetFirstPortion() const
Definition: porlay.cxx:673
sal_uInt16 Count() const
iterate SwTextAttr in potentially merged text frame
Definition: txtfrm.hxx:981
long GetHeight() const
Definition: swfont.hxx:283
std::pair< SwTextNode *, sal_Int32 > MapViewToModel(MergedPara const &, TextFrameIndex nIndex)
Definition: txtfrm.cxx:1163
SwDoc * GetDoc()
Definition: node.hxx:702
void SetAutoCompleteWordDirty(bool bNew) const
Definition: txtedt.cxx:2279
SwLayoutFrame * GetUpper()
Definition: frame.hxx:656
bool HasArea() const
Definition: swrect.hxx:290
bool Relax(const SwRect &rRect)
If there is no flying object frame standing in rRect (usually the current row), then we are turning o...
Definition: txtfly.hxx:318
void InvalidateSmartTags() const
Definition: pagefrm.hxx:372
bool isFramePrintAreaValid() const
Definition: frame.hxx:164
SwGrammarMarkUp * GetGrammarCheck()
Definition: txtedt.cxx:2187
bool IsUndersized() const
Definition: flowfrm.hxx:158
SwTextNode * pParaPropsNode
most paragraph properties are taken from the first non-empty node
Definition: txtfrm.hxx:962
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2813
virtual void HandlePortion(SwPortionHandler &rPH) const
Definition: porlin.cxx:319
void Invalidate(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:425
Provides access to settings of a document.
bool IsNoTextNode() const
Definition: node.hxx:648
SvxInterLineSpaceRule GetInterLineSpaceRule() const
SwFrame * GetPrev()
Definition: frame.hxx:655
SwTextFrame * GetFormatted(bool bForceQuickFormat=false)
In case the SwLineLayout was cleared out of the s_pTextCache, recreate it.
Definition: txtfrm.cxx:3361
void RemoveFootnotesForNode(SwRootFrame const &rLayout, SwTextNode const &rTextNode, std::vector< std::pair< sal_Int32, sal_Int32 >> const *const pExtents)
Definition: txtfrm.cxx:814
void Modify(bool bChgToRTL)
Definition: txtfrm.cxx:721
sal_uInt16 GetLineHeight() const
Definition: itrtxt.hxx:116
SwWrongList * GetSmartTags()
Definition: txtedt.cxx:2212
Marks a node in the document model.
Definition: ndindex.hxx:31
#define RES_LINENUMBER
Definition: hintids.hxx:223
SvxAdjust GetNumAdjust() const
sal_Int32 nLen
Definition: hints.hxx:106
void RecalcAllLines()
Definition: txtfrm.cxx:3817
void RemoveFromCache()
Removes this frame completely from the Cache.
Definition: txtcache.cxx:119
const SvxLineSpacingItem & GetLineSpacing(bool=true) const
Definition: paratr.hxx:178
text is moved into pDestNode
Definition: hints.hxx:100
void TruncLines(bool bNoteFollow=false)
Definition: itrtxt.cxx:324
OUString mergedText
note: cannot be const currently to avoid UB because SwTextGuess::Guess const_casts it and modifies it...
Definition: txtfrm.hxx:960
SwTextNode * pDestNode
Definition: hints.hxx:103
void SSize(const Size &rNew)
Definition: swrect.hxx:176
OUString aErgoSum
Definition: ftninfo.hxx:95
bool IsLocked() const
Definition: txtfrm.hxx:505
TextFrameIndex GetParLen() const
Definition: porlay.cxx:2163
bool isFrameAreaSizeValid() const
Definition: frame.hxx:163
static void lcl_SetScriptInval(SwTextFrame &rFrame, TextFrameIndex const nPos)
Definition: txtfrm.cxx:1860
SvxNumPositionAndSpaceMode GetPositionAndSpaceMode() const
TextFrameIndex GetLen() const
Definition: porlin.hxx:74
#define RES_FMT_CHG
Definition: hintids.hxx:286
void CalcHeightOfLastLine(const bool _bUseFont=false)
method to determine height of last line, needed for proportional line spacing
Definition: txtfrm.cxx:3546
#define RES_TXTATR_INETFMT
Definition: hintids.hxx:142
A page of the document layout.
Definition: pagefrm.hxx:40
SfxItemPool * GetPool() const
long X() const
SwTextFrame * MakeTextFrame(SwTextNode &rNode, SwFrame *, sw::FrameMode eMode)
Definition: txtfrm.cxx:808
std::pair< SwTextNode *, sal_Int32 > MapViewToModel(TextFrameIndex nIndex) const
map position in potentially merged text frame to SwPosition
Definition: txtfrm.cxx:1230
void InvalidateWindows(const SwRect &rRect)
Definition: viewsh.cxx:552
const long LONG_MAX
virtual void Format(vcl::RenderContext *pRenderContext, const SwBorderAttrs *pAttrs=nullptr) override
Definition: frmform.cxx:1748
short GetInterLineSpace() const
< purpose of derivation from SwClient: character style for displaying the numbers.
Definition: lineinfo.hxx:37
SwBorderAttrs * Get()
Definition: frmtool.cxx:2439
SwTextNode * GetParaPropsNode(SwRootFrame const &rLayout, SwNodeIndex const &rNode)
Definition: txtfrm.cxx:336
bool isPARATR(const sal_uInt16 nWhich)
Definition: hintids.hxx:361
SwFieldType * GetTyp() const
Definition: fldbas.hxx:383
void InvalidateSize()
Definition: frame.hxx:1005
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1091
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
void SetLeft(SwRect &rRect, long nNew) const
Definition: frame.hxx:1364
MergedAttrIterByEnd(SwTextFrame const &rFrame)
Definition: txtfrm.cxx:157
sal_uInt16 const aFrameFormatSetRange[]
Definition: init.cxx:234
void InvalidateRange(const SwCharRange &, const long=0)
Definition: txtfrm.cxx:1684
SwPosition GetParaPropsPos(SwRootFrame const &rLayout, SwPosition const &rPos)
Definition: txtfrm.cxx:350
bool RemoveFootnote(const SwContentFrame *, const SwTextFootnote *, bool bPrep=true)
Definition: ftnfrm.cxx:1681
void SwitchLTRtoRTL(SwRect &rRect) const
Calculates the coordinates of a rectangle when switching from LTR to RTL layout.
Definition: txtfrm.cxx:693
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:78
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:50
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:77
bool IsFootnoteNumFrame() const
Am I a FootnoteFrame, with a number at the start of the paragraph?
Definition: txtfrm.hxx:611
long GetWidth(const SwRect &rRect) const
Definition: frame.hxx:1357
sal_uInt16 Count() const
Definition: hints.hxx:245
bool IsLayoutFrame() const
Definition: frame.hxx:1146
bool IsPrepMustFit() const
Definition: porlay.hxx:289
void Left(const long nLeft)
Definition: swrect.hxx:193
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
void Bottom(const long nBottom)
Definition: swrect.hxx:207
void SetOfst(TextFrameIndex nNewOfst)
Definition: txtfrm.hxx:854
void Broadcast(const SfxHint &rHint)
sal_uInt16 GetLineCount(TextFrameIndex nPos)
Determines the line count.
Definition: txtfrm.cxx:3741
void SetDevFont(const SwViewShell *pSh, OutputDevice &rOut)
Definition: fntcache.cxx:642
#define RES_VIRTPAGENUM_INFO
Definition: hintids.hxx:304
bool IsBreakNow(SwTextMargin &rLine)
Definition: widorp.cxx:168
#define RES_TXTATR_FIELD
Definition: hintids.hxx:151
#define LANGUAGE_ENGLISH
bool IsVertLR() const
Definition: frame.hxx:955
#define RES_TXTATR_AUTOFMT
Definition: hintids.hxx:141
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:67
SwTwips mnAdditionalFirstLineOffset
Definition: txtfrm.hxx:184
general base class for all free-flowing frames
Definition: flyfrm.hxx:60
void CheckKeep()
Definition: flowfrm.cxx:146
virtual SwFrameFormat & GetFrameFormat()=0
#define SAL_WARN_IF(condition, area, stream)
sal_Int32 const nLen
Definition: hints.hxx:116
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:681
#define RES_CHRATR_CTL_LANGUAGE
Definition: hintids.hxx:98
bool IsNumbered(SwRootFrame const *pLayout=nullptr) const
Returns is this text node is numbered.
Definition: ndtxt.cxx:2888
SwRepaint & GetRepaint()
Definition: porlay.hxx:264
void ClearPara()
Removes the Line information from the Cache but retains the entry itself.
Definition: txtcache.cxx:103
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:426
void Width(long nNew)
Definition: swrect.hxx:185
vcl::Window * GetWin() const
Definition: viewsh.hxx:340
const SwFrame * ContainsAny(const bool _bInvestigateFootnoteForSections=false) const
Method doesn't investigate content of footnotes by default.
Definition: findfrm.cxx:125
void SetFont(const vcl::Font &rNewFont)
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:261
SwTextNode const *const m_pNode
Definition: txtfrm.hxx:1008
#define RES_TXTATR_ANNOTATION
Definition: hintids.hxx:154
MergedAttrIterBase(SwTextFrame const &rFrame)
Definition: txtfrm.cxx:89
static TextFrameIndex UpdateMergedParaForInsert(MergedPara &rMerged, bool const isRealInsert, SwTextNode const &rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
Definition: txtfrm.cxx:905
void SetFieldFollow(const bool bNew)
Definition: txtfrm.hxx:238
TextFrameIndex MapModelToView(SwTextNode const *pNode, sal_Int32 nIndex) const
Definition: txtfrm.cxx:1251
sal_Int32 GetIndex() const
Definition: index.hxx:95
bool IsCountedInList() const
Definition: ndtxt.cxx:4240
bool IsNoTextFrame() const
Definition: frame.hxx:1214
SwTwips GetHeightOfLastLine() const
Definition: txtfrm.hxx:756
void SetMergedPara(std::unique_ptr< sw::MergedPara > p)
Definition: txtfrm.cxx:1273
void SwapWidthAndHeight()
Swaps width and height of the text frame.
Definition: txtfrm.cxx:430
LanguageType GetAppLanguage()
Definition: init.cxx:729
IDocumentSettingAccess const & getIDocumentSettingAccess() const
Definition: doc.cxx:175
sw::MergedPara const * m_pMerged
Definition: txtfrm.hxx:985
SwTwips mnFlyAnchorOfstNoWrap
Definition: txtfrm.hxx:173
bool IsRightToLeft() const
Definition: frame.hxx:963
std::unique_ptr< sw::MergedPara > m_pMergedPara
redline merge data
Definition: txtfrm.hxx:187
void SetWrong(SwWrongList *pNew, bool bDelete=true)
Definition: txtedt.cxx:2152
static TextFrameIndex FindBrk(const OUString &rText, TextFrameIndex nStart, TextFrameIndex nEnd)
Returns the first possible break point in the current line.
Definition: txtfrm.cxx:1630
Organizer of the contact between SwTextNodes and grammar checker.
SwFrameType mnFrameType
Definition: frame.hxx:395
sal_Int32 nStart
Definition: txtfrm.hxx:86
void SetRight(SwRect &rRect, long nNew) const
Definition: frame.hxx:1365
TextFrameIndex CalcFlyPos(SwFrameFormat const *pSearch)
Calculates the position of FlyInContentFrames.
Definition: porfly.cxx:186
SwWrongList * GetWrong()
Definition: txtedt.cxx:2164
virtual OutputDevice * getReferenceDevice(bool bCreate) const =0
Returns the current reference device.
sal_uInt16 Width() const
Definition: possiz.hxx:46
MergedAttrIterReverse(SwTextFrame const &rFrame)
Definition: txtfrm.cxx:209
const SwLineLayout * PrevLine()
Definition: itrtxt.cxx:171
bool IsPrtFormat() const
Definition: viewopt.hxx:502
bool sw_HideObj(const SwTextFrame &_rFrame, const RndStdIds _eAnchorType, SwPosition const &rAnchorPos, SwAnchoredObject *_pAnchoredObj)
as-character anchored graphics, which are used for a graphic bullet list.
Definition: txtfrm.cxx:1483
SwScriptInfo & GetScriptInfo()
Definition: porlay.hxx:270
double getLength(const B2DPolygon &rCandidate)
const std::vector< sal_uInt16 > & getFmtAttrs() const
Definition: hints.hxx:160
void SetPrep()
Definition: porlay.hxx:284
bool IsParaPropsNode(SwRootFrame const &rLayout, SwTextNode const &rNode)
Definition: txtfrm.cxx:319
sal_Int32 nLen
Definition: hints.hxx:126
virtual void Skip(TextFrameIndex nLength)=0
skip characters.
long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1358
bool IsHideRedlines() const
Replacement for sw::DocumentRedlineManager::GetRedlineFlags() (this is layout-level redline hiding)...
Definition: rootfrm.hxx:416
virtual void MoveObjToInvisibleLayer(SdrObject *_pDrawObj)
method to move drawing object to corresponding invisible layer
Definition: dcontact.cxx:234
#define RES_TXTATR_FLYCNT
Definition: hintids.hxx:152
void SetWidow(const bool bNew)
Definition: txtfrm.hxx:235
virtual bool get(DocumentSettingId id) const =0
Return the specified document setting.
void DelFrames(const SwRootFrame *)
Definition: atrftn.cxx:464
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:723
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
static void lcl_SetWrong(SwTextFrame &rFrame, SwTextNode const &rNode, sal_Int32 const nPos, sal_Int32 const nCnt, bool const bMove)
Definition: txtfrm.cxx:1795
SwParaPortion * pOldPara
Definition: txtfrm.cxx:3115
bool IsFixLineHeight() const
Definition: porlay.hxx:295
void Unlock()
Definition: swcache.cxx:483
static bool GetBoundsOfHiddenRange(const SwTextNode &rNode, sal_Int32 nPos, sal_Int32 &rnStartPos, sal_Int32 &rnEndPos, std::vector< sal_Int32 > *pList=nullptr)
Hidden text range information - static and non-version.
Definition: porlay.cxx:1546
void SetPrepMustFit(const bool bNew)
Definition: porlay.hxx:288
void SetPrepWidows()
Definition: porlay.hxx:286
sal_uInt16 GetRealHeight() const
Definition: porlay.hxx:153
static bool lcl_ErgoVadis(SwTextFrame *pFrame, TextFrameIndex &rPos, const PrepareHint ePrep)
Definition: txtfrm.cxx:2691
def text(shape, st)
const SwLineLayout * GetCurr() const
Definition: itrtxt.hxx:83
#define RES_OBJECTDYING
Definition: hintids.hxx:285
SwTextNode const * pLastNode
mainly for sanity checks
Definition: txtfrm.hxx:966
bool IsVertical() const
Definition: frame.hxx:949
SwTextAttr const * NextAttr(SwTextNode const *&rpNode)
Definition: txtfrm.cxx:172
SwDocPosUpdate is sent to signal that only the frames from or to a specified document-global position...
Definition: hints.hxx:183
virtual void DestroyImpl() override
Definition: txtfrm.cxx:860
long GetTop(const SwRect &rRect) const
Definition: frame.hxx:1353
void InvalidatePrt_()
Definition: frame.hxx:757
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:627
void ClearItem(sal_uInt16 nWhichL)
Definition: hints.cxx:128
void AddToListRLHidden()
Definition: ndtxt.cxx:4301
RndStdIds
SwDoc & GetDoc()
Definition: txtfrm.hxx:448
SwTwips mnHeightOfLastLine
Definition: txtfrm.hxx:179
virtual bool WouldFit(SwTwips &nMaxHeight, bool &bSplit, bool bTst) override
nMaxHeight is the required height bSplit indicates, that the paragraph has to be split bTst indicates...
Definition: txtfrm.cxx:3224
int FieldCanHideParaWeight(SwFieldIds eFieldId) const
Definition: ndtxt.hxx:711
Small Helper class: Prepares a test format.
Definition: txtfrm.cxx:3112
bool IsOn() const
Definition: txtfly.hxx:313
static bool hasA11yRelevantAttribute(const std::vector< sal_uInt16 > &rWhichFmtAttr)
Definition: txtfrm.cxx:1954
Left
SwTextNode *const pFirstNode
except break attributes, those are taken from the first node
Definition: txtfrm.hxx:964
bool IsShowHiddenChar(bool bHard=false) const
Definition: viewopt.hxx:282
sal_uInt16 getWhichAttr() const
Definition: hints.hxx:155
SwTwips mnFlyAnchorVertOfstNoWrap
The y position for wrap-through flys anchored at this paragraph.
Definition: txtfrm.hxx:175
bool IsCount() const
Definition: fmtline.hxx:58
TextFrameIndex GetEnd() const
Definition: itrtxt.hxx:89
sal_uInt16 GetDropLines() const
Definition: itrtxt.hxx:202
sal_uInt16 FirstLineHeight() const
Returns the first line height.
Definition: txtfrm.cxx:3726
#define RES_PAGEDESC
Definition: hintids.hxx:200
void VisitPortions(SwPortionHandler &rPH) const
Visit all portions for Accessibility.
Definition: txtfrm.cxx:3871
#define RES_BREAK
Definition: hintids.hxx:201
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:72
void InvalidateWordCount() const
Definition: pagefrm.hxx:380
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:204
sal_Int32 nPos
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...
class for collecting anchored objects
Definition: sortedobjs.hxx:48
SwPosition MapViewToModelPos(TextFrameIndex nIndex) const
Definition: txtfrm.cxx:1245
TextFrameIndex & Len()
Definition: porlay.hxx:49
SwFieldIds Which() const
Definition: fldbas.hxx:266
SdrObjUserCall * GetUserCall() const
bool IsIdxInside(TextFrameIndex nPos, TextFrameIndex nLen) const
Definition: txtfrm.cxx:1655
const SwPosition & GetContentAnchor() const
Definition: dcontact.hxx:152
const SwTextNode & GetTextNode() const
Definition: txtftn.hxx:69
const SwFootnoteInfo & GetFootnoteInfo() const
Definition: doc.hxx:623
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
sal_uInt16 Which() const
SwRootFrame * getRootFrame()
Definition: frame.hxx:657
virtual void Modify(const SfxPoolItem *, const SfxPoolItem *) override
Definition: wsfrm.cxx:2302
bool mbIsSwapped
Definition: txtfrm.hxx:224
void SetInvalid(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:253
void HideFootnotes(TextFrameIndex nStart, TextFrameIndex nEnd)
Definition: txtfrm.cxx:1452
long Y() const
virtual void SwClientNotify(SwModify const &rModify, SfxHint const &rHint) override
Definition: txtfrm.cxx:1969
std::pair< SwTextNode *, SwTextNode * > GetFirstAndLastNode(SwRootFrame const &rLayout, SwNodeIndex const &rPos)
Definition: txtfrm.cxx:363
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
virtual void DestroyImpl() override
Definition: ssfrm.cxx:421
#define RES_PARATR_LINESPACING
Definition: hintids.hxx:162
OUString aQuoVadis
Definition: ftninfo.hxx:94
#define RES_CHRATR_RSID
Definition: hintids.hxx:108
bool isPARATR_LIST(const sal_uInt16 nWhich)
Definition: hintids.hxx:365
void ChgThisLines()
Definition: txtfrm.cxx:3762
#define PROTOCOL_ENTER(pFrame, nFunc, nAct, pPar)
Definition: dbg_lay.hxx:92
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1075
SwTextFrame * pFrame
Definition: txtfrm.cxx:3114
SwFrameSwapper(const SwTextFrame *pFrame, bool bSwapIfNotSwapped)
Definition: txtfrm.cxx:677
SwFrame * GetNext()
Definition: frame.hxx:654
const SwFormatLineNumber & GetLineNumber(bool=true) const
Definition: fmtline.hxx:64
SwLayoutModeModifier(const OutputDevice &rOutp)
Definition: txtfrm.cxx:711
SwTextNode const * m_pNode
Definition: txtfrm.hxx:986
bool HasFootnote() const
Definition: txtfrm.hxx:510
void setHeight(long nHeight)
bool UpdateQuoVadis(const OUString &rQuo)
Is called in SwTextFrame::Prepare()
Definition: txtftn.cxx:1525