File: | home/maarten/src/libreoffice/core/sw/source/core/crsr/trvltbl.cxx |
Warning: | line 530, column 21 Forming reference to null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||
38 | bool 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 | ||||
100 | bool 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 | ||||
114 | static 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 | ||||
126 | bool 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 | ||||
252 | bool 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 | ||||
285 | bool 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 | */ | |||
345 | static 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() | |||
423 | static 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 | ||||
480 | bool 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(); | |||
| ||||
488 | if( pTableNd ) | |||
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 { | |||
505 | while( aIdx.GetIndex() && | |||
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() ) | |||
517 | { | |||
518 | SvxSearchDialogWrapper::SetSearchLabel( SearchLabel::StartWrapped ); | |||
519 | aIdx = nLastNd; | |||
520 | continue; | |||
521 | } | |||
522 | ||||
523 | { | |||
524 | if( &fnPosTable == &fnMoveForward ) // at the beginning? | |||
525 | { | |||
526 | aIdx = *aIdx.GetNode().StartOfSectionNode(); | |||
527 | if( !lcl_FindNextCell( aIdx, bInReadOnly )) | |||
528 | { | |||
529 | // skip table | |||
530 | aIdx.Assign( *pTableNd, -1 ); | |||
| ||||
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 | ||||
560 | bool 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 | ||||
632 | bool 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 | ||||
666 | bool 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 | ||||
681 | bool 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 | ||||
725 | bool 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 | ||||
745 | OUString 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 | ||||
793 | bool 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 | ||||
806 | bool 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 | ||||
869 | void 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 | ||||
908 | void SwCursorShell::ClearTableBoxContent() | |||
909 | { | |||
910 | delete m_pBoxIdx; | |||
911 | m_pBoxIdx = nullptr; | |||
912 | m_pBoxPtr = nullptr; | |||
913 | } | |||
914 | ||||
915 | bool 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: */ |
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. |
31 | class 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 | |
53 | public: |
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 | |
122 | inline std::ostream &operator <<(std::ostream& s, const SwNodeIndex& index) |
123 | { |
124 | return s << "SwNodeIndex (node " << index.GetIndex() << ")"; |
125 | }; |
126 | |
127 | // SwRange |
128 | |
129 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwNodeRange |
130 | { |
131 | public: |
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 | |
152 | inline sal_uLong SwNodeIndex::GetIndex() const |
153 | { |
154 | return m_pNode->GetIndex(); |
155 | } |
156 | inline const SwNodes& SwNodeIndex::GetNodes() const |
157 | { |
158 | return m_pNode->GetNodes(); |
159 | } |
160 | inline SwNodes& SwNodeIndex::GetNodes() |
161 | { |
162 | return m_pNode->GetNodes(); |
163 | } |
164 | inline bool SwNodeIndex::operator< ( sal_uLong const nOther ) const |
165 | { |
166 | return m_pNode->GetIndex() < nOther; |
167 | } |
168 | inline bool SwNodeIndex::operator<=( sal_uLong const nOther ) const |
169 | { |
170 | return m_pNode->GetIndex() <= nOther; |
171 | } |
172 | inline bool SwNodeIndex::operator> ( sal_uLong const nOther ) const |
173 | { |
174 | return m_pNode->GetIndex() > nOther; |
175 | } |
176 | inline bool SwNodeIndex::operator>=( sal_uLong const nOther ) const |
177 | { |
178 | return m_pNode->GetIndex() >= nOther; |
179 | } |
180 | inline bool SwNodeIndex::operator==( sal_uLong const nOther ) const |
181 | { |
182 | return m_pNode->GetIndex() == nOther; |
183 | } |
184 | inline bool SwNodeIndex::operator!=( sal_uLong const nOther ) const |
185 | { |
186 | return m_pNode->GetIndex() != nOther; |
187 | } |
188 | inline bool SwNodeIndex::operator<( const SwNodeIndex& rIndex ) const |
189 | { |
190 | return m_pNode->GetIndex() < rIndex.GetIndex(); |
191 | } |
192 | inline bool SwNodeIndex::operator<=( const SwNodeIndex& rIndex ) const |
193 | { |
194 | return m_pNode->GetIndex() <= rIndex.GetIndex(); |
195 | } |
196 | inline bool SwNodeIndex::operator>( const SwNodeIndex& rIndex ) const |
197 | { |
198 | return m_pNode->GetIndex() > rIndex.GetIndex(); |
199 | } |
200 | inline bool SwNodeIndex::operator>=( const SwNodeIndex& rIndex ) const |
201 | { |
202 | return m_pNode->GetIndex() >= rIndex.GetIndex(); |
203 | } |
204 | inline bool SwNodeIndex::operator==( const SwNodeIndex& rIdx ) const |
205 | { |
206 | return m_pNode == rIdx.m_pNode; |
207 | } |
208 | inline bool SwNodeIndex::operator!=( const SwNodeIndex& rIdx ) const |
209 | { |
210 | return m_pNode != rIdx.m_pNode; |
211 | } |
212 | |
213 | inline sal_uLong SwNodeIndex::operator++() |
214 | { |
215 | m_pNode = GetNodes()[ m_pNode->GetIndex()+1 ]; |
216 | return m_pNode->GetIndex(); |
217 | } |
218 | inline sal_uLong SwNodeIndex::operator--() |
219 | { |
220 | m_pNode = GetNodes()[ m_pNode->GetIndex()-1 ]; |
221 | return m_pNode->GetIndex(); |
222 | } |
223 | inline sal_uLong SwNodeIndex::operator++(int) |
224 | { |
225 | sal_uLong nOldIndex = m_pNode->GetIndex(); |
226 | m_pNode = GetNodes()[ nOldIndex + 1 ]; |
227 | return nOldIndex; |
228 | } |
229 | inline sal_uLong SwNodeIndex::operator--(int) |
230 | { |
231 | sal_uLong nOldIndex = m_pNode->GetIndex(); |
232 | m_pNode = GetNodes()[ nOldIndex - 1 ]; |
233 | return nOldIndex; |
234 | } |
235 | |
236 | inline sal_uLong SwNodeIndex::operator+=( sal_uLong const nOffset ) |
237 | { |
238 | m_pNode = GetNodes()[ m_pNode->GetIndex() + nOffset ]; |
239 | return m_pNode->GetIndex(); |
240 | } |
241 | inline sal_uLong SwNodeIndex::operator-=( sal_uLong const nOffset ) |
242 | { |
243 | m_pNode = GetNodes()[ m_pNode->GetIndex() - nOffset ]; |
244 | return m_pNode->GetIndex(); |
245 | } |
246 | |
247 | inline SwNodeIndex& SwNodeIndex::operator=( sal_uLong const nNew ) |
248 | { |
249 | m_pNode = GetNodes()[ nNew ]; |
250 | return *this; |
251 | } |
252 | |
253 | SwNodeIndex& SwNodeIndex::operator=( const SwNodeIndex& rIdx ) |
254 | { |
255 | *this = *(rIdx.m_pNode); |
256 | return *this; |
257 | } |
258 | |
259 | SwNodeIndex& 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 | |
272 | SwNodeIndex& SwNodeIndex::Assign( SwNodes const & rNds, sal_uLong nIdx ) |
273 | { |
274 | *this = *rNds[ nIdx ]; |
275 | return *this; |
276 | } |
277 | |
278 | SwNodeIndex& 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: */ |
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 | |
34 | class SwContentFrame; |
35 | class SwContentNode; |
36 | class SwDoc; |
37 | class SwEndNode; |
38 | class SwFrame; |
39 | class SwFrameFormat; |
40 | class SwGrfNode; |
41 | class SwNoTextNode; |
42 | class SwNodeIndex; |
43 | class SwOLENode; |
44 | class SwRect; |
45 | class SwSection; |
46 | class SwSectionFormat; |
47 | class SwTOXBase; |
48 | class SwSectionNode; |
49 | class SwStartNode; |
50 | class SwTabFrame; |
51 | class SwRootFrame; |
52 | class SwTable; |
53 | class SwTableNode; |
54 | class SwTableBox; |
55 | class SwTextNode; |
56 | class SwPageDesc; |
57 | class SwViewShell; |
58 | struct SwPosition; |
59 | class IStyleAccess; |
60 | class IDocumentSettingAccess; |
61 | class IDocumentDeviceAccess; |
62 | class IDocumentMarkAccess; |
63 | class IDocumentRedlineAccess; |
64 | class IDocumentStylePoolAccess; |
65 | class IDocumentLinksAdministration; |
66 | class IDocumentFieldsAccess; |
67 | class IDocumentContentOperations; |
68 | class IDocumentListItems; |
69 | class Point; |
70 | enum class SvxFrameDirection; |
71 | typedef std::vector<SwOLENode*> SwOLENodes; // docary.hxx |
72 | |
73 | namespace drawinglayer::attribute { |
74 | class SdrAllFillAttributesHelper; |
75 | typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr; |
76 | } |
77 | |
78 | /// Base class of the Writer document model elements. |
79 | class 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 | |
90 | public: |
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; } |
98 | private: |
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 | |
111 | protected: |
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 | |
119 | public: |
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(); } |
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 | |
305 | private: |
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. |
311 | class 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 | |
323 | protected: |
324 | SwStartNode( const SwNodeIndex &rWhere, |
325 | const SwNodeType nNodeType = SwNodeType::Start, |
326 | SwStartNodeType = SwNormalStartNode ); |
327 | public: |
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 | |
335 | private: |
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. |
341 | class 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 | |
350 | protected: |
351 | SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd ); |
352 | |
353 | private: |
354 | SwEndNode( const SwEndNode & rNode ) = delete; |
355 | SwEndNode & operator= ( const SwEndNode & rNode ) = delete; |
356 | }; |
357 | |
358 | // SwContentNode |
359 | |
360 | class 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 | |
367 | protected: |
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 | |
387 | public: |
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 | |
488 | private: |
489 | SwContentNode( const SwContentNode & rNode ) = delete; |
490 | SwContentNode & operator= ( const SwContentNode & rNode ) = delete; |
491 | }; |
492 | |
493 | // SwTableNode |
494 | |
495 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwTableNode : public SwStartNode, public sw::BroadcastingModify |
496 | { |
497 | friend class SwNodes; |
498 | std::unique_ptr<SwTable> m_pTable; |
499 | protected: |
500 | virtual ~SwTableNode() override; |
501 | |
502 | public: |
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 | |
526 | private: |
527 | SwTableNode( const SwTableNode & rNode ) = delete; |
528 | SwTableNode & operator= ( const SwTableNode & rNode ) = delete; |
529 | }; |
530 | |
531 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwSectionNode |
532 | : public SwStartNode |
533 | { |
534 | friend class SwNodes; |
535 | |
536 | private: |
537 | SwSectionNode(const SwSectionNode&) = delete; |
538 | SwSectionNode& operator=(const SwSectionNode&) = delete; |
539 | |
540 | std::unique_ptr<SwSection> const m_pSection; |
541 | |
542 | protected: |
543 | virtual ~SwSectionNode() override; |
544 | |
545 | public: |
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 | |
581 | Some of the nodes are then replaced with SwPlaceholderNode, and at the end of the operation, removed again. |
582 | FIXME find out if this is really necessary, and if we can avoid creation of the SwPlaceholderNodes in the first place. |
583 | */ |
584 | class SwPlaceholderNode final : private SwNode |
585 | { |
586 | private: |
587 | friend class SwNodes; |
588 | SwPlaceholderNode(const SwNodeIndex &rWhere); |
589 | }; |
590 | |
591 | inline SwEndNode *SwNode::GetEndNode() |
592 | { |
593 | return SwNodeType::End == m_nNodeType ? static_cast<SwEndNode*>(this) : nullptr; |
594 | } |
595 | inline const SwEndNode *SwNode::GetEndNode() const |
596 | { |
597 | return SwNodeType::End == m_nNodeType ? static_cast<const SwEndNode*>(this) : nullptr; |
598 | } |
599 | inline SwStartNode *SwNode::GetStartNode() |
600 | { |
601 | return SwNodeType::Start & m_nNodeType ? static_cast<SwStartNode*>(this) : nullptr; |
602 | } |
603 | inline const SwStartNode *SwNode::GetStartNode() const |
604 | { |
605 | return SwNodeType::Start & m_nNodeType ? static_cast<const SwStartNode*>(this) : nullptr; |
606 | } |
607 | inline SwTableNode *SwNode::GetTableNode() |
608 | { |
609 | return SwNodeType::Table == m_nNodeType ? static_cast<SwTableNode*>(this) : nullptr; |
610 | } |
611 | inline const SwTableNode *SwNode::GetTableNode() const |
612 | { |
613 | return SwNodeType::Table == m_nNodeType ? static_cast<const SwTableNode*>(this) : nullptr; |
614 | } |
615 | inline SwSectionNode *SwNode::GetSectionNode() |
616 | { |
617 | return SwNodeType::Section == m_nNodeType ? static_cast<SwSectionNode*>(this) : nullptr; |
618 | } |
619 | inline const SwSectionNode *SwNode::GetSectionNode() const |
620 | { |
621 | return SwNodeType::Section == m_nNodeType ? static_cast<const SwSectionNode*>(this) : nullptr; |
622 | } |
623 | inline SwContentNode *SwNode::GetContentNode() |
624 | { |
625 | return SwNodeType::ContentMask & m_nNodeType ? static_cast<SwContentNode*>(this) : nullptr; |
626 | } |
627 | inline const SwContentNode *SwNode::GetContentNode() const |
628 | { |
629 | return SwNodeType::ContentMask & m_nNodeType ? static_cast<const SwContentNode*>(this) : nullptr; |
630 | } |
631 | |
632 | inline bool SwNode::IsStartNode() const |
633 | { |
634 | return bool(SwNodeType::Start & m_nNodeType); |
635 | } |
636 | inline bool SwNode::IsContentNode() const |
637 | { |
638 | return bool(SwNodeType::ContentMask & m_nNodeType); |
639 | } |
640 | inline bool SwNode::IsEndNode() const |
641 | { |
642 | return SwNodeType::End == m_nNodeType; |
643 | } |
644 | inline bool SwNode::IsTextNode() const |
645 | { |
646 | return SwNodeType::Text == m_nNodeType; |
647 | } |
648 | inline bool SwNode::IsTableNode() const |
649 | { |
650 | return SwNodeType::Table == m_nNodeType; |
651 | } |
652 | inline bool SwNode::IsSectionNode() const |
653 | { |
654 | return SwNodeType::Section == m_nNodeType; |
655 | } |
656 | inline bool SwNode::IsNoTextNode() const |
657 | { |
658 | return bool(SwNodeType::NoTextMask & m_nNodeType); |
659 | } |
660 | inline bool SwNode::IsOLENode() const |
661 | { |
662 | return SwNodeType::Ole == m_nNodeType; |
663 | } |
664 | inline bool SwNode::IsGrfNode() const |
665 | { |
666 | return SwNodeType::Grf == m_nNodeType; |
667 | } |
668 | |
669 | inline const SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp ) const |
670 | { |
671 | return const_cast<SwNode*>(this)->FindSttNodeByType( eTyp ); |
672 | } |
673 | inline const SwTableNode* SwNode::FindTableNode() const |
674 | { |
675 | return const_cast<SwNode*>(this)->FindTableNode(); |
676 | } |
677 | inline const SwSectionNode* SwNode::FindSectionNode() const |
678 | { |
679 | return const_cast<SwNode*>(this)->FindSectionNode(); |
680 | } |
681 | inline sal_uLong SwNode::StartOfSectionIndex() const |
682 | { |
683 | return m_pStartOfSection->GetIndex(); |
684 | } |
685 | inline 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 | } |
690 | inline const SwEndNode* SwNode::EndOfSectionNode() const |
691 | { |
692 | const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection; |
693 | return pStNd->m_pEndOfSection; |
694 | } |
695 | inline SwEndNode* SwNode::EndOfSectionNode() |
696 | { |
697 | const SwStartNode* pStNd = IsStartNode() ? static_cast<const SwStartNode*>(this) : m_pStartOfSection; |
698 | return pStNd->m_pEndOfSection; |
699 | } |
700 | |
701 | inline SwNodes& SwNode::GetNodes() |
702 | { |
703 | return static_cast<SwNodes&>(GetArray()); |
704 | } |
705 | inline const SwNodes& SwNode::GetNodes() const |
706 | { |
707 | return static_cast<SwNodes&>(GetArray()); |
708 | } |
709 | |
710 | inline SwFormatColl* SwContentNode::GetCondFormatColl() const |
711 | { |
712 | return m_pCondColl; |
713 | } |
714 | |
715 | inline SwFormatColl& SwContentNode::GetAnyFormatColl() const |
716 | { |
717 | return m_pCondColl |
718 | ? *m_pCondColl |
719 | : *const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(GetRegisteredIn())); |
720 | } |
721 | |
722 | inline const SwAttrSet& SwContentNode::GetSwAttrSet() const |
723 | { |
724 | return mpAttrSet ? *GetpSwAttrSet() : GetAnyFormatColl().GetAttrSet(); |
725 | } |
726 | |
727 | //FEATURE::CONDCOLL |
728 | |
729 | inline const SfxPoolItem& SwContentNode::GetAttr( sal_uInt16 nWhich, |
730 | bool bInParents ) const |
731 | { |
732 | return GetSwAttrSet().Get( nWhich, bInParents ); |
733 | } |
734 | |
735 | inline SwPlaceholderNode::SwPlaceholderNode(const SwNodeIndex &rWhere) |
736 | : SwNode(rWhere, SwNodeType::PlaceHolder) |
737 | { |
738 | } |
739 | |
740 | inline 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: */ |
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 | |
30 | struct BlockInfo; |
31 | class BigPtrArray; |
32 | |
33 | class BigPtrEntry |
34 | { |
35 | friend class BigPtrArray; |
36 | BlockInfo* m_pBlock; |
37 | sal_uInt16 m_nOffset; |
38 | public: |
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 | |
55 | struct 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 | |
64 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) BigPtrArray |
65 | { |
66 | protected: |
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 | |
83 | public: |
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 | |
97 | inline 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 |
100 | return m_pBlock->nStart + m_nOffset; |
101 | } |
102 | |
103 | inline BigPtrArray& BigPtrEntry::GetArray() const |
104 | { |
105 | return *m_pBlock->pBigArr; |
106 | } |
107 | |
108 | #endif |
109 | |
110 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |