File: | home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx |
Warning: | line 358, column 34 Called C++ object pointer is null |
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 <pagefrm.hxx> | |||
21 | #include <rootfrm.hxx> | |||
22 | #include <dcontact.hxx> | |||
23 | #include <flyfrm.hxx> | |||
24 | #include <txtfrm.hxx> | |||
25 | #include <cellfrm.hxx> | |||
26 | #include <swtable.hxx> | |||
27 | #include <fmtfsize.hxx> | |||
28 | #include <editeng/boxitem.hxx> | |||
29 | #include <editeng/shaditem.hxx> | |||
30 | #include <IDocumentRedlineAccess.hxx> | |||
31 | #include <fmtclds.hxx> | |||
32 | #include <viewimp.hxx> | |||
33 | #include <sortedobjs.hxx> | |||
34 | #include <hints.hxx> | |||
35 | #include <frmtool.hxx> | |||
36 | #include <ndtxt.hxx> | |||
37 | ||||
38 | // No inline cause we need the function pointers | |||
39 | long SwFrame::GetTopMargin() const | |||
40 | { return getFramePrintArea().Top(); } | |||
41 | long SwFrame::GetBottomMargin() const | |||
42 | { return getFrameArea().Height() -getFramePrintArea().Height() -getFramePrintArea().Top(); } | |||
43 | long SwFrame::GetLeftMargin() const | |||
44 | { return getFramePrintArea().Left(); } | |||
45 | long SwFrame::GetRightMargin() const | |||
46 | { return getFrameArea().Width() - getFramePrintArea().Width() - getFramePrintArea().Left(); } | |||
47 | long SwFrame::GetPrtLeft() const | |||
48 | { return getFrameArea().Left() + getFramePrintArea().Left(); } | |||
49 | long SwFrame::GetPrtBottom() const | |||
50 | { return getFrameArea().Top() + getFramePrintArea().Height() + getFramePrintArea().Top(); } | |||
51 | long SwFrame::GetPrtRight() const | |||
52 | { return getFrameArea().Left() + getFramePrintArea().Width() + getFramePrintArea().Left(); } | |||
53 | long SwFrame::GetPrtTop() const | |||
54 | { return getFrameArea().Top() + getFramePrintArea().Top(); } | |||
55 | ||||
56 | bool SwFrame::SetMinLeft( long nDeadline ) | |||
57 | { | |||
58 | SwTwips nDiff = nDeadline - getFrameArea().Left(); | |||
59 | if( nDiff > 0 ) | |||
60 | { | |||
61 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
62 | aFrm.Left( nDeadline ); | |||
63 | ||||
64 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
65 | aPrt.Width( aPrt.Width() - nDiff ); | |||
66 | ||||
67 | return true; | |||
68 | } | |||
69 | return false; | |||
70 | } | |||
71 | ||||
72 | bool SwFrame::SetMaxBottom( long nDeadline ) | |||
73 | { | |||
74 | SwTwips nDiff = getFrameArea().Top() + getFrameArea().Height() - nDeadline; | |||
75 | if( nDiff > 0 ) | |||
76 | { | |||
77 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
78 | aFrm.Height( aFrm.Height() - nDiff ); | |||
79 | ||||
80 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
81 | aPrt.Height( aPrt.Height() - nDiff ); | |||
82 | ||||
83 | return true; | |||
84 | } | |||
85 | return false; | |||
86 | } | |||
87 | ||||
88 | bool SwFrame::SetMaxRight( long nDeadline ) | |||
89 | { | |||
90 | SwTwips nDiff = getFrameArea().Left() + getFrameArea().Width() - nDeadline; | |||
91 | if( nDiff > 0 ) | |||
92 | { | |||
93 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
94 | aFrm.Width( aFrm.Width() - nDiff ); | |||
95 | ||||
96 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
97 | aPrt.Width( aPrt.Width() - nDiff ); | |||
98 | ||||
99 | return true; | |||
100 | } | |||
101 | return false; | |||
102 | } | |||
103 | ||||
104 | void SwFrame::MakeBelowPos( const SwFrame* pUp, const SwFrame* pPrv, bool bNotify ) | |||
105 | { | |||
106 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
107 | ||||
108 | if( pPrv ) | |||
109 | { | |||
110 | aFrm.Pos( pPrv->getFrameArea().Pos() ); | |||
111 | aFrm.Pos().AdjustY(pPrv->getFrameArea().Height() ); | |||
112 | } | |||
113 | else | |||
114 | { | |||
115 | aFrm.Pos( pUp->getFrameArea().Pos() ); | |||
116 | aFrm.Pos() += pUp->getFramePrintArea().Pos(); | |||
117 | } | |||
118 | ||||
119 | if( bNotify ) | |||
120 | { | |||
121 | aFrm.Pos().AdjustY(1 ); | |||
122 | } | |||
123 | } | |||
124 | ||||
125 | void SwFrame::MakeLeftPos( const SwFrame* pUp, const SwFrame* pPrv, bool bNotify ) | |||
126 | { | |||
127 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
128 | ||||
129 | if( pPrv ) | |||
130 | { | |||
131 | aFrm.Pos( pPrv->getFrameArea().Pos() ); | |||
132 | aFrm.Pos().AdjustX( -(aFrm.Width()) ); | |||
133 | } | |||
134 | else | |||
135 | { | |||
136 | aFrm.Pos( pUp->getFrameArea().Pos() ); | |||
137 | aFrm.Pos() += pUp->getFramePrintArea().Pos(); | |||
138 | aFrm.Pos().AdjustX(pUp->getFramePrintArea().Width() - aFrm.Width() ); | |||
139 | } | |||
140 | ||||
141 | if( bNotify ) | |||
142 | { | |||
143 | aFrm.Pos().AdjustX( -1 ); | |||
144 | } | |||
145 | } | |||
146 | ||||
147 | void SwFrame::MakeRightPos( const SwFrame* pUp, const SwFrame* pPrv, bool bNotify ) | |||
148 | { | |||
149 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | |||
150 | ||||
151 | if( pPrv ) | |||
152 | { | |||
153 | aFrm.Pos( pPrv->getFrameArea().Pos() ); | |||
154 | aFrm.Pos().AdjustX(pPrv->getFrameArea().Width() ); | |||
155 | } | |||
156 | else | |||
157 | { | |||
158 | aFrm.Pos( pUp->getFrameArea().Pos() ); | |||
159 | aFrm.Pos() += pUp->getFramePrintArea().Pos(); | |||
160 | } | |||
161 | ||||
162 | if( bNotify ) | |||
163 | { | |||
164 | aFrm.Pos().AdjustX(1 ); | |||
165 | } | |||
166 | } | |||
167 | ||||
168 | void SwFrame::SetTopBottomMargins( long nTop, long nBot ) | |||
169 | { | |||
170 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
171 | aPrt.Top( nTop ); | |||
172 | aPrt.Height( getFrameArea().Height() - nTop - nBot ); | |||
173 | } | |||
174 | ||||
175 | void SwFrame::SetLeftRightMargins( long nLeft, long nRight) | |||
176 | { | |||
177 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
178 | aPrt.Left( nLeft ); | |||
179 | aPrt.Width( getFrameArea().Width() - nLeft - nRight ); | |||
180 | } | |||
181 | ||||
182 | void SwFrame::SetRightLeftMargins( long nRight, long nLeft) | |||
183 | { | |||
184 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | |||
185 | aPrt.Left( nLeft ); | |||
186 | aPrt.Width( getFrameArea().Width() - nLeft - nRight ); | |||
187 | } | |||
188 | ||||
189 | /// checks the layout direction and invalidates the lower frames recursively, if necessary. | |||
190 | void SwFrame::CheckDirChange() | |||
191 | { | |||
192 | bool bOldVert = mbVertical; | |||
193 | bool bOldR2L = mbRightToLeft; | |||
194 | SetInvalidVert( true ); | |||
195 | mbInvalidR2L = true; | |||
196 | bool bChg = bOldR2L != IsRightToLeft(); | |||
197 | bool bOldVertL2R = IsVertLR(); | |||
198 | if( !(( IsVertical() != bOldVert ) || bChg || bOldVertL2R != IsVertLR()) ) | |||
199 | return; | |||
200 | ||||
201 | InvalidateAll(); | |||
202 | if( IsLayoutFrame() ) | |||
203 | { | |||
204 | // set minimum row height for vertical cells in horizontal table: | |||
205 | if ( IsCellFrame() && GetUpper() ) | |||
206 | { | |||
207 | if ( IsVertical() != GetUpper()->IsVertical() && | |||
208 | static_cast<SwCellFrame*>(this)->GetTabBox()->getRowSpan() == 1 ) | |||
209 | { | |||
210 | enum { | |||
211 | MIN_VERT_CELL_HEIGHT = 1135 | |||
212 | }; | |||
213 | ||||
214 | SwTableLine* pLine = const_cast<SwTableLine*>(static_cast<SwCellFrame*>(this)->GetTabBox()->GetUpper()); | |||
215 | SwFrameFormat* pFrameFormat = pLine->GetFrameFormat(); | |||
216 | SwFormatFrameSize aNew( pFrameFormat->GetFrameSize() ); | |||
217 | if ( SwFrameSize::Fixed != aNew.GetHeightSizeType() ) | |||
218 | aNew.SetHeightSizeType( SwFrameSize::Minimum ); | |||
219 | if ( aNew.GetHeight() < MIN_VERT_CELL_HEIGHT ) | |||
220 | aNew.SetHeight( MIN_VERT_CELL_HEIGHT ); | |||
221 | SwDoc* pDoc = pFrameFormat->GetDoc(); | |||
222 | pDoc->SetAttr( aNew, *pLine->ClaimFrameFormat() ); | |||
223 | } | |||
224 | } | |||
225 | ||||
226 | SwFrame* pFrame = static_cast<SwLayoutFrame*>(this)->Lower(); | |||
227 | const SwFormatCol* pCol = nullptr; | |||
228 | SwLayoutFrame* pBody = nullptr; | |||
229 | if( pFrame ) | |||
230 | { | |||
231 | if( IsPageFrame() ) | |||
232 | { | |||
233 | // If we're a page frame and we change our layout direction, | |||
234 | // we have to look for columns and rearrange them. | |||
235 | pBody = static_cast<SwPageFrame*>(this)->FindBodyCont(); | |||
236 | if(pBody && pBody->Lower() && pBody->Lower()->IsColumnFrame()) | |||
237 | pCol = &static_cast<SwPageFrame*>(this)->GetFormat()->GetCol(); | |||
238 | } | |||
239 | else if( pFrame->IsColumnFrame() ) | |||
240 | { | |||
241 | pBody = static_cast<SwLayoutFrame*>(this); | |||
242 | const SwFrameFormat *pFormat = pBody->GetFormat(); | |||
243 | if( pFormat ) | |||
244 | pCol = &pFormat->GetCol(); | |||
245 | } | |||
246 | } | |||
247 | while( pFrame ) | |||
248 | { | |||
249 | pFrame->CheckDirChange(); | |||
250 | pFrame = pFrame->GetNext(); | |||
251 | } | |||
252 | if( pCol ) | |||
253 | pBody->AdjustColumns( pCol, true ); | |||
254 | } | |||
255 | else if( IsTextFrame() ) | |||
256 | static_cast<SwTextFrame*>(this)->Prepare(); | |||
257 | ||||
258 | // #i31698# - notify anchored objects also for page frames. | |||
259 | // Remove code above for special handling of page frames | |||
260 | if ( !GetDrawObjs() ) | |||
261 | return; | |||
262 | ||||
263 | const SwSortedObjs *pObjs = GetDrawObjs(); | |||
264 | const size_t nCnt = pObjs->size(); | |||
265 | for ( size_t i = 0; i < nCnt; ++i ) | |||
266 | { | |||
267 | SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; | |||
268 | if( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr ) | |||
269 | static_cast<SwFlyFrame*>(pAnchoredObj)->CheckDirChange(); | |||
270 | else | |||
271 | { | |||
272 | // OD 2004-04-06 #i26791# - direct object | |||
273 | // positioning no longer needed. Instead | |||
274 | // invalidate | |||
275 | pAnchoredObj->InvalidateObjPos(); | |||
276 | } | |||
277 | // #i31698# - update layout direction of | |||
278 | // anchored object | |||
279 | { | |||
280 | ::setContextWritingMode( pAnchoredObj->DrawObj(), pAnchoredObj->GetAnchorFrameContainingAnchPos() ); | |||
281 | pAnchoredObj->UpdateLayoutDir(); | |||
282 | } | |||
283 | } | |||
284 | } | |||
285 | ||||
286 | /// returns the position for anchors based on frame direction | |||
287 | // OD 2004-03-10 #i11860# - consider lower space and line spacing of | |||
288 | // previous frame according to new option 'Use former object positioning' | |||
289 | Point SwFrame::GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const | |||
290 | { | |||
291 | Point aAnchor = getFrameArea().Pos(); | |||
292 | ||||
293 | if ( ( IsVertical() && !IsVertLR() ) || IsRightToLeft() ) | |||
294 | aAnchor.AdjustX(getFrameArea().Width() ); | |||
295 | ||||
296 | if ( IsTextFrame() ) | |||
297 | { | |||
298 | SwTwips nBaseOfstForFly = | |||
299 | static_cast<const SwTextFrame*>(this)->GetBaseOffsetForFly( bIgnoreFlysAnchoredAtThisFrame ); | |||
300 | if ( IsVertical() ) | |||
301 | aAnchor.AdjustY(nBaseOfstForFly ); | |||
302 | else | |||
303 | aAnchor.AdjustX(nBaseOfstForFly ); | |||
304 | ||||
305 | // OD 2004-03-10 #i11860# - if option 'Use former object positioning' | |||
306 | // is OFF, consider the lower space and the line spacing of the | |||
307 | // previous frame and the spacing considered for the page grid | |||
308 | const SwTextFrame* pThisTextFrame = static_cast<const SwTextFrame*>(this); | |||
309 | const SwTwips nUpperSpaceAmountConsideredForPrevFrameAndPageGrid = | |||
310 | pThisTextFrame->GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid(); | |||
311 | if ( IsVertical() ) | |||
312 | { | |||
313 | aAnchor.AdjustX( -nUpperSpaceAmountConsideredForPrevFrameAndPageGrid ); | |||
314 | } | |||
315 | else | |||
316 | { | |||
317 | aAnchor.AdjustY(nUpperSpaceAmountConsideredForPrevFrameAndPageGrid ); | |||
318 | } | |||
319 | } | |||
320 | ||||
321 | return aAnchor; | |||
322 | } | |||
323 | ||||
324 | void SwFrame::DestroyImpl() | |||
325 | { | |||
326 | mbInDtor = true; | |||
327 | ||||
328 | // accessible objects for fly and cell frames have been already disposed | |||
329 | // by the destructors of the derived classes. | |||
330 | if (IsAccessibleFrame() && !(IsFlyFrame() || IsCellFrame()) | |||
331 | && (GetDep() || IsTextFrame())) // sw_redlinehide: text frame may not have Dep! | |||
332 | { | |||
333 | assert(!IsTextFrame() || GetDep() || static_cast<SwTextFrame*>(this)->GetMergedPara())(static_cast <bool> (!IsTextFrame() || GetDep() || static_cast <SwTextFrame*>(this)->GetMergedPara()) ? void (0) : __assert_fail ("!IsTextFrame() || GetDep() || static_cast<SwTextFrame*>(this)->GetMergedPara()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 333, __extension__ __PRETTY_FUNCTION__)); | |||
334 | SwRootFrame *pRootFrame = getRootFrame(); | |||
335 | if( pRootFrame && pRootFrame->IsAnyShellAccessible() ) | |||
336 | { | |||
337 | SwViewShell *pVSh = pRootFrame->GetCurrShell(); | |||
338 | if( pVSh && pVSh->Imp() ) | |||
339 | { | |||
340 | OSL_ENSURE( !GetLower(), "Lowers should be dispose already!" )do { if (true && (!(!GetLower()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "340" ": "), "%s", "Lowers should be dispose already!"); } } while (false); | |||
341 | pVSh->Imp()->DisposeAccessibleFrame( this ); | |||
342 | } | |||
343 | } | |||
344 | } | |||
345 | ||||
346 | if (!m_pDrawObjs) | |||
347 | return; | |||
348 | ||||
349 | for (size_t i = m_pDrawObjs->size(); i; ) | |||
350 | { | |||
351 | SwAnchoredObject* pAnchoredObj = (*m_pDrawObjs)[--i]; | |||
352 | if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr ) | |||
353 | { | |||
354 | SwFrame::DestroyFrame(static_cast<SwFlyFrame*>(pAnchoredObj)); | |||
355 | } | |||
356 | else | |||
357 | { | |||
358 | SdrObject* pSdrObj = pAnchoredObj->DrawObj(); | |||
| ||||
359 | SwDrawContact* pContact = | |||
360 | static_cast<SwDrawContact*>(pSdrObj->GetUserCall()); | |||
361 | OSL_ENSURE( pContact,do { if (true && (!(pContact))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "362" ": "), "%s", "<SwFrame::~SwFrame> - missing contact for drawing object" ); } } while (false) | |||
362 | "<SwFrame::~SwFrame> - missing contact for drawing object" )do { if (true && (!(pContact))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "362" ": "), "%s", "<SwFrame::~SwFrame> - missing contact for drawing object" ); } } while (false); | |||
363 | if ( pContact ) | |||
364 | { | |||
365 | pContact->DisconnectObjFromLayout( pSdrObj ); | |||
366 | } | |||
367 | } | |||
368 | } | |||
369 | m_pDrawObjs.reset(); | |||
370 | } | |||
371 | ||||
372 | SwFrame::~SwFrame() | |||
373 | { | |||
374 | assert(m_isInDestroy)(static_cast <bool> (m_isInDestroy) ? void (0) : __assert_fail ("m_isInDestroy", "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 374, __extension__ __PRETTY_FUNCTION__)); // check that only DestroySwFrame does "delete" | |||
375 | assert(!IsDeleteForbidden())(static_cast <bool> (!IsDeleteForbidden()) ? void (0) : __assert_fail ("!IsDeleteForbidden()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 375, __extension__ __PRETTY_FUNCTION__)); // check that it's not deleted while deletes are forbidden | |||
376 | #if OSL_DEBUG_LEVEL1 > 0 | |||
377 | // JP 15.10.2001: for detection of access to deleted frames | |||
378 | mpRoot = reinterpret_cast<SwRootFrame*>(0x33333333); | |||
379 | #endif | |||
380 | } | |||
381 | ||||
382 | void SwFrame::DestroyFrame(SwFrame *const pFrame) | |||
383 | { | |||
384 | if (pFrame) | |||
385 | { | |||
386 | pFrame->m_isInDestroy = true; | |||
387 | pFrame->DestroyImpl(); | |||
388 | assert(pFrame->mbInDtor)(static_cast <bool> (pFrame->mbInDtor) ? void (0) : __assert_fail ("pFrame->mbInDtor", "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 388, __extension__ __PRETTY_FUNCTION__)); // check that nobody forgot to call base class | |||
389 | delete pFrame; | |||
390 | } | |||
391 | } | |||
392 | ||||
393 | const SwFrameFormat * SwLayoutFrame::GetFormat() const | |||
394 | { | |||
395 | return static_cast< const SwFrameFormat * >( GetDep() ); | |||
396 | } | |||
397 | ||||
398 | SwFrameFormat * SwLayoutFrame::GetFormat() | |||
399 | { | |||
400 | return static_cast< SwFrameFormat * >( GetDep() ); | |||
401 | } | |||
402 | ||||
403 | void SwLayoutFrame::SetFrameFormat( SwFrameFormat *pNew ) | |||
404 | { | |||
405 | if ( pNew != GetFormat() ) | |||
406 | { | |||
407 | SwFormatChg aOldFormat( GetFormat() ); | |||
408 | pNew->Add( this ); | |||
409 | SwFormatChg aNewFormat( pNew ); | |||
410 | ModifyNotification( &aOldFormat, &aNewFormat ); | |||
411 | } | |||
412 | } | |||
413 | ||||
414 | SwContentFrame::SwContentFrame( SwContentNode * const pContent, SwFrame* pSib ) : | |||
415 | SwFrame( pContent, pSib ), | |||
416 | SwFlowFrame( static_cast<SwFrame&>(*this) ) | |||
417 | { | |||
418 | assert(!getRootFrame()->IsHideRedlines() || pContent->IsCreateFrameWhenHidingRedlines())(static_cast <bool> (!getRootFrame()->IsHideRedlines () || pContent->IsCreateFrameWhenHidingRedlines()) ? void ( 0) : __assert_fail ("!getRootFrame()->IsHideRedlines() || pContent->IsCreateFrameWhenHidingRedlines()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 418, __extension__ __PRETTY_FUNCTION__)); | |||
419 | } | |||
420 | ||||
421 | void SwContentFrame::DestroyImpl() | |||
422 | { | |||
423 | const SwContentNode* pCNd(dynamic_cast<SwContentNode*>(GetDep())); | |||
424 | if (nullptr == pCNd && IsTextFrame()) | |||
425 | { | |||
426 | pCNd = static_cast<SwTextFrame*>(this)->GetTextNodeFirst(); | |||
427 | } | |||
428 | // IsInDtor shouldn't be happening with ViewShell owning layout | |||
429 | assert(nullptr == pCNd || !pCNd->GetDoc().IsInDtor())(static_cast <bool> (nullptr == pCNd || !pCNd->GetDoc ().IsInDtor()) ? void (0) : __assert_fail ("nullptr == pCNd || !pCNd->GetDoc().IsInDtor()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 429, __extension__ __PRETTY_FUNCTION__)); | |||
430 | if (nullptr != pCNd && !pCNd->GetDoc().IsInDtor()) | |||
431 | { | |||
432 | //Unregister from root if I'm still in turbo there. | |||
433 | SwRootFrame *pRoot = getRootFrame(); | |||
434 | if( pRoot && pRoot->GetTurbo() == this ) | |||
435 | { | |||
436 | pRoot->DisallowTurbo(); | |||
437 | pRoot->ResetTurbo(); | |||
438 | } | |||
439 | } | |||
440 | ||||
441 | SwFrame::DestroyImpl(); | |||
442 | } | |||
443 | ||||
444 | SwContentFrame::~SwContentFrame() | |||
445 | { | |||
446 | } | |||
447 | ||||
448 | void SwTextFrame::RegisterToNode(SwTextNode & rNode, bool const isForceNodeAsFirst) | |||
449 | { | |||
450 | if (isForceNodeAsFirst && m_pMergedPara) | |||
451 | { // nothing registered here, in particular no delete redlines (insert | |||
452 | // redline might end on empty node where delete rl starts, should be ok) | |||
453 | assert(m_pMergedPara->pFirstNode->GetIndex() + 1 == rNode.GetIndex())(static_cast <bool> (m_pMergedPara->pFirstNode->GetIndex () + 1 == rNode.GetIndex()) ? void (0) : __assert_fail ("m_pMergedPara->pFirstNode->GetIndex() + 1 == rNode.GetIndex()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 453, __extension__ __PRETTY_FUNCTION__)); | |||
454 | assert(rNode.GetDoc().getIDocumentRedlineAccess().GetRedlinePos((static_cast <bool> (rNode.GetDoc().getIDocumentRedlineAccess ().GetRedlinePos( *m_pMergedPara->pFirstNode, RedlineType:: Delete) == SwRedlineTable::npos) ? void (0) : __assert_fail ( "rNode.GetDoc().getIDocumentRedlineAccess().GetRedlinePos( *m_pMergedPara->pFirstNode, RedlineType::Delete) == SwRedlineTable::npos" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 455, __extension__ __PRETTY_FUNCTION__)) | |||
455 | *m_pMergedPara->pFirstNode, RedlineType::Delete) == SwRedlineTable::npos)(static_cast <bool> (rNode.GetDoc().getIDocumentRedlineAccess ().GetRedlinePos( *m_pMergedPara->pFirstNode, RedlineType:: Delete) == SwRedlineTable::npos) ? void (0) : __assert_fail ( "rNode.GetDoc().getIDocumentRedlineAccess().GetRedlinePos( *m_pMergedPara->pFirstNode, RedlineType::Delete) == SwRedlineTable::npos" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 455, __extension__ __PRETTY_FUNCTION__)); | |||
456 | } | |||
457 | assert(&rNode != GetDep())(static_cast <bool> (&rNode != GetDep()) ? void (0) : __assert_fail ("&rNode != GetDep()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 457, __extension__ __PRETTY_FUNCTION__)); | |||
458 | assert(!m_pMergedPara(static_cast <bool> (!m_pMergedPara || (m_pMergedPara-> pFirstNode->GetIndex() < rNode.GetIndex()) || (rNode.GetIndex () + 1 == m_pMergedPara->pFirstNode->GetIndex())) ? void (0) : __assert_fail ("!m_pMergedPara || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex()) || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 460, __extension__ __PRETTY_FUNCTION__)) | |||
459 | || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())(static_cast <bool> (!m_pMergedPara || (m_pMergedPara-> pFirstNode->GetIndex() < rNode.GetIndex()) || (rNode.GetIndex () + 1 == m_pMergedPara->pFirstNode->GetIndex())) ? void (0) : __assert_fail ("!m_pMergedPara || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex()) || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 460, __extension__ __PRETTY_FUNCTION__)) | |||
460 | || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex()))(static_cast <bool> (!m_pMergedPara || (m_pMergedPara-> pFirstNode->GetIndex() < rNode.GetIndex()) || (rNode.GetIndex () + 1 == m_pMergedPara->pFirstNode->GetIndex())) ? void (0) : __assert_fail ("!m_pMergedPara || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex()) || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 460, __extension__ __PRETTY_FUNCTION__)); | |||
461 | SwTextNode & rFirstNode( | |||
462 | (!isForceNodeAsFirst && m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex()) | |||
463 | ? *m_pMergedPara->pFirstNode | |||
464 | : rNode); | |||
465 | // sw_redlinehide: use New here, because the only caller also calls lcl_ChangeFootnoteRef | |||
466 | m_pMergedPara = sw::CheckParaRedlineMerge(*this, rFirstNode, sw::FrameMode::New); | |||
467 | if (!m_pMergedPara) | |||
468 | { | |||
469 | rNode.Add(this); | |||
470 | } | |||
471 | } | |||
472 | ||||
473 | void SwLayoutFrame::DestroyImpl() | |||
474 | { | |||
475 | while (!m_VertPosOrientFramesFor.empty()) | |||
| ||||
476 | { | |||
477 | SwAnchoredObject *pObj = *m_VertPosOrientFramesFor.begin(); | |||
478 | pObj->ClearVertPosOrientFrame(); | |||
479 | } | |||
480 | ||||
481 | assert(m_VertPosOrientFramesFor.empty())(static_cast <bool> (m_VertPosOrientFramesFor.empty()) ? void (0) : __assert_fail ("m_VertPosOrientFramesFor.empty()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 481, __extension__ __PRETTY_FUNCTION__)); | |||
482 | ||||
483 | SwFrame *pFrame = m_pLower; | |||
484 | ||||
485 | if( GetFormat() && !GetFormat()->GetDoc()->IsInDtor() ) | |||
486 | { | |||
487 | while ( pFrame ) | |||
488 | { | |||
489 | //First delete the Objs of the Frame because they can't unregister | |||
490 | //from the page after remove. | |||
491 | //We don't want to create an endless loop only because one couldn't | |||
492 | //unregister. | |||
493 | ||||
494 | while ( pFrame->GetDrawObjs() && pFrame->GetDrawObjs()->size() ) | |||
495 | { | |||
496 | const size_t nCnt = pFrame->GetDrawObjs()->size(); | |||
497 | // #i28701# | |||
498 | SwAnchoredObject* pAnchoredObj = (*pFrame->GetDrawObjs())[0]; | |||
499 | if (SwFlyFrame* pFlyFrame = dynamic_cast<SwFlyFrame*>(pAnchoredObj)) | |||
500 | { | |||
501 | SwFrame::DestroyFrame(pFlyFrame); | |||
502 | assert(!pFrame->GetDrawObjs() || nCnt > pFrame->GetDrawObjs()->size())(static_cast <bool> (!pFrame->GetDrawObjs() || nCnt > pFrame->GetDrawObjs()->size()) ? void (0) : __assert_fail ("!pFrame->GetDrawObjs() || nCnt > pFrame->GetDrawObjs()->size()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 502, __extension__ __PRETTY_FUNCTION__)); | |||
503 | } | |||
504 | else | |||
505 | { | |||
506 | pAnchoredObj->ClearTmpConsiderWrapInfluence(); | |||
507 | SdrObject* pSdrObj = pAnchoredObj->DrawObj(); | |||
508 | SwDrawContact* pContact = | |||
509 | static_cast<SwDrawContact*>(pSdrObj->GetUserCall()); | |||
510 | OSL_ENSURE( pContact,do { if (true && (!(pContact))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "511" ": "), "%s", "<SwFrame::~SwFrame> - missing contact for drawing object" ); } } while (false) | |||
511 | "<SwFrame::~SwFrame> - missing contact for drawing object" )do { if (true && (!(pContact))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "511" ": "), "%s", "<SwFrame::~SwFrame> - missing contact for drawing object" ); } } while (false); | |||
512 | if ( pContact ) | |||
513 | { | |||
514 | pContact->DisconnectObjFromLayout( pSdrObj ); | |||
515 | } | |||
516 | ||||
517 | if ( pFrame->GetDrawObjs() && | |||
518 | nCnt == pFrame->GetDrawObjs()->size() ) | |||
519 | { | |||
520 | pFrame->GetDrawObjs()->Remove( *pAnchoredObj ); | |||
521 | } | |||
522 | } | |||
523 | } | |||
524 | pFrame->RemoveFromLayout(); | |||
525 | SwFrame::DestroyFrame(pFrame); | |||
526 | pFrame = m_pLower; | |||
527 | } | |||
528 | //Delete the Flys, the last one also deletes the array. | |||
529 | while ( GetDrawObjs() && GetDrawObjs()->size() ) | |||
530 | { | |||
531 | const size_t nCnt = GetDrawObjs()->size(); | |||
532 | ||||
533 | // #i28701# | |||
534 | SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[0]; | |||
535 | if ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) != nullptr ) | |||
536 | { | |||
537 | SwFrame::DestroyFrame(static_cast<SwFlyFrame*>(pAnchoredObj)); | |||
538 | assert(!GetDrawObjs() || nCnt > GetDrawObjs()->size())(static_cast <bool> (!GetDrawObjs() || nCnt > GetDrawObjs ()->size()) ? void (0) : __assert_fail ("!GetDrawObjs() || nCnt > GetDrawObjs()->size()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" , 538, __extension__ __PRETTY_FUNCTION__)); | |||
539 | } | |||
540 | else | |||
541 | { | |||
542 | SdrObject* pSdrObj = pAnchoredObj->DrawObj(); | |||
543 | SwDrawContact* pContact = | |||
544 | static_cast<SwDrawContact*>(pSdrObj->GetUserCall()); | |||
545 | OSL_ENSURE( pContact,do { if (true && (!(pContact))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "546" ": "), "%s", "<SwFrame::~SwFrame> - missing contact for drawing object" ); } } while (false) | |||
546 | "<SwFrame::~SwFrame> - missing contact for drawing object" )do { if (true && (!(pContact))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "546" ": "), "%s", "<SwFrame::~SwFrame> - missing contact for drawing object" ); } } while (false); | |||
547 | if ( pContact ) | |||
548 | { | |||
549 | pContact->DisconnectObjFromLayout( pSdrObj ); | |||
550 | } | |||
551 | ||||
552 | if ( GetDrawObjs() && nCnt == GetDrawObjs()->size() ) | |||
553 | { | |||
554 | GetDrawObjs()->Remove( *pAnchoredObj ); | |||
555 | } | |||
556 | } | |||
557 | } | |||
558 | } | |||
559 | else | |||
560 | { | |||
561 | while( pFrame ) | |||
562 | { | |||
563 | SwFrame *pNxt = pFrame->GetNext(); | |||
564 | SwFrame::DestroyFrame(pFrame); | |||
565 | pFrame = pNxt; | |||
566 | } | |||
567 | } | |||
568 | ||||
569 | SwFrame::DestroyImpl(); | |||
570 | } | |||
571 | ||||
572 | SwLayoutFrame::~SwLayoutFrame() | |||
573 | { | |||
574 | } | |||
575 | ||||
576 | /** | |||
577 | |* The paintarea is the area, in which the content of a frame is allowed | |||
578 | |* to be displayed. This region could be larger than the printarea (getFramePrintArea()) | |||
579 | |* of the upper, it includes e.g. often the margin of the page. | |||
580 | |*/ | |||
581 | SwRect SwFrame::GetPaintArea() const | |||
582 | { | |||
583 | // NEW TABLES | |||
584 | // Cell frames may not leave their upper: | |||
585 | SwRect aRect = IsRowFrame() ? GetUpper()->getFrameArea() : getFrameArea(); | |||
586 | const bool bVert = IsVertical(); | |||
587 | SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; | |||
588 | SwRectFnSet aRectFnSet(this); | |||
589 | long nRight = (aRect.*fnRect->fnGetRight)(); | |||
590 | long nLeft = (aRect.*fnRect->fnGetLeft)(); | |||
591 | const SwFrame* pTmp = this; | |||
592 | bool bLeft = true; | |||
593 | bool bRight = true; | |||
594 | long nRowSpan = 0; | |||
595 | while( pTmp ) | |||
596 | { | |||
597 | if( pTmp->IsCellFrame() && pTmp->GetUpper() && | |||
598 | pTmp->GetUpper()->IsVertical() != pTmp->IsVertical() ) | |||
599 | nRowSpan = static_cast<const SwCellFrame*>(pTmp)->GetTabBox()->getRowSpan(); | |||
600 | long nTmpRight = (pTmp->getFrameArea().*fnRect->fnGetRight)(); | |||
601 | long nTmpLeft = (pTmp->getFrameArea().*fnRect->fnGetLeft)(); | |||
602 | if( pTmp->IsRowFrame() && nRowSpan > 1 ) | |||
603 | { | |||
604 | const SwFrame* pNxt = pTmp; | |||
605 | while( --nRowSpan > 0 && pNxt->GetNext() ) | |||
606 | pNxt = pNxt->GetNext(); | |||
607 | if( pTmp->IsVertical() ) | |||
608 | nTmpLeft = (pNxt->getFrameArea().*fnRect->fnGetLeft)(); | |||
609 | else | |||
610 | { | |||
611 | // pTmp is a row frame, but it's not vertical. | |||
612 | if (IsVertLRBT()) | |||
613 | { | |||
614 | // This frame cell is OK to expand towards the physical down direction. | |||
615 | // Physical down is left. | |||
616 | nTmpLeft = (pNxt->getFrameArea().*fnRect->fnGetLeft)(); | |||
617 | } | |||
618 | else | |||
619 | { | |||
620 | nTmpRight = (pNxt->getFrameArea().*fnRect->fnGetRight)(); | |||
621 | } | |||
622 | } | |||
623 | } | |||
624 | OSL_ENSURE( pTmp, "GetPaintArea lost in time and space" )do { if (true && (!(pTmp))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/ssfrm.cxx" ":" "624" ": "), "%s", "GetPaintArea lost in time and space" ); } } while (false); | |||
625 | if( pTmp->IsPageFrame() || pTmp->IsFlyFrame() || | |||
626 | pTmp->IsCellFrame() || pTmp->IsRowFrame() || //nobody leaves a table! | |||
627 | pTmp->IsRootFrame() ) | |||
628 | { | |||
629 | if( bLeft || aRectFnSet.XDiff(nTmpLeft, nLeft) > 0 ) | |||
630 | nLeft = nTmpLeft; | |||
631 | if( bRight || aRectFnSet.XDiff(nRight, nTmpRight) > 0 ) | |||
632 | nRight = nTmpRight; | |||
633 | if( pTmp->IsPageFrame() || pTmp->IsFlyFrame() || pTmp->IsRootFrame() ) | |||
634 | break; | |||
635 | bLeft = false; | |||
636 | bRight = false; | |||
637 | } | |||
638 | else if( pTmp->IsColumnFrame() ) // nobody enters neighbour columns | |||
639 | { | |||
640 | bool bR2L = pTmp->IsRightToLeft(); | |||
641 | // the first column has _no_ influence to the left range | |||
642 | if( bR2L ? pTmp->GetNext() : pTmp->GetPrev() ) | |||
643 | { | |||
644 | if( bLeft || aRectFnSet.XDiff(nTmpLeft, nLeft) > 0 ) | |||
645 | nLeft = nTmpLeft; | |||
646 | bLeft = false; | |||
647 | } | |||
648 | // the last column has _no_ influence to the right range | |||
649 | if( bR2L ? pTmp->GetPrev() : pTmp->GetNext() ) | |||
650 | { | |||
651 | if( bRight || aRectFnSet.XDiff(nRight, nTmpRight) > 0 ) | |||
652 | nRight = nTmpRight; | |||
653 | bRight = false; | |||
654 | } | |||
655 | } | |||
656 | else if( bVert && pTmp->IsBodyFrame() ) | |||
657 | { | |||
658 | // Header and footer frames have always horizontal direction and | |||
659 | // limit the body frame. | |||
660 | // A previous frame of a body frame must be a header, | |||
661 | // the next frame of a body frame may be a footnotecontainer or | |||
662 | // a footer. The footnotecontainer has the same direction like | |||
663 | // the body frame. | |||
664 | if( pTmp->GetPrev() && ( bLeft || aRectFnSet.XDiff(nTmpLeft, nLeft) > 0 ) ) | |||
665 | { | |||
666 | nLeft = nTmpLeft; | |||
667 | bLeft = false; | |||
668 | } | |||
669 | if( pTmp->GetNext() && | |||
670 | ( pTmp->GetNext()->IsFooterFrame() || pTmp->GetNext()->GetNext() ) | |||
671 | && ( bRight || aRectFnSet.XDiff(nRight, nTmpRight) > 0 ) ) | |||
672 | { | |||
673 | nRight = nTmpRight; | |||
674 | bRight = false; | |||
675 | } | |||
676 | } | |||
677 | pTmp = pTmp->GetUpper(); | |||
678 | } | |||
679 | (aRect.*fnRect->fnSetLeft)( nLeft ); | |||
680 | (aRect.*fnRect->fnSetRight)( nRight ); | |||
681 | return aRect; | |||
682 | } | |||
683 | ||||
684 | /** | |||
685 | |* The unionframe is the framearea (getFrameArea()) of a frame expanded by the | |||
686 | |* printarea, if there's a negative margin at the left or right side. | |||
687 | |*/ | |||
688 | SwRect SwFrame::UnionFrame( bool bBorder ) const | |||
689 | { | |||
690 | bool bVert = IsVertical(); | |||
691 | SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; | |||
692 | long nLeft = (getFrameArea().*fnRect->fnGetLeft)(); | |||
693 | long nWidth = (getFrameArea().*fnRect->fnGetWidth)(); | |||
694 | long nPrtLeft = (getFramePrintArea().*fnRect->fnGetLeft)(); | |||
695 | long nPrtWidth = (getFramePrintArea().*fnRect->fnGetWidth)(); | |||
696 | SwRectFnSet aRectFnSet(this); | |||
697 | if (aRectFnSet.XInc(nPrtLeft, nPrtWidth) > nWidth) | |||
698 | nWidth = nPrtLeft + nPrtWidth; | |||
699 | if( nPrtLeft < 0 ) | |||
700 | { | |||
701 | nLeft += nPrtLeft; | |||
702 | nWidth -= nPrtLeft; | |||
703 | } | |||
704 | SwTwips nRight = aRectFnSet.XInc(nLeft, nWidth); | |||
705 | long nAdd = 0; | |||
706 | if( bBorder ) | |||
707 | { | |||
708 | SwBorderAttrAccess aAccess( SwFrame::GetCache(), this ); | |||
709 | const SwBorderAttrs &rAttrs = *aAccess.Get(); | |||
710 | const SvxBoxItem &rBox = rAttrs.GetBox(); | |||
711 | if ( rBox.GetLeft() ) | |||
712 | nLeft -= rBox.CalcLineSpace( SvxBoxItemLine::LEFT ); | |||
713 | else | |||
714 | nLeft -= rBox.GetDistance( SvxBoxItemLine::LEFT ) + 1; | |||
715 | if ( rBox.GetRight() ) | |||
716 | nAdd += rBox.CalcLineSpace( SvxBoxItemLine::RIGHT ); | |||
717 | else | |||
718 | nAdd += rBox.GetDistance( SvxBoxItemLine::RIGHT ) + 1; | |||
719 | if( rAttrs.GetShadow().GetLocation() != SvxShadowLocation::NONE ) | |||
720 | { | |||
721 | const SvxShadowItem &rShadow = rAttrs.GetShadow(); | |||
722 | nLeft -= rShadow.CalcShadowSpace( SvxShadowItemSide::LEFT ); | |||
723 | nAdd += rShadow.CalcShadowSpace( SvxShadowItemSide::RIGHT ); | |||
724 | } | |||
725 | } | |||
726 | if( IsTextFrame() && static_cast<const SwTextFrame*>(this)->HasPara() ) | |||
727 | { | |||
728 | long nTmp = static_cast<const SwTextFrame*>(this)->HangingMargin(); | |||
729 | if( nTmp > nAdd ) | |||
730 | nAdd = nTmp; | |||
731 | } | |||
732 | nWidth = aRectFnSet.XDiff(aRectFnSet.XInc(nRight, nAdd), nLeft); | |||
733 | SwRect aRet( getFrameArea() ); | |||
734 | (aRet.*fnRect->fnSetLeft)(nLeft); | |||
735 | (aRet.*fnRect->fnSetWidth)( nWidth ); | |||
736 | return aRet; | |||
737 | } | |||
738 | ||||
739 | /* 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_SOURCE_CORE_INC_FRAME_HXX |
21 | #define INCLUDED_SW_SOURCE_CORE_INC_FRAME_HXX |
22 | |
23 | #include <drawinglayer/primitive2d/baseprimitive2d.hxx> |
24 | #include <editeng/borderline.hxx> |
25 | #include <svl/poolitem.hxx> |
26 | #include <swtypes.hxx> |
27 | #include <swrect.hxx> |
28 | #include <calbck.hxx> |
29 | #include <svl/SfxBroadcaster.hxx> |
30 | #include <o3tl/typed_flags_set.hxx> |
31 | #include <com/sun/star/style/TabStop.hpp> |
32 | #include <basegfx/matrix/b2dhommatrix.hxx> |
33 | #include <vcl/outdev.hxx> |
34 | |
35 | #include <memory> |
36 | |
37 | namespace drawinglayer::processor2d { class BaseProcessor2D; } |
38 | |
39 | class SwLayoutFrame; |
40 | class SwRootFrame; |
41 | class SwPageFrame; |
42 | class SwBodyFrame; |
43 | class SwFlyFrame; |
44 | class SwSectionFrame; |
45 | class SwFootnoteFrame; |
46 | class SwFootnoteBossFrame; |
47 | class SwTabFrame; |
48 | class SwRowFrame; |
49 | class SwContentFrame; |
50 | class SwAttrSet; |
51 | class Color; |
52 | class SwBorderAttrs; |
53 | class SwCache; |
54 | class SvxBrushItem; |
55 | class SvxFormatBreakItem; |
56 | class SwFormatPageDesc; |
57 | class SwSelectionList; |
58 | struct SwPosition; |
59 | struct SwCursorMoveState; |
60 | class SwFormat; |
61 | class SwPrintData; |
62 | class SwSortedObjs; |
63 | class SwAnchoredObject; |
64 | enum class SvxFrameDirection; |
65 | class IDocumentDrawModelAccess; |
66 | |
67 | // Each FrameType is represented here as a bit. |
68 | // The bits must be set in a way that it can be determined with masking of |
69 | // which kind of FrameType an instance is _and_ from what classes it was derived. |
70 | // Each frame has in its base class a member that must be set by the |
71 | // constructors accordingly. |
72 | enum class SwFrameType |
73 | { |
74 | None = 0x0000, |
75 | Root = 0x0001, |
76 | Page = 0x0002, |
77 | Column = 0x0004, |
78 | Header = 0x0008, |
79 | Footer = 0x0010, |
80 | FtnCont = 0x0020, |
81 | Ftn = 0x0040, |
82 | Body = 0x0080, |
83 | Fly = 0x0100, |
84 | Section = 0x0200, |
85 | // UNUSED 0x0400 |
86 | Tab = 0x0800, |
87 | Row = 0x1000, |
88 | Cell = 0x2000, |
89 | Txt = 0x4000, |
90 | NoTxt = 0x8000, |
91 | }; |
92 | |
93 | namespace o3tl |
94 | { |
95 | template<> struct typed_flags<SwFrameType> : is_typed_flags<SwFrameType, 0xfbff> {}; |
96 | }; |
97 | |
98 | // for internal use some common combinations |
99 | #define FRM_LAYOUTSwFrameType(0x3bFF) SwFrameType(0x3bFF) |
100 | #define FRM_ALLSwFrameType(0xfbff) SwFrameType(0xfbff) |
101 | #define FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt) (SwFrameType::Txt | SwFrameType::NoTxt) |
102 | #define FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column) (SwFrameType::Page | SwFrameType::Column) |
103 | #define FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType ::Tab | SwFrameType::Cell | SwFrameType::Txt) (SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType::Tab | SwFrameType::Cell | SwFrameType::Txt) |
104 | #define FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell) (SwFrameType::Column | SwFrameType::Cell) |
105 | #define FRM_NOTE_VERT(SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType ::Txt) (SwFrameType::FtnCont | SwFrameType::Ftn | SwFrameType::Section | SwFrameType::Tab | SwFrameType::Row | SwFrameType::Cell | SwFrameType::Txt) |
106 | #define FRM_HEADFOOT(SwFrameType::Header | SwFrameType::Footer) (SwFrameType::Header | SwFrameType::Footer) |
107 | #define FRM_BODYFTNC(SwFrameType::FtnCont | SwFrameType::Body) (SwFrameType::FtnCont | SwFrameType::Body) |
108 | |
109 | // for GetNextLeaf/GetPrevLeaf. |
110 | enum MakePageType |
111 | { |
112 | MAKEPAGE_NONE, // do not create page/footnote |
113 | MAKEPAGE_APPEND, // only append page if needed |
114 | MAKEPAGE_INSERT, // add or append page if needed |
115 | MAKEPAGE_FTN, // add footnote if needed |
116 | MAKEPAGE_NOSECTION // Don't create section frames |
117 | }; |
118 | |
119 | namespace drawinglayer::attribute { |
120 | class SdrAllFillAttributesHelper; |
121 | typedef std::shared_ptr< SdrAllFillAttributesHelper > SdrAllFillAttributesHelperPtr; |
122 | } |
123 | |
124 | /// Helper class to isolate geometry-defining members of SwFrame |
125 | /// and to control their accesses. Moved to own class to have no |
126 | /// hidden accesses to 'private' members anymore. |
127 | /// |
128 | /// Added most important flags about the state of this geometric |
129 | /// information and if it is valid or not |
130 | class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SwFrameAreaDefinition |
131 | { |
132 | private: |
133 | friend void FriendHackInvalidateRowFrame(SwFrameAreaDefinition &); |
134 | |
135 | // The absolute position and size of the SwFrame in the document. |
136 | // This values are set by the layouter implementations |
137 | SwRect maFrameArea; |
138 | |
139 | // The 'inner' Frame Area defined by a SwRect relative to FrameArea: |
140 | // When identical to FrameArea, Pos() will be (0, 0) and Size identical. |
141 | SwRect maFramePrintArea; |
142 | |
143 | // bitfield |
144 | bool mbFrameAreaPositionValid : 1; |
145 | bool mbFrameAreaSizeValid : 1; |
146 | bool mbFramePrintAreaValid : 1; |
147 | |
148 | // #i65250# |
149 | // frame ID is now in general available - used for layout loop control |
150 | static sal_uInt32 mnLastFrameId; |
151 | const sal_uInt32 mnFrameId; |
152 | |
153 | protected: |
154 | // write access to mb*Valid flags |
155 | void setFrameAreaPositionValid(bool bNew); |
156 | void setFrameAreaSizeValid(bool bNew); |
157 | void setFramePrintAreaValid(bool bNew); |
158 | |
159 | public: |
160 | SwFrameAreaDefinition(); |
161 | virtual ~SwFrameAreaDefinition(); |
162 | |
163 | // read access to mb*Valid flags |
164 | bool isFrameAreaPositionValid() const { return mbFrameAreaPositionValid; } |
165 | bool isFrameAreaSizeValid() const { return mbFrameAreaSizeValid; } |
166 | bool isFramePrintAreaValid() const { return mbFramePrintAreaValid; } |
167 | |
168 | // syntactic sugar: test whole FrameAreaDefinition |
169 | bool isFrameAreaDefinitionValid() const { return isFrameAreaPositionValid() && isFrameAreaSizeValid() && isFramePrintAreaValid(); } |
170 | |
171 | // #i65250# |
172 | sal_uInt32 GetFrameId() const { return mnFrameId; } |
173 | |
174 | // read accesses to FrameArea definitions - only const access allowed. |
175 | // Do *not* const_cast results, it is necessary to track changes. use |
176 | // the below offered WriteAccess helper classes instead |
177 | const SwRect& getFrameArea() const { return maFrameArea; } |
178 | const SwRect& getFramePrintArea() const { return maFramePrintArea; } |
179 | |
180 | // helper class(es) for FrameArea manipulation. These |
181 | // have to be used to apply changes to FrameAreas. They hold a copy of the |
182 | // SwRect for manipulation. It gets written back at destruction. Thus, this |
183 | // mechanism depends on scope usage, take care. It prevents errors using |
184 | // different instances of SwFrame in get/set methods which is more safe |
185 | class FrameAreaWriteAccess : public SwRect |
186 | { |
187 | private: |
188 | SwFrameAreaDefinition& mrTarget; |
189 | |
190 | FrameAreaWriteAccess(const FrameAreaWriteAccess&) = delete; |
191 | FrameAreaWriteAccess& operator=(const FrameAreaWriteAccess&) = delete; |
192 | |
193 | public: |
194 | FrameAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFrameArea()), mrTarget(rTarget) {} |
195 | ~FrameAreaWriteAccess(); |
196 | void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; } |
197 | }; |
198 | |
199 | // same helper for FramePrintArea |
200 | class FramePrintAreaWriteAccess : public SwRect |
201 | { |
202 | private: |
203 | SwFrameAreaDefinition& mrTarget; |
204 | |
205 | FramePrintAreaWriteAccess(const FramePrintAreaWriteAccess&) = delete; |
206 | FramePrintAreaWriteAccess& operator=(const FramePrintAreaWriteAccess&) = delete; |
207 | |
208 | public: |
209 | FramePrintAreaWriteAccess(SwFrameAreaDefinition& rTarget) : SwRect(rTarget.getFramePrintArea()), mrTarget(rTarget) {} |
210 | ~FramePrintAreaWriteAccess(); |
211 | void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; } |
212 | }; |
213 | |
214 | // RotateFlyFrame3 - Support for Transformations |
215 | // Hand out the Transformations for the current FrameAreaDefinition |
216 | // for the FrameArea and FramePrintArea. |
217 | // FramePrintArea is not relative to FrameArea in this |
218 | // transformation representation (to make it easier to use and understand). |
219 | // There is no 'set' method since SwFrame is a layout object. For |
220 | // some cases rotation will be included (used for SwGrfNode in inner |
221 | // SwFrame of a SwFlyFrame) |
222 | virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const; |
223 | virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const; |
224 | |
225 | // RotateFlyFrame3 - Support for Transformations |
226 | // Modify current transformations by applying given translation |
227 | virtual void transform_translate(const Point& rOffset); |
228 | }; |
229 | |
230 | /// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate |
231 | /// transformable. It provides some tooling to do so. To use, add as member |
232 | /// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >') |
233 | class TransformableSwFrame |
234 | { |
235 | private: |
236 | // The SwFrameAreaDefinition to work on |
237 | SwFrameAreaDefinition& mrSwFrameAreaDefinition; |
238 | |
239 | // FrameAreaTransformation and FramePrintAreaTransformation |
240 | // !identity when needed (translate/scale is used (e.g. rotation)) |
241 | basegfx::B2DHomMatrix maFrameAreaTransformation; |
242 | basegfx::B2DHomMatrix maFramePrintAreaTransformation; |
243 | |
244 | public: |
245 | TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition) |
246 | : mrSwFrameAreaDefinition(rSwFrameAreaDefinition), |
247 | maFrameAreaTransformation(), |
248 | maFramePrintAreaTransformation() |
249 | { |
250 | } |
251 | |
252 | // get SwFrameArea in transformation form |
253 | const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const |
254 | { |
255 | return maFrameAreaTransformation; |
256 | } |
257 | |
258 | // get SwFramePrintArea in transformation form |
259 | const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const |
260 | { |
261 | return maFramePrintAreaTransformation; |
262 | } |
263 | |
264 | // Helpers to re-create the untransformed SwRect(s) originally |
265 | // in the SwFrameAreaDefinition, based on the current Transformations. |
266 | SwRect getUntransformedFrameArea() const; |
267 | SwRect getUntransformedFramePrintArea() const; |
268 | |
269 | // Helper method to re-create FrameAreaTransformations based on the |
270 | // current FrameAreaDefinition transformed by given rotation and Center |
271 | void createFrameAreaTransformations( |
272 | double fRotation, |
273 | const basegfx::B2DPoint& rCenter); |
274 | |
275 | // Tooling method to reset the SwRect(s) in the current |
276 | // SwFrameAreaDefinition which are already adapted to |
277 | // Transformation back to the untransformed state, using |
278 | // the getUntransformedFrame*Area calls above when needed. |
279 | // Only the SwRect(s) are changed back, not the transformations. |
280 | void restoreFrameAreas(); |
281 | |
282 | // Re-Creates the SwRect(s) as BoundAreas based on the current |
283 | // set Transformations. |
284 | void adaptFrameAreasToTransformations(); |
285 | |
286 | // Modify current definitions by applying the given transformation |
287 | void transform(const basegfx::B2DHomMatrix& aTransform); |
288 | }; |
289 | |
290 | /** |
291 | * Base class of the Writer layout elements. |
292 | * |
293 | * This includes not only fly frames, but everything down to the paragraph |
294 | * level: pages, headers, footers, etc. (Inside a paragraph SwLinePortion |
295 | * instances are used.) |
296 | */ |
297 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwFrame : public SwFrameAreaDefinition, public SwClient, public SfxBroadcaster |
298 | { |
299 | // the hidden Frame |
300 | friend class SwFlowFrame; |
301 | friend class SwLayoutFrame; |
302 | friend class SwLooping; |
303 | friend class SwDeletionChecker; // for GetDep() |
304 | |
305 | // voids lower during creation of a column |
306 | friend SwFrame *SaveContent( SwLayoutFrame *, SwFrame* pStart ); |
307 | friend void RestoreContent( SwFrame *, SwLayoutFrame *, SwFrame *pSibling ); |
308 | |
309 | // for validating a mistakenly invalidated one in SwContentFrame::MakeAll |
310 | friend void ValidateSz( SwFrame *pFrame ); |
311 | // implemented in text/txtftn.cxx, prevents Footnote oscillation |
312 | friend void ValidateText( SwFrame *pFrame ); |
313 | |
314 | friend void MakeNxt( SwFrame *pFrame, SwFrame *pNxt ); |
315 | |
316 | // cache for (border) attributes |
317 | static SwCache *mpCache; |
318 | |
319 | SwRootFrame *mpRoot; |
320 | SwLayoutFrame *mpUpper; |
321 | SwFrame *mpNext; |
322 | SwFrame *mpPrev; |
323 | |
324 | // sw_redlinehide: hide these dangerous SwClient functions |
325 | using SwClient::GetRegisteredInNonConst; |
326 | using SwClient::GetRegisteredIn; |
327 | |
328 | SwFrame *FindNext_(); |
329 | SwFrame *FindPrev_(); |
330 | |
331 | /** method to determine next content frame in the same environment |
332 | for a flow frame (content frame, table frame, section frame) |
333 | |
334 | #i27138# - adding documentation: |
335 | Travelling downwards through the layout to determine the next content |
336 | frame in the same environment. There are several environments in a |
337 | document, which form a closed context regarding this function. These |
338 | environments are: |
339 | - Each page header |
340 | - Each page footer |
341 | - Each unlinked fly frame |
342 | - Each group of linked fly frames |
343 | - All footnotes |
344 | - All document body frames |
345 | #i27138# - adding parameter <_bInSameFootnote> |
346 | Its default value is <false>. If its value is <true>, the environment |
347 | 'All footnotes' is no longer treated. Instead each footnote is treated |
348 | as an own environment. |
349 | |
350 | @param _bInSameFootnote |
351 | input parameter - boolean indicating, that the found next content |
352 | frame has to be in the same footnote frame. This parameter is only |
353 | relevant for flow frames in footnotes. |
354 | |
355 | @return SwContentFrame* |
356 | pointer to the found next content frame. It's NULL, if none exists. |
357 | */ |
358 | SwContentFrame* FindNextCnt_( const bool _bInSameFootnote ); |
359 | |
360 | /** method to determine previous content frame in the same environment |
361 | for a flow frame (content frame, table frame, section frame) |
362 | |
363 | #i27138# |
364 | Travelling upwards through the layout to determine the previous content |
365 | frame in the same environment. There are several environments in a |
366 | document, which form a closed context regarding this function. These |
367 | environments are: |
368 | - Each page header |
369 | - Each page footer |
370 | - Each unlinked fly frame |
371 | - Each group of linked fly frames |
372 | - All footnotes |
373 | - All document body frames |
374 | #i27138# - adding parameter <_bInSameFootnote> |
375 | Its default value is <false>. If its value is <true>, the environment |
376 | 'All footnotes' is no longer treated. Instead each footnote is treated |
377 | as an own environment. |
378 | |
379 | The found previous content frame has to be in the same footnote frame. This is only |
380 | relevant for flow frames in footnotes. |
381 | |
382 | @return SwContentFrame* |
383 | pointer to the found previous content frame. It's NULL, if none exists. |
384 | */ |
385 | SwContentFrame* FindPrevCnt_(); |
386 | |
387 | void UpdateAttrFrame( const SfxPoolItem*, const SfxPoolItem*, sal_uInt8 & ); |
388 | SwFrame* GetIndNext_(); |
389 | void SetDirFlags( bool bVert ); |
390 | |
391 | const SwLayoutFrame* ImplGetNextLayoutLeaf( bool bFwd ) const; |
392 | |
393 | SwPageFrame* ImplFindPageFrame(); |
394 | |
395 | protected: |
396 | std::unique_ptr<SwSortedObjs> m_pDrawObjs; // draw objects, can be null |
397 | SwFrameType mnFrameType; //Who am I? |
398 | |
399 | bool mbInDtor : 1; |
400 | bool mbInvalidR2L : 1; |
401 | bool mbDerivedR2L : 1; |
402 | bool mbRightToLeft : 1; |
403 | bool mbInvalidVert : 1; |
404 | bool mbDerivedVert : 1; |
405 | bool mbVertical : 1; |
406 | |
407 | bool mbVertLR : 1; |
408 | bool mbVertLRBT : 1; |
409 | |
410 | bool mbValidLineNum : 1; |
411 | bool mbFixSize : 1; |
412 | |
413 | // if true, frame will be painted completely even content was changed |
414 | // only partially. For ContentFrames a border (from Action) will exclusively |
415 | // painted if <mbCompletePaint> is true. |
416 | bool mbCompletePaint : 1; |
417 | |
418 | bool mbRetouche : 1; // frame is responsible for retouching |
419 | |
420 | bool mbInfInvalid : 1; // InfoFlags are invalid |
421 | bool mbInfBody : 1; // Frame is in document body |
422 | bool mbInfTab : 1; // Frame is in a table |
423 | bool mbInfFly : 1; // Frame is in a Fly |
424 | bool mbInfFootnote : 1; // Frame is in a footnote |
425 | bool mbInfSct : 1; // Frame is in a section |
426 | bool mbColLocked : 1; // lock Grow/Shrink for column-wise section |
427 | // or fly frames, will be set in Format |
428 | bool m_isInDestroy : 1; |
429 | bool mbForbidDelete : 1; |
430 | |
431 | void ColLock() { mbColLocked = true; } |
432 | void ColUnlock() { mbColLocked = false; } |
433 | |
434 | virtual void DestroyImpl(); |
435 | virtual ~SwFrame() override; |
436 | |
437 | // Only used by SwRootFrame Ctor to get 'this' into mpRoot... |
438 | void setRootFrame( SwRootFrame* pRoot ) { mpRoot = pRoot; } |
439 | |
440 | SwPageFrame *InsertPage( SwPageFrame *pSibling, bool bFootnote ); |
441 | void PrepareMake(vcl::RenderContext* pRenderContext); |
442 | void OptPrepareMake(); |
443 | virtual void MakePos(); |
444 | // Format next frame of table frame to assure keeping attributes. |
445 | // In case of nested tables method <SwFrame::MakeAll()> is called to |
446 | // avoid formatting of superior table frame. |
447 | friend SwFrame* sw_FormatNextContentForKeep( SwTabFrame* pTabFrame ); |
448 | |
449 | virtual void MakeAll(vcl::RenderContext* pRenderContext) = 0; |
450 | // adjust frames of a page |
451 | SwTwips AdjustNeighbourhood( SwTwips nDiff, bool bTst = false ); |
452 | |
453 | // change only frame size not the size of PrtArea |
454 | virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) = 0; |
455 | virtual SwTwips GrowFrame ( SwTwips, bool bTst = false, bool bInfo = false ) = 0; |
456 | |
457 | /// use these so we can grep for SwFrame's GetRegisteredIn accesses |
458 | /// beware that SwTextFrame may return sw::WriterMultiListener |
459 | SwModify *GetDep() { return GetRegisteredInNonConst(); } |
460 | const SwModify *GetDep() const { return GetRegisteredIn(); } |
461 | |
462 | SwFrame( SwModify*, SwFrame* ); |
463 | |
464 | void CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool bBrowse ); |
465 | |
466 | /** enumeration for the different invalidations |
467 | #i28701# |
468 | */ |
469 | enum InvalidationType |
470 | { |
471 | INVALID_SIZE, INVALID_PRTAREA, INVALID_POS, INVALID_LINENUM, INVALID_ALL |
472 | }; |
473 | |
474 | /** method to determine, if an invalidation is allowed. |
475 | #i28701 |
476 | */ |
477 | virtual bool InvalidationAllowed( const InvalidationType _nInvalid ) const; |
478 | |
479 | /** method to perform additional actions on an invalidation |
480 | |
481 | #i28701# |
482 | Method has *only* to contain actions, which has to be performed on |
483 | *every* assignment of the corresponding flag to <false>. |
484 | */ |
485 | virtual void ActionOnInvalidation( const InvalidationType _nInvalid ); |
486 | |
487 | // draw shadow and borders |
488 | void PaintShadow( const SwRect&, SwRect&, const SwBorderAttrs& ) const; |
489 | virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override; |
490 | |
491 | virtual const IDocumentDrawModelAccess& getIDocumentDrawModelAccess( ); |
492 | |
493 | public: |
494 | virtual css::uno::Sequence< css::style::TabStop > GetTabStopInfo( SwTwips ) |
495 | { |
496 | return css::uno::Sequence< css::style::TabStop >(); |
497 | } |
498 | |
499 | |
500 | SwFrameType GetType() const { return mnFrameType; } |
501 | |
502 | static SwCache &GetCache() { return *mpCache; } |
503 | static SwCache *GetCachePtr() { return mpCache; } |
504 | static void SetCache( SwCache *pNew ) { mpCache = pNew; } |
505 | |
506 | // change PrtArea size and FrameSize |
507 | SwTwips Shrink( SwTwips, bool bTst = false, bool bInfo = false ); |
508 | SwTwips Grow ( SwTwips, bool bTst = false, bool bInfo = false ); |
509 | |
510 | // different methods for inserting in layout tree (for performance reasons) |
511 | |
512 | // insert before pBehind or at the end of the chain below mpUpper |
513 | void InsertBefore( SwLayoutFrame* pParent, SwFrame* pBehind ); |
514 | // insert after pBefore or at the beginning of the chain below mpUpper |
515 | void InsertBehind( SwLayoutFrame *pParent, SwFrame *pBefore ); |
516 | // insert before pBehind or at the end of the chain while considering |
517 | // the siblings of pSct |
518 | bool InsertGroupBefore( SwFrame* pParent, SwFrame* pWhere, SwFrame* pSct ); |
519 | void RemoveFromLayout(); |
520 | |
521 | // For internal use only - who ignores this will be put in a sack and has |
522 | // to stay there for two days |
523 | // Does special treatment for Get_[Next|Prev]Leaf() (for tables). |
524 | SwLayoutFrame *GetLeaf( MakePageType eMakePage, bool bFwd ); |
525 | SwLayoutFrame *GetNextLeaf ( MakePageType eMakePage ); |
526 | SwLayoutFrame *GetNextFootnoteLeaf( MakePageType eMakePage ); |
527 | SwLayoutFrame *GetNextSctLeaf( MakePageType eMakePage ); |
528 | SwLayoutFrame *GetNextCellLeaf(); |
529 | SwLayoutFrame *GetPrevLeaf (); |
530 | SwLayoutFrame *GetPrevFootnoteLeaf( MakePageType eMakeFootnote ); |
531 | SwLayoutFrame *GetPrevSctLeaf(); |
532 | SwLayoutFrame *GetPrevCellLeaf(); |
533 | const SwLayoutFrame *GetLeaf ( MakePageType eMakePage, bool bFwd, |
534 | const SwFrame *pAnch ) const; |
535 | |
536 | bool WrongPageDesc( SwPageFrame* pNew ); |
537 | |
538 | //#i28701# - new methods to append/remove drawing objects |
539 | void AppendDrawObj( SwAnchoredObject& _rNewObj ); |
540 | void RemoveDrawObj( SwAnchoredObject& _rToRemoveObj ); |
541 | |
542 | // work with chain of FlyFrames |
543 | void AppendFly( SwFlyFrame *pNew ); |
544 | void RemoveFly( SwFlyFrame *pToRemove ); |
545 | const SwSortedObjs *GetDrawObjs() const { return m_pDrawObjs.get(); } |
546 | SwSortedObjs *GetDrawObjs() { return m_pDrawObjs.get(); } |
547 | // #i28701# - change purpose of method and adjust its name |
548 | void InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs = true ); |
549 | |
550 | virtual void PaintSwFrameShadowAndBorder( |
551 | const SwRect&, |
552 | const SwPageFrame* pPage, |
553 | const SwBorderAttrs&) const; |
554 | void PaintBaBo( const SwRect&, const SwPageFrame *pPage, |
555 | const bool bOnlyTextBackground = false) const; |
556 | void PaintSwFrameBackground( const SwRect&, const SwPageFrame *pPage, |
557 | const SwBorderAttrs &, |
558 | const bool bLowerMode = false, |
559 | const bool bLowerBorder = false, |
560 | const bool bOnlyTextBackground = false ) const; |
561 | void PaintBorderLine( const SwRect&, const SwRect&, const SwPageFrame*, |
562 | const Color *pColor, |
563 | const SvxBorderLineStyle = SvxBorderLineStyle::SOLID ) const; |
564 | |
565 | std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> CreateProcessor2D( ) const; |
566 | void ProcessPrimitives( const drawinglayer::primitive2d::Primitive2DContainer& rSequence ) const; |
567 | |
568 | // retouch, not in the area of the given Rect! |
569 | void Retouch( const SwPageFrame *pPage, const SwRect &rRect ) const; |
570 | |
571 | bool GetBackgroundBrush( |
572 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr& rFillAttributes, |
573 | const SvxBrushItem*& rpBrush, |
574 | const Color*& rpColor, |
575 | SwRect &rOrigRect, |
576 | bool bLowerMode, |
577 | bool bConsiderTextBox ) const; |
578 | |
579 | inline void SetCompletePaint() const; |
580 | inline void ResetCompletePaint() const; |
581 | bool IsCompletePaint() const { return mbCompletePaint; } |
582 | |
583 | inline void SetRetouche() const; |
584 | inline void ResetRetouche() const; |
585 | bool IsRetouche() const { return mbRetouche; } |
586 | |
587 | void SetInfFlags(); |
588 | void InvalidateInfFlags() { mbInfInvalid = true; } |
589 | inline bool IsInDocBody() const; // use InfoFlags, determine flags |
590 | inline bool IsInFootnote() const; // if necessary |
591 | inline bool IsInTab() const; |
592 | inline bool IsInFly() const; |
593 | inline bool IsInSct() const; |
594 | |
595 | // If frame is inside a split table row, this function returns |
596 | // the corresponding row frame in the follow table. |
597 | const SwRowFrame* IsInSplitTableRow() const; |
598 | |
599 | // If frame is inside a follow flow row, this function returns |
600 | // the corresponding row frame master table |
601 | const SwRowFrame* IsInFollowFlowRow() const; |
602 | |
603 | bool IsInBalancedSection() const; |
604 | |
605 | inline bool IsVertical() const; |
606 | inline bool IsVertLR() const; |
607 | inline bool IsVertLRBT() const; |
608 | |
609 | void SetDerivedVert( bool bNew ){ mbDerivedVert = bNew; } |
610 | void SetInvalidVert( bool bNew) { mbInvalidVert = bNew; } |
611 | inline bool IsRightToLeft() const; |
612 | void SetDerivedR2L( bool bNew ) { mbDerivedR2L = bNew; } |
613 | |
614 | void CheckDirChange(); |
615 | // returns upper left frame position for LTR and |
616 | // upper right frame position for Asian / RTL frames |
617 | Point GetFrameAnchorPos( bool bIgnoreFlysAnchoredAtThisFrame ) const; |
618 | |
619 | /** determine, if frame is moveable in given environment |
620 | |
621 | method replaced 'old' method <bool IsMoveable() const>. |
622 | Determines, if frame is moveable in given environment. if no environment |
623 | is given (parameter _pLayoutFrame == 0), the movability in the actual |
624 | environment (<GetUpper()) is checked. |
625 | |
626 | @param _pLayoutFrame |
627 | input parameter - given environment (layout frame), in which the movability |
628 | will be checked. If not set ( == 0 ), actual environment is taken. |
629 | |
630 | @return boolean, indicating, if frame is moveable in given environment |
631 | */ |
632 | bool IsMoveable( const SwLayoutFrame* _pLayoutFrame = nullptr ) const; |
633 | |
634 | // Is it permitted for the (Text)Frame to add a footnote in the current |
635 | // environment (not e.g. for repeating table headlines) |
636 | bool IsFootnoteAllowed() const; |
637 | |
638 | virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ); |
639 | |
640 | virtual void CheckDirection( bool bVert ); |
641 | |
642 | void ReinitializeFrameSizeAttrFlags(); |
643 | |
644 | /// WARNING: this may not return correct RES_PAGEDESC/RES_BREAK items for |
645 | /// SwTextFrame, use GetBreakItem()/GetPageDescItem() instead |
646 | const SwAttrSet *GetAttrSet() const; |
647 | virtual const SvxFormatBreakItem& GetBreakItem() const; |
648 | virtual const SwFormatPageDesc& GetPageDescItem() const; |
649 | |
650 | bool HasFixSize() const { return mbFixSize; } |
651 | |
652 | // check all pages (starting from the given) and correct them if needed |
653 | static void CheckPageDescs( SwPageFrame *pStart, bool bNotifyFields = true, SwPageFrame** ppPrev = nullptr); |
654 | |
655 | // might return 0, with and without const |
656 | SwFrame *GetNext() { return mpNext; } |
657 | SwFrame *GetPrev() { return mpPrev; } |
658 | SwLayoutFrame *GetUpper() { return mpUpper; } |
659 | SwRootFrame *getRootFrame(){ return mpRoot; } |
660 | SwPageFrame *FindPageFrame() { return IsPageFrame() ? reinterpret_cast<SwPageFrame*>(this) : ImplFindPageFrame(); } |
661 | SwFrame *FindColFrame(); |
662 | SwRowFrame *FindRowFrame(); |
663 | SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnotes = false ); |
664 | SwTabFrame *ImplFindTabFrame(); |
665 | SwFootnoteFrame *ImplFindFootnoteFrame(); |
666 | SwFlyFrame *ImplFindFlyFrame(); |
667 | SwSectionFrame *ImplFindSctFrame(); |
668 | const SwBodyFrame *ImplFindBodyFrame() const; |
669 | SwFrame *FindFooterOrHeader(); |
670 | SwFrame *GetLower(); |
671 | const SwFrame *GetNext() const { return mpNext; } |
672 | const SwFrame *GetPrev() const { return mpPrev; } |
673 | const SwLayoutFrame *GetUpper() const { return mpUpper; } |
674 | const SwRootFrame *getRootFrame() const { return mpRoot; } |
675 | inline SwTabFrame *FindTabFrame(); |
676 | inline SwFootnoteFrame *FindFootnoteFrame(); |
677 | inline SwFlyFrame *FindFlyFrame(); |
678 | inline SwSectionFrame *FindSctFrame(); |
679 | inline SwFrame *FindNext(); |
680 | // #i27138# - add parameter <_bInSameFootnote> |
681 | SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ); |
682 | inline SwFrame *FindPrev(); |
683 | inline const SwPageFrame *FindPageFrame() const; |
684 | inline const SwFootnoteBossFrame *FindFootnoteBossFrame( bool bFootnote = false ) const; |
685 | inline const SwFrame *FindColFrame() const; |
686 | inline const SwFrame *FindFooterOrHeader() const; |
687 | inline const SwTabFrame *FindTabFrame() const; |
688 | inline const SwFootnoteFrame *FindFootnoteFrame() const; |
689 | inline const SwFlyFrame *FindFlyFrame() const; |
690 | inline const SwSectionFrame *FindSctFrame() const; |
691 | inline const SwBodyFrame *FindBodyFrame() const; |
692 | inline const SwFrame *FindNext() const; |
693 | // #i27138# - add parameter <_bInSameFootnote> |
694 | const SwContentFrame* FindNextCnt( const bool _bInSameFootnote = false ) const; |
695 | inline const SwFrame *FindPrev() const; |
696 | const SwFrame *GetLower() const; |
697 | |
698 | SwContentFrame* FindPrevCnt(); |
699 | |
700 | const SwContentFrame* FindPrevCnt() const; |
701 | |
702 | // #i79774# |
703 | SwFrame* GetIndPrev_() const; |
704 | SwFrame* GetIndPrev() const |
705 | { return ( mpPrev || !IsInSct() ) ? mpPrev : GetIndPrev_(); } |
706 | |
707 | SwFrame* GetIndNext() |
708 | { return ( mpNext || !IsInSct() ) ? mpNext : GetIndNext_(); } |
709 | const SwFrame* GetIndNext() const { return const_cast<SwFrame*>(this)->GetIndNext(); } |
710 | |
711 | sal_uInt16 GetPhyPageNum() const; // page number without offset |
712 | sal_uInt16 GetVirtPageNum() const; // page number with offset |
713 | bool OnRightPage() const { return 0 != GetPhyPageNum() % 2; }; |
714 | bool WannaRightPage() const; |
715 | bool OnFirstPage() const; |
716 | |
717 | inline const SwLayoutFrame *GetPrevLayoutLeaf() const; |
718 | inline const SwLayoutFrame *GetNextLayoutLeaf() const; |
719 | inline SwLayoutFrame *GetPrevLayoutLeaf(); |
720 | inline SwLayoutFrame *GetNextLayoutLeaf(); |
721 | |
722 | virtual void Calc(vcl::RenderContext* pRenderContext) const; // here might be "formatted" |
723 | inline void OptCalc() const; // here we assume (for optimization) that |
724 | // the predecessors are already formatted |
725 | Point GetRelPos() const; |
726 | |
727 | // PaintArea is the area where content might be displayed. |
728 | // The margin of a page or the space between columns belongs to it. |
729 | SwRect GetPaintArea() const; |
730 | |
731 | // UnionFrame is the union of Frame- and PrtArea, normally identical |
732 | // to the FrameArea except in case of negative Prt margins. |
733 | SwRect UnionFrame( bool bBorder = false ) const; |
734 | |
735 | virtual Size ChgSize( const Size& aNewSize ); |
736 | |
737 | virtual void Cut() = 0; |
738 | virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) = 0; |
739 | |
740 | void ValidateLineNum() { mbValidLineNum = true; } |
741 | |
742 | bool GetValidLineNumFlag()const { return mbValidLineNum; } |
743 | |
744 | // Only invalidate Frame |
745 | // #i28701# - add call to method <ActionOnInvalidation(..)> |
746 | // for all invalidation methods. |
747 | // #i28701# - use method <InvalidationAllowed(..)> to |
748 | // decide, if invalidation will to be performed or not. |
749 | // #i26945# - no additional invalidation, if it's already |
750 | // invalidate. |
751 | void InvalidateSize_() |
752 | { |
753 | if ( isFrameAreaSizeValid() && InvalidationAllowed( INVALID_SIZE ) ) |
754 | { |
755 | setFrameAreaSizeValid(false); |
756 | ActionOnInvalidation( INVALID_SIZE ); |
757 | } |
758 | } |
759 | void InvalidatePrt_() |
760 | { |
761 | if ( isFramePrintAreaValid() && InvalidationAllowed( INVALID_PRTAREA ) ) |
762 | { |
763 | setFramePrintAreaValid(false); |
764 | ActionOnInvalidation( INVALID_PRTAREA ); |
765 | } |
766 | } |
767 | void InvalidatePos_() |
768 | { |
769 | if ( isFrameAreaPositionValid() && InvalidationAllowed( INVALID_POS ) ) |
770 | { |
771 | setFrameAreaPositionValid(false); |
772 | ActionOnInvalidation( INVALID_POS ); |
773 | } |
774 | } |
775 | void InvalidateLineNum_() |
776 | { |
777 | if ( mbValidLineNum && InvalidationAllowed( INVALID_LINENUM ) ) |
778 | { |
779 | mbValidLineNum = false; |
780 | ActionOnInvalidation( INVALID_LINENUM ); |
781 | } |
782 | } |
783 | void InvalidateAll_() |
784 | { |
785 | if ( ( isFrameAreaSizeValid() || isFramePrintAreaValid() || isFrameAreaPositionValid() ) && InvalidationAllowed( INVALID_ALL ) ) |
786 | { |
787 | setFrameAreaSizeValid(false); |
788 | setFrameAreaPositionValid(false); |
789 | setFramePrintAreaValid(false); |
790 | ActionOnInvalidation( INVALID_ALL ); |
791 | } |
792 | } |
793 | // also notify page at the same time |
794 | inline void InvalidateSize(); |
795 | inline void InvalidatePrt(); |
796 | inline void InvalidatePos(); |
797 | inline void InvalidateLineNum(); |
798 | inline void InvalidateAll(); |
799 | void ImplInvalidateSize(); |
800 | void ImplInvalidatePrt(); |
801 | void ImplInvalidatePos(); |
802 | void ImplInvalidateLineNum(); |
803 | |
804 | inline void InvalidateNextPos( bool bNoFootnote = false ); |
805 | void ImplInvalidateNextPos( bool bNoFootnote ); |
806 | |
807 | /** method to invalidate printing area of next frame |
808 | #i11859# |
809 | */ |
810 | void InvalidateNextPrtArea(); |
811 | |
812 | void InvalidatePage( const SwPageFrame *pPage = nullptr ) const; |
813 | |
814 | virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const; |
815 | |
816 | virtual bool GetModelPositionForViewPoint( SwPosition *, Point&, |
817 | SwCursorMoveState* = nullptr, bool bTestBackground = false ) const; |
818 | virtual bool GetCharRect( SwRect &, const SwPosition&, |
819 | SwCursorMoveState* = nullptr, bool bAllowFarAway = true ) const; |
820 | virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&, |
821 | SwPrintData const*const pPrintData = nullptr ) const; |
822 | |
823 | // HACK: shortcut between frame and formatting |
824 | // It's your own fault if you cast void* incorrectly! In any case check |
825 | // the void* for 0. |
826 | virtual bool Prepare( const PrepareHint ePrep = PrepareHint::Clear, |
827 | const void *pVoid = nullptr, bool bNotify = true ); |
828 | |
829 | // true if it is the correct class, false otherwise |
830 | inline bool IsLayoutFrame() const; |
831 | inline bool IsRootFrame() const; |
832 | inline bool IsPageFrame() const; |
833 | inline bool IsColumnFrame() const; |
834 | inline bool IsFootnoteBossFrame() const; // footnote bosses might be PageFrames or ColumnFrames |
835 | inline bool IsHeaderFrame() const; |
836 | inline bool IsFooterFrame() const; |
837 | inline bool IsFootnoteContFrame() const; |
838 | inline bool IsFootnoteFrame() const; |
839 | inline bool IsBodyFrame() const; |
840 | inline bool IsColBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above ColumnFrame |
841 | inline bool IsPageBodyFrame() const; // implemented in layfrm.hxx, BodyFrame above PageFrame |
842 | inline bool IsFlyFrame() const; |
843 | inline bool IsSctFrame() const; |
844 | inline bool IsTabFrame() const; |
845 | inline bool IsRowFrame() const; |
846 | inline bool IsCellFrame() const; |
847 | inline bool IsContentFrame() const; |
848 | inline bool IsTextFrame() const; |
849 | inline bool IsNoTextFrame() const; |
850 | // Frames where its PrtArea depends on their neighbors and that are |
851 | // positioned in the content flow |
852 | inline bool IsFlowFrame() const; |
853 | // Frames that are capable of retouching or that might need to retouch behind |
854 | // themselves |
855 | inline bool IsRetoucheFrame() const; |
856 | inline bool IsAccessibleFrame() const; |
857 | |
858 | void PrepareCursor(); // CursorShell is allowed to call this |
859 | |
860 | // Is the Frame (or the section containing it) protected? Same for Fly in |
861 | // Fly in ... and footnotes |
862 | bool IsProtected() const; |
863 | |
864 | bool IsColLocked() const { return mbColLocked; } |
865 | virtual bool IsDeleteForbidden() const { return mbForbidDelete; } |
866 | |
867 | /// this is the only way to delete a SwFrame instance |
868 | static void DestroyFrame(SwFrame *const pFrame); |
869 | |
870 | bool IsInDtor() const { return mbInDtor; } |
871 | |
872 | // No inline cause we need the function pointers |
873 | long GetTopMargin() const; |
874 | long GetBottomMargin() const; |
875 | long GetLeftMargin() const; |
876 | long GetRightMargin() const; |
877 | void SetTopBottomMargins( long, long ); |
878 | void SetLeftRightMargins( long, long ); |
879 | void SetRightLeftMargins( long, long ); |
880 | long GetPrtLeft() const; |
881 | long GetPrtBottom() const; |
882 | long GetPrtRight() const; |
883 | long GetPrtTop() const; |
884 | bool SetMinLeft( long ); |
885 | bool SetMaxBottom( long ); |
886 | bool SetMaxRight( long ); |
887 | void MakeBelowPos( const SwFrame*, const SwFrame*, bool ); |
888 | void MakeLeftPos( const SwFrame*, const SwFrame*, bool ); |
889 | void MakeRightPos( const SwFrame*, const SwFrame*, bool ); |
890 | bool IsNeighbourFrame() const |
891 | { return bool(GetType() & FRM_NEIGHBOUR(SwFrameType::Column | SwFrameType::Cell)); } |
892 | |
893 | // NEW TABLES |
894 | // Some functions for covered/covering table cells. This way unnecessary |
895 | // includes can be avoided |
896 | virtual bool IsLeaveUpperAllowed() const; |
897 | virtual bool IsCoveredCell() const; |
898 | bool IsInCoveredCell() const; |
899 | |
900 | // #i81146# new loop control |
901 | bool KnowsFormat( const SwFormat& rFormat ) const; |
902 | void RegisterToFormat( SwFormat& rFormat ); |
903 | void ValidateThisAndAllLowers( const sal_uInt16 nStage ); |
904 | |
905 | void ForbidDelete() { mbForbidDelete = true; } |
906 | void AllowDelete() { mbForbidDelete = false; } |
907 | |
908 | drawinglayer::attribute::SdrAllFillAttributesHelperPtr getSdrAllFillAttributesHelper() const; |
909 | bool supportsFullDrawingLayerFillAttributeSet() const; |
910 | |
911 | public: |
912 | // if writer is NULL, dumps the layout structure as XML in layout.xml |
913 | virtual void dumpAsXml(xmlTextWriterPtr writer = nullptr) const; |
914 | void dumpTopMostAsXml(xmlTextWriterPtr writer = nullptr) const; |
915 | void dumpInfosAsXml(xmlTextWriterPtr writer) const; |
916 | virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const; |
917 | void dumpChildrenAsXml(xmlTextWriterPtr writer) const; |
918 | bool IsCollapse() const; |
919 | }; |
920 | |
921 | inline bool SwFrame::IsInDocBody() const |
922 | { |
923 | if ( mbInfInvalid ) |
924 | const_cast<SwFrame*>(this)->SetInfFlags(); |
925 | return mbInfBody; |
926 | } |
927 | inline bool SwFrame::IsInFootnote() const |
928 | { |
929 | if ( mbInfInvalid ) |
930 | const_cast<SwFrame*>(this)->SetInfFlags(); |
931 | return mbInfFootnote; |
932 | } |
933 | inline bool SwFrame::IsInTab() const |
934 | { |
935 | if ( mbInfInvalid ) |
936 | const_cast<SwFrame*>(this)->SetInfFlags(); |
937 | return mbInfTab; |
938 | } |
939 | inline bool SwFrame::IsInFly() const |
940 | { |
941 | if ( mbInfInvalid ) |
942 | const_cast<SwFrame*>(this)->SetInfFlags(); |
943 | return mbInfFly; |
944 | } |
945 | inline bool SwFrame::IsInSct() const |
946 | { |
947 | if ( mbInfInvalid ) |
948 | const_cast<SwFrame*>(this)->SetInfFlags(); |
949 | return mbInfSct; |
950 | } |
951 | bool SwFrame::IsVertical() const |
952 | { |
953 | if( mbInvalidVert ) |
954 | const_cast<SwFrame*>(this)->SetDirFlags( true ); |
955 | return mbVertical; |
956 | } |
957 | inline bool SwFrame::IsVertLR() const |
958 | { |
959 | return mbVertLR; |
960 | } |
961 | inline bool SwFrame::IsVertLRBT() const |
962 | { |
963 | return mbVertLRBT; |
964 | } |
965 | inline bool SwFrame::IsRightToLeft() const |
966 | { |
967 | if( mbInvalidR2L ) |
968 | const_cast<SwFrame*>(this)->SetDirFlags( false ); |
969 | return mbRightToLeft; |
970 | } |
971 | |
972 | inline void SwFrame::SetCompletePaint() const |
973 | { |
974 | const_cast<SwFrame*>(this)->mbCompletePaint = true; |
975 | } |
976 | inline void SwFrame::ResetCompletePaint() const |
977 | { |
978 | const_cast<SwFrame*>(this)->mbCompletePaint = false; |
979 | } |
980 | |
981 | inline void SwFrame::SetRetouche() const |
982 | { |
983 | const_cast<SwFrame*>(this)->mbRetouche = true; |
984 | } |
985 | inline void SwFrame::ResetRetouche() const |
986 | { |
987 | const_cast<SwFrame*>(this)->mbRetouche = false; |
988 | } |
989 | |
990 | inline SwLayoutFrame *SwFrame::GetNextLayoutLeaf() |
991 | { |
992 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetNextLayoutLeaf()); |
993 | } |
994 | inline SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() |
995 | { |
996 | return const_cast<SwLayoutFrame*>(static_cast<const SwFrame*>(this)->GetPrevLayoutLeaf()); |
997 | } |
998 | inline const SwLayoutFrame *SwFrame::GetNextLayoutLeaf() const |
999 | { |
1000 | return ImplGetNextLayoutLeaf( true ); |
1001 | } |
1002 | inline const SwLayoutFrame *SwFrame::GetPrevLayoutLeaf() const |
1003 | { |
1004 | return ImplGetNextLayoutLeaf( false ); |
1005 | } |
1006 | |
1007 | inline void SwFrame::InvalidateSize() |
1008 | { |
1009 | if ( isFrameAreaSizeValid() ) |
1010 | { |
1011 | ImplInvalidateSize(); |
1012 | } |
1013 | } |
1014 | inline void SwFrame::InvalidatePrt() |
1015 | { |
1016 | if ( isFramePrintAreaValid() ) |
1017 | { |
1018 | ImplInvalidatePrt(); |
1019 | } |
1020 | } |
1021 | inline void SwFrame::InvalidatePos() |
1022 | { |
1023 | if ( isFrameAreaPositionValid() ) |
1024 | { |
1025 | ImplInvalidatePos(); |
1026 | } |
1027 | } |
1028 | inline void SwFrame::InvalidateLineNum() |
1029 | { |
1030 | if ( mbValidLineNum ) |
1031 | ImplInvalidateLineNum(); |
1032 | } |
1033 | inline void SwFrame::InvalidateAll() |
1034 | { |
1035 | if ( InvalidationAllowed( INVALID_ALL ) ) |
1036 | { |
1037 | if ( isFrameAreaDefinitionValid() ) |
1038 | { |
1039 | ImplInvalidatePos(); |
1040 | } |
1041 | |
1042 | setFrameAreaSizeValid(false); |
1043 | setFrameAreaPositionValid(false); |
1044 | setFramePrintAreaValid(false); |
1045 | |
1046 | // #i28701# |
1047 | ActionOnInvalidation( INVALID_ALL ); |
1048 | } |
1049 | } |
1050 | inline void SwFrame::InvalidateNextPos( bool bNoFootnote ) |
1051 | { |
1052 | if ( mpNext && !mpNext->IsSctFrame() ) |
1053 | mpNext->InvalidatePos(); |
1054 | else |
1055 | ImplInvalidateNextPos( bNoFootnote ); |
1056 | } |
1057 | |
1058 | inline void SwFrame::OptCalc() const |
1059 | { |
1060 | if ( !isFrameAreaPositionValid() || !isFramePrintAreaValid() || !isFrameAreaSizeValid() ) |
1061 | { |
1062 | const_cast<SwFrame*>(this)->OptPrepareMake(); |
1063 | } |
1064 | } |
1065 | inline const SwPageFrame *SwFrame::FindPageFrame() const |
1066 | { |
1067 | return const_cast<SwFrame*>(this)->FindPageFrame(); |
1068 | } |
1069 | inline const SwFrame *SwFrame::FindColFrame() const |
1070 | { |
1071 | return const_cast<SwFrame*>(this)->FindColFrame(); |
1072 | } |
1073 | inline const SwFrame *SwFrame::FindFooterOrHeader() const |
1074 | { |
1075 | return const_cast<SwFrame*>(this)->FindFooterOrHeader(); |
1076 | } |
1077 | inline SwTabFrame *SwFrame::FindTabFrame() |
1078 | { |
1079 | return IsInTab() ? ImplFindTabFrame() : nullptr; |
1080 | } |
1081 | inline const SwFootnoteBossFrame *SwFrame::FindFootnoteBossFrame( bool bFootnote ) const |
1082 | { |
1083 | return const_cast<SwFrame*>(this)->FindFootnoteBossFrame( bFootnote ); |
1084 | } |
1085 | inline SwFootnoteFrame *SwFrame::FindFootnoteFrame() |
1086 | { |
1087 | return IsInFootnote() ? ImplFindFootnoteFrame() : nullptr; |
1088 | } |
1089 | inline SwFlyFrame *SwFrame::FindFlyFrame() |
1090 | { |
1091 | return IsInFly() ? ImplFindFlyFrame() : nullptr; |
1092 | } |
1093 | inline SwSectionFrame *SwFrame::FindSctFrame() |
1094 | { |
1095 | return IsInSct() ? ImplFindSctFrame() : nullptr; |
1096 | } |
1097 | |
1098 | inline const SwBodyFrame *SwFrame::FindBodyFrame() const |
1099 | { |
1100 | return IsInDocBody() ? ImplFindBodyFrame() : nullptr; |
1101 | } |
1102 | |
1103 | inline const SwTabFrame *SwFrame::FindTabFrame() const |
1104 | { |
1105 | return IsInTab() ? const_cast<SwFrame*>(this)->ImplFindTabFrame() : nullptr; |
1106 | } |
1107 | inline const SwFootnoteFrame *SwFrame::FindFootnoteFrame() const |
1108 | { |
1109 | return IsInFootnote() ? const_cast<SwFrame*>(this)->ImplFindFootnoteFrame() : nullptr; |
1110 | } |
1111 | inline const SwFlyFrame *SwFrame::FindFlyFrame() const |
1112 | { |
1113 | return IsInFly() ? const_cast<SwFrame*>(this)->ImplFindFlyFrame() : nullptr; |
1114 | } |
1115 | inline const SwSectionFrame *SwFrame::FindSctFrame() const |
1116 | { |
1117 | return IsInSct() ? const_cast<SwFrame*>(this)->ImplFindSctFrame() : nullptr; |
1118 | } |
1119 | inline SwFrame *SwFrame::FindNext() |
1120 | { |
1121 | if ( mpNext ) |
1122 | return mpNext; |
1123 | else |
1124 | return FindNext_(); |
1125 | } |
1126 | inline const SwFrame *SwFrame::FindNext() const |
1127 | { |
1128 | if ( mpNext ) |
1129 | return mpNext; |
1130 | else |
1131 | return const_cast<SwFrame*>(this)->FindNext_(); |
1132 | } |
1133 | inline SwFrame *SwFrame::FindPrev() |
1134 | { |
1135 | if ( mpPrev && !mpPrev->IsSctFrame() ) |
1136 | return mpPrev; |
1137 | else |
1138 | return FindPrev_(); |
1139 | } |
1140 | inline const SwFrame *SwFrame::FindPrev() const |
1141 | { |
1142 | if ( mpPrev && !mpPrev->IsSctFrame() ) |
1143 | return mpPrev; |
1144 | else |
1145 | return const_cast<SwFrame*>(this)->FindPrev_(); |
1146 | } |
1147 | |
1148 | inline bool SwFrame::IsLayoutFrame() const |
1149 | { |
1150 | return bool(GetType() & FRM_LAYOUTSwFrameType(0x3bFF)); |
1151 | } |
1152 | inline bool SwFrame::IsRootFrame() const |
1153 | { |
1154 | return mnFrameType == SwFrameType::Root; |
1155 | } |
1156 | inline bool SwFrame::IsPageFrame() const |
1157 | { |
1158 | return mnFrameType == SwFrameType::Page; |
1159 | } |
1160 | inline bool SwFrame::IsColumnFrame() const |
1161 | { |
1162 | return mnFrameType == SwFrameType::Column; |
1163 | } |
1164 | inline bool SwFrame::IsFootnoteBossFrame() const |
1165 | { |
1166 | return bool(GetType() & FRM_FTNBOSS(SwFrameType::Page | SwFrameType::Column)); |
1167 | } |
1168 | inline bool SwFrame::IsHeaderFrame() const |
1169 | { |
1170 | return mnFrameType == SwFrameType::Header; |
1171 | } |
1172 | inline bool SwFrame::IsFooterFrame() const |
1173 | { |
1174 | return mnFrameType == SwFrameType::Footer; |
1175 | } |
1176 | inline bool SwFrame::IsFootnoteContFrame() const |
1177 | { |
1178 | return mnFrameType == SwFrameType::FtnCont; |
1179 | } |
1180 | inline bool SwFrame::IsFootnoteFrame() const |
1181 | { |
1182 | return mnFrameType == SwFrameType::Ftn; |
1183 | } |
1184 | inline bool SwFrame::IsBodyFrame() const |
1185 | { |
1186 | return mnFrameType == SwFrameType::Body; |
1187 | } |
1188 | inline bool SwFrame::IsFlyFrame() const |
1189 | { |
1190 | return mnFrameType == SwFrameType::Fly; |
1191 | } |
1192 | inline bool SwFrame::IsSctFrame() const |
1193 | { |
1194 | return mnFrameType == SwFrameType::Section; |
1195 | } |
1196 | inline bool SwFrame::IsTabFrame() const |
1197 | { |
1198 | return mnFrameType == SwFrameType::Tab; |
1199 | } |
1200 | inline bool SwFrame::IsRowFrame() const |
1201 | { |
1202 | return mnFrameType == SwFrameType::Row; |
1203 | } |
1204 | inline bool SwFrame::IsCellFrame() const |
1205 | { |
1206 | return mnFrameType == SwFrameType::Cell; |
1207 | } |
1208 | inline bool SwFrame::IsContentFrame() const |
1209 | { |
1210 | return bool(GetType() & FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)); |
1211 | } |
1212 | inline bool SwFrame::IsTextFrame() const |
1213 | { |
1214 | return mnFrameType == SwFrameType::Txt; |
1215 | } |
1216 | inline bool SwFrame::IsNoTextFrame() const |
1217 | { |
1218 | return mnFrameType == SwFrameType::NoTxt; |
1219 | } |
1220 | inline bool SwFrame::IsFlowFrame() const |
1221 | { |
1222 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section)); |
1223 | } |
1224 | inline bool SwFrame::IsRetoucheFrame() const |
1225 | { |
1226 | return bool(GetType() & (FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt)|SwFrameType::Tab|SwFrameType::Section|SwFrameType::Ftn)); |
1227 | } |
1228 | inline bool SwFrame::IsAccessibleFrame() const |
1229 | { |
1230 | return bool(GetType() & FRM_ACCESSIBLE(SwFrameType::Root | SwFrameType::Page | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn | SwFrameType::Fly | SwFrameType ::Tab | SwFrameType::Cell | SwFrameType::Txt)); |
1231 | } |
1232 | |
1233 | //use this to protect a SwFrame for a given scope from getting deleted |
1234 | class SwFrameDeleteGuard |
1235 | { |
1236 | private: |
1237 | SwFrame *m_pForbidFrame; |
1238 | public: |
1239 | //Flag pFrame for SwFrameDeleteGuard lifetime that we shouldn't delete |
1240 | //it in e.g. SwSectionFrame::MergeNext etc because we will need it |
1241 | //again after the SwFrameDeleteGuard dtor |
1242 | explicit SwFrameDeleteGuard(SwFrame* pFrame) |
1243 | : m_pForbidFrame((pFrame && !pFrame->IsDeleteForbidden()) ? |
1244 | pFrame : nullptr) |
1245 | { |
1246 | if (m_pForbidFrame) |
1247 | m_pForbidFrame->ForbidDelete(); |
1248 | } |
1249 | |
1250 | SwFrameDeleteGuard(const SwFrameDeleteGuard&) =delete; |
1251 | |
1252 | ~SwFrameDeleteGuard() |
1253 | { |
1254 | if (m_pForbidFrame) |
1255 | m_pForbidFrame->AllowDelete(); |
1256 | } |
1257 | |
1258 | SwFrameDeleteGuard& operator=(const SwFrameDeleteGuard&) =delete; |
1259 | }; |
1260 | |
1261 | typedef long (SwFrame::*SwFrameGet)() const; |
1262 | typedef bool (SwFrame::*SwFrameMax)( long ); |
1263 | typedef void (SwFrame::*SwFrameMakePos)( const SwFrame*, const SwFrame*, bool ); |
1264 | typedef long (*SwOperator)( long, long ); |
1265 | typedef void (SwFrame::*SwFrameSet)( long, long ); |
1266 | |
1267 | struct SwRectFnCollection |
1268 | { |
1269 | SwRectGet fnGetTop; |
1270 | SwRectGet fnGetBottom; |
1271 | SwRectGet fnGetLeft; |
1272 | SwRectGet fnGetRight; |
1273 | SwRectGet fnGetWidth; |
1274 | SwRectGet fnGetHeight; |
1275 | SwRectPoint fnGetPos; |
1276 | SwRectSize fnGetSize; |
1277 | |
1278 | SwRectSet fnSetTop; |
1279 | SwRectSet fnSetBottom; |
1280 | SwRectSet fnSetLeft; |
1281 | SwRectSet fnSetRight; |
1282 | SwRectSet fnSetWidth; |
1283 | SwRectSet fnSetHeight; |
1284 | |
1285 | SwRectSet fnSubTop; |
1286 | SwRectSet fnAddBottom; |
1287 | SwRectSet fnSubLeft; |
1288 | SwRectSet fnAddRight; |
1289 | SwRectSet fnAddWidth; |
1290 | SwRectSet fnAddHeight; |
1291 | |
1292 | SwRectSet fnSetPosX; |
1293 | SwRectSet fnSetPosY; |
1294 | |
1295 | SwFrameGet fnGetTopMargin; |
1296 | SwFrameGet fnGetBottomMargin; |
1297 | SwFrameGet fnGetLeftMargin; |
1298 | SwFrameGet fnGetRightMargin; |
1299 | SwFrameSet fnSetXMargins; |
1300 | SwFrameSet fnSetYMargins; |
1301 | SwFrameGet fnGetPrtTop; |
1302 | SwFrameGet fnGetPrtBottom; |
1303 | SwFrameGet fnGetPrtLeft; |
1304 | SwFrameGet fnGetPrtRight; |
1305 | SwRectDist fnTopDist; |
1306 | SwRectDist fnBottomDist; |
1307 | SwRectDist fnLeftDist; |
1308 | SwRectDist fnRightDist; |
1309 | SwFrameMax fnSetLimit; |
1310 | SwRectMax fnOverStep; |
1311 | |
1312 | SwRectSetPos fnSetPos; |
1313 | SwFrameMakePos fnMakePos; |
1314 | SwOperator fnXDiff; |
1315 | SwOperator fnYDiff; |
1316 | SwOperator fnXInc; |
1317 | SwOperator fnYInc; |
1318 | |
1319 | SwRectSetTwice fnSetLeftAndWidth; |
1320 | SwRectSetTwice fnSetTopAndHeight; |
1321 | }; |
1322 | |
1323 | typedef SwRectFnCollection* SwRectFn; |
1324 | |
1325 | // This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical) |
1326 | extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T; |
1327 | class SwRectFnSet { |
1328 | public: |
1329 | explicit SwRectFnSet(const SwFrame *pFrame) |
1330 | : m_bVert(pFrame->IsVertical()) |
1331 | , m_bVertL2R(pFrame->IsVertLR()) |
1332 | , m_bVertL2RB2T(pFrame->IsVertLRBT()) |
1333 | { |
1334 | m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori; |
1335 | } |
1336 | |
1337 | void Refresh(const SwFrame *pFrame) |
1338 | { |
1339 | m_bVert = pFrame->IsVertical(); |
1340 | m_bVertL2R = pFrame->IsVertLR(); |
1341 | m_bVertL2RB2T = pFrame->IsVertLRBT(); |
1342 | m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori; |
1343 | } |
1344 | |
1345 | bool IsVert() const { return m_bVert; } |
1346 | bool IsVertL2R() const { return m_bVertL2R; } |
1347 | SwRectFn FnRect() const { return m_fnRect; } |
1348 | |
1349 | bool PosDiff(const SwRect &rRect1, const SwRect &rRect2) const |
1350 | { |
1351 | return ((rRect1.*m_fnRect->fnGetTop)() != (rRect2.*m_fnRect->fnGetTop)() |
1352 | || (rRect1.*m_fnRect->fnGetLeft)() != (rRect2.*m_fnRect->fnGetLeft)()); |
1353 | } |
1354 | |
1355 | long GetTop (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetTop) (); } |
1356 | long GetBottom(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetBottom)(); } |
1357 | long GetLeft (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetLeft) (); } |
1358 | long GetRight (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetRight) (); } |
1359 | long GetWidth (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetWidth) (); } |
1360 | long GetHeight(const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetHeight)(); } |
1361 | Point GetPos (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetPos) (); } |
1362 | Size GetSize (const SwRect& rRect) const { return (rRect.*m_fnRect->fnGetSize) (); } |
1363 | |
1364 | void SetTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetTop) (nNew); } |
1365 | void SetBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetBottom)(nNew); } |
1366 | void SetLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetLeft) (nNew); } |
1367 | void SetRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetRight) (nNew); } |
1368 | void SetWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetWidth) (nNew); } |
1369 | void SetHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetHeight)(nNew); } |
1370 | |
1371 | void SubTop (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubTop) (nNew); } |
1372 | void AddBottom(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddBottom)(nNew); } |
1373 | void SubLeft (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSubLeft) (nNew); } |
1374 | void AddRight (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddRight) (nNew); } |
1375 | void AddWidth (SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddWidth) (nNew); } |
1376 | void AddHeight(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnAddHeight)(nNew); } |
1377 | |
1378 | void SetPosX(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosX)(nNew); } |
1379 | void SetPosY(SwRect& rRect, long nNew) const { (rRect.*m_fnRect->fnSetPosY)(nNew); } |
1380 | |
1381 | long GetTopMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetTopMargin) (); } |
1382 | long GetBottomMargin(const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetBottomMargin)(); } |
1383 | long GetLeftMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetLeftMargin) (); } |
1384 | long GetRightMargin (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetRightMargin) (); } |
1385 | void SetXMargins(SwFrame& rFrame, long nLeft, long nRight) const { (rFrame.*m_fnRect->fnSetXMargins)(nLeft, nRight); } |
1386 | void SetYMargins(SwFrame& rFrame, long nTop, long nBottom) const { (rFrame.*m_fnRect->fnSetYMargins)(nTop, nBottom); } |
1387 | long GetPrtTop (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtTop) (); } |
1388 | long GetPrtBottom (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtBottom) (); } |
1389 | long GetPrtLeft (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtLeft) (); } |
1390 | long GetPrtRight (const SwFrame& rFrame) const { return (rFrame.*m_fnRect->fnGetPrtRight) (); } |
1391 | long TopDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnTopDist) (nPos); } |
1392 | long BottomDist(const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnBottomDist) (nPos); } |
1393 | long LeftDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnLeftDist) (nPos); } |
1394 | long RightDist (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnRightDist) (nPos); } |
1395 | void SetLimit (SwFrame& rFrame, long nNew) const { (rFrame.*m_fnRect->fnSetLimit) (nNew); } |
1396 | bool OverStep (const SwRect& rRect, long nPos) const { return (rRect.*m_fnRect->fnOverStep) (nPos); } |
1397 | |
1398 | void SetPos(SwRect& rRect, const Point& rNew) const { (rRect.*m_fnRect->fnSetPos)(rNew); } |
1399 | void MakePos(SwFrame& rFrame, const SwFrame* pUp, const SwFrame* pPrv, bool bNotify) const { (rFrame.*m_fnRect->fnMakePos)(pUp, pPrv, bNotify); } |
1400 | long XDiff(long n1, long n2) const { return (m_fnRect->fnXDiff) (n1, n2); } |
1401 | long YDiff(long n1, long n2) const { return (m_fnRect->fnYDiff) (n1, n2); } |
1402 | long XInc (long n1, long n2) const { return (m_fnRect->fnXInc) (n1, n2); } |
1403 | long YInc (long n1, long n2) const { return (m_fnRect->fnYInc) (n1, n2); } |
1404 | |
1405 | void SetLeftAndWidth(SwRect& rRect, long nLeft, long nWidth) const { (rRect.*m_fnRect->fnSetLeftAndWidth)(nLeft, nWidth); } |
1406 | void SetTopAndHeight(SwRect& rRect, long nTop, long nHeight) const { (rRect.*m_fnRect->fnSetTopAndHeight)(nTop, nHeight); } |
1407 | |
1408 | private: |
1409 | bool m_bVert; |
1410 | bool m_bVertL2R; |
1411 | bool m_bVertL2RB2T; |
1412 | SwRectFn m_fnRect; |
1413 | }; |
1414 | |
1415 | #endif |
1416 | |
1417 | /* 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_O3TL_TYPED_FLAGS_SET_HXX |
21 | #define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX |
22 | |
23 | #include <sal/config.h> |
24 | |
25 | #include <cassert> |
26 | #include <type_traits> |
27 | |
28 | #include <o3tl/underlyingenumvalue.hxx> |
29 | #include <sal/types.h> |
30 | |
31 | namespace o3tl { |
32 | |
33 | namespace detail { |
34 | |
35 | template<typename T> constexpr |
36 | typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative( |
37 | T value) |
38 | { |
39 | return value >= 0; |
40 | } |
41 | |
42 | template<typename T> constexpr |
43 | typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T) |
44 | { |
45 | return true; |
46 | } |
47 | |
48 | } |
49 | |
50 | template<typename T> struct typed_flags {}; |
51 | |
52 | /// Mark a (scoped) enumeration as a set of bit flags, with accompanying |
53 | /// operations. |
54 | /// |
55 | /// template<> |
56 | /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {}; |
57 | /// |
58 | /// All relevant values must be non-negative. (Typically, the enumeration's |
59 | /// underlying type will either be fixed and unsigned, or it will be unfixed--- |
60 | /// and can thus default to a signed type---and all enumerators will have non- |
61 | /// negative values.) |
62 | /// |
63 | /// \param E the enumeration type. |
64 | /// \param M the all-bits-set value for the bit flags. |
65 | template<typename E, typename std::underlying_type<E>::type M> |
66 | struct is_typed_flags { |
67 | static_assert( |
68 | M >= 0, "is_typed_flags expects only non-negative bit values"); |
69 | |
70 | typedef E Self; |
71 | |
72 | class Wrap { |
73 | public: |
74 | typedef is_typed_flags Unwrapped; |
75 | |
76 | explicit constexpr Wrap(typename std::underlying_type<E>::type value): |
77 | value_(value) |
78 | { |
79 | assert(detail::isNonNegative(value))(static_cast <bool> (detail::isNonNegative(value)) ? void (0) : __assert_fail ("detail::isNonNegative(value)", "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 79, __extension__ __PRETTY_FUNCTION__)); |
80 | assert((static_cast <bool> (static_cast<typename std::underlying_type <E>::type>(~0) == M || (value & ~M) == 0) ? void (0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 84, __extension__ __PRETTY_FUNCTION__)) |
81 | static_cast<typename std::underlying_type<E>::type>(~0) == M(static_cast <bool> (static_cast<typename std::underlying_type <E>::type>(~0) == M || (value & ~M) == 0) ? void (0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 84, __extension__ __PRETTY_FUNCTION__)) |
82 | // avoid "operands don't affect result" warnings when M(static_cast <bool> (static_cast<typename std::underlying_type <E>::type>(~0) == M || (value & ~M) == 0) ? void (0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 84, __extension__ __PRETTY_FUNCTION__)) |
83 | // covers all bits of the underlying type(static_cast <bool> (static_cast<typename std::underlying_type <E>::type>(~0) == M || (value & ~M) == 0) ? void (0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 84, __extension__ __PRETTY_FUNCTION__)) |
84 | || (value & ~M) == 0)(static_cast <bool> (static_cast<typename std::underlying_type <E>::type>(~0) == M || (value & ~M) == 0) ? void (0) : __assert_fail ("static_cast<typename std::underlying_type<E>::type>(~0) == M || (value & ~M) == 0" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 84, __extension__ __PRETTY_FUNCTION__)); |
85 | } |
86 | |
87 | constexpr operator E() const { return static_cast<E>(value_); } |
88 | |
89 | explicit constexpr operator typename std::underlying_type<E>::type() |
90 | const |
91 | { return value_; } |
92 | |
93 | explicit constexpr operator bool() const { return value_ != 0; } |
94 | |
95 | private: |
96 | typename std::underlying_type<E>::type value_; |
97 | }; |
98 | |
99 | static typename std::underlying_type<E>::type const mask = M; |
100 | }; |
101 | |
102 | } |
103 | |
104 | template<typename E> |
105 | constexpr typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) { |
106 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 108, __extension__ __PRETTY_FUNCTION__)) |
107 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 108, __extension__ __PRETTY_FUNCTION__)) |
108 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 108, __extension__ __PRETTY_FUNCTION__)); |
109 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
110 | o3tl::typed_flags<E>::mask |
111 | & ~o3tl::underlyingEnumValue(rhs)); |
112 | } |
113 | |
114 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ~( |
115 | typename o3tl::typed_flags<E>::Wrap rhs) |
116 | { |
117 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
118 | o3tl::typed_flags<E>::mask |
119 | & ~o3tl::underlyingEnumValue<E>(rhs)); |
120 | } |
121 | |
122 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^( |
123 | E lhs, E rhs) |
124 | { |
125 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 127, __extension__ __PRETTY_FUNCTION__)) |
126 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 127, __extension__ __PRETTY_FUNCTION__)) |
127 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 127, __extension__ __PRETTY_FUNCTION__)); |
128 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 130, __extension__ __PRETTY_FUNCTION__)) |
129 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 130, __extension__ __PRETTY_FUNCTION__)) |
130 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 130, __extension__ __PRETTY_FUNCTION__)); |
131 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
132 | o3tl::underlyingEnumValue(lhs) |
133 | ^ o3tl::underlyingEnumValue(rhs)); |
134 | } |
135 | |
136 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^( |
137 | E lhs, typename o3tl::typed_flags<E>::Wrap rhs) |
138 | { |
139 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 141, __extension__ __PRETTY_FUNCTION__)) |
140 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 141, __extension__ __PRETTY_FUNCTION__)) |
141 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 141, __extension__ __PRETTY_FUNCTION__)); |
142 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
143 | o3tl::underlyingEnumValue(lhs) |
144 | ^ o3tl::underlyingEnumValue<E>(rhs)); |
145 | } |
146 | |
147 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^( |
148 | typename o3tl::typed_flags<E>::Wrap lhs, E rhs) |
149 | { |
150 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 152, __extension__ __PRETTY_FUNCTION__)) |
151 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 152, __extension__ __PRETTY_FUNCTION__)) |
152 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 152, __extension__ __PRETTY_FUNCTION__)); |
153 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
154 | o3tl::underlyingEnumValue<E>(lhs) |
155 | ^ o3tl::underlyingEnumValue(rhs)); |
156 | } |
157 | |
158 | template<typename W> constexpr |
159 | typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator ^( |
160 | W lhs, W rhs) |
161 | { |
162 | return static_cast<W>( |
163 | o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs) |
164 | ^ o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs)); |
165 | } |
166 | |
167 | template<typename E> |
168 | constexpr typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) { |
169 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 171, __extension__ __PRETTY_FUNCTION__)) |
170 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 171, __extension__ __PRETTY_FUNCTION__)) |
171 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 171, __extension__ __PRETTY_FUNCTION__)); |
172 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 174, __extension__ __PRETTY_FUNCTION__)) |
173 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 174, __extension__ __PRETTY_FUNCTION__)) |
174 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 174, __extension__ __PRETTY_FUNCTION__)); |
175 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
176 | o3tl::underlyingEnumValue(lhs) |
177 | & o3tl::underlyingEnumValue(rhs)); |
178 | } |
179 | |
180 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &( |
181 | E lhs, typename o3tl::typed_flags<E>::Wrap rhs) |
182 | { |
183 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 185, __extension__ __PRETTY_FUNCTION__)) |
184 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 185, __extension__ __PRETTY_FUNCTION__)) |
185 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 185, __extension__ __PRETTY_FUNCTION__)); |
186 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
187 | o3tl::underlyingEnumValue(lhs) |
188 | & o3tl::underlyingEnumValue<E>(rhs)); |
189 | } |
190 | |
191 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &( |
192 | typename o3tl::typed_flags<E>::Wrap lhs, E rhs) |
193 | { |
194 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 196, __extension__ __PRETTY_FUNCTION__)) |
195 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 196, __extension__ __PRETTY_FUNCTION__)) |
196 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 196, __extension__ __PRETTY_FUNCTION__)); |
197 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
198 | o3tl::underlyingEnumValue<E>(lhs) |
199 | & o3tl::underlyingEnumValue(rhs)); |
200 | } |
201 | |
202 | template<typename W> constexpr |
203 | typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator &( |
204 | W lhs, W rhs) |
205 | { |
206 | return static_cast<W>( |
207 | o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs) |
208 | & o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs)); |
209 | } |
210 | |
211 | template<typename E> |
212 | constexpr typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) { |
213 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 215, __extension__ __PRETTY_FUNCTION__)) |
214 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 215, __extension__ __PRETTY_FUNCTION__)) |
215 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 215, __extension__ __PRETTY_FUNCTION__)); |
216 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 218, __extension__ __PRETTY_FUNCTION__)) |
217 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 218, __extension__ __PRETTY_FUNCTION__)) |
218 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 218, __extension__ __PRETTY_FUNCTION__)); |
219 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
220 | o3tl::underlyingEnumValue(lhs) |
221 | | o3tl::underlyingEnumValue(rhs)); |
222 | } |
223 | |
224 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |( |
225 | E lhs, typename o3tl::typed_flags<E>::Wrap rhs) |
226 | { |
227 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 229, __extension__ __PRETTY_FUNCTION__)) |
228 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 229, __extension__ __PRETTY_FUNCTION__)) |
229 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 229, __extension__ __PRETTY_FUNCTION__)); |
230 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
231 | o3tl::underlyingEnumValue(lhs) |
232 | | o3tl::underlyingEnumValue<E>(rhs)); |
233 | } |
234 | |
235 | template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |( |
236 | typename o3tl::typed_flags<E>::Wrap lhs, E rhs) |
237 | { |
238 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 240, __extension__ __PRETTY_FUNCTION__)) |
239 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 240, __extension__ __PRETTY_FUNCTION__)) |
240 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 240, __extension__ __PRETTY_FUNCTION__)); |
241 | return static_cast<typename o3tl::typed_flags<E>::Wrap>( |
242 | o3tl::underlyingEnumValue<E>(lhs) |
243 | | o3tl::underlyingEnumValue(rhs)); |
244 | } |
245 | |
246 | template<typename W> constexpr |
247 | typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator |( |
248 | W lhs, W rhs) |
249 | { |
250 | return static_cast<W>( |
251 | o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs) |
252 | | o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs)); |
253 | } |
254 | |
255 | template<typename E> |
256 | inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) { |
257 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 259, __extension__ __PRETTY_FUNCTION__)) |
258 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 259, __extension__ __PRETTY_FUNCTION__)) |
259 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 259, __extension__ __PRETTY_FUNCTION__)); |
260 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 262, __extension__ __PRETTY_FUNCTION__)) |
261 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 262, __extension__ __PRETTY_FUNCTION__)) |
262 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 262, __extension__ __PRETTY_FUNCTION__)); |
263 | lhs = lhs & rhs; |
264 | return lhs; |
265 | } |
266 | |
267 | template<typename E> |
268 | inline typename o3tl::typed_flags<E>::Self operator &=( |
269 | E & lhs, typename o3tl::typed_flags<E>::Wrap rhs) |
270 | { |
271 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 273, __extension__ __PRETTY_FUNCTION__)) |
272 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 273, __extension__ __PRETTY_FUNCTION__)) |
273 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 273, __extension__ __PRETTY_FUNCTION__)); |
274 | lhs = lhs & rhs; |
275 | return lhs; |
276 | } |
277 | |
278 | template<typename E> |
279 | inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) { |
280 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 282, __extension__ __PRETTY_FUNCTION__)) |
281 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 282, __extension__ __PRETTY_FUNCTION__)) |
282 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 282, __extension__ __PRETTY_FUNCTION__)); |
283 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 285, __extension__ __PRETTY_FUNCTION__)) |
284 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 285, __extension__ __PRETTY_FUNCTION__)) |
285 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 285, __extension__ __PRETTY_FUNCTION__)); |
286 | lhs = lhs | rhs; |
287 | return lhs; |
288 | } |
289 | |
290 | template<typename E> |
291 | inline typename o3tl::typed_flags<E>::Self operator |=( |
292 | E & lhs, typename o3tl::typed_flags<E>::Wrap rhs) |
293 | { |
294 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 296, __extension__ __PRETTY_FUNCTION__)) |
295 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 296, __extension__ __PRETTY_FUNCTION__)) |
296 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 296, __extension__ __PRETTY_FUNCTION__)); |
297 | lhs = lhs | rhs; |
298 | return lhs; |
299 | } |
300 | |
301 | template<typename E> |
302 | inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) { |
303 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 305, __extension__ __PRETTY_FUNCTION__)) |
304 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 305, __extension__ __PRETTY_FUNCTION__)) |
305 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 305, __extension__ __PRETTY_FUNCTION__)); |
306 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 308, __extension__ __PRETTY_FUNCTION__)) |
307 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 308, __extension__ __PRETTY_FUNCTION__)) |
308 | o3tl::underlyingEnumValue(rhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(rhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(rhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 308, __extension__ __PRETTY_FUNCTION__)); |
309 | lhs = lhs ^ rhs; |
310 | return lhs; |
311 | } |
312 | |
313 | template<typename E> |
314 | inline typename o3tl::typed_flags<E>::Self operator ^=( |
315 | E & lhs, typename o3tl::typed_flags<E>::Wrap rhs) |
316 | { |
317 | assert((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 319, __extension__ __PRETTY_FUNCTION__)) |
318 | o3tl::detail::isNonNegative((static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 319, __extension__ __PRETTY_FUNCTION__)) |
319 | o3tl::underlyingEnumValue(lhs)))(static_cast <bool> (o3tl::detail::isNonNegative( o3tl:: underlyingEnumValue(lhs))) ? void (0) : __assert_fail ("o3tl::detail::isNonNegative( o3tl::underlyingEnumValue(lhs))" , "/home/maarten/src/libreoffice/core/include/o3tl/typed_flags_set.hxx" , 319, __extension__ __PRETTY_FUNCTION__)); |
320 | lhs = lhs ^ rhs; |
321 | return lhs; |
322 | } |
323 | |
324 | #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */ |
325 | |
326 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | // unique_ptr implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2008-2020 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file bits/unique_ptr.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{memory} |
28 | */ |
29 | |
30 | #ifndef _UNIQUE_PTR_H1 |
31 | #define _UNIQUE_PTR_H1 1 |
32 | |
33 | #include <bits/c++config.h> |
34 | #include <debug/assertions.h> |
35 | #include <type_traits> |
36 | #include <utility> |
37 | #include <tuple> |
38 | #include <bits/stl_function.h> |
39 | #include <bits/functional_hash.h> |
40 | #if __cplusplus201703L > 201703L |
41 | # include <compare> |
42 | # include <ostream> |
43 | #endif |
44 | |
45 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
46 | { |
47 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
48 | |
49 | /** |
50 | * @addtogroup pointer_abstractions |
51 | * @{ |
52 | */ |
53 | |
54 | #if _GLIBCXX_USE_DEPRECATED1 |
55 | #pragma GCC diagnostic push |
56 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
57 | template<typename> class auto_ptr; |
58 | #pragma GCC diagnostic pop |
59 | #endif |
60 | |
61 | /// Primary template of default_delete, used by unique_ptr for single objects |
62 | template<typename _Tp> |
63 | struct default_delete |
64 | { |
65 | /// Default constructor |
66 | constexpr default_delete() noexcept = default; |
67 | |
68 | /** @brief Converting constructor. |
69 | * |
70 | * Allows conversion from a deleter for objects of another type, `_Up`, |
71 | * only if `_Up*` is convertible to `_Tp*`. |
72 | */ |
73 | template<typename _Up, |
74 | typename = _Require<is_convertible<_Up*, _Tp*>>> |
75 | default_delete(const default_delete<_Up>&) noexcept { } |
76 | |
77 | /// Calls `delete __ptr` |
78 | void |
79 | operator()(_Tp* __ptr) const |
80 | { |
81 | static_assert(!is_void<_Tp>::value, |
82 | "can't delete pointer to incomplete type"); |
83 | static_assert(sizeof(_Tp)>0, |
84 | "can't delete pointer to incomplete type"); |
85 | delete __ptr; |
86 | } |
87 | }; |
88 | |
89 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
90 | // DR 740 - omit specialization for array objects with a compile time length |
91 | |
92 | /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>` |
93 | template<typename _Tp> |
94 | struct default_delete<_Tp[]> |
95 | { |
96 | public: |
97 | /// Default constructor |
98 | constexpr default_delete() noexcept = default; |
99 | |
100 | /** @brief Converting constructor. |
101 | * |
102 | * Allows conversion from a deleter for arrays of another type, such as |
103 | * a const-qualified version of `_Tp`. |
104 | * |
105 | * Conversions from types derived from `_Tp` are not allowed because |
106 | * it is undefined to `delete[]` an array of derived types through a |
107 | * pointer to the base type. |
108 | */ |
109 | template<typename _Up, |
110 | typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>> |
111 | default_delete(const default_delete<_Up[]>&) noexcept { } |
112 | |
113 | /// Calls `delete[] __ptr` |
114 | template<typename _Up> |
115 | typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type |
116 | operator()(_Up* __ptr) const |
117 | { |
118 | static_assert(sizeof(_Tp)>0, |
119 | "can't delete pointer to incomplete type"); |
120 | delete [] __ptr; |
121 | } |
122 | }; |
123 | |
124 | /// @cond undocumented |
125 | |
126 | // Manages the pointer and deleter of a unique_ptr |
127 | template <typename _Tp, typename _Dp> |
128 | class __uniq_ptr_impl |
129 | { |
130 | template <typename _Up, typename _Ep, typename = void> |
131 | struct _Ptr |
132 | { |
133 | using type = _Up*; |
134 | }; |
135 | |
136 | template <typename _Up, typename _Ep> |
137 | struct |
138 | _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> |
139 | { |
140 | using type = typename remove_reference<_Ep>::type::pointer; |
141 | }; |
142 | |
143 | public: |
144 | using _DeleterConstraint = enable_if< |
145 | __and_<__not_<is_pointer<_Dp>>, |
146 | is_default_constructible<_Dp>>::value>; |
147 | |
148 | using pointer = typename _Ptr<_Tp, _Dp>::type; |
149 | |
150 | static_assert( !is_rvalue_reference<_Dp>::value, |
151 | "unique_ptr's deleter type must be a function object type" |
152 | " or an lvalue reference type" ); |
153 | |
154 | __uniq_ptr_impl() = default; |
155 | __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } |
156 | |
157 | template<typename _Del> |
158 | __uniq_ptr_impl(pointer __p, _Del&& __d) |
159 | : _M_t(__p, std::forward<_Del>(__d)) { } |
160 | |
161 | __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept |
162 | : _M_t(std::move(__u._M_t)) |
163 | { __u._M_ptr() = nullptr; } |
164 | |
165 | __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept |
166 | { |
167 | reset(__u.release()); |
168 | _M_deleter() = std::forward<_Dp>(__u._M_deleter()); |
169 | return *this; |
170 | } |
171 | |
172 | pointer& _M_ptr() { return std::get<0>(_M_t); } |
173 | pointer _M_ptr() const { return std::get<0>(_M_t); } |
174 | _Dp& _M_deleter() { return std::get<1>(_M_t); } |
175 | const _Dp& _M_deleter() const { return std::get<1>(_M_t); } |
176 | |
177 | void reset(pointer __p) noexcept |
178 | { |
179 | const pointer __old_p = _M_ptr(); |
180 | _M_ptr() = __p; |
181 | if (__old_p) |
182 | _M_deleter()(__old_p); |
183 | } |
184 | |
185 | pointer release() noexcept |
186 | { |
187 | pointer __p = _M_ptr(); |
188 | _M_ptr() = nullptr; |
189 | return __p; |
190 | } |
191 | |
192 | void |
193 | swap(__uniq_ptr_impl& __rhs) noexcept |
194 | { |
195 | using std::swap; |
196 | swap(this->_M_ptr(), __rhs._M_ptr()); |
197 | swap(this->_M_deleter(), __rhs._M_deleter()); |
198 | } |
199 | |
200 | private: |
201 | tuple<pointer, _Dp> _M_t; |
202 | }; |
203 | |
204 | // Defines move construction + assignment as either defaulted or deleted. |
205 | template <typename _Tp, typename _Dp, |
206 | bool = is_move_constructible<_Dp>::value, |
207 | bool = is_move_assignable<_Dp>::value> |
208 | struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp> |
209 | { |
210 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
211 | __uniq_ptr_data(__uniq_ptr_data&&) = default; |
212 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; |
213 | }; |
214 | |
215 | template <typename _Tp, typename _Dp> |
216 | struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp> |
217 | { |
218 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
219 | __uniq_ptr_data(__uniq_ptr_data&&) = default; |
220 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; |
221 | }; |
222 | |
223 | template <typename _Tp, typename _Dp> |
224 | struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp> |
225 | { |
226 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
227 | __uniq_ptr_data(__uniq_ptr_data&&) = delete; |
228 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; |
229 | }; |
230 | |
231 | template <typename _Tp, typename _Dp> |
232 | struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp> |
233 | { |
234 | using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; |
235 | __uniq_ptr_data(__uniq_ptr_data&&) = delete; |
236 | __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; |
237 | }; |
238 | /// @endcond |
239 | |
240 | /// 20.7.1.2 unique_ptr for single objects. |
241 | template <typename _Tp, typename _Dp = default_delete<_Tp>> |
242 | class unique_ptr |
243 | { |
244 | template <typename _Up> |
245 | using _DeleterConstraint = |
246 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
247 | |
248 | __uniq_ptr_data<_Tp, _Dp> _M_t; |
249 | |
250 | public: |
251 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
252 | using element_type = _Tp; |
253 | using deleter_type = _Dp; |
254 | |
255 | private: |
256 | // helper template for detecting a safe conversion from another |
257 | // unique_ptr |
258 | template<typename _Up, typename _Ep> |
259 | using __safe_conversion_up = __and_< |
260 | is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, |
261 | __not_<is_array<_Up>> |
262 | >; |
263 | |
264 | public: |
265 | // Constructors. |
266 | |
267 | /// Default constructor, creates a unique_ptr that owns nothing. |
268 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
269 | constexpr unique_ptr() noexcept |
270 | : _M_t() |
271 | { } |
272 | |
273 | /** Takes ownership of a pointer. |
274 | * |
275 | * @param __p A pointer to an object of @c element_type |
276 | * |
277 | * The deleter will be value-initialized. |
278 | */ |
279 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
280 | explicit |
281 | unique_ptr(pointer __p) noexcept |
282 | : _M_t(__p) |
283 | { } |
284 | |
285 | /** Takes ownership of a pointer. |
286 | * |
287 | * @param __p A pointer to an object of @c element_type |
288 | * @param __d A reference to a deleter. |
289 | * |
290 | * The deleter will be initialized with @p __d |
291 | */ |
292 | template<typename _Del = deleter_type, |
293 | typename = _Require<is_copy_constructible<_Del>>> |
294 | unique_ptr(pointer __p, const deleter_type& __d) noexcept |
295 | : _M_t(__p, __d) { } |
296 | |
297 | /** Takes ownership of a pointer. |
298 | * |
299 | * @param __p A pointer to an object of @c element_type |
300 | * @param __d An rvalue reference to a (non-reference) deleter. |
301 | * |
302 | * The deleter will be initialized with @p std::move(__d) |
303 | */ |
304 | template<typename _Del = deleter_type, |
305 | typename = _Require<is_move_constructible<_Del>>> |
306 | unique_ptr(pointer __p, |
307 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
308 | _Del&&> __d) noexcept |
309 | : _M_t(__p, std::move(__d)) |
310 | { } |
311 | |
312 | template<typename _Del = deleter_type, |
313 | typename _DelUnref = typename remove_reference<_Del>::type> |
314 | unique_ptr(pointer, |
315 | __enable_if_t<is_lvalue_reference<_Del>::value, |
316 | _DelUnref&&>) = delete; |
317 | |
318 | /// Creates a unique_ptr that owns nothing. |
319 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
320 | constexpr unique_ptr(nullptr_t) noexcept |
321 | : _M_t() |
322 | { } |
323 | |
324 | // Move constructors. |
325 | |
326 | /// Move constructor. |
327 | unique_ptr(unique_ptr&&) = default; |
328 | |
329 | /** @brief Converting constructor from another type |
330 | * |
331 | * Requires that the pointer owned by @p __u is convertible to the |
332 | * type of pointer owned by this object, @p __u does not own an array, |
333 | * and @p __u has a compatible deleter type. |
334 | */ |
335 | template<typename _Up, typename _Ep, typename = _Require< |
336 | __safe_conversion_up<_Up, _Ep>, |
337 | typename conditional<is_reference<_Dp>::value, |
338 | is_same<_Ep, _Dp>, |
339 | is_convertible<_Ep, _Dp>>::type>> |
340 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
341 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
342 | { } |
343 | |
344 | #if _GLIBCXX_USE_DEPRECATED1 |
345 | #pragma GCC diagnostic push |
346 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
347 | /// Converting constructor from @c auto_ptr |
348 | template<typename _Up, typename = _Require< |
349 | is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> |
350 | unique_ptr(auto_ptr<_Up>&& __u) noexcept; |
351 | #pragma GCC diagnostic pop |
352 | #endif |
353 | |
354 | /// Destructor, invokes the deleter if the stored pointer is not null. |
355 | ~unique_ptr() noexcept |
356 | { |
357 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
358 | "unique_ptr's deleter must be invocable with a pointer"); |
359 | auto& __ptr = _M_t._M_ptr(); |
360 | if (__ptr != nullptr) |
361 | get_deleter()(std::move(__ptr)); |
362 | __ptr = pointer(); |
363 | } |
364 | |
365 | // Assignment. |
366 | |
367 | /** @brief Move assignment operator. |
368 | * |
369 | * Invokes the deleter if this object owns a pointer. |
370 | */ |
371 | unique_ptr& operator=(unique_ptr&&) = default; |
372 | |
373 | /** @brief Assignment from another type. |
374 | * |
375 | * @param __u The object to transfer ownership from, which owns a |
376 | * convertible pointer to a non-array object. |
377 | * |
378 | * Invokes the deleter if this object owns a pointer. |
379 | */ |
380 | template<typename _Up, typename _Ep> |
381 | typename enable_if< __and_< |
382 | __safe_conversion_up<_Up, _Ep>, |
383 | is_assignable<deleter_type&, _Ep&&> |
384 | >::value, |
385 | unique_ptr&>::type |
386 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
387 | { |
388 | reset(__u.release()); |
389 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
390 | return *this; |
391 | } |
392 | |
393 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
394 | unique_ptr& |
395 | operator=(nullptr_t) noexcept |
396 | { |
397 | reset(); |
398 | return *this; |
399 | } |
400 | |
401 | // Observers. |
402 | |
403 | /// Dereference the stored pointer. |
404 | typename add_lvalue_reference<element_type>::type |
405 | operator*() const |
406 | { |
407 | __glibcxx_assert(get() != pointer()); |
408 | return *get(); |
409 | } |
410 | |
411 | /// Return the stored pointer. |
412 | pointer |
413 | operator->() const noexcept |
414 | { |
415 | _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); |
416 | return get(); |
417 | } |
418 | |
419 | /// Return the stored pointer. |
420 | pointer |
421 | get() const noexcept |
422 | { return _M_t._M_ptr(); } |
423 | |
424 | /// Return a reference to the stored deleter. |
425 | deleter_type& |
426 | get_deleter() noexcept |
427 | { return _M_t._M_deleter(); } |
428 | |
429 | /// Return a reference to the stored deleter. |
430 | const deleter_type& |
431 | get_deleter() const noexcept |
432 | { return _M_t._M_deleter(); } |
433 | |
434 | /// Return @c true if the stored pointer is not null. |
435 | explicit operator bool() const noexcept |
436 | { return get() == pointer() ? false : true; } |
437 | |
438 | // Modifiers. |
439 | |
440 | /// Release ownership of any stored pointer. |
441 | pointer |
442 | release() noexcept |
443 | { return _M_t.release(); } |
444 | |
445 | /** @brief Replace the stored pointer. |
446 | * |
447 | * @param __p The new pointer to store. |
448 | * |
449 | * The deleter will be invoked if a pointer is already owned. |
450 | */ |
451 | void |
452 | reset(pointer __p = pointer()) noexcept |
453 | { |
454 | static_assert(__is_invocable<deleter_type&, pointer>::value, |
455 | "unique_ptr's deleter must be invocable with a pointer"); |
456 | _M_t.reset(std::move(__p)); |
457 | } |
458 | |
459 | /// Exchange the pointer and deleter with another object. |
460 | void |
461 | swap(unique_ptr& __u) noexcept |
462 | { |
463 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); |
464 | _M_t.swap(__u._M_t); |
465 | } |
466 | |
467 | // Disable copy from lvalue. |
468 | unique_ptr(const unique_ptr&) = delete; |
469 | unique_ptr& operator=(const unique_ptr&) = delete; |
470 | }; |
471 | |
472 | /// 20.7.1.3 unique_ptr for array objects with a runtime length |
473 | // [unique.ptr.runtime] |
474 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
475 | // DR 740 - omit specialization for array objects with a compile time length |
476 | template<typename _Tp, typename _Dp> |
477 | class unique_ptr<_Tp[], _Dp> |
478 | { |
479 | template <typename _Up> |
480 | using _DeleterConstraint = |
481 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
482 | |
483 | __uniq_ptr_data<_Tp, _Dp> _M_t; |
484 | |
485 | template<typename _Up> |
486 | using __remove_cv = typename remove_cv<_Up>::type; |
487 | |
488 | // like is_base_of<_Tp, _Up> but false if unqualified types are the same |
489 | template<typename _Up> |
490 | using __is_derived_Tp |
491 | = __and_< is_base_of<_Tp, _Up>, |
492 | __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; |
493 | |
494 | public: |
495 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
496 | using element_type = _Tp; |
497 | using deleter_type = _Dp; |
498 | |
499 | // helper template for detecting a safe conversion from another |
500 | // unique_ptr |
501 | template<typename _Up, typename _Ep, |
502 | typename _UPtr = unique_ptr<_Up, _Ep>, |
503 | typename _UP_pointer = typename _UPtr::pointer, |
504 | typename _UP_element_type = typename _UPtr::element_type> |
505 | using __safe_conversion_up = __and_< |
506 | is_array<_Up>, |
507 | is_same<pointer, element_type*>, |
508 | is_same<_UP_pointer, _UP_element_type*>, |
509 | is_convertible<_UP_element_type(*)[], element_type(*)[]> |
510 | >; |
511 | |
512 | // helper template for detecting a safe conversion from a raw pointer |
513 | template<typename _Up> |
514 | using __safe_conversion_raw = __and_< |
515 | __or_<__or_<is_same<_Up, pointer>, |
516 | is_same<_Up, nullptr_t>>, |
517 | __and_<is_pointer<_Up>, |
518 | is_same<pointer, element_type*>, |
519 | is_convertible< |
520 | typename remove_pointer<_Up>::type(*)[], |
521 | element_type(*)[]> |
522 | > |
523 | > |
524 | >; |
525 | |
526 | // Constructors. |
527 | |
528 | /// Default constructor, creates a unique_ptr that owns nothing. |
529 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
530 | constexpr unique_ptr() noexcept |
531 | : _M_t() |
532 | { } |
533 | |
534 | /** Takes ownership of a pointer. |
535 | * |
536 | * @param __p A pointer to an array of a type safely convertible |
537 | * to an array of @c element_type |
538 | * |
539 | * The deleter will be value-initialized. |
540 | */ |
541 | template<typename _Up, |
542 | typename _Vp = _Dp, |
543 | typename = _DeleterConstraint<_Vp>, |
544 | typename = typename enable_if< |
545 | __safe_conversion_raw<_Up>::value, bool>::type> |
546 | explicit |
547 | unique_ptr(_Up __p) noexcept |
548 | : _M_t(__p) |
549 | { } |
550 | |
551 | /** Takes ownership of a pointer. |
552 | * |
553 | * @param __p A pointer to an array of a type safely convertible |
554 | * to an array of @c element_type |
555 | * @param __d A reference to a deleter. |
556 | * |
557 | * The deleter will be initialized with @p __d |
558 | */ |
559 | template<typename _Up, typename _Del = deleter_type, |
560 | typename = _Require<__safe_conversion_raw<_Up>, |
561 | is_copy_constructible<_Del>>> |
562 | unique_ptr(_Up __p, const deleter_type& __d) noexcept |
563 | : _M_t(__p, __d) { } |
564 | |
565 | /** Takes ownership of a pointer. |
566 | * |
567 | * @param __p A pointer to an array of a type safely convertible |
568 | * to an array of @c element_type |
569 | * @param __d A reference to a deleter. |
570 | * |
571 | * The deleter will be initialized with @p std::move(__d) |
572 | */ |
573 | template<typename _Up, typename _Del = deleter_type, |
574 | typename = _Require<__safe_conversion_raw<_Up>, |
575 | is_move_constructible<_Del>>> |
576 | unique_ptr(_Up __p, |
577 | __enable_if_t<!is_lvalue_reference<_Del>::value, |
578 | _Del&&> __d) noexcept |
579 | : _M_t(std::move(__p), std::move(__d)) |
580 | { } |
581 | |
582 | template<typename _Up, typename _Del = deleter_type, |
583 | typename _DelUnref = typename remove_reference<_Del>::type, |
584 | typename = _Require<__safe_conversion_raw<_Up>>> |
585 | unique_ptr(_Up, |
586 | __enable_if_t<is_lvalue_reference<_Del>::value, |
587 | _DelUnref&&>) = delete; |
588 | |
589 | /// Move constructor. |
590 | unique_ptr(unique_ptr&&) = default; |
591 | |
592 | /// Creates a unique_ptr that owns nothing. |
593 | template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>> |
594 | constexpr unique_ptr(nullptr_t) noexcept |
595 | : _M_t() |
596 | { } |
597 | |
598 | template<typename _Up, typename _Ep, typename = _Require< |
599 | __safe_conversion_up<_Up, _Ep>, |
600 | typename conditional<is_reference<_Dp>::value, |
601 | is_same<_Ep, _Dp>, |
602 | is_convertible<_Ep, _Dp>>::type>> |
603 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
604 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
605 | { } |
606 | |
607 | /// Destructor, invokes the deleter if the stored pointer is not null. |
608 | ~unique_ptr() |
609 | { |
610 | auto& __ptr = _M_t._M_ptr(); |
611 | if (__ptr != nullptr) |
612 | get_deleter()(__ptr); |
613 | __ptr = pointer(); |
614 | } |
615 | |
616 | // Assignment. |
617 | |
618 | /** @brief Move assignment operator. |
619 | * |
620 | * Invokes the deleter if this object owns a pointer. |
621 | */ |
622 | unique_ptr& |
623 | operator=(unique_ptr&&) = default; |
624 | |
625 | /** @brief Assignment from another type. |
626 | * |
627 | * @param __u The object to transfer ownership from, which owns a |
628 | * convertible pointer to an array object. |
629 | * |
630 | * Invokes the deleter if this object owns a pointer. |
631 | */ |
632 | template<typename _Up, typename _Ep> |
633 | typename |
634 | enable_if<__and_<__safe_conversion_up<_Up, _Ep>, |
635 | is_assignable<deleter_type&, _Ep&&> |
636 | >::value, |
637 | unique_ptr&>::type |
638 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
639 | { |
640 | reset(__u.release()); |
641 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
642 | return *this; |
643 | } |
644 | |
645 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
646 | unique_ptr& |
647 | operator=(nullptr_t) noexcept |
648 | { |
649 | reset(); |
650 | return *this; |
651 | } |
652 | |
653 | // Observers. |
654 | |
655 | /// Access an element of owned array. |
656 | typename std::add_lvalue_reference<element_type>::type |
657 | operator[](size_t __i) const |
658 | { |
659 | __glibcxx_assert(get() != pointer()); |
660 | return get()[__i]; |
661 | } |
662 | |
663 | /// Return the stored pointer. |
664 | pointer |
665 | get() const noexcept |
666 | { return _M_t._M_ptr(); } |
667 | |
668 | /// Return a reference to the stored deleter. |
669 | deleter_type& |
670 | get_deleter() noexcept |
671 | { return _M_t._M_deleter(); } |
672 | |
673 | /// Return a reference to the stored deleter. |
674 | const deleter_type& |
675 | get_deleter() const noexcept |
676 | { return _M_t._M_deleter(); } |
677 | |
678 | /// Return @c true if the stored pointer is not null. |
679 | explicit operator bool() const noexcept |
680 | { return get() == pointer() ? false : true; } |
681 | |
682 | // Modifiers. |
683 | |
684 | /// Release ownership of any stored pointer. |
685 | pointer |
686 | release() noexcept |
687 | { return _M_t.release(); } |
688 | |
689 | /** @brief Replace the stored pointer. |
690 | * |
691 | * @param __p The new pointer to store. |
692 | * |
693 | * The deleter will be invoked if a pointer is already owned. |
694 | */ |
695 | template <typename _Up, |
696 | typename = _Require< |
697 | __or_<is_same<_Up, pointer>, |
698 | __and_<is_same<pointer, element_type*>, |
699 | is_pointer<_Up>, |
700 | is_convertible< |
701 | typename remove_pointer<_Up>::type(*)[], |
702 | element_type(*)[] |
703 | > |
704 | > |
705 | > |
706 | >> |
707 | void |
708 | reset(_Up __p) noexcept |
709 | { _M_t.reset(std::move(__p)); } |
710 | |
711 | void reset(nullptr_t = nullptr) noexcept |
712 | { reset(pointer()); } |
713 | |
714 | /// Exchange the pointer and deleter with another object. |
715 | void |
716 | swap(unique_ptr& __u) noexcept |
717 | { |
718 | static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); |
719 | _M_t.swap(__u._M_t); |
720 | } |
721 | |
722 | // Disable copy from lvalue. |
723 | unique_ptr(const unique_ptr&) = delete; |
724 | unique_ptr& operator=(const unique_ptr&) = delete; |
725 | }; |
726 | |
727 | /// @relates unique_ptr @{ |
728 | |
729 | /// Swap overload for unique_ptr |
730 | template<typename _Tp, typename _Dp> |
731 | inline |
732 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
733 | // Constrained free swap overload, see p0185r1 |
734 | typename enable_if<__is_swappable<_Dp>::value>::type |
735 | #else |
736 | void |
737 | #endif |
738 | swap(unique_ptr<_Tp, _Dp>& __x, |
739 | unique_ptr<_Tp, _Dp>& __y) noexcept |
740 | { __x.swap(__y); } |
741 | |
742 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
743 | template<typename _Tp, typename _Dp> |
744 | typename enable_if<!__is_swappable<_Dp>::value>::type |
745 | swap(unique_ptr<_Tp, _Dp>&, |
746 | unique_ptr<_Tp, _Dp>&) = delete; |
747 | #endif |
748 | |
749 | /// Equality operator for unique_ptr objects, compares the owned pointers |
750 | template<typename _Tp, typename _Dp, |
751 | typename _Up, typename _Ep> |
752 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
753 | operator==(const unique_ptr<_Tp, _Dp>& __x, |
754 | const unique_ptr<_Up, _Ep>& __y) |
755 | { return __x.get() == __y.get(); } |
756 | |
757 | /// unique_ptr comparison with nullptr |
758 | template<typename _Tp, typename _Dp> |
759 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
760 | operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
761 | { return !__x; } |
762 | |
763 | #ifndef __cpp_lib_three_way_comparison |
764 | /// unique_ptr comparison with nullptr |
765 | template<typename _Tp, typename _Dp> |
766 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
767 | operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
768 | { return !__x; } |
769 | |
770 | /// Inequality operator for unique_ptr objects, compares the owned pointers |
771 | template<typename _Tp, typename _Dp, |
772 | typename _Up, typename _Ep> |
773 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
774 | operator!=(const unique_ptr<_Tp, _Dp>& __x, |
775 | const unique_ptr<_Up, _Ep>& __y) |
776 | { return __x.get() != __y.get(); } |
777 | |
778 | /// unique_ptr comparison with nullptr |
779 | template<typename _Tp, typename _Dp> |
780 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
781 | operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
782 | { return (bool)__x; } |
783 | |
784 | /// unique_ptr comparison with nullptr |
785 | template<typename _Tp, typename _Dp> |
786 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
787 | operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
788 | { return (bool)__x; } |
789 | #endif // three way comparison |
790 | |
791 | /// Relational operator for unique_ptr objects, compares the owned pointers |
792 | template<typename _Tp, typename _Dp, |
793 | typename _Up, typename _Ep> |
794 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
795 | operator<(const unique_ptr<_Tp, _Dp>& __x, |
796 | const unique_ptr<_Up, _Ep>& __y) |
797 | { |
798 | typedef typename |
799 | std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, |
800 | typename unique_ptr<_Up, _Ep>::pointer>::type _CT; |
801 | return std::less<_CT>()(__x.get(), __y.get()); |
802 | } |
803 | |
804 | /// unique_ptr comparison with nullptr |
805 | template<typename _Tp, typename _Dp> |
806 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
807 | operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
808 | { |
809 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
810 | nullptr); |
811 | } |
812 | |
813 | /// unique_ptr comparison with nullptr |
814 | template<typename _Tp, typename _Dp> |
815 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
816 | operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
817 | { |
818 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
819 | __x.get()); |
820 | } |
821 | |
822 | /// Relational operator for unique_ptr objects, compares the owned pointers |
823 | template<typename _Tp, typename _Dp, |
824 | typename _Up, typename _Ep> |
825 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
826 | operator<=(const unique_ptr<_Tp, _Dp>& __x, |
827 | const unique_ptr<_Up, _Ep>& __y) |
828 | { return !(__y < __x); } |
829 | |
830 | /// unique_ptr comparison with nullptr |
831 | template<typename _Tp, typename _Dp> |
832 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
833 | operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
834 | { return !(nullptr < __x); } |
835 | |
836 | /// unique_ptr comparison with nullptr |
837 | template<typename _Tp, typename _Dp> |
838 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
839 | operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
840 | { return !(__x < nullptr); } |
841 | |
842 | /// Relational operator for unique_ptr objects, compares the owned pointers |
843 | template<typename _Tp, typename _Dp, |
844 | typename _Up, typename _Ep> |
845 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
846 | operator>(const unique_ptr<_Tp, _Dp>& __x, |
847 | const unique_ptr<_Up, _Ep>& __y) |
848 | { return (__y < __x); } |
849 | |
850 | /// unique_ptr comparison with nullptr |
851 | template<typename _Tp, typename _Dp> |
852 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
853 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
854 | { |
855 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
856 | __x.get()); |
857 | } |
858 | |
859 | /// unique_ptr comparison with nullptr |
860 | template<typename _Tp, typename _Dp> |
861 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
862 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
863 | { |
864 | return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
865 | nullptr); |
866 | } |
867 | |
868 | /// Relational operator for unique_ptr objects, compares the owned pointers |
869 | template<typename _Tp, typename _Dp, |
870 | typename _Up, typename _Ep> |
871 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
872 | operator>=(const unique_ptr<_Tp, _Dp>& __x, |
873 | const unique_ptr<_Up, _Ep>& __y) |
874 | { return !(__x < __y); } |
875 | |
876 | /// unique_ptr comparison with nullptr |
877 | template<typename _Tp, typename _Dp> |
878 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
879 | operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
880 | { return !(__x < nullptr); } |
881 | |
882 | /// unique_ptr comparison with nullptr |
883 | template<typename _Tp, typename _Dp> |
884 | _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool |
885 | operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
886 | { return !(nullptr < __x); } |
887 | |
888 | #ifdef __cpp_lib_three_way_comparison |
889 | template<typename _Tp, typename _Dp, typename _Up, typename _Ep> |
890 | requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer, |
891 | typename unique_ptr<_Up, _Ep>::pointer> |
892 | inline |
893 | compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer, |
894 | typename unique_ptr<_Up, _Ep>::pointer> |
895 | operator<=>(const unique_ptr<_Tp, _Dp>& __x, |
896 | const unique_ptr<_Up, _Ep>& __y) |
897 | { return compare_three_way()(__x.get(), __y.get()); } |
898 | |
899 | template<typename _Tp, typename _Dp> |
900 | requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer> |
901 | inline |
902 | compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer> |
903 | operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
904 | { |
905 | using pointer = typename unique_ptr<_Tp, _Dp>::pointer; |
906 | return compare_three_way()(__x.get(), static_cast<pointer>(nullptr)); |
907 | } |
908 | #endif |
909 | // @} relates unique_ptr |
910 | |
911 | /// @cond undocumented |
912 | template<typename _Up, typename _Ptr = typename _Up::pointer, |
913 | bool = __poison_hash<_Ptr>::__enable_hash_call> |
914 | struct __uniq_ptr_hash |
915 | #if ! _GLIBCXX_INLINE_VERSION0 |
916 | : private __poison_hash<_Ptr> |
917 | #endif |
918 | { |
919 | size_t |
920 | operator()(const _Up& __u) const |
921 | noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>()))) |
922 | { return hash<_Ptr>()(__u.get()); } |
923 | }; |
924 | |
925 | template<typename _Up, typename _Ptr> |
926 | struct __uniq_ptr_hash<_Up, _Ptr, false> |
927 | : private __poison_hash<_Ptr> |
928 | { }; |
929 | /// @endcond |
930 | |
931 | /// std::hash specialization for unique_ptr. |
932 | template<typename _Tp, typename _Dp> |
933 | struct hash<unique_ptr<_Tp, _Dp>> |
934 | : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, |
935 | public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>> |
936 | { }; |
937 | |
938 | #if __cplusplus201703L >= 201402L |
939 | /// @relates unique_ptr @{ |
940 | #define __cpp_lib_make_unique201304 201304 |
941 | |
942 | /// @cond undocumented |
943 | |
944 | template<typename _Tp> |
945 | struct _MakeUniq |
946 | { typedef unique_ptr<_Tp> __single_object; }; |
947 | |
948 | template<typename _Tp> |
949 | struct _MakeUniq<_Tp[]> |
950 | { typedef unique_ptr<_Tp[]> __array; }; |
951 | |
952 | template<typename _Tp, size_t _Bound> |
953 | struct _MakeUniq<_Tp[_Bound]> |
954 | { struct __invalid_type { }; }; |
955 | |
956 | /// @endcond |
957 | |
958 | /// std::make_unique for single objects |
959 | template<typename _Tp, typename... _Args> |
960 | inline typename _MakeUniq<_Tp>::__single_object |
961 | make_unique(_Args&&... __args) |
962 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } |
963 | |
964 | /// std::make_unique for arrays of unknown bound |
965 | template<typename _Tp> |
966 | inline typename _MakeUniq<_Tp>::__array |
967 | make_unique(size_t __num) |
968 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } |
969 | |
970 | /// Disable std::make_unique for arrays of known bound |
971 | template<typename _Tp, typename... _Args> |
972 | inline typename _MakeUniq<_Tp>::__invalid_type |
973 | make_unique(_Args&&...) = delete; |
974 | // @} relates unique_ptr |
975 | #endif // C++14 |
976 | |
977 | #if __cplusplus201703L > 201703L && __cpp_concepts |
978 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
979 | // 2948. unique_ptr does not define operator<< for stream output |
980 | /// Stream output operator for unique_ptr |
981 | template<typename _CharT, typename _Traits, typename _Tp, typename _Dp> |
982 | inline basic_ostream<_CharT, _Traits>& |
983 | operator<<(basic_ostream<_CharT, _Traits>& __os, |
984 | const unique_ptr<_Tp, _Dp>& __p) |
985 | requires requires { __os << __p.get(); } |
986 | { |
987 | __os << __p.get(); |
988 | return __os; |
989 | } |
990 | #endif // C++20 |
991 | |
992 | // @} group pointer_abstractions |
993 | |
994 | #if __cplusplus201703L >= 201703L |
995 | namespace __detail::__variant |
996 | { |
997 | template<typename> struct _Never_valueless_alt; // see <variant> |
998 | |
999 | // Provide the strong exception-safety guarantee when emplacing a |
1000 | // unique_ptr into a variant. |
1001 | template<typename _Tp, typename _Del> |
1002 | struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>> |
1003 | : std::true_type |
1004 | { }; |
1005 | } // namespace __detail::__variant |
1006 | #endif // C++17 |
1007 | |
1008 | _GLIBCXX_END_NAMESPACE_VERSION |
1009 | } // namespace |
1010 | |
1011 | #endif /* _UNIQUE_PTR_H */ |