Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx
Warning:line 530, column 21
Forming reference to null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name trvltbl.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx

/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx

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 <crsrsh.hxx>
22#include <doc.hxx>
23#include <cntfrm.hxx>
24#include <editsh.hxx>
25#include <pam.hxx>
26#include <swtable.hxx>
27#include <frmfmt.hxx>
28#include <viscrs.hxx>
29#include "callnk.hxx"
30#include <tabfrm.hxx>
31#include <ndtxt.hxx>
32#include <shellres.hxx>
33#include <cellfrm.hxx>
34#include <IDocumentLayoutAccess.hxx>
35#include <svx/srchdlg.hxx>
36
37/// set cursor into next/previous cell
38bool SwCursorShell::GoNextCell( bool bAppendLine )
39{
40 bool bRet = false;
41 const SwTableNode* pTableNd = nullptr;
42
43 if( IsTableMode() || nullptr != ( pTableNd = IsCursorInTable() ))
44 {
45 SwCursor* pCursor = m_pTableCursor ? m_pTableCursor : m_pCurrentCursor;
46 SwCallLink aLk( *this ); // watch Cursor-Moves
47 bRet = true;
48
49 // Check if we have to move the cursor to a covered cell before
50 // proceeding:
51 const SwNode* pTableBoxStartNode = pCursor->GetNode().FindTableBoxStartNode();
52 const SwTableBox* pTableBox = nullptr;
53
54 if ( pCursor->GetCursorRowSpanOffset() )
55 {
56 pTableBox = pTableBoxStartNode->GetTableBox();
57 if ( pTableBox->getRowSpan() > 1 )
58 {
59 if ( !pTableNd )
60 pTableNd = IsCursorInTable();
61 assert (pTableNd)(static_cast <bool> (pTableNd) ? void (0) : __assert_fail
("pTableNd", "/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
, 61, __extension__ __PRETTY_FUNCTION__))
;
62 pTableBox = & pTableBox->FindEndOfRowSpan( pTableNd->GetTable(),
63 static_cast<sal_uInt16>(pTableBox->getRowSpan() + pCursor->GetCursorRowSpanOffset() ) );
64 pTableBoxStartNode = pTableBox->GetSttNd();
65 }
66 }
67
68 SwNodeIndex aCellStt( *pTableBoxStartNode->EndOfSectionNode(), 1 );
69
70 // if there is another StartNode after the EndNode of a cell then
71 // there is another cell
72 if( !aCellStt.GetNode().IsStartNode() )
73 {
74 if( pCursor->HasMark() || !bAppendLine )
75 bRet = false;
76 else if (pTableNd)
77 {
78 // if there is no list anymore then create new one
79 if ( !pTableBox )
80 pTableBox = pTableNd->GetTable().GetTableBox(
81 pCursor->GetPoint()->nNode.GetNode().
82 StartOfSectionIndex() );
83
84 OSL_ENSURE( pTableBox, "Box is not in this table" )do { if (true && (!(pTableBox))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
":" "84" ": "), "%s", "Box is not in this table"); } } while
(false)
;
85 SwSelBoxes aBoxes;
86
87 // the document might change; w/o Action views would not be notified
88 static_cast<SwEditShell*>(this)->StartAllAction();
89 bRet = mxDoc->InsertRow( SwTable::SelLineFromBox( pTableBox, aBoxes, false ));
90 static_cast<SwEditShell*>(this)->EndAllAction();
91 }
92 }
93 bRet = bRet && pCursor->GoNextCell();
94 if( bRet )
95 UpdateCursor();
96 }
97 return bRet;
98}
99
100bool SwCursorShell::GoPrevCell()
101{
102 bool bRet = false;
103 if( IsTableMode() || IsCursorInTable() )
104 {
105 SwCursor* pCursor = m_pTableCursor ? m_pTableCursor : m_pCurrentCursor;
106 SwCallLink aLk( *this ); // watch Cursor-Moves
107 bRet = pCursor->GoPrevCell();
108 if( bRet )
109 UpdateCursor(); // update current cursor
110 }
111 return bRet;
112}
113
114static const SwFrame* lcl_FindMostUpperCellFrame( const SwFrame* pFrame )
115{
116 while ( pFrame &&
117 ( !pFrame->IsCellFrame() ||
118 !pFrame->GetUpper()->GetUpper()->IsTabFrame() ||
119 pFrame->GetUpper()->GetUpper()->GetUpper()->IsInTab() ) )
120 {
121 pFrame = pFrame->GetUpper();
122 }
123 return pFrame;
124}
125
126bool SwCursorShell::SelTableRowOrCol( bool bRow, bool bRowSimple )
127{
128 // check if the current cursor's SPoint/Mark are in a table
129 SwFrame *pFrame = GetCurrFrame();
130 if( !pFrame->IsInTab() )
131 return false;
132
133 const SwTabFrame* pTabFrame = pFrame->FindTabFrame();
134 const SwTabFrame* pMasterTabFrame = pTabFrame->IsFollow() ? pTabFrame->FindMaster( true ) : pTabFrame;
135 const SwTable* pTable = pTabFrame->GetTable();
136
137 CurrShell aCurr( this );
138
139 const SwTableBox* pStt = nullptr;
140 const SwTableBox* pEnd = nullptr;
141
142 // search box based on layout
143 SwSelBoxes aBoxes;
144 SwTableSearchType eType = bRow ? SwTableSearchType::Row : SwTableSearchType::Col;
145 const bool bCheckProtected = !IsReadOnlyAvailable();
146
147 if( bCheckProtected )
148 eType = static_cast<SwTableSearchType>(eType | SwTableSearchType::Protect);
149
150 if ( !bRowSimple )
151 {
152 GetTableSel( *this, aBoxes, eType );
153
154 if( aBoxes.empty() )
155 return false;
156
157 pStt = aBoxes[0];
158 pEnd = aBoxes.back();
159 }
160 // #i32329# Enhanced table selection
161 else if ( pTable->IsNewModel() )
162 {
163 const SwShellCursor *pCursor = GetCursor_();
164 SwTable::SearchType eSearchType = bRow ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL;
165 pTable->CreateSelection( *pCursor, aBoxes, eSearchType, bCheckProtected );
166 if( aBoxes.empty() )
167 return false;
168
169 pStt = aBoxes[0];
170 pEnd = aBoxes.back();
171
172 m_eEnhancedTableSel = eSearchType;
173 }
174 else
175 {
176 const SwShellCursor *pCursor = GetCursor_();
177 const SwFrame* pStartFrame = pFrame;
178 const SwContentNode *pCNd = pCursor->GetContentNode( false );
179 std::pair<Point, bool> const tmp(pCursor->GetMkPos(), true);
180 const SwFrame* pEndFrame = pCNd
181 ? pCNd->getLayoutFrame(GetLayout(), nullptr, &tmp)
182 : nullptr;
183
184 if ( bRow )
185 {
186 pStartFrame = lcl_FindMostUpperCellFrame( pStartFrame );
187 pEndFrame = lcl_FindMostUpperCellFrame( pEndFrame );
188 }
189
190 if ( !pStartFrame || !pEndFrame )
191 return false;
192
193 const bool bVert = pFrame->ImplFindTabFrame()->IsVertical();
194
195 // If we select upwards it is sufficient to set pStt and pEnd
196 // to the first resp. last box of the selection obtained from
197 // GetTableSel. However, selecting downwards requires the frames
198 // located at the corners of the selection. This does not work
199 // for column selections in vertical tables:
200 const bool bSelectUp = ( bVert && !bRow ) ||
201 *pCursor->GetPoint() <= *pCursor->GetMark();
202 SwCellFrames aCells;
203 GetTableSel( static_cast<const SwCellFrame*>(pStartFrame),
204 static_cast<const SwCellFrame*>(pEndFrame),
205 aBoxes, bSelectUp ? nullptr : &aCells, eType );
206
207 if( aBoxes.empty() || ( !bSelectUp && 4 != aCells.size() ) )
208 return false;
209
210 if ( bSelectUp )
211 {
212 pStt = aBoxes[0];
213 pEnd = aBoxes.back();
214 }
215 else
216 {
217 // will become point of table cursor
218 pStt = aCells[bVert ? 0 : (bRow ? 2 : 1)]->GetTabBox();
219 // will become mark of table cursor
220 pEnd = aCells[bVert ? 3 : (bRow ? 1 : 2)]->GetTabBox();
221 }
222 }
223
224 // if no table cursor exists, create one
225 if( !m_pTableCursor )
226 {
227 m_pTableCursor = new SwShellTableCursor( *this, *m_pCurrentCursor->GetPoint() );
228 m_pCurrentCursor->DeleteMark();
229 m_pCurrentCursor->SwSelPaintRects::Hide();
230 }
231
232 m_pTableCursor->DeleteMark();
233
234 // set start and end of a column
235 m_pTableCursor->GetPoint()->nNode = *pEnd->GetSttNd();
236 m_pTableCursor->Move( fnMoveForward, GoInContent );
237 m_pTableCursor->SetMark();
238 m_pTableCursor->GetPoint()->nNode = *pStt->GetSttNd()->EndOfSectionNode();
239 m_pTableCursor->Move( fnMoveBackward, GoInContent );
240
241 // set PtPos 'close' to the reference table, otherwise we might get problems
242 // with the repeated headlines check in UpdateCursor():
243 if ( !bRow )
244 m_pTableCursor->GetPtPos() = pMasterTabFrame->IsVertical()
245 ? pMasterTabFrame->getFrameArea().TopRight()
246 : pMasterTabFrame->getFrameArea().TopLeft();
247
248 UpdateCursor();
249 return true;
250}
251
252bool SwCursorShell::SelTable()
253{
254 // check if the current cursor's SPoint/Mark are in a table
255 SwFrame *pFrame = GetCurrFrame();
256 if( !pFrame->IsInTab() )
257 return false;
258
259 const SwTabFrame *pTableFrame = pFrame->ImplFindTabFrame();
260 const SwTabFrame* pMasterTabFrame = pTableFrame->IsFollow() ? pTableFrame->FindMaster( true ) : pTableFrame;
261 const SwTableNode* pTableNd = pTableFrame->GetTable()->GetTableNode();
262
263 CurrShell aCurr( this );
264
265 if( !m_pTableCursor )
266 {
267 m_pTableCursor = new SwShellTableCursor( *this, *m_pCurrentCursor->GetPoint() );
268 m_pCurrentCursor->DeleteMark();
269 m_pCurrentCursor->SwSelPaintRects::Hide();
270 }
271
272 m_pTableCursor->DeleteMark();
273 m_pTableCursor->GetPoint()->nNode = *pTableNd;
274 m_pTableCursor->Move( fnMoveForward, GoInContent );
275 m_pTableCursor->SetMark();
276 // set MkPos 'close' to the master table, otherwise we might get problems
277 // with the repeated headlines check in UpdateCursor():
278 m_pTableCursor->GetMkPos() = pMasterTabFrame->IsVertical() ? pMasterTabFrame->getFrameArea().TopRight() : pMasterTabFrame->getFrameArea().TopLeft();
279 m_pTableCursor->GetPoint()->nNode = *pTableNd->EndOfSectionNode();
280 m_pTableCursor->Move( fnMoveBackward, GoInContent );
281 UpdateCursor();
282 return true;
283}
284
285bool SwCursorShell::SelTableBox()
286{
287 // if we're in a table, create a table cursor, and select the cell
288 // that the current cursor's point resides in
289
290 // search for start node of our table box. If not found, exit really
291 const SwStartNode* pStartNode =
292 m_pCurrentCursor->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
293
294#if OSL_DEBUG_LEVEL1 > 0
295 // the old code checks whether we're in a table by asking the
296 // frame. This should yield the same result as searching for the
297 // table box start node, right?
298 SwFrame *pFrame = GetCurrFrame();
299 OSL_ENSURE( !pFrame->IsInTab() == !(pStartNode != nullptr),do { if (true && (!(!pFrame->IsInTab() == !(pStartNode
!= nullptr)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
":" "300" ": "), "%s", "Schroedinger's table: We're in a box, and also we aren't."
); } } while (false)
300 "Schroedinger's table: We're in a box, and also we aren't." )do { if (true && (!(!pFrame->IsInTab() == !(pStartNode
!= nullptr)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
":" "300" ": "), "%s", "Schroedinger's table: We're in a box, and also we aren't."
); } } while (false)
;
301#endif
302 if( pStartNode == nullptr )
303 return false;
304
305 CurrShell aCurr( this );
306
307 // create a table cursor, if there isn't one already
308 if( !m_pTableCursor )
309 {
310 m_pTableCursor = new SwShellTableCursor( *this, *m_pCurrentCursor->GetPoint() );
311 m_pCurrentCursor->DeleteMark();
312 m_pCurrentCursor->SwSelPaintRects::Hide();
313 }
314
315 // select the complete box with our shiny new m_pTableCursor
316 // 1. delete mark, and move point to first content node in box
317 m_pTableCursor->DeleteMark();
318 *(m_pTableCursor->GetPoint()) = SwPosition( *pStartNode );
319 m_pTableCursor->Move( fnMoveForward, GoInNode );
320
321 // 2. set mark, and move point to last content node in box
322 m_pTableCursor->SetMark();
323 *(m_pTableCursor->GetPoint()) = SwPosition( *(pStartNode->EndOfSectionNode()) );
324 m_pTableCursor->Move( fnMoveBackward, GoInNode );
325
326 // 3. exchange
327 m_pTableCursor->Exchange();
328
329 // with some luck, UpdateCursor() will now update everything that
330 // needs updating
331 UpdateCursor();
332
333 return true;
334}
335
336// TODO: provide documentation
337/** get the next non-protected cell inside a table
338
339 @param[in,out] rIdx is on a table node
340 @param bInReadOnly ???
341
342 @return <false> if no suitable cell could be found, otherwise <rIdx> points
343 to content in a suitable cell and <true> is returned.
344*/
345static bool lcl_FindNextCell( SwNodeIndex& rIdx, bool bInReadOnly )
346{
347 // check protected cells
348 SwNodeIndex aTmp( rIdx, 2 ); // TableNode + StartNode
349
350 // the resulting cell should be in that table:
351 const SwTableNode* pTableNd = rIdx.GetNode().GetTableNode();
352
353 if ( !pTableNd )
354 {
355 OSL_FAIL( "lcl_FindNextCell not celled with table start node!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
":" "355" ": "), "%s", "lcl_FindNextCell not celled with table start node!"
); } } while (false)
;
356 return false;
357 }
358
359 const SwNode* pTableEndNode = pTableNd->EndOfSectionNode();
360
361 SwNodes& rNds = aTmp.GetNode().GetNodes();
362 SwContentNode* pCNd = aTmp.GetNode().GetContentNode();
363
364 // no content node => go to next content node
365 if( !pCNd )
366 pCNd = rNds.GoNext( &aTmp );
367
368 // robust
369 if ( !pCNd )
370 return false;
371
372 SwContentFrame* pFrame = pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
373
374 if ( nullptr == pFrame || pCNd->FindTableNode() != pTableNd ||
375 (!bInReadOnly && pFrame->IsProtected() ) )
376 {
377 // we are not located inside a 'valid' cell. We have to continue searching...
378
379 // skip behind current section. This might be the end of the table cell
380 // or behind an inner section or...
381 aTmp.Assign( *pCNd->EndOfSectionNode(), 1 );
382
383 // loop to find a suitable cell...
384 for( ;; )
385 {
386 SwNode* pNd = &aTmp.GetNode();
387
388 // we break this loop if we reached the end of the table.
389 // to make this code even more robust, we also break if we are
390 // already behind the table end node:
391 if( pNd == pTableEndNode || /*robust: */ pNd->GetIndex() > pTableEndNode->GetIndex() )
392 return false;
393
394 // ok, get the next content node:
395 pCNd = aTmp.GetNode().GetContentNode();
396 if( nullptr == pCNd )
397 pCNd = rNds.GoNext( &aTmp );
398
399 // robust:
400 if ( !pCNd )
401 return false;
402
403 // check if we have found a suitable table cell:
404 pFrame = pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
405
406 if ( nullptr != pFrame && pCNd->FindTableNode() == pTableNd &&
407 (bInReadOnly || !pFrame->IsProtected() ) )
408 {
409 // finally, we have found a suitable table cell => set index and return
410 rIdx = *pCNd;
411 return true;
412 }
413
414 // continue behind the current section:
415 aTmp.Assign( *pCNd->EndOfSectionNode(), +1 );
416 }
417 }
418 rIdx = *pCNd;
419 return true;
420}
421
422/// see lcl_FindNextCell()
423static bool lcl_FindPrevCell( SwNodeIndex& rIdx, bool bInReadOnly )
424{
425 SwNodeIndex aTmp( rIdx, -2 ); // TableNode + EndNode
426
427 const SwNode* pTableEndNode = &rIdx.GetNode();
428 const SwTableNode* pTableNd = pTableEndNode->StartOfSectionNode()->GetTableNode();
429
430 if ( !pTableNd )
431 {
432 OSL_FAIL( "lcl_FindPrevCell not celled with table start node!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
":" "432" ": "), "%s", "lcl_FindPrevCell not celled with table start node!"
); } } while (false)
;
433 return false;
434 }
435
436 SwContentNode* pCNd = aTmp.GetNode().GetContentNode();
437
438 if( !pCNd )
439 pCNd = SwNodes::GoPrevious( &aTmp );
440
441 if ( !pCNd )
442 return false;
443
444 SwContentFrame* pFrame = pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
445
446 if( nullptr == pFrame || pCNd->FindTableNode() != pTableNd ||
447 (!bInReadOnly && pFrame->IsProtected() ))
448 {
449 // skip before current section
450 aTmp.Assign( *pCNd->StartOfSectionNode(), -1 );
451 for( ;; )
452 {
453 SwNode* pNd = &aTmp.GetNode();
454
455 if( pNd == pTableNd || pNd->GetIndex() < pTableNd->GetIndex() )
456 return false;
457
458 pCNd = aTmp.GetNode().GetContentNode();
459 if( nullptr == pCNd )
460 pCNd = SwNodes::GoPrevious( &aTmp );
461
462 if ( !pCNd )
463 return false;
464
465 pFrame = pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() );
466
467 if( nullptr != pFrame && pCNd->FindTableNode() == pTableNd &&
468 (bInReadOnly || !pFrame->IsProtected() ) )
469 {
470 rIdx = *pCNd;
471 return true; // ok, not protected
472 }
473 aTmp.Assign( *pCNd->StartOfSectionNode(), - 1 );
474 }
475 }
476 rIdx = *pCNd;
477 return true;
478}
479
480bool GotoPrevTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable,
481 bool bInReadOnly )
482{
483 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
484
485 SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode );
486
487 SwTableNode* pTableNd = aIdx.GetNode().FindTableNode();
1
'pTableNd' initialized here
488 if( pTableNd )
2
Assuming 'pTableNd' is null
3
Taking false branch
489 {
490 // #i26532#: If we are inside a table, we may not go backward to the
491 // table start node, because we would miss any tables inside this table.
492 SwTableNode* pInnerTableNd = nullptr;
493 SwNodeIndex aTmpIdx( aIdx );
494 while( aTmpIdx.GetIndex() &&
495 nullptr == ( pInnerTableNd = aTmpIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
496 --aTmpIdx;
497
498 if( pInnerTableNd == pTableNd )
499 aIdx.Assign( *pTableNd, - 1 );
500 }
501
502 SwNodeIndex aOldIdx = aIdx;
503 sal_uLong nLastNd = rCurrentCursor.GetDoc().GetNodes().Count() - 1;
504 do {
30
Loop condition is true. Execution continues on line 505
505 while( aIdx.GetIndex() &&
4
Calling 'SwNodeIndex::GetIndex'
14
Returning from 'SwNodeIndex::GetIndex'
15
Assuming the condition is false
31
Calling 'SwNodeIndex::GetIndex'
41
Returning from 'SwNodeIndex::GetIndex'
42
Assuming the condition is false
506 nullptr == ( pTableNd = aIdx.GetNode().StartOfSectionNode()->GetTableNode()) )
507 {
508 --aIdx;
509 if ( aIdx == aOldIdx )
510 {
511 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
512 return false;
513 }
514 }
515
516 if ( !aIdx.GetIndex() )
16
Calling 'SwNodeIndex::GetIndex'
26
Returning from 'SwNodeIndex::GetIndex'
27
Assuming the condition is true
28
Taking true branch
43
Calling 'SwNodeIndex::GetIndex'
53
Returning from 'SwNodeIndex::GetIndex'
54
Assuming the condition is false
55
Taking false branch
517 {
518 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped );
519 aIdx = nLastNd;
520 continue;
29
Execution continues on line 555
521 }
522
523 {
524 if( &fnPosTable == &fnMoveForward ) // at the beginning?
56
Assuming the condition is true
57
Taking true branch
525 {
526 aIdx = *aIdx.GetNode().StartOfSectionNode();
527 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
58
Assuming the condition is true
59
Taking true branch
528 {
529 // skip table
530 aIdx.Assign( *pTableNd, -1 );
60
Forming reference to null pointer
531 continue;
532 }
533 }
534 else
535 {
536 // check protected cells
537 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
538 {
539 // skip table
540 aIdx.Assign( *pTableNd, -1 );
541 continue;
542 }
543 }
544
545 SwTextNode* pTextNode = aIdx.GetNode().GetTextNode();
546 if ( pTextNode )
547 {
548 rCurrentCursor.GetPoint()->nNode = *pTextNode;
549 rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ?
550 pTextNode->Len() :
551 0 );
552 }
553 return true;
554 }
555 } while( true );
556
557 return false;
558}
559
560bool GotoNextTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable,
561 bool bInReadOnly )
562{
563 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::Empty );
564
565 SwNodeIndex aIdx( rCurrentCursor.GetPoint()->nNode );
566 SwTableNode* pTableNd = aIdx.GetNode().FindTableNode();
567
568 if( pTableNd )
569 aIdx.Assign( *pTableNd->EndOfSectionNode(), 1 );
570
571 SwNodeIndex aOldIdx = aIdx;
572 sal_uLong nLastNd = rCurrentCursor.GetDoc().GetNodes().Count() - 1;
573 do {
574 while( aIdx.GetIndex() < nLastNd &&
575 nullptr == ( pTableNd = aIdx.GetNode().GetTableNode()) )
576 {
577 ++aIdx;
578 if ( aIdx == aOldIdx )
579 {
580 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::NavElementNotFound );
581 return false;
582 }
583 }
584
585 if ( aIdx.GetIndex() == nLastNd )
586 {
587 SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::EndWrapped );
588 aIdx = 0;
589 continue;
590 }
591
592 assert( pTableNd )(static_cast <bool> (pTableNd) ? void (0) : __assert_fail
("pTableNd", "/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
, 592, __extension__ __PRETTY_FUNCTION__))
; // coverity, should never be nullptr
593
594 if( &fnPosTable == &fnMoveForward ) // at the beginning?
595 {
596 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
597 {
598 // skip table
599 aIdx.Assign( *pTableNd->EndOfSectionNode(), + 1 );
600 continue;
601 }
602 }
603 else
604 {
605 aIdx = *aIdx.GetNode().EndOfSectionNode();
606 // check protected cells
607 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
608 {
609 // skip table
610 aIdx.Assign( *pTableNd->EndOfSectionNode(), + 1 );
611 continue;
612 }
613 }
614
615 SwTextNode* pTextNode = aIdx.GetNode().GetTextNode();
616 if ( pTextNode )
617 {
618 rCurrentCursor.GetPoint()->nNode = *pTextNode;
619 rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ?
620 pTextNode->Len() :
621 0 );
622 }
623 return true;
624
625 } while( true );
626
627 // the flow is such that it is not possible to get there
628
629 return false;
630}
631
632bool GotoCurrTable( SwPaM& rCurrentCursor, SwMoveFnCollection const & fnPosTable,
633 bool bInReadOnly )
634{
635 SwTableNode* pTableNd = rCurrentCursor.GetPoint()->nNode.GetNode().FindTableNode();
636 if( !pTableNd )
637 return false;
638
639 SwTextNode* pTextNode = nullptr;
640 if( &fnPosTable == &fnMoveBackward ) // to the end of the table
641 {
642 SwNodeIndex aIdx( *pTableNd->EndOfSectionNode() );
643 if( !lcl_FindPrevCell( aIdx, bInReadOnly ))
644 return false;
645 pTextNode = aIdx.GetNode().GetTextNode();
646 }
647 else
648 {
649 SwNodeIndex aIdx( *pTableNd );
650 if( !lcl_FindNextCell( aIdx, bInReadOnly ))
651 return false;
652 pTextNode = aIdx.GetNode().GetTextNode();
653 }
654
655 if ( pTextNode )
656 {
657 rCurrentCursor.GetPoint()->nNode = *pTextNode;
658 rCurrentCursor.GetPoint()->nContent.Assign( pTextNode, &fnPosTable == &fnMoveBackward ?
659 pTextNode->Len() :
660 0 );
661 }
662
663 return true;
664}
665
666bool SwCursor::MoveTable( SwWhichTable fnWhichTable, SwMoveFnCollection const & fnPosTable )
667{
668 bool bRet = false;
669 SwTableCursor* pTableCursor = dynamic_cast<SwTableCursor*>(this);
670
671 if( pTableCursor || !HasMark() )
672 {
673 SwCursorSaveState aSaveState( *this );
674 bRet = (*fnWhichTable)( *this, fnPosTable, IsReadOnlyAvailable() ) &&
675 !IsSelOvr( SwCursorSelOverFlags::CheckNodeSection |
676 SwCursorSelOverFlags::Toggle );
677 }
678 return bRet;
679}
680
681bool SwCursorShell::MoveTable( SwWhichTable fnWhichTable, SwMoveFnCollection const & fnPosTable )
682{
683 SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
684
685 SwShellCursor* pCursor = m_pTableCursor ? m_pTableCursor : m_pCurrentCursor;
686 bool bCheckPos;
687 bool bRet;
688 sal_uLong nPtNd = 0;
689 sal_Int32 nPtCnt = 0;
690
691 if ( !m_pTableCursor && m_pCurrentCursor->HasMark() )
692 {
693 // switch to table mode
694 m_pTableCursor = new SwShellTableCursor( *this, *m_pCurrentCursor->GetPoint() );
695 m_pCurrentCursor->DeleteMark();
696 m_pCurrentCursor->SwSelPaintRects::Hide();
697 m_pTableCursor->SetMark();
698 pCursor = m_pTableCursor;
699 bCheckPos = false;
700 }
701 else
702 {
703 bCheckPos = true;
704 nPtNd = pCursor->GetPoint()->nNode.GetIndex();
705 nPtCnt = pCursor->GetPoint()->nContent.GetIndex();
706 }
707
708 bRet = pCursor->MoveTable( fnWhichTable, fnPosTable );
709
710 if( bRet )
711 {
712 // #i45028# - set "top" position for repeated headline rows
713 pCursor->GetPtPos() = Point();
714
715 UpdateCursor(SwCursorShell::SCROLLWIN|SwCursorShell::CHKRANGE|SwCursorShell::READONLY);
716
717 if( bCheckPos &&
718 pCursor->GetPoint()->nNode.GetIndex() == nPtNd &&
719 pCursor->GetPoint()->nContent.GetIndex() == nPtCnt )
720 bRet = false;
721 }
722 return bRet;
723}
724
725bool SwCursorShell::IsTableComplexForChart()
726{
727 bool bRet = false;
728
729 // Here we may trigger table formatting so we better do that inside an action
730 StartAction();
731 const SwTableNode* pTNd = m_pCurrentCursor->GetPoint()->nNode.GetNode().FindTableNode();
732 if( pTNd )
733 {
734 // in a table; check if table or section is balanced
735 OUString sSel;
736 if( m_pTableCursor )
737 sSel = GetBoxNms();
738 bRet = pTNd->GetTable().IsTableComplexForChart( sSel );
739 }
740 EndAction();
741
742 return bRet;
743}
744
745OUString SwCursorShell::GetBoxNms() const
746{
747 OUString sNm;
748 const SwPosition* pPos;
749 SwFrame* pFrame;
750
751 if( IsTableMode() )
752 {
753 SwContentNode *pCNd = m_pTableCursor->Start()->nNode.GetNode().GetContentNode();
754 pFrame = pCNd ? pCNd->getLayoutFrame( GetLayout() ) : nullptr;
755 if( !pFrame )
756 return sNm;
757
758 do {
759 pFrame = pFrame->GetUpper();
760 } while ( pFrame && !pFrame->IsCellFrame() );
761
762 OSL_ENSURE( pFrame, "no frame for this box" )do { if (true && (!(pFrame))) { sal_detail_logFormat(
(SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx"
":" "762" ": "), "%s", "no frame for this box"); } } while (
false)
;
763
764 if( !pFrame )
765 return sNm;
766
767 sNm = static_cast<SwCellFrame*>(pFrame)->GetTabBox()->GetName() + ":";
768 pPos = m_pTableCursor->End();
769 }
770 else
771 {
772 const SwTableNode* pTableNd = IsCursorInTable();
773 if( !pTableNd )
774 return sNm;
775 pPos = GetCursor()->GetPoint();
776 }
777
778 SwContentNode* pCNd = pPos->nNode.GetNode().GetContentNode();
779 pFrame = pCNd ? pCNd->getLayoutFrame( GetLayout() ) : nullptr;
780
781 if( pFrame )
782 {
783 do {
784 pFrame = pFrame->GetUpper();
785 } while ( pFrame && !pFrame->IsCellFrame() );
786
787 if( pFrame )
788 sNm += static_cast<SwCellFrame*>(pFrame)->GetTabBox()->GetName();
789 }
790 return sNm;
791}
792
793bool SwCursorShell::GotoTable( const OUString& rName )
794{
795 SwCallLink aLk( *this ); // watch Cursor-Moves
796 bool bRet = !m_pTableCursor && m_pCurrentCursor->GotoTable( rName );
797 if( bRet )
798 {
799 m_pCurrentCursor->GetPtPos() = Point();
800 UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
801 SwCursorShell::READONLY );
802 }
803 return bRet;
804}
805
806bool SwCursorShell::CheckTableBoxContent( const SwPosition* pPos )
807{
808 if( !m_pBoxIdx || !m_pBoxPtr || IsSelTableCells() || !IsAutoUpdateCells() )
809 return false;
810
811 // check if box content is consistent with given box format, reset if not
812 SwTableBox* pChkBox = nullptr;
813 SwStartNode* pSttNd = nullptr;
814 if( !pPos )
815 {
816 // get stored position
817 if (nullptr != (pSttNd = m_pBoxIdx->GetNode().GetStartNode()) &&
818 SwTableBoxStartNode == pSttNd->GetStartNodeType() &&
819 m_pBoxPtr == pSttNd->FindTableNode()->GetTable().
820 GetTableBox( m_pBoxIdx->GetIndex() ) )
821 pChkBox = m_pBoxPtr;
822 }
823 else
824 {
825 pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode );
826 if( pSttNd)
827 pChkBox = pSttNd->FindTableNode()->GetTable().GetTableBox( pSttNd->GetIndex() );
828 }
829
830 // box has more than one paragraph
831 if( pChkBox && pSttNd->GetIndex() + 2 != pSttNd->EndOfSectionIndex() )
832 pChkBox = nullptr;
833
834 // destroy pointer before next action starts
835 if( !pPos && !pChkBox )
836 ClearTableBoxContent();
837
838 // cursor not anymore in this section?
839 if( pChkBox && !pPos &&
840 ( m_pCurrentCursor->HasMark() || m_pCurrentCursor->GetNext() != m_pCurrentCursor ||
841 pSttNd->GetIndex() + 1 == m_pCurrentCursor->GetPoint()->nNode.GetIndex() ))
842 pChkBox = nullptr;
843
844 // Did the content of a box change at all? This is important if e.g. Undo
845 // could not restore the content properly.
846 if( pChkBox )
847 {
848 const SwTextNode* pNd = GetDoc()->GetNodes()[
849 pSttNd->GetIndex() + 1 ]->GetTextNode();
850 if( !pNd ||
851 ( pNd->GetText() == SwViewShell::GetShellRes()->aCalc_Error &&
852 SfxItemState::SET == pChkBox->GetFrameFormat()->
853 GetItemState( RES_BOXATR_FORMULA )) )
854 pChkBox = nullptr;
855 }
856
857 if( pChkBox )
858 {
859 // destroy pointer before next action starts
860 ClearTableBoxContent();
861 StartAction();
862 GetDoc()->ChkBoxNumFormat( *pChkBox, true );
863 EndAction();
864 }
865
866 return nullptr != pChkBox;
867}
868
869void SwCursorShell::SaveTableBoxContent( const SwPosition* pPos )
870{
871 if( IsSelTableCells() || !IsAutoUpdateCells() )
872 return ;
873
874 if( !pPos )
875 pPos = m_pCurrentCursor->GetPoint();
876
877 SwStartNode* pSttNd = pPos->nNode.GetNode().FindSttNodeByType( SwTableBoxStartNode );
878
879 bool bCheckBox = false;
880 if( pSttNd && m_pBoxIdx )
881 {
882 if( pSttNd == &m_pBoxIdx->GetNode() )
883 pSttNd = nullptr;
884 else
885 bCheckBox = true;
886 }
887 else
888 bCheckBox = nullptr != m_pBoxIdx;
889
890 if( bCheckBox )
891 {
892 // check m_pBoxIdx
893 SwPosition aPos( *m_pBoxIdx );
894 CheckTableBoxContent( &aPos );
895 }
896
897 if( pSttNd )
898 {
899 m_pBoxPtr = pSttNd->FindTableNode()->GetTable().GetTableBox( pSttNd->GetIndex() );
900
901 if( m_pBoxIdx )
902 *m_pBoxIdx = *pSttNd;
903 else
904 m_pBoxIdx = new SwNodeIndex( *pSttNd );
905 }
906}
907
908void SwCursorShell::ClearTableBoxContent()
909{
910 delete m_pBoxIdx;
911 m_pBoxIdx = nullptr;
912 m_pBoxPtr = nullptr;
913}
914
915bool SwCursorShell::EndAllTableBoxEdit()
916{
917 bool bRet = false;
918 for(SwViewShell& rSh : GetRingContainer())
919 {
920 if( dynamic_cast<const SwCursorShell *>(&rSh) != nullptr )
921 bRet |= static_cast<SwCursorShell*>(&rSh)->CheckTableBoxContent(
922 static_cast<SwCursorShell*>(&rSh)->m_pCurrentCursor->GetPoint() );
923
924 }
925 return bRet;
926}
927
928/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/sw/inc/ndindex.hxx

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#ifndef INCLUDED_SW_INC_NDINDEX_HXX
20#define INCLUDED_SW_INC_NDINDEX_HXX
21
22#include <iostream>
23
24#include <tools/solar.h>
25
26#include "node.hxx"
27#include "ring.hxx"
28#include "ndarr.hxx"
29
30/// Marks a node in the document model.
31class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwNodeIndex final : public sw::Ring<SwNodeIndex>
32{
33 SwNode * m_pNode;
34
35 // These are not allowed!
36 SwNodeIndex( SwNodes& rNds, sal_uInt16 nIdx ) = delete;
37 SwNodeIndex( SwNodes& rNds, int nIdx ) = delete;
38 void RegisterIndex( SwNodes& rNodes )
39 {
40 if(!rNodes.m_vIndices)
41 rNodes.m_vIndices = this;
42 MoveTo(rNodes.m_vIndices);
43 }
44 void DeRegisterIndex( SwNodes& rNodes )
45 {
46 if(rNodes.m_vIndices == this)
47 rNodes.m_vIndices = GetNextInRing();
48 MoveTo(nullptr);
49 if(rNodes.m_vIndices == this)
50 rNodes.m_vIndices = nullptr;
51 }
52
53public:
54 SwNodeIndex( SwNodes& rNds, sal_uLong nIdx = 0 )
55 : m_pNode( rNds[ nIdx ] )
56 {
57 RegisterIndex( rNds );
58 };
59 SwNodeIndex( const SwNodeIndex& rIdx, long nDiff = 0 )
60 : sw::Ring<SwNodeIndex>()
61 {
62 if( nDiff )
63 m_pNode = rIdx.GetNodes()[ rIdx.GetIndex() + nDiff ];
64 else
65 m_pNode = rIdx.m_pNode;
66 RegisterIndex( m_pNode->GetNodes() );
67 }
68
69 SwNodeIndex( const SwNode& rNd, long nDiff = 0 )
70 {
71 if( nDiff )
72 m_pNode = rNd.GetNodes()[ rNd.GetIndex() + nDiff ];
73 else
74 m_pNode = const_cast<SwNode*>(&rNd);
75 RegisterIndex( m_pNode->GetNodes() );
76 }
77
78 virtual ~SwNodeIndex() override
79 { DeRegisterIndex( m_pNode->GetNodes() ); }
80
81 inline sal_uLong operator++();
82 inline sal_uLong operator--();
83 inline sal_uLong operator++(int);
84 inline sal_uLong operator--(int);
85
86 inline sal_uLong operator+=( sal_uLong );
87 inline sal_uLong operator-=( sal_uLong );
88
89 inline bool operator< ( const SwNodeIndex& ) const;
90 inline bool operator<=( const SwNodeIndex& ) const;
91 inline bool operator> ( const SwNodeIndex& ) const;
92 inline bool operator>=( const SwNodeIndex& ) const;
93 inline bool operator==( const SwNodeIndex& ) const;
94 inline bool operator!=( const SwNodeIndex& ) const;
95
96 inline bool operator< ( sal_uLong ) const;
97 inline bool operator<=( sal_uLong ) const;
98 inline bool operator> ( sal_uLong ) const;
99 inline bool operator>=( sal_uLong ) const;
100 inline bool operator==( sal_uLong ) const;
101 inline bool operator!=( sal_uLong ) const;
102
103 inline SwNodeIndex& operator=( sal_uLong );
104 inline SwNodeIndex& operator=( const SwNodeIndex& );
105 inline SwNodeIndex& operator=( const SwNode& );
106
107 // Return value of index as sal_uLong.
108 inline sal_uLong GetIndex() const;
109
110 // Enables assignments without creation of a temporary object.
111 inline SwNodeIndex& Assign( SwNodes const & rNds, sal_uLong );
112 inline SwNodeIndex& Assign( const SwNode& rNd, long nOffset = 0 );
113
114 // Gets pointer on NodesArray.
115 inline const SwNodes& GetNodes() const;
116 inline SwNodes& GetNodes();
117
118 SwNodeIndex* GetNext() { return GetNextInRing(); }
119 SwNode& GetNode() const { return *m_pNode; }
120};
121
122inline std::ostream &operator <<(std::ostream& s, const SwNodeIndex& index)
123{
124 return s << "SwNodeIndex (node " << index.GetIndex() << ")";
125};
126
127// SwRange
128
129class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwNodeRange
130{
131public:
132 SwNodeIndex aStart;
133 SwNodeIndex aEnd;
134
135 SwNodeRange( const SwNodeIndex &rS, const SwNodeIndex &rE )
136 : aStart( rS ), aEnd( rE ) {};
137 SwNodeRange( const SwNodeRange &rRange )
138 : aStart( rRange.aStart ), aEnd( rRange.aEnd ) {};
139
140 SwNodeRange( SwNodes& rNds, sal_uLong nSttIdx, sal_uLong nEndIdx = 0 )
141 : aStart( rNds, nSttIdx ), aEnd( rNds, nEndIdx ) {};
142
143 SwNodeRange( const SwNodeIndex& rS, long nSttDiff, const SwNodeIndex& rE, long nEndDiff = 0 )
144 : aStart( rS, nSttDiff ), aEnd( rE, nEndDiff ) {};
145 SwNodeRange( const SwNode& rS, long nSttDiff, const SwNode& rE, long nEndDiff = 0 )
146 : aStart( rS, nSttDiff ), aEnd( rE, nEndDiff ) {};
147};
148
149// For inlines node.hxx is needed which in turn needs this one.
150// Therefore all inlines accessing m_pNode are implemented here.
151
152inline sal_uLong SwNodeIndex::GetIndex() const
153{
154 return m_pNode->GetIndex();
5
Calling 'SwNode::GetIndex'
12
Returning from 'SwNode::GetIndex'
13
Returning value, which participates in a condition later
17
Calling 'SwNode::GetIndex'
24
Returning from 'SwNode::GetIndex'
25
Returning value, which participates in a condition later
32
Calling 'SwNode::GetIndex'
39
Returning from 'SwNode::GetIndex'
40
Returning value, which participates in a condition later
44
Calling 'SwNode::GetIndex'
51
Returning from 'SwNode::GetIndex'
52
Returning value, which participates in a condition later
155}
156inline const SwNodes& SwNodeIndex::GetNodes() const
157{
158 return m_pNode->GetNodes();
159}
160inline SwNodes& SwNodeIndex::GetNodes()
161{
162 return m_pNode->GetNodes();
163}
164inline bool SwNodeIndex::operator< ( sal_uLong const nOther ) const
165{
166 return m_pNode->GetIndex() < nOther;
167}
168inline bool SwNodeIndex::operator<=( sal_uLong const nOther ) const
169{
170 return m_pNode->GetIndex() <= nOther;
171}
172inline bool SwNodeIndex::operator> ( sal_uLong const nOther ) const
173{
174 return m_pNode->GetIndex() > nOther;
175}
176inline bool SwNodeIndex::operator>=( sal_uLong const nOther ) const
177{
178 return m_pNode->GetIndex() >= nOther;
179}
180inline bool SwNodeIndex::operator==( sal_uLong const nOther ) const
181{
182 return m_pNode->GetIndex() == nOther;
183}
184inline bool SwNodeIndex::operator!=( sal_uLong const nOther ) const
185{
186 return m_pNode->GetIndex() != nOther;
187}
188inline bool SwNodeIndex::operator<( const SwNodeIndex& rIndex ) const
189{
190 return m_pNode->GetIndex() < rIndex.GetIndex();
191}
192inline bool SwNodeIndex::operator<=( const SwNodeIndex& rIndex ) const
193{
194 return m_pNode->GetIndex() <= rIndex.GetIndex();
195}
196inline bool SwNodeIndex::operator>( const SwNodeIndex& rIndex ) const
197{
198 return m_pNode->GetIndex() > rIndex.GetIndex();
199}
200inline bool SwNodeIndex::operator>=( const SwNodeIndex& rIndex ) const
201{
202 return m_pNode->GetIndex() >= rIndex.GetIndex();
203}
204inline bool SwNodeIndex::operator==( const SwNodeIndex& rIdx ) const
205{
206 return m_pNode == rIdx.m_pNode;
207}
208inline bool SwNodeIndex::operator!=( const SwNodeIndex& rIdx ) const
209{
210 return m_pNode != rIdx.m_pNode;
211}
212
213inline sal_uLong SwNodeIndex::operator++()
214{
215 m_pNode = GetNodes()[ m_pNode->GetIndex()+1 ];
216 return m_pNode->GetIndex();
217}
218inline sal_uLong SwNodeIndex::operator--()
219{
220 m_pNode = GetNodes()[ m_pNode->GetIndex()-1 ];
221 return m_pNode->GetIndex();
222}
223inline sal_uLong SwNodeIndex::operator++(int)
224{
225 sal_uLong nOldIndex = m_pNode->GetIndex();
226 m_pNode = GetNodes()[ nOldIndex + 1 ];
227 return nOldIndex;
228}
229inline sal_uLong SwNodeIndex::operator--(int)
230{
231 sal_uLong nOldIndex = m_pNode->GetIndex();
232 m_pNode = GetNodes()[ nOldIndex - 1 ];
233 return nOldIndex;
234}
235
236inline sal_uLong SwNodeIndex::operator+=( sal_uLong const nOffset )
237{
238 m_pNode = GetNodes()[ m_pNode->GetIndex() + nOffset ];
239 return m_pNode->GetIndex();
240}
241inline sal_uLong SwNodeIndex::operator-=( sal_uLong const nOffset )
242{
243 m_pNode = GetNodes()[ m_pNode->GetIndex() - nOffset ];
244 return m_pNode->GetIndex();
245}
246
247inline SwNodeIndex& SwNodeIndex::operator=( sal_uLong const nNew )
248{
249 m_pNode = GetNodes()[ nNew ];
250 return *this;
251}
252
253SwNodeIndex& SwNodeIndex::operator=( const SwNodeIndex& rIdx )
254{
255 *this = *(rIdx.m_pNode);
256 return *this;
257}
258
259SwNodeIndex& SwNodeIndex::operator=( const SwNode& rNd )
260{
261 if (&m_pNode->GetNodes() != &rNd.GetNodes())
262 {
263 DeRegisterIndex( m_pNode->GetNodes() );
264 m_pNode = const_cast<SwNode*>(&rNd);
265 RegisterIndex( m_pNode->GetNodes() );
266 }
267 else
268 m_pNode = const_cast<SwNode*>(&rNd);
269 return *this;
270}
271
272SwNodeIndex& SwNodeIndex::Assign( SwNodes const & rNds, sal_uLong nIdx )
273{
274 *this = *rNds[ nIdx ];
275 return *this;
276}
277
278SwNodeIndex& SwNodeIndex::Assign( const SwNode& rNd, long nOffset )
279{
280 *this = rNd;
281
282 if( nOffset )
283 m_pNode = m_pNode->GetNodes()[ m_pNode->GetIndex() + nOffset ];
284
285 return *this;
286}
287
288#endif
289
290/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/sw/inc/node.hxx

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#ifndef INCLUDED_SW_INC_NODE_HXX
21#define INCLUDED_SW_INC_NODE_HXX
22
23#include <sal/types.h>
24
25#include "swdllapi.h"
26#include "ndarr.hxx"
27#include "ndtyp.hxx"
28#include "index.hxx"
29#include "fmtcol.hxx"
30
31#include <memory>
32#include <vector>
33
34class SwContentFrame;
35class SwContentNode;
36class SwDoc;
37class SwEndNode;
38class SwFrame;
39class SwFrameFormat;
40class SwGrfNode;
41class SwNoTextNode;
42class SwNodeIndex;
43class SwOLENode;
44class SwRect;
45class SwSection;
46class SwSectionFormat;
47class SwTOXBase;
48class SwSectionNode;
49class SwStartNode;
50class SwTabFrame;
51class SwRootFrame;
52class SwTable;
53class SwTableNode;
54class SwTableBox;
55class SwTextNode;
56class SwPageDesc;
57class SwViewShell;
58struct SwPosition;
59class IStyleAccess;
60class IDocumentSettingAccess;
61class IDocumentDeviceAccess;
62class IDocumentMarkAccess;
63class IDocumentRedlineAccess;
64class IDocumentStylePoolAccess;
65class IDocumentLinksAdministration;
66class IDocumentFieldsAccess;
67class IDocumentContentOperations;
68class IDocumentListItems;
69class Point;
70enum class SvxFrameDirection;
71typedef std::vector<SwOLENode*> SwOLENodes; // docary.hxx
72
73namespace drawinglayer::attribute {
74 class SdrAllFillAttributesHelper;
75 typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr;
76}
77
78/// Base class of the Writer document model elements.
79class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwNode
80 : private BigPtrEntry
81{
82 friend class SwNodes;
83
84 SwNodeType m_nNodeType;
85
86 /// For text nodes: level of auto format. Was put here because we had still free bits.
87 sal_uInt8 m_nAFormatNumLvl : 3;
88 bool m_bIgnoreDontExpand : 1; ///< for Text Attributes - ignore the flag
89
90public:
91 /// sw_redlinehide: redline node merge state
92 enum class Merge { None, First, NonFirst, Hidden };
93 bool IsCreateFrameWhenHidingRedlines() const {
94 return m_eMerge == Merge::None || m_eMerge == Merge::First;
95 }
96 void SetRedlineMergeFlag(Merge const eMerge) { m_eMerge = eMerge; }
97 Merge GetRedlineMergeFlag() const { return m_eMerge; }
98private:
99 Merge m_eMerge;
100
101#ifdef DBG_UTIL
102 static long s_nSerial;
103 long m_nSerial;
104#endif
105
106 /// all SwFrameFormat that are anchored at the node
107 /// invariant: SwFrameFormat is in the list iff
108 /// SwFrameFormat::GetAnchor().GetContentAnchor() points to this node
109 std::unique_ptr<std::vector<SwFrameFormat*>> m_pAnchoredFlys;
110
111protected:
112 SwStartNode* m_pStartOfSection;
113
114 SwNode( const SwNodeIndex &rWhere, const SwNodeType nNodeId );
115
116 /// for the initial StartNode
117 SwNode( SwNodes& rNodes, sal_uLong nPos, const SwNodeType nNodeId );
118
119public:
120 /** the = 0 forces the class to be an abstract base class, but the dtor can be still called
121 from subclasses */
122 virtual ~SwNode() override = 0;
123
124#ifdef DBG_UTIL
125 long GetSerial() const { return m_nSerial; }
126#endif
127
128 sal_uInt16 GetSectionLevel() const;
129
130 inline sal_uLong StartOfSectionIndex() const;
131 const SwStartNode* StartOfSectionNode() const { return m_pStartOfSection; }
132 SwStartNode* StartOfSectionNode() { return m_pStartOfSection; }
133
134 inline sal_uLong EndOfSectionIndex() const;
135 inline const SwEndNode* EndOfSectionNode() const;
136 inline SwEndNode* EndOfSectionNode();
137
138 sal_uInt8 GetAutoFormatLvl() const { return m_nAFormatNumLvl; }
139 void SetAutoFormatLvl( sal_uInt8 nVal ) { m_nAFormatNumLvl = nVal; }
140
141 bool IsIgnoreDontExpand() const { return m_bIgnoreDontExpand; }
142 void SetIgnoreDontExpand( bool bNew ) { m_bIgnoreDontExpand = bNew; }
143
144 SwNodeType GetNodeType() const { return m_nNodeType; }
145
146 inline SwStartNode *GetStartNode();
147 inline const SwStartNode *GetStartNode() const;
148 inline SwContentNode *GetContentNode();
149 inline const SwContentNode *GetContentNode() const;
150 inline SwEndNode *GetEndNode();
151 inline const SwEndNode *GetEndNode() const;
152 inline SwTextNode *GetTextNode();
153 inline const SwTextNode *GetTextNode() const;
154 inline SwOLENode *GetOLENode();
155 inline const SwOLENode *GetOLENode() const;
156 inline SwNoTextNode *GetNoTextNode();
157 inline const SwNoTextNode *GetNoTextNode() const;
158 inline SwGrfNode *GetGrfNode();
159 inline const SwGrfNode *GetGrfNode() const;
160 inline SwTableNode *GetTableNode();
161 inline const SwTableNode *GetTableNode() const;
162 inline SwSectionNode *GetSectionNode();
163 inline const SwSectionNode *GetSectionNode() const;
164
165 inline bool IsStartNode() const;
166 inline bool IsContentNode() const;
167 inline bool IsEndNode() const;
168 inline bool IsTextNode() const;
169 inline bool IsTableNode() const;
170 inline bool IsSectionNode() const;
171 inline bool IsOLENode() const;
172 inline bool IsNoTextNode() const;
173 inline bool IsGrfNode() const;
174
175 /**
176 Checks if this node is in redlines.
177
178 @retval true this node is in redlines
179 @retval false else
180 */
181 bool IsInRedlines() const;
182
183 /** Search table node, in which it is. If it is in no table
184 @return 0. */
185 SwTableNode *FindTableNode();
186 inline const SwTableNode *FindTableNode() const;
187
188 /** Search section node, in which it is. If it is in no section
189 @return 0. */
190 SwSectionNode *FindSectionNode();
191 inline const SwSectionNode *FindSectionNode() const;
192
193 SwStartNode* FindSttNodeByType( SwStartNodeType eTyp );
194 inline const SwStartNode* FindSttNodeByType( SwStartNodeType eTyp ) const;
195
196 const SwStartNode* FindTableBoxStartNode() const
197 { return FindSttNodeByType( SwTableBoxStartNode ); }
198 const SwStartNode* FindFlyStartNode() const
199 { return FindSttNodeByType( SwFlyStartNode ); }
200 const SwStartNode* FindFootnoteStartNode() const
201 { return FindSttNodeByType( SwFootnoteStartNode ); }
202 const SwStartNode* FindHeaderStartNode() const
203 { return FindSttNodeByType( SwHeaderStartNode ); }
204 const SwStartNode* FindFooterStartNode() const
205 { return FindSttNodeByType( SwFooterStartNode ); }
206
207 /// Node is in which nodes-array/doc?
208 inline SwNodes& GetNodes();
209 inline const SwNodes& GetNodes() const;
210
211 SwDoc& GetDoc()
212 {
213 return GetNodes().GetDoc();
214 }
215
216 const SwDoc& GetDoc() const
217 {
218 return GetNodes().GetDoc();
219 }
220
221 /** Provides access to the document setting interface
222 */
223 const IDocumentSettingAccess* getIDocumentSettingAccess() const;
224
225 /** Provides access to the document device interface
226 */
227 const IDocumentDeviceAccess& getIDocumentDeviceAccess() const;
228
229 /** Provides access to the document bookmark interface
230 */
231 const IDocumentMarkAccess* getIDocumentMarkAccess() const;
232
233 /** Provides access to the document redline interface
234 */
235 const IDocumentRedlineAccess& getIDocumentRedlineAccess() const;
236
237 /** Provides access to the document style pool interface
238 */
239 const IDocumentStylePoolAccess& getIDocumentStylePoolAccess() const;
240
241 /** Provides access to the document draw model interface
242 */
243 const IDocumentDrawModelAccess& getIDocumentDrawModelAccess() const;
244
245 /** Provides access to the document layout interface
246 */
247 const IDocumentLayoutAccess& getIDocumentLayoutAccess() const;
248 IDocumentLayoutAccess& getIDocumentLayoutAccess();
249
250 /** Provides access to the document links administration interface
251 */
252 const IDocumentLinksAdministration& getIDocumentLinksAdministration() const;
253 IDocumentLinksAdministration& getIDocumentLinksAdministration();
254
255 /** Provides access to the document fields administration interface
256 */
257 const IDocumentFieldsAccess& getIDocumentFieldsAccess() const;
258 IDocumentFieldsAccess& getIDocumentFieldsAccess();
259
260 /** Provides access to the document content operations interface
261 */
262 IDocumentContentOperations& getIDocumentContentOperations();
263
264 /** Provides access to the document automatic styles interface
265 */
266 IStyleAccess& getIDocumentStyleAccess();
267
268 /** Provides access to the document's numbered items interface */
269 IDocumentListItems& getIDocumentListItems();
270
271 /// Is node in the visible area of the Shell?
272 bool IsInVisibleArea( SwViewShell const * pSh ) const;
273 /// Is node in a protected area?
274 bool IsInProtectSect() const;
275 /** Is node in something that is protected (range, frame,
276 table cells ... including anchor in case of frames or footnotes)? */
277 bool IsProtect() const;
278
279 /** Search PageDesc with which this node is formatted. If layout is existent
280 search over layout, else only the hard way is left: search over the nodes
281 to the front!! */
282 const SwPageDesc* FindPageDesc( size_t* pPgDescNdIdx = nullptr ) const;
283
284 /// If node is in a fly return the respective format.
285 SwFrameFormat* GetFlyFormat() const;
286
287 /// If node is in a table return the respective table box.
288 SwTableBox* GetTableBox() const;
289
290 sal_uLong GetIndex() const { return GetPos(); }
6
Calling 'BigPtrEntry::GetPos'
10
Returning from 'BigPtrEntry::GetPos'
11
Returning value, which participates in a condition later
18
Calling 'BigPtrEntry::GetPos'
22
Returning from 'BigPtrEntry::GetPos'
23
Returning value, which participates in a condition later
33
Calling 'BigPtrEntry::GetPos'
37
Returning from 'BigPtrEntry::GetPos'
38
Returning value, which participates in a condition later
45
Calling 'BigPtrEntry::GetPos'
49
Returning from 'BigPtrEntry::GetPos'
50
Returning value, which participates in a condition later
291
292 const SwTextNode* FindOutlineNodeOfLevel(sal_uInt8 nLvl, SwRootFrame const* pLayout = nullptr) const;
293
294 sal_uInt8 HasPrevNextLayNode() const;
295
296 std::vector<SwFrameFormat *> const* GetAnchoredFlys() const { return m_pAnchoredFlys.get(); }
297 void AddAnchoredFly(SwFrameFormat *);
298 void RemoveAnchoredFly(SwFrameFormat *);
299
300 /**
301 * Dumps the node structure to the given destination (file nodes.xml in the current directory by default)
302 */
303 virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
304
305private:
306 SwNode( const SwNode & rNodes ) = delete;
307 SwNode & operator= ( const SwNode & rNodes ) = delete;
308};
309
310/// Starts a section of nodes in the document model.
311class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwStartNode: public SwNode
312{
313 friend class SwNode;
314 friend class SwNodes;
315 friend class SwEndNode; ///< to set the theEndOfSection !!
316
317 SwEndNode* m_pEndOfSection;
318 SwStartNodeType m_eStartNodeType;
319
320 /// for the initial StartNode
321 SwStartNode( SwNodes& rNodes, sal_uLong nPos );
322
323protected:
324 SwStartNode( const SwNodeIndex &rWhere,
325 const SwNodeType nNodeType = SwNodeType::Start,
326 SwStartNodeType = SwNormalStartNode );
327public:
328 SwStartNodeType GetStartNodeType() const { return m_eStartNodeType; }
329
330 /// Call ChkCondcoll to all ContentNodes of section.
331 void CheckSectionCondColl() const;
332
333 virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override;
334
335private:
336 SwStartNode( const SwStartNode & rNode ) = delete;
337 SwStartNode & operator= ( const SwStartNode & rNode ) = delete;
338};
339
340/// Ends a section of nodes in the document model.
341class SwEndNode : public SwNode
342{
343 friend class SwNodes;
344 friend class SwTableNode; ///< To enable creation of its EndNote.
345 friend class SwSectionNode; ///< To enable creation of its EndNote.
346
347 /// for the initial StartNode
348 SwEndNode( SwNodes& rNodes, sal_uLong nPos, SwStartNode& rSttNd );
349
350protected:
351 SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd );
352
353private:
354 SwEndNode( const SwEndNode & rNode ) = delete;
355 SwEndNode & operator= ( const SwEndNode & rNode ) = delete;
356};
357
358// SwContentNode
359
360class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwContentNode: public sw::BroadcastingModify, public SwNode, public SwIndexReg
361{
362
363 sw::WriterMultiListener m_aCondCollListener;
364 SwFormatColl* m_pCondColl;
365 mutable bool mbSetModifyAtAttr;
366
367protected:
368 SwContentNode( const SwNodeIndex &rWhere, const SwNodeType nNodeType,
369 SwFormatColl *pFormatColl );
370 /** the = 0 forces the class to be an abstract base class, but the dtor can be still called
371 from subclasses */
372 virtual ~SwContentNode() override = 0;
373
374 /** Attribute-set for all auto attributes of a ContentNode.
375 (e.g. TextNode or NoTextNode). */
376 std::shared_ptr<const SfxItemSet> mpAttrSet;
377
378 /// Make respective nodes create the specific AttrSets.
379 virtual void NewAttrSet( SwAttrPool& ) = 0;
380
381 /** There some functions that like to remove items from the internal
382 SwAttrSet (handle): */
383 sal_uInt16 ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds );
384
385 virtual void SwClientNotify( const SwModify&, const SfxHint& rHint) override;
386
387public:
388
389 /** MakeFrame will be called for a certain layout
390 pSib is another SwFrame of the same layout (e.g. the SwRootFrame itself, a sibling, the parent) */
391 virtual SwContentFrame *MakeFrame( SwFrame* pSib ) = 0;
392
393 virtual SwContentNode *JoinNext();
394 /** Is it possible to join two nodes?
395 In pIdx the second position can be returned. */
396 bool CanJoinNext( SwNodeIndex* pIdx =nullptr ) const;
397 bool CanJoinPrev( SwNodeIndex* pIdx =nullptr ) const;
398
399 void MakeStartIndex( SwIndex * pIdx ) { pIdx->Assign( this, 0 ); }
400 void MakeEndIndex( SwIndex * pIdx ) { pIdx->Assign( this, Len() ); }
401
402 bool GoNext(SwIndex *, sal_uInt16 nMode ) const;
403 bool GoPrevious(SwIndex *, sal_uInt16 nMode ) const;
404
405 /// @see GetFrameOfModify
406 SwContentFrame *getLayoutFrame( const SwRootFrame*,
407 const SwPosition *pPos = nullptr,
408 std::pair<Point, bool> const* pViewPosAndCalcFrame = nullptr) const;
409 /** @return the real size of the frame or an empty rectangle if
410 no layout exists. Needed for export filters. */
411 SwRect FindLayoutRect( const bool bPrtArea = false,
412 const Point* pPoint = nullptr ) const;
413 SwRect FindPageFrameRect() const;
414
415 /** Method creates all views of document for given node. The content
416 frames that are created are put in the respective layout. */
417 void MakeFramesForAdjacentContentNode(SwContentNode& rNode);
418
419 /** Method deletes all views of document for the node. The content-
420 frames are removed from the respective layout.
421 */
422 void DelFrames(SwRootFrame const* pLayout);
423
424 /** @return count of elements of node content. Default is 1.
425 There are differences between text node and formula node. */
426 virtual sal_Int32 Len() const;
427
428 virtual SwContentNode* MakeCopy(SwDoc&, const SwNodeIndex&, bool bNewFrames) const = 0;
429
430 /// Get information from Client.
431 virtual bool GetInfo( SfxPoolItem& ) const override;
432
433 /// SS for PoolItems: hard attributation.
434
435 /// If bInParent is FALSE search for attribute only in this node.
436 const SfxPoolItem& GetAttr( sal_uInt16 nWhich, bool bInParent=true ) const;
437 bool GetAttr( SfxItemSet& rSet ) const;
438 /// made virtual
439 virtual bool SetAttr( const SfxPoolItem& );
440 virtual bool SetAttr( const SfxItemSet& rSet );
441 virtual bool ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 = 0 );
442 virtual bool ResetAttr( const std::vector<sal_uInt16>& rWhichArr );
443 virtual sal_uInt16 ResetAllAttr();
444
445 /// Obtains attribute that is not delivered via conditional style!
446 const SfxPoolItem* GetNoCondAttr( sal_uInt16 nWhich, bool bInParents ) const;
447
448 /** Does node has already its own auto-attributes?
449 Access to SwAttrSet. */
450 inline const SwAttrSet &GetSwAttrSet() const;
451 const SwAttrSet *GetpSwAttrSet() const { return static_cast<const SwAttrSet*>(mpAttrSet.get()); }
452 bool HasSwAttrSet() const { return mpAttrSet != nullptr; }
453
454 virtual SwFormatColl* ChgFormatColl( SwFormatColl* );
455 SwFormatColl* GetFormatColl() const { return const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(GetRegisteredIn())); }
456
457//FEATURE::CONDCOLL
458 inline SwFormatColl& GetAnyFormatColl() const;
459 void SetCondFormatColl( SwFormatColl* );
460 inline SwFormatColl* GetCondFormatColl() const;
461
462 bool IsAnyCondition( SwCollCondition& rTmp ) const;
463 void ChkCondColl();
464//FEATURE::CONDCOLL
465
466 /** Invalidates NumRule at the node. NumRule is updated
467 on EndAction of a Shell at the latest. */
468 bool InvalidateNumRule();
469
470 /** determines the text direction for a certain
471 position. @return -1, if text direction could *not* be determined. */
472 SvxFrameDirection GetTextDirection( const SwPosition& rPos,
473 const Point* pPt ) const;
474
475 void SetModifyAtAttr( bool bSetModifyAtAttr ) const { mbSetModifyAtAttr = bSetModifyAtAttr; }
476 bool GetModifyAtAttr() const { return mbSetModifyAtAttr; }
477
478 static std::unique_ptr<SwOLENodes> CreateOLENodesArray( const SwFormatColl& rColl, bool bOnlyWithInvalidSize );
479
480 // Access to DrawingLayer FillAttributes in a preprocessed form for primitive usage
481 virtual drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const;
482
483 virtual void ModifyNotification(const SfxPoolItem* pOld, const SfxPoolItem* pNew) override
484 {
485 SwClientNotify(*this, sw::LegacyModifyHint(pOld, pNew));
486 }
487
488private:
489 SwContentNode( const SwContentNode & rNode ) = delete;
490 SwContentNode & operator= ( const SwContentNode & rNode ) = delete;
491};
492
493// SwTableNode
494
495class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwTableNode : public SwStartNode, public sw::BroadcastingModify
496{
497 friend class SwNodes;
498 std::unique_ptr<SwTable> m_pTable;
499protected:
500 virtual ~SwTableNode() override;
501
502public:
503 SwTableNode( const SwNodeIndex & );
504
505 const SwTable& GetTable() const { return *m_pTable; }
506 SwTable& GetTable() { return *m_pTable; }
507 SwTabFrame *MakeFrame( SwFrame* );
508
509 /// Creates the frms for the table node (i.e. the TabFrames).
510 void MakeOwnFrames(SwNodeIndex* pIdxBehind);
511
512 /** Method deletes all views of document for the node.
513 The content frames are removed from the respective layout. */
514 void DelFrames(SwRootFrame const* pLayout = nullptr);
515
516 /** Method creates all views of the document for the previous node.
517 The content frames that are created are put into the respective layout. */
518 void MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx);
519
520 SwTableNode* MakeCopy( SwDoc&, const SwNodeIndex& ) const;
521 void SetNewTable( std::unique_ptr<SwTable> , bool bNewFrames=true );
522
523 // Removes redline objects that relate to this table from the 'Extra Redlines' table
524 void RemoveRedlines();
525
526private:
527 SwTableNode( const SwTableNode & rNode ) = delete;
528 SwTableNode & operator= ( const SwTableNode & rNode ) = delete;
529};
530
531class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwSectionNode
532 : public SwStartNode
533{
534 friend class SwNodes;
535
536private:
537 SwSectionNode(const SwSectionNode&) = delete;
538 SwSectionNode& operator=(const SwSectionNode&) = delete;
539
540 std::unique_ptr<SwSection> const m_pSection;
541
542protected:
543 virtual ~SwSectionNode() override;
544
545public:
546 SwSectionNode(SwNodeIndex const&,
547 SwSectionFormat & rFormat, SwTOXBase const*const pTOXBase);
548
549 const SwSection& GetSection() const { return *m_pSection; }
550 SwSection& GetSection() { return *m_pSection; }
551
552 SwFrame *MakeFrame( SwFrame* );
553
554 /** Creates the frms for the SectionNode (i.e. the SectionFrames).
555 On default the frames are created until the end of the range.
556 When another NodeIndex pEnd is passed a MakeFrames is called up to it.
557 Used by TableToText. */
558 void MakeOwnFrames(SwNodeIndex* pIdxBehind, SwNodeIndex* pEnd = nullptr);
559
560 /** Method deletes all views of document for the node. The
561 content frames are removed from the respective layout. */
562 void DelFrames(SwRootFrame const* pLayout = nullptr, bool bForce = false);
563
564 /** Method creates all views of document for the previous node.
565 The content frames created are put into the respective layout. */
566 void MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx);
567
568 SwSectionNode* MakeCopy( SwDoc&, const SwNodeIndex& ) const;
569
570 /// Set pointer in format of section on itself.
571 void NodesArrChgd();
572
573 /** Check for not hidden areas whether there is content that is not in
574 a hidden sub-area. */
575 bool IsContentHidden() const;
576
577};
578
579/** This class is internal, used only during DocumentContentOperationsManager::CopyWithFlyInFly(), and for undo.
580
581Some of the nodes are then replaced with SwPlaceholderNode, and at the end of the operation, removed again.
582FIXME find out if this is really necessary, and if we can avoid creation of the SwPlaceholderNodes in the first place.
583*/
584class SwPlaceholderNode final : private SwNode
585{
586private:
587 friend class SwNodes;
588 SwPlaceholderNode(const SwNodeIndex &rWhere);
589};
590
591inline SwEndNode *SwNode::GetEndNode()
592{
593 return SwNodeType::End == m_nNodeType ? static_cast<SwEndNode*>(this) : nullptr;
594}
595inline const SwEndNode *SwNode::GetEndNode() const
596{
597 return SwNodeType::End == m_nNodeType ? static_cast<const SwEndNode*>(this) : nullptr;
598}
599inline SwStartNode *SwNode::GetStartNode()
600{
601 return SwNodeType::Start & m_nNodeType ? static_cast<SwStartNode*>(this) : nullptr;
602}
603inline const SwStartNode *SwNode::GetStartNode() const
604{
605 return SwNodeType::Start & m_nNodeType ? static_cast<const SwStartNode*>(this) : nullptr;
606}
607inline SwTableNode *SwNode::GetTableNode()
608{
609 return SwNodeType::Table == m_nNodeType ? static_cast<SwTableNode*>(this) : nullptr;
610}
611inline const SwTableNode *SwNode::GetTableNode() const
612{
613 return SwNodeType::Table == m_nNodeType ? static_cast<const SwTableNode*>(this) : nullptr;
614}
615inline SwSectionNode *SwNode::GetSectionNode()
616{
617 return SwNodeType::Section == m_nNodeType ? static_cast<SwSectionNode*>(this) : nullptr;
618}
619inline const SwSectionNode *SwNode::GetSectionNode() const
620{
621 return SwNodeType::Section == m_nNodeType ? static_cast<const SwSectionNode*>(this) : nullptr;
622}
623inline SwContentNode *SwNode::GetContentNode()
624{
625 return SwNodeType::ContentMask & m_nNodeType ? static_cast<SwContentNode*>(this) : nullptr;
626}
627inline const SwContentNode *SwNode::GetContentNode() const
628{
629 return SwNodeType::ContentMask & m_nNodeType ? static_cast<const SwContentNode*>(this) : nullptr;
630}
631
632inline bool SwNode::IsStartNode() const
633{
634 return bool(SwNodeType::Start & m_nNodeType);
635}
636inline bool SwNode::IsContentNode() const
637{
638 return bool(SwNodeType::ContentMask & m_nNodeType);
639}
640inline bool SwNode::IsEndNode() const
641{
642 return SwNodeType::End == m_nNodeType;
643}
644inline bool SwNode::IsTextNode() const
645{
646 return SwNodeType::Text == m_nNodeType;
647}
648inline bool SwNode::IsTableNode() const
649{
650 return SwNodeType::Table == m_nNodeType;
651}
652inline bool SwNode::IsSectionNode() const
653{
654 return SwNodeType::Section == m_nNodeType;
655}
656inline bool SwNode::IsNoTextNode() const
657{
658 return bool(SwNodeType::NoTextMask & m_nNodeType);
659}
660inline bool SwNode::IsOLENode() const
661{
662 return SwNodeType::Ole == m_nNodeType;
663}
664inline bool SwNode::IsGrfNode() const
665{
666 return SwNodeType::Grf == m_nNodeType;
667}
668
669inline const SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp ) const
670{
671 return const_cast<SwNode*>(this)->FindSttNodeByType( eTyp );
672}
673inline const SwTableNode* SwNode::FindTableNode() const
674{
675 return const_cast<SwNode*>(this)->FindTableNode();
676}
677inline const SwSectionNode* SwNode::FindSectionNode() const
678{
679 return const_cast<SwNode*>(this)->FindSectionNode();
680}
681inline sal_uLong SwNode::StartOfSectionIndex() const
682{
683 return m_pStartOfSection->GetIndex();
684}
685inline sal_uLong SwNode::EndOfSectionIndex() const
686{
687 const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection;
688 return pStNd->m_pEndOfSection->GetIndex();
689}
690inline const SwEndNode* SwNode::EndOfSectionNode() const
691{
692 const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection;
693 return pStNd->m_pEndOfSection;
694}
695inline SwEndNode* SwNode::EndOfSectionNode()
696{
697 const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection;
698 return pStNd->m_pEndOfSection;
699}
700
701inline SwNodes& SwNode::GetNodes()
702{
703 return static_cast<SwNodes&>(GetArray());
704}
705inline const SwNodes& SwNode::GetNodes() const
706{
707 return static_cast<SwNodes&>(GetArray());
708}
709
710inline SwFormatColl* SwContentNode::GetCondFormatColl() const
711{
712 return m_pCondColl;
713}
714
715inline SwFormatColl& SwContentNode::GetAnyFormatColl() const
716{
717 return m_pCondColl
718 ? *m_pCondColl
719 : *const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(GetRegisteredIn()));
720}
721
722inline const SwAttrSet& SwContentNode::GetSwAttrSet() const
723{
724 return mpAttrSet ? *GetpSwAttrSet() : GetAnyFormatColl().GetAttrSet();
725}
726
727//FEATURE::CONDCOLL
728
729inline const SfxPoolItem& SwContentNode::GetAttr( sal_uInt16 nWhich,
730 bool bInParents ) const
731{
732 return GetSwAttrSet().Get( nWhich, bInParents );
733}
734
735inline SwPlaceholderNode::SwPlaceholderNode(const SwNodeIndex &rWhere)
736 : SwNode(rWhere, SwNodeType::PlaceHolder)
737{
738}
739
740inline SwNodePtr SwNodes::operator[]( sal_uLong n ) const
741{
742 return static_cast<SwNodePtr>(BigPtrArray::operator[] ( n ));
743}
744
745#endif
746
747/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/sw/inc/bparr.hxx

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#ifndef INCLUDED_SW_INC_BPARR_HXX
21#define INCLUDED_SW_INC_BPARR_HXX
22
23#include <assert.h>
24
25#include <tools/solar.h>
26#include "swdllapi.h"
27#include <array>
28#include <memory>
29
30struct BlockInfo;
31class BigPtrArray;
32
33class BigPtrEntry
34{
35 friend class BigPtrArray;
36 BlockInfo* m_pBlock;
37 sal_uInt16 m_nOffset;
38public:
39 BigPtrEntry() : m_pBlock(nullptr), m_nOffset(0) {}
40 virtual ~BigPtrEntry() = default;
41
42 inline sal_uLong GetPos() const;
43 inline BigPtrArray& GetArray() const;
44};
45
46// 1000 entries per Block = a bit less than 4K
47#define MAXENTRY1000 1000
48
49// number of entries that may remain free during compression
50// this value is for the worst case; because we defined MAXBLOCK with ca 25%
51// overhead, 80% = 800 entries are enough
52// if complete compression is desired, 100 has to be specified
53#define COMPRESSLVL80 80
54
55struct BlockInfo final
56{
57 BigPtrArray* pBigArr; ///< in this array the block is located
58 std::array<BigPtrEntry*, MAXENTRY1000>
59 mvData; ///< data block
60 sal_uLong nStart, nEnd; ///< start- and end index
61 sal_uInt16 nElem; ///< number of elements
62};
63
64class SW_DLLPUBLIC__attribute__ ((visibility("default"))) BigPtrArray
65{
66protected:
67 std::unique_ptr<BlockInfo*[]>
68 m_ppInf; ///< block info
69 sal_uLong m_nSize; ///< number of elements
70 sal_uInt16 m_nMaxBlock; ///< current max. number of blocks
71 sal_uInt16 m_nBlock; ///< number of blocks
72 mutable
73 sal_uInt16 m_nCur; ///< last used block
74
75 sal_uInt16 Index2Block( sal_uLong ) const; ///< block search
76 BlockInfo* InsBlock( sal_uInt16 ); ///< insert block
77 void BlockDel( sal_uInt16 ); ///< some blocks were deleted
78 void UpdIndex( sal_uInt16 ); ///< recalculate indices
79
80 // fill all blocks
81 sal_uInt16 Compress();
82
83public:
84 BigPtrArray();
85 ~BigPtrArray();
86
87 sal_uLong Count() const { return m_nSize; }
88
89 void Insert( BigPtrEntry* p, sal_uLong pos );
90 void Remove( sal_uLong pos, sal_uLong n = 1 );
91 void Move( sal_uLong from, sal_uLong to );
92 void Replace( sal_uLong pos, BigPtrEntry* p);
93
94 BigPtrEntry* operator[]( sal_uLong ) const;
95};
96
97inline sal_uLong BigPtrEntry::GetPos() const
98{
99 assert(this == m_pBlock->mvData[ m_nOffset ])(static_cast <bool> (this == m_pBlock->mvData[ m_nOffset
]) ? void (0) : __assert_fail ("this == m_pBlock->mvData[ m_nOffset ]"
, "/home/maarten/src/libreoffice/core/sw/inc/bparr.hxx", 99, __extension__
__PRETTY_FUNCTION__))
; // element not in the block
7
Assuming the condition is true
8
'?' condition is true
19
Assuming the condition is true
20
'?' condition is true
34
Assuming the condition is true
35
'?' condition is true
46
Assuming the condition is true
47
'?' condition is true
100 return m_pBlock->nStart + m_nOffset;
9
Returning value, which participates in a condition later
21
Returning value, which participates in a condition later
36
Returning value, which participates in a condition later
48
Returning value, which participates in a condition later
101}
102
103inline BigPtrArray& BigPtrEntry::GetArray() const
104{
105 return *m_pBlock->pBigArr;
106}
107
108#endif
109
110/* vim:set shiftwidth=4 softtabstop=4 expandtab: */