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 <hintids.hxx>
21 #include <com/sun/star/i18n/ScriptType.hpp>
22 #include <com/sun/star/i18n/XBreakIterator.hpp>
23 #include <fmtcntnt.hxx>
24 #include <txatbase.hxx>
25 #include <frmatr.hxx>
26 #include <viscrs.hxx>
27 #include "callnk.hxx"
28 #include <crsrsh.hxx>
29 #include <doc.hxx>
30 #include <frmfmt.hxx>
31 #include <txtfrm.hxx>
32 #include <tabfrm.hxx>
33 #include <rowfrm.hxx>
34 #include <fmtfsize.hxx>
35 #include <ndtxt.hxx>
36 #include <flyfrm.hxx>
37 #include <breakit.hxx>
38 
40  : rShell( rSh )
41 {
42  // remember SPoint-values of current cursor
44  SwNode& rNd = pCursor->GetPoint()->nNode.GetNode();
45  nNode = rNd.GetIndex();
46  nContent = pCursor->GetPoint()->nContent.GetIndex();
47  nNdTyp = rNd.GetNodeType();
48  bHasSelection = ( *pCursor->GetPoint() != *pCursor->GetMark() );
49 
50  if( rNd.IsTextNode() )
52  !rShell.ActionPend() );
53  else
54  {
55  nLeftFramePos = 0;
56 
57  // A special treatment for SwFeShell:
58  // When deleting the header/footer, footnotes SwFeShell sets the
59  // Cursor to NULL (Node + Content).
60  // If the Cursor is not on a ContentNode (ContentNode) this fact gets
61  // saved in nNdType.
63  nNdTyp = SwNodeType::NONE;
64  }
65 }
66 
67 static void lcl_notifyRow(const SwContentNode* pNode, SwCursorShell const & rShell)
68 {
69  if ( !pNode )
70  return;
71 
72  SwFrame *const pMyFrame = pNode->getLayoutFrame( rShell.GetLayout() );
73  if ( !pMyFrame )
74  return;
75 
76  // We need to emulated a change of the row height in order
77  // to have the complete row redrawn
78  SwRowFrame *const pRow = pMyFrame->FindRowFrame();
79  if ( !pRow )
80  return;
81 
82  const SwTableLine* pLine = pRow->GetTabLine( );
83  // Avoid redrawing the complete row if there are no nested tables
84  for (SwFrame *pCell = pRow->GetLower(); pCell; pCell = pCell->GetNext())
85  {
86  for (SwFrame *pContent = pCell->GetLower(); pContent; pContent = pContent->GetNext())
87  {
88  if (pContent->GetType() == SwFrameType::Tab)
89  {
90  SwFormatFrameSize aSize = pLine->GetFrameFormat()->GetFrameSize();
91  pRow->ModifyNotification(nullptr, &aSize);
92  return;
93  }
94  }
95  }
96 }
97 
98 SwCallLink::~SwCallLink() COVERITY_NOEXCEPT_FALSE
99 {
100  if( nNdTyp == SwNodeType::NONE || !rShell.m_bCallChgLnk ) // see ctor
101  return ;
102 
103  // If travelling over Nodes check formats and register them anew at the
104  // new Node.
105  SwPaM* pCurrentCursor = rShell.IsTableMode() ? rShell.GetTableCrs() : rShell.GetCursor();
106  SwContentNode * pCNd = pCurrentCursor->GetContentNode();
107  if( !pCNd )
108  return;
109 
110  lcl_notifyRow(pCNd, rShell);
111 
112  const SwDoc *pDoc=rShell.GetDoc();
113  const SwContentNode *pNode = nullptr;
114  if ( pDoc && nNode < pDoc->GetNodes( ).Count( ) )
115  {
116  pNode = pDoc->GetNodes()[nNode]->GetContentNode();
117  }
118  lcl_notifyRow(pNode, rShell);
119 
120  sal_Int32 nCmp, nCurrentContent = pCurrentCursor->GetPoint()->nContent.GetIndex();
121  SwNodeType nNdWhich = pCNd->GetNodeType();
122  sal_uLong nCurrentNode = pCurrentCursor->GetPoint()->nNode.GetIndex();
123 
124  // Register the Shell as dependent at the current Node. By doing this all
125  // attribute changes can be signaled over the link.
126  pCNd->Add( &rShell );
127 
128  if( nNdTyp != nNdWhich || nNode != nCurrentNode )
129  {
130  // Every time a switch between nodes occurs, there is a chance that
131  // new attributes do apply - meaning text-attributes.
132  // So the currently applying attributes would have to be determined.
133  // That can be done in one go by the handler.
134  rShell.CallChgLnk();
135  }
136  else if( !bHasSelection != (*pCurrentCursor->GetPoint() == *pCurrentCursor->GetMark()) )
137  {
138  // always call change link when selection changes
139  rShell.CallChgLnk();
140  }
141  else if( rShell.m_aChgLnk.IsSet() && SwNodeType::Text == nNdWhich &&
142  nContent != nCurrentContent )
143  {
144  // If travelling with left/right only and the frame is
145  // unchanged (columns!) then check text hints.
146  if( nLeftFramePos == SwCallLink::getLayoutFrame( rShell.GetLayout(), *pCNd->GetTextNode(), nCurrentContent,
147  !rShell.ActionPend() ) &&
148  (( nCmp = nContent ) + 1 == nCurrentContent || // Right
149  nContent -1 == ( nCmp = nCurrentContent )) ) // Left
150  {
151  if( nCmp == nCurrentContent && pCurrentCursor->HasMark() ) // left & select
152  ++nCmp;
153 
154  if ( pCNd->GetTextNode()->HasHints() )
155  {
156  const SwpHints &rHts = pCNd->GetTextNode()->GetSwpHints();
157 
158  for( size_t n = 0; n < rHts.Count(); ++n )
159  {
160  const SwTextAttr* pHt = rHts.Get( n );
161  const sal_Int32 *pEnd = pHt->End();
162  const sal_Int32 nStart = pHt->GetStart();
163 
164  // If "only start" or "start and end equal" then call on
165  // every overflow of start.
166  if( ( !pEnd || ( nStart == *pEnd ) ) &&
167  ( nStart == nContent || nStart == nCurrentContent) )
168  {
169  rShell.CallChgLnk();
170  return;
171  }
172 
173  // If the attribute has an area and that area is not empty ...
174  else if( pEnd && nStart < *pEnd &&
175  // ... then test if travelling occurred via start/end.
176  ( nStart == nCmp ||
177  ( pHt->DontExpand() ? nCmp == *pEnd-1
178  : nCmp == *pEnd ) ))
179  {
180  rShell.CallChgLnk();
181  return;
182  }
183  }
184  }
185 
186  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
187  const OUString rText = pCNd->GetTextNode()->GetText();
188  if( !nCmp ||
189  g_pBreakIt->GetBreakIter()->getScriptType( rText, nContent )
190  != g_pBreakIt->GetBreakIter()->getScriptType(rText, nCurrentContent))
191  {
192  rShell.CallChgLnk();
193  return;
194  }
195  }
196  else
197  // If travelling more than one character with home/end/.. then
198  // always call ChgLnk, because it can not be determined here what
199  // has changed. Something may have changed.
200  rShell.CallChgLnk();
201  }
202 
203  const SwFrame* pFrame;
204  const SwFlyFrame *pFlyFrame;
205  if (!rShell.ActionPend() && nullptr != (pFrame = pCNd->getLayoutFrame(rShell.GetLayout(), nullptr, nullptr)) &&
206  nullptr != ( pFlyFrame = pFrame->FindFlyFrame() ) && !rShell.IsTableMode() )
207  {
208  const SwNodeIndex* pIndex = pFlyFrame->GetFormat()->GetContent().GetContentIdx();
209  OSL_ENSURE( pIndex, "Fly without Content" );
210 
211  if (!pIndex)
212  return;
213 
214  const SwNode& rStNd = pIndex->GetNode();
215 
216  if( rStNd.EndOfSectionNode()->StartOfSectionIndex() > nNode ||
217  nNode > rStNd.EndOfSectionIndex() )
218  rShell.GetFlyMacroLnk().Call( pFlyFrame->GetFormat() );
219  }
220 }
221 
223  SwTextNode const & rNd, sal_Int32 nCntPos, bool /*bCalcFrame*/)
224 {
225  SwTextFrame* pFrame = static_cast<SwTextFrame*>(rNd.getLayoutFrame(pRoot, nullptr, nullptr));
226  SwTextFrame* pNext;
227  if ( pFrame && !pFrame->IsHiddenNow() )
228  {
229  if( pFrame->HasFollow() )
230  {
231  TextFrameIndex const nPos(pFrame->MapModelToView(&rNd, nCntPos));
232  while( nullptr != ( pNext = pFrame->GetFollow() ) &&
233  nPos >= pNext->GetOfst())
234  pFrame = pNext;
235  }
236 
237  return pFrame->getFrameArea().Left();
238  }
239  return 0;
240 }
241 
242 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
Base class of the Writer layout elements.
Definition: frame.hxx:295
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
sal_uLong GetIndex() const
Definition: node.hxx:282
void Add(SwClient *pDepend)
Definition: calbck.cxx:217
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:2816
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:185
sal_uLong StartOfSectionIndex() const
Definition: node.hxx:673
const OUString & GetText() const
Definition: ndtxt.hxx:211
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:645
sal_uIntPtr sal_uLong
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:1150
Definition: doc.hxx:185
bool HasFollow() const
Definition: flowfrm.hxx:165
TextFrameIndex GetOfst() const
Definition: txtfrm.hxx:426
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
SwNode & GetNode() const
Definition: ndindex.hxx:118
static void lcl_notifyRow(const SwContentNode *pNode, SwCursorShell const &rShell)
Definition: callnk.cxx:67
The root element of a Writer document layout.
Definition: rootfrm.hxx:79
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
bool IsHiddenNow() const
Hidden.
Definition: txtfrm.cxx:1349
SwNodeType GetNodeType() const
Definition: node.hxx:144
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:175
Link< SwCursorShell *, void > m_aChgLnk
link will be called by every attribute/ format changes at cursor position.
Definition: crsrsh.hxx:175
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:34
sal_uLong GetIndex() const
Definition: ndindex.hxx:151
sal_Int32 GetStart() const
Definition: txatbase.hxx:82
SwRowFrame * FindRowFrame()
Definition: findfrm.cxx:538
SwDoc * GetDoc() const
Definition: viewsh.hxx:284
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1087
bool m_bCallChgLnk
flag for derived classes
Definition: crsrsh.hxx:216
const Link< const SwFlyFrameFormat *, void > & GetFlyMacroLnk() const
Definition: crsrsh.hxx:482
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:844
virtual void ModifyNotification(const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue)
Definition: calbck.hxx:154
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
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:902
const SwPosition * GetPoint() const
Definition: pam.hxx:207
Count
bool ActionPend() const
Definition: viewsh.hxx:199
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
SwFrameFormat * GetFrameFormat()
Definition: swtable.hxx:366
Marks a node in the document model.
Definition: ndindex.hxx:31
SwpHints & GetSwpHints()
getters for SwpHints
Definition: ndtxt.hxx:809
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
void CallChgLnk()
Definition: crsrsh.cxx:2416
void Left(const long nLeft)
Definition: swrect.hxx:193
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
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:60
TextFrameIndex MapModelToView(SwTextNode const *pNode, sal_Int32 nIndex) const
Definition: txtfrm.cxx:1243
sal_Int32 GetIndex() const
Definition: index.hxx:95
SwNodes & GetNodes()
Definition: doc.hxx:403
const sal_Int32 * End() const
Definition: txatbase.hxx:148
SwFrame * GetLower()
Definition: findfrm.cxx:169
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter()
Definition: breakit.hxx:62
bool DontExpand() const
Definition: txatbase.hxx:92
const SwTableLine * GetTabLine() const
Definition: rowfrm.hxx:68
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2072
sal_Int32 nPos
bool IsTextNode() const
Definition: node.hxx:636
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:843
bool HasHints() const
Definition: ndtxt.hxx:221
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:28
SwFrame * GetNext()
Definition: frame.hxx:654
Base class of the Writer document model elements.
Definition: node.hxx:79