LibreOffice Module sw (master)  1
callnk.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 <com/sun/star/i18n/XBreakIterator.hpp>
21 #include <osl/diagnose.h>
22 #include <fmtcntnt.hxx>
23 #include <txatbase.hxx>
24 #include "callnk.hxx"
25 #include <crsrsh.hxx>
26 #include <doc.hxx>
27 #include <frmfmt.hxx>
28 #include <txtfrm.hxx>
29 #include <rowfrm.hxx>
30 #include <fmtfsize.hxx>
31 #include <ndtxt.hxx>
32 #include <flyfrm.hxx>
33 #include <breakit.hxx>
34 
36  : m_rShell( rSh )
37 {
38  // remember SPoint-values of current cursor
40  SwNode& rNd = pCursor->GetPoint()->nNode.GetNode();
41  m_nNode = rNd.GetIndex();
42  m_nContent = pCursor->GetPoint()->nContent.GetIndex();
43  m_nNodeType = rNd.GetNodeType();
44  m_bHasSelection = ( *pCursor->GetPoint() != *pCursor->GetMark() );
45 
46  if( rNd.IsTextNode() )
48  !m_rShell.ActionPend() );
49  else
50  {
51  m_nLeftFramePos = 0;
52 
53  // A special treatment for SwFeShell:
54  // When deleting the header/footer, footnotes SwFeShell sets the
55  // Cursor to NULL (Node + Content).
56  // If the Cursor is not on a ContentNode (ContentNode) this fact gets
57  // saved in nNdType.
59  m_nNodeType = SwNodeType::NONE;
60  }
61 }
62 
63 static void lcl_notifyRow(const SwContentNode* pNode, SwCursorShell & rShell)
64 {
65  if ( !pNode )
66  return;
67 
68  SwFrame *const pMyFrame = pNode->getLayoutFrame( rShell.GetLayout() );
69  if ( !pMyFrame )
70  return;
71 
72  // We need to emulated a change of the row height in order
73  // to have the complete row redrawn
74  SwRowFrame *const pRow = pMyFrame->FindRowFrame();
75  if ( !pRow )
76  return;
77 
78  const SwTableLine* pLine = pRow->GetTabLine( );
79 
80  if (rShell.IsTableMode() || (rShell.StartsWithTable() && rShell.ExtendedSelectedAll()))
81  {
82  // If we have a table selection, then avoid the notification: it's not necessary (the text
83  // cursor needs no updating) and the notification may kill the selection overlay, leading to
84  // flicker.
85  // Same for whole-document selection when it starts with a table.
86  return;
87  }
88 
89  const SwFormatFrameSize aSize = pLine->GetFrameFormat()->GetFrameSize();
90  pRow->OnFrameSize(aSize);
91 }
92 
93 SwCallLink::~SwCallLink() COVERITY_NOEXCEPT_FALSE
94 {
95  if( m_nNodeType == SwNodeType::NONE || !m_rShell.m_bCallChgLnk ) // see ctor
96  return ;
97 
98  // If travelling over Nodes check formats and register them anew at the
99  // new Node.
100  SwPaM* pCurrentCursor = m_rShell.IsTableMode() ? m_rShell.GetTableCrs() : m_rShell.GetCursor();
101  SwContentNode * pCNd = pCurrentCursor->GetContentNode();
102  if( !pCNd )
103  return;
104 
105  lcl_notifyRow(pCNd, m_rShell);
106 
107  const SwDoc *pDoc=m_rShell.GetDoc();
108  const SwContentNode *pNode = nullptr;
109  if ( pDoc && m_nNode < pDoc->GetNodes( ).Count( ) )
110  {
111  pNode = pDoc->GetNodes()[m_nNode]->GetContentNode();
112  }
113  lcl_notifyRow(pNode, m_rShell);
114 
115  sal_Int32 nCmp, nCurrentContent = pCurrentCursor->GetPoint()->nContent.GetIndex();
116  SwNodeType nNdWhich = pCNd->GetNodeType();
117  sal_uLong nCurrentNode = pCurrentCursor->GetPoint()->nNode.GetIndex();
118 
119  // Register the Shell as dependent at the current Node. By doing this all
120  // attribute changes can be signaled over the link.
121  pCNd->Add( &m_rShell );
122 
123  const bool bCurrentHasSelection = (*pCurrentCursor->GetPoint() != *pCurrentCursor->GetMark());
124 
125  if( m_nNodeType != nNdWhich || m_nNode != nCurrentNode )
126  {
127  // Every time a switch between nodes occurs, there is a chance that
128  // new attributes do apply - meaning text-attributes.
129  // So the currently applying attributes would have to be determined.
130  // That can be done in one go by the handler.
132  }
133  else if (m_bHasSelection != bCurrentHasSelection)
134  {
135  // always call change link when selection changes
137  }
138  else if( m_rShell.m_aChgLnk.IsSet() && SwNodeType::Text == nNdWhich &&
139  m_nContent != nCurrentContent )
140  {
141  // If travelling with left/right only and the frame is
142  // unchanged (columns!) then check text hints.
143  if( m_nLeftFramePos == SwCallLink::getLayoutFrame( m_rShell.GetLayout(), *pCNd->GetTextNode(), nCurrentContent,
144  !m_rShell.ActionPend() ) &&
145  (( nCmp = m_nContent ) + 1 == nCurrentContent || // Right
146  m_nContent -1 == ( nCmp = nCurrentContent )) ) // Left
147  {
148  if( nCmp == nCurrentContent && pCurrentCursor->HasMark() ) // left & select
149  ++nCmp;
150 
151  if ( pCNd->GetTextNode()->HasHints() )
152  {
153  const SwpHints &rHts = pCNd->GetTextNode()->GetSwpHints();
154 
155  for( size_t n = 0; n < rHts.Count(); ++n )
156  {
157  const SwTextAttr* pHt = rHts.Get( n );
158  const sal_Int32 *pEnd = pHt->End();
159  const sal_Int32 nStart = pHt->GetStart();
160 
161  // If "only start" or "start and end equal" then call on
162  // every overflow of start.
163  if( ( !pEnd || ( nStart == *pEnd ) ) &&
164  ( nStart == m_nContent || nStart == nCurrentContent) )
165  {
167  return;
168  }
169 
170  // If the attribute has an area and that area is not empty ...
171  else if( pEnd && nStart < *pEnd &&
172  // ... then test if travelling occurred via start/end.
173  ( nStart == nCmp ||
174  ( pHt->DontExpand() ? nCmp == *pEnd-1
175  : nCmp == *pEnd ) ))
176  {
178  return;
179  }
180  }
181  }
182 
183  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
184  const OUString rText = pCNd->GetTextNode()->GetText();
185  if( !nCmp ||
186  g_pBreakIt->GetBreakIter()->getScriptType( rText, m_nContent )
187  != g_pBreakIt->GetBreakIter()->getScriptType(rText, nCurrentContent))
188  {
190  return;
191  }
192  }
193  else
194  // If travelling more than one character with home/end/.. then
195  // always call ChgLnk, because it can not be determined here what
196  // has changed. Something may have changed.
198  }
199 
200  const SwFrame* pFrame;
201  const SwFlyFrame *pFlyFrame;
202  if (m_rShell.ActionPend())
203  return;
204  pFrame = pCNd->getLayoutFrame(m_rShell.GetLayout(), nullptr, nullptr);
205  if (!pFrame)
206  return;
207  pFlyFrame = pFrame->FindFlyFrame();
208  if ( !pFlyFrame || m_rShell.IsTableMode() )
209  return;
210 
211  const SwNodeIndex* pIndex = pFlyFrame->GetFormat()->GetContent().GetContentIdx();
212  OSL_ENSURE( pIndex, "Fly without Content" );
213 
214  if (!pIndex)
215  return;
216 
217  const SwNode& rStNd = pIndex->GetNode();
218 
219  if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > m_nNode ||
220  m_nNode > rStNd.EndOfSectionIndex() )
221  m_rShell.GetFlyMacroLnk().Call( pFlyFrame->GetFormat() );
222 }
223 
225  SwTextNode const & rNd, sal_Int32 nCntPos, bool /*bCalcFrame*/)
226 {
227  SwTextFrame* pFrame = static_cast<SwTextFrame*>(rNd.getLayoutFrame(pRoot, nullptr, nullptr));
228  SwTextFrame* pNext;
229  if ( pFrame && !pFrame->IsHiddenNow() )
230  {
231  if( pFrame->HasFollow() )
232  {
233  TextFrameIndex const nPos(pFrame->MapModelToView(&rNd, nCntPos));
234  for (;;)
235  {
236  pNext = pFrame->GetFollow();
237  if(!pNext || nPos < pNext->GetOffset())
238  break;
239  pFrame = pNext;
240  }
241  }
242 
243  return pFrame->getFrameArea().Left();
244  }
245  return 0;
246 }
247 
248 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:683
Base class of the Writer layout elements.
Definition: frame.hxx:315
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:158
sal_uLong GetIndex() const
Definition: node.hxx:291
void Add(SwClient *pDepend)
Definition: calbck.cxx:173
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:2877
sal_uLong StartOfSectionIndex() const
Definition: node.hxx:674
const OUString & GetText() const
Definition: ndtxt.hxx:215
void Left(const tools::Long nLeft)
Definition: swrect.hxx:194
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:642
sal_uIntPtr sal_uLong
long Long
const SwPosition * GetMark() const
Definition: pam.hxx:209
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1213
sal_Int64 n
Definition: doc.hxx:188
bool HasFollow() const
Definition: flowfrm.hxx:165
SwTableLine is one table row in the document model.
Definition: swtable.hxx:357
SwNode & GetNode() const
Definition: ndindex.hxx:119
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
bool IsHiddenNow() const
Hidden.
Definition: txtfrm.cxx:1362
SwNodeType GetNodeType() const
Definition: node.hxx:145
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:180
A wrapper around SfxPoolItem to store the start position of (usually) a text portion, with an optional end.
Definition: txatbase.hxx:41
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
sal_Int32 GetStart() const
Definition: txatbase.hxx:86
SwRowFrame * FindRowFrame()
Definition: findfrm.cxx:539
SwDoc * GetDoc() const
Definition: viewsh.hxx:281
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1112
bool m_bCallChgLnk
flag for derived classes
Definition: crsrsh.hxx:213
const Link< const SwFlyFrameFormat *, void > & GetFlyMacroLnk() const
Definition: crsrsh.hxx:479
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:855
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
void OnFrameSize(const SfxPoolItem &)
Definition: tabfrm.cxx:3913
bool ExtendedSelectedAll()
If ExtendedSelectAll() was called and selection didn't change since then.
Definition: crsrsh.cxx:607
size_t Count() const
Definition: ndhints.hxx:142
SwNodeType
Definition: ndtyp.hxx:28
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
const SwPaM * GetTableCrs() const
Definition: crsrsh.hxx:898
const SwPosition * GetPoint() const
Definition: pam.hxx:207
Count
bool ActionPend() const
Definition: viewsh.hxx:196
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:379
Marks a node in the document model.
Definition: ndindex.hxx:31
SwpHints & GetSwpHints()
getters for SwpHints
Definition: ndtxt.hxx:816
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
void CallChgLnk()
Definition: crsrsh.cxx:2527
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:678
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:195
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:67
general base class for all free-flowing frames
Definition: flyfrm.hxx:78
TextFrameIndex MapModelToView(SwTextNode const *pNode, sal_Int32 nIndex) const
Definition: txtfrm.cxx:1254
sal_Int32 GetIndex() const
Definition: index.hxx:91
bool StartsWithTable()
If document body starts with a table.
Definition: crsrsh.cxx:626
SwNodes & GetNodes()
Definition: doc.hxx:409
const sal_Int32 * End() const
Definition: txatbase.hxx:152
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
bool DontExpand() const
Definition: txatbase.hxx:96
Link< LinkParamNone *, void > m_aChgLnk
link will be called by every attribute/ format changes at cursor position.
Definition: crsrsh.hxx:171
const SwTableLine * GetTabLine() const
Definition: rowfrm.hxx:70
static void lcl_notifyRow(const SwContentNode *pNode, SwCursorShell &rShell)
Definition: callnk.cxx:63
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2067
bool IsTextNode() const
Definition: node.hxx:637
sal_uInt16 nPos
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:850
bool HasHints() const
Definition: ndtxt.hxx:225
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:28
Base class of the Writer document model elements.
Definition: node.hxx:80