File: | home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx |
Warning: | line 1445, column 21 Forming reference to null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | ||||||
2 | /* | ||||||
3 | * This file is part of the LibreOffice project. | ||||||
4 | * | ||||||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | ||||||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
8 | * | ||||||
9 | * This file incorporates work covered by the following license notice: | ||||||
10 | * | ||||||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | ||||||
12 | * contributor license agreements. See the NOTICE file distributed | ||||||
13 | * with this work for additional information regarding copyright | ||||||
14 | * ownership. The ASF licenses this file to you under the Apache | ||||||
15 | * License, Version 2.0 (the "License"); you may not use this file | ||||||
16 | * except in compliance with the License. You may obtain a copy of | ||||||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | ||||||
18 | */ | ||||||
19 | |||||||
20 | #include <sal/config.h> | ||||||
21 | #include <sal/log.hxx> | ||||||
22 | |||||||
23 | #include <o3tl/safeint.hxx> | ||||||
24 | #include <svl/itemiter.hxx> | ||||||
25 | #include <txtftn.hxx> | ||||||
26 | #include <fmtftn.hxx> | ||||||
27 | #include <fmtclbl.hxx> | ||||||
28 | #include <sectfrm.hxx> | ||||||
29 | #include <cellfrm.hxx> | ||||||
30 | #include <section.hxx> | ||||||
31 | #include <IDocumentSettingAccess.hxx> | ||||||
32 | #include <rootfrm.hxx> | ||||||
33 | #include <pagefrm.hxx> | ||||||
34 | #include <txtfrm.hxx> | ||||||
35 | #include <fmtclds.hxx> | ||||||
36 | #include <colfrm.hxx> | ||||||
37 | #include <tabfrm.hxx> | ||||||
38 | #include <ftnfrm.hxx> | ||||||
39 | #include <layouter.hxx> | ||||||
40 | #include <dbg_lay.hxx> | ||||||
41 | #include <viewopt.hxx> | ||||||
42 | #include <viewimp.hxx> | ||||||
43 | #include <editeng/brushitem.hxx> | ||||||
44 | #include <fmtftntx.hxx> | ||||||
45 | #include <flyfrm.hxx> | ||||||
46 | #include <sortedobjs.hxx> | ||||||
47 | #include <hints.hxx> | ||||||
48 | #include <frmatr.hxx> | ||||||
49 | #include <frmtool.hxx> | ||||||
50 | |||||||
51 | namespace | ||||||
52 | { | ||||||
53 | /** | ||||||
54 | * Performs the correct type of position invalidation depending on if we're in | ||||||
55 | * CalcContent(). | ||||||
56 | */ | ||||||
57 | void InvalidateFramePos(SwFrame* pFrame, bool bInCalcContent) | ||||||
58 | { | ||||||
59 | if (bInCalcContent) | ||||||
60 | pFrame->InvalidatePos_(); | ||||||
61 | else | ||||||
62 | pFrame->InvalidatePos(); | ||||||
63 | } | ||||||
64 | } | ||||||
65 | |||||||
66 | SwSectionFrame::SwSectionFrame( SwSection &rSect, SwFrame* pSib ) | ||||||
67 | : SwLayoutFrame( rSect.GetFormat(), pSib ) | ||||||
68 | , SwFlowFrame( static_cast<SwFrame&>(*this) ) | ||||||
69 | , m_pSection( &rSect ) | ||||||
70 | , m_bFootnoteAtEnd(false) | ||||||
71 | , m_bEndnAtEnd(false) | ||||||
72 | , m_bContentLock(false) | ||||||
73 | , m_bOwnFootnoteNum(false) | ||||||
74 | , m_bFootnoteLock(false) | ||||||
75 | { | ||||||
76 | mnFrameType = SwFrameType::Section; | ||||||
77 | |||||||
78 | CalcFootnoteAtEndFlag(); | ||||||
79 | CalcEndAtEndFlag(); | ||||||
80 | } | ||||||
81 | |||||||
82 | SwSectionFrame::SwSectionFrame( SwSectionFrame &rSect, bool bMaster ) : | ||||||
83 | SwLayoutFrame( rSect.GetFormat(), rSect.getRootFrame() ), | ||||||
84 | SwFlowFrame( static_cast<SwFrame&>(*this) ), | ||||||
85 | m_pSection( rSect.GetSection() ), | ||||||
86 | m_bFootnoteAtEnd( rSect.IsFootnoteAtEnd() ), | ||||||
87 | m_bEndnAtEnd( rSect.IsEndnAtEnd() ), | ||||||
88 | m_bContentLock( false ), | ||||||
89 | m_bOwnFootnoteNum( false ), | ||||||
90 | m_bFootnoteLock( false ) | ||||||
91 | { | ||||||
92 | mnFrameType = SwFrameType::Section; | ||||||
93 | |||||||
94 | PROTOCOL( this, PROT::Section, bMaster ? DbgAction::CreateMaster : DbgAction::CreateFollow, &rSect ) | ||||||
95 | |||||||
96 | if( bMaster ) | ||||||
97 | { | ||||||
98 | SwSectionFrame* pMaster = rSect.IsFollow() ? rSect.FindMaster() : nullptr; | ||||||
99 | if (pMaster) | ||||||
100 | pMaster->SetFollow( this ); | ||||||
101 | SetFollow( &rSect ); | ||||||
102 | } | ||||||
103 | else | ||||||
104 | { | ||||||
105 | SetFollow( rSect.GetFollow() ); | ||||||
106 | rSect.SetFollow( this ); | ||||||
107 | if( !GetFollow() ) | ||||||
108 | rSect.SimpleFormat(); | ||||||
109 | if( !rSect.IsColLocked() ) | ||||||
110 | rSect.InvalidateSize(); | ||||||
111 | } | ||||||
112 | } | ||||||
113 | |||||||
114 | // NOTE: call <SwSectionFrame::Init()> directly after creation of a new section | ||||||
115 | // frame and its insert in the layout. | ||||||
116 | void SwSectionFrame::Init() | ||||||
117 | { | ||||||
118 | assert(GetUpper() && "SwSectionFrame::Init before insertion?!")(static_cast <bool> (GetUpper() && "SwSectionFrame::Init before insertion?!" ) ? void (0) : __assert_fail ("GetUpper() && \"SwSectionFrame::Init before insertion?!\"" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 118, __extension__ __PRETTY_FUNCTION__)); | ||||||
119 | SwRectFnSet aRectFnSet(this); | ||||||
120 | long nWidth = aRectFnSet.GetWidth(GetUpper()->getFramePrintArea()); | ||||||
121 | |||||||
122 | { | ||||||
123 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
124 | aRectFnSet.SetWidth( aFrm, nWidth ); | ||||||
125 | aRectFnSet.SetHeight( aFrm, 0 ); | ||||||
126 | } | ||||||
127 | |||||||
128 | // #109700# LRSpace for sections | ||||||
129 | const SvxLRSpaceItem& rLRSpace = GetFormat()->GetLRSpace(); | ||||||
130 | |||||||
131 | { | ||||||
132 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | ||||||
133 | aRectFnSet.SetLeft( aPrt, rLRSpace.GetLeft() ); | ||||||
134 | aRectFnSet.SetWidth( aPrt, nWidth - rLRSpace.GetLeft() - rLRSpace.GetRight() ); | ||||||
135 | aRectFnSet.SetHeight( aPrt, 0 ); | ||||||
136 | } | ||||||
137 | |||||||
138 | const SwFormatCol &rCol = GetFormat()->GetCol(); | ||||||
139 | if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFootnote() ) | ||||||
140 | { | ||||||
141 | const SwFormatCol *pOld = Lower() ? &rCol : new SwFormatCol; | ||||||
142 | ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() ); | ||||||
143 | if( pOld != &rCol ) | ||||||
144 | delete pOld; | ||||||
145 | } | ||||||
146 | } | ||||||
147 | |||||||
148 | void SwSectionFrame::DestroyImpl() | ||||||
149 | { | ||||||
150 | if( GetFormat() && !GetFormat()->GetDoc()->IsInDtor() ) | ||||||
151 | { | ||||||
152 | SwRootFrame *pRootFrame = getRootFrame(); | ||||||
153 | if( pRootFrame ) | ||||||
154 | pRootFrame->RemoveFromList( this ); | ||||||
155 | if( IsFollow() ) | ||||||
156 | { | ||||||
157 | SwSectionFrame *pMaster = FindMaster(); | ||||||
158 | if( pMaster ) | ||||||
159 | { | ||||||
160 | PROTOCOL( this, PROT::Section, DbgAction::DelFollow, pMaster ) | ||||||
161 | pMaster->SetFollow( GetFollow() ); | ||||||
162 | // A Master always grabs the space until the lower edge of his | ||||||
163 | // Upper. If he doesn't have a Follow anymore, he can | ||||||
164 | // release it, which is why the Size of the Master is | ||||||
165 | // invalidated. | ||||||
166 | if( !GetFollow() ) | ||||||
167 | pMaster->InvalidateSize(); | ||||||
168 | } | ||||||
169 | } | ||||||
170 | #if defined DBG_UTIL | ||||||
171 | else if( HasFollow() ) | ||||||
172 | { | ||||||
173 | PROTOCOL( this, PROT::Section, DbgAction::DelMaster, GetFollow() ) | ||||||
174 | } | ||||||
175 | #endif | ||||||
176 | } | ||||||
177 | |||||||
178 | SwLayoutFrame::DestroyImpl(); | ||||||
179 | } | ||||||
180 | |||||||
181 | SwSectionFrame::~SwSectionFrame() | ||||||
182 | { | ||||||
183 | } | ||||||
184 | |||||||
185 | void SwSectionFrame::DelEmpty( bool bRemove ) | ||||||
186 | { | ||||||
187 | if( IsColLocked() ) | ||||||
188 | { | ||||||
189 | OSL_ENSURE( !bRemove, "Don't delete locked SectionFrames" )do { if (true && (!(!bRemove))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "189" ": "), "%s", "Don't delete locked SectionFrames"); } } while (false); | ||||||
190 | return; | ||||||
191 | } | ||||||
192 | SwFrame* pUp = GetUpper(); | ||||||
193 | if( pUp ) | ||||||
194 | { | ||||||
195 | // #i27138# | ||||||
196 | // notify accessibility paragraphs objects about changed | ||||||
197 | // CONTENT_FLOWS_FROM/_TO relation. | ||||||
198 | // Relation CONTENT_FLOWS_FROM for current next paragraph will change | ||||||
199 | // and relation CONTENT_FLOWS_TO for current previous paragraph will change. | ||||||
200 | { | ||||||
201 | SwViewShell* pViewShell( getRootFrame()->GetCurrShell() ); | ||||||
202 | if ( pViewShell && pViewShell->GetLayout() && | ||||||
203 | pViewShell->GetLayout()->IsAnyShellAccessible() ) | ||||||
204 | { | ||||||
205 | pViewShell->InvalidateAccessibleParaFlowRelation( | ||||||
206 | dynamic_cast<SwTextFrame*>(FindNextCnt( true )), | ||||||
207 | dynamic_cast<SwTextFrame*>(FindPrevCnt()) ); | ||||||
208 | } | ||||||
209 | } | ||||||
210 | Cut_( bRemove ); | ||||||
211 | } | ||||||
212 | SwSectionFrame *pMaster = IsFollow() ? FindMaster() : nullptr; | ||||||
213 | if (pMaster) | ||||||
214 | { | ||||||
215 | pMaster->SetFollow( GetFollow() ); | ||||||
216 | // A Master always grabs the space until the lower edge of his | ||||||
217 | // Upper. If he doesn't have a Follow anymore, he can | ||||||
218 | // release it, which is why the Size of the Master is | ||||||
219 | // invalidated. | ||||||
220 | if( !GetFollow() && !pMaster->IsColLocked() ) | ||||||
221 | pMaster->InvalidateSize(); | ||||||
222 | } | ||||||
223 | SetFollow(nullptr); | ||||||
224 | if( !pUp ) | ||||||
225 | return; | ||||||
226 | |||||||
227 | { | ||||||
228 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
229 | aFrm.Height( 0 ); | ||||||
230 | } | ||||||
231 | |||||||
232 | // If we are destroyed immediately anyway, we don't need | ||||||
233 | // to put us into the list | ||||||
234 | if( bRemove ) | ||||||
235 | { // If we already were half dead before this DelEmpty, | ||||||
236 | // we are likely in the list and have to remove us from | ||||||
237 | // it | ||||||
238 | if( !m_pSection && getRootFrame() ) | ||||||
239 | getRootFrame()->RemoveFromList( this ); | ||||||
240 | } | ||||||
241 | else if( getRootFrame() ) | ||||||
242 | { | ||||||
243 | getRootFrame()->InsertEmptySct( this ); | ||||||
244 | } | ||||||
245 | |||||||
246 | m_pSection = nullptr; // like this a reanimation is virtually impossible though | ||||||
247 | } | ||||||
248 | |||||||
249 | void SwSectionFrame::Cut() | ||||||
250 | { | ||||||
251 | Cut_( true ); | ||||||
252 | } | ||||||
253 | |||||||
254 | void SwSectionFrame::Cut_( bool bRemove ) | ||||||
255 | { | ||||||
256 | OSL_ENSURE( GetUpper(), "Cut without Upper()." )do { if (true && (!(GetUpper()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "256" ": "), "%s", "Cut without Upper()."); } } while (false ); | ||||||
257 | |||||||
258 | PROTOCOL( this, PROT::Cut, DbgAction::NONE, GetUpper() ) | ||||||
259 | |||||||
260 | SwPageFrame *pPage = FindPageFrame(); | ||||||
261 | InvalidatePage( pPage ); | ||||||
262 | SwFrame *pFrame = GetNext(); | ||||||
263 | SwFrame* pPrepFrame = nullptr; | ||||||
264 | while( pFrame && pFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pFrame)->GetSection() ) | ||||||
265 | pFrame = pFrame->GetNext(); | ||||||
266 | if( pFrame ) | ||||||
267 | { // The former successor might have calculated a gap to the predecessor | ||||||
268 | // which is now obsolete since he becomes the first | ||||||
269 | pFrame->InvalidatePrt_(); | ||||||
270 | pFrame->InvalidatePos_(); | ||||||
271 | if( pFrame->IsSctFrame() ) | ||||||
272 | pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny(); | ||||||
273 | if ( pFrame && pFrame->IsContentFrame() ) | ||||||
274 | { | ||||||
275 | pFrame->InvalidatePage( pPage ); | ||||||
276 | if( IsInFootnote() && !GetIndPrev() ) | ||||||
277 | pPrepFrame = pFrame; | ||||||
278 | } | ||||||
279 | } | ||||||
280 | else | ||||||
281 | { | ||||||
282 | InvalidateNextPos(); | ||||||
283 | // Someone has to take over the retouching: predecessor or Upper | ||||||
284 | pFrame = GetPrev(); | ||||||
285 | if ( nullptr != pFrame ) | ||||||
286 | { | ||||||
287 | pFrame->SetRetouche(); | ||||||
288 | pFrame->Prepare( PrepareHint::WidowsOrphans ); | ||||||
289 | if ( pFrame->IsContentFrame() ) | ||||||
290 | pFrame->InvalidatePage( pPage ); | ||||||
291 | } | ||||||
292 | // If I am (was) the only FlowFrame in my Upper, then he has to take over | ||||||
293 | // the retouching. | ||||||
294 | // Furthermore a blank page could have emerged | ||||||
295 | else | ||||||
296 | { SwRootFrame *pRoot = static_cast<SwRootFrame*>(pPage->GetUpper()); | ||||||
297 | pRoot->SetSuperfluous(); | ||||||
298 | GetUpper()->SetCompletePaint(); | ||||||
299 | } | ||||||
300 | } | ||||||
301 | // First remove, then shrink Upper | ||||||
302 | SwLayoutFrame *pUp = GetUpper(); | ||||||
303 | if( bRemove ) | ||||||
304 | { | ||||||
305 | RemoveFromLayout(); | ||||||
306 | if( pUp && !pUp->Lower() && pUp->IsFootnoteFrame() && !pUp->IsColLocked() && | ||||||
307 | pUp->GetUpper() ) | ||||||
308 | { | ||||||
309 | pUp->Cut(); | ||||||
310 | SwFrame::DestroyFrame(pUp); | ||||||
311 | pUp = nullptr; | ||||||
312 | } | ||||||
313 | } | ||||||
314 | if( pPrepFrame ) | ||||||
315 | pPrepFrame->Prepare( PrepareHint::FootnoteInvalidation ); | ||||||
316 | if ( !pUp ) | ||||||
317 | return; | ||||||
318 | |||||||
319 | SwRectFnSet aRectFnSet(this); | ||||||
320 | SwTwips nFrameHeight = aRectFnSet.GetHeight(getFrameArea()); | ||||||
321 | if( nFrameHeight <= 0 ) | ||||||
322 | return; | ||||||
323 | |||||||
324 | if( !bRemove ) | ||||||
325 | { | ||||||
326 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
327 | aRectFnSet.SetHeight( aFrm, 0 ); | ||||||
328 | |||||||
329 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | ||||||
330 | aRectFnSet.SetHeight( aPrt, 0 ); | ||||||
331 | } | ||||||
332 | |||||||
333 | pUp->Shrink( nFrameHeight ); | ||||||
334 | } | ||||||
335 | |||||||
336 | void SwSectionFrame::Paste( SwFrame* pParent, SwFrame* pSibling ) | ||||||
337 | { | ||||||
338 | OSL_ENSURE( pParent, "No parent for Paste()." )do { if (true && (!(pParent))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "338" ": "), "%s", "No parent for Paste()."); } } while ( false); | ||||||
339 | OSL_ENSURE( pParent->IsLayoutFrame(), "Parent is ContentFrame." )do { if (true && (!(pParent->IsLayoutFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "339" ": "), "%s", "Parent is ContentFrame."); } } while (false); | ||||||
340 | OSL_ENSURE( pParent != this, "I'm my own parent." )do { if (true && (!(pParent != this))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "340" ": "), "%s", "I'm my own parent."); } } while (false ); | ||||||
341 | OSL_ENSURE( pSibling != this, "I'm my own neighbour." )do { if (true && (!(pSibling != this))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "341" ": "), "%s", "I'm my own neighbour."); } } while ( false); | ||||||
342 | OSL_ENSURE( !GetPrev() && !GetUpper(),do { if (true && (!(!GetPrev() && !GetUpper() ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "343" ": "), "%s", "I am still registered somewhere."); } } while (false) | ||||||
343 | "I am still registered somewhere." )do { if (true && (!(!GetPrev() && !GetUpper() ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "343" ": "), "%s", "I am still registered somewhere."); } } while (false); | ||||||
344 | |||||||
345 | PROTOCOL( this, PROT::Paste, DbgAction::NONE, GetUpper() ) | ||||||
346 | |||||||
347 | // Add to the tree | ||||||
348 | SwSectionFrame* pSect = pParent->FindSctFrame(); | ||||||
349 | // Assure that parent is not inside a table frame, which is inside the found section frame. | ||||||
350 | if ( pSect ) | ||||||
351 | { | ||||||
352 | SwTabFrame* pTableFrame = pParent->FindTabFrame(); | ||||||
353 | if ( pTableFrame && | ||||||
354 | pSect->IsAnLower( pTableFrame ) ) | ||||||
355 | { | ||||||
356 | pSect = nullptr; | ||||||
357 | } | ||||||
358 | } | ||||||
359 | |||||||
360 | SwRectFnSet aRectFnSet(pParent); | ||||||
361 | if( pSect && HasToBreak( pSect ) ) | ||||||
362 | { | ||||||
363 | if( pParent->IsColBodyFrame() ) // dealing with a single-column area | ||||||
364 | { | ||||||
365 | // If we are coincidentally at the end of a column, pSibling | ||||||
366 | // has to point to the first frame of the next column in order | ||||||
367 | // for the content of the next column to be moved correctly to the | ||||||
368 | // newly created pSect by the InsertGroup | ||||||
369 | SwColumnFrame *pCol = static_cast<SwColumnFrame*>(pParent->GetUpper()); | ||||||
370 | while( !pSibling && nullptr != ( pCol = static_cast<SwColumnFrame*>(pCol->GetNext()) ) ) | ||||||
371 | pSibling = static_cast<SwLayoutFrame*>(pCol->Lower())->Lower(); | ||||||
372 | if( pSibling ) | ||||||
373 | { | ||||||
374 | // Even worse: every following column content has to | ||||||
375 | // be attached to the pSibling-chain in order to be | ||||||
376 | // taken along | ||||||
377 | SwFrame *pTmp = pSibling; | ||||||
378 | while ( nullptr != ( pCol = static_cast<SwColumnFrame*>(pCol->GetNext()) ) ) | ||||||
379 | { | ||||||
380 | while ( pTmp->GetNext() ) | ||||||
381 | pTmp = pTmp->GetNext(); | ||||||
382 | SwFrame* pSave = ::SaveContent( pCol ); | ||||||
383 | if (pSave) | ||||||
384 | ::RestoreContent( pSave, pSibling->GetUpper(), pTmp ); | ||||||
385 | } | ||||||
386 | } | ||||||
387 | } | ||||||
388 | pParent = pSect; | ||||||
389 | pSect = new SwSectionFrame( *static_cast<SwSectionFrame*>(pParent)->GetSection(), pParent ); | ||||||
390 | // if pParent is decomposed into two parts, its Follow has to be attached | ||||||
391 | // to the new second part | ||||||
392 | pSect->SetFollow( static_cast<SwSectionFrame*>(pParent)->GetFollow() ); | ||||||
393 | static_cast<SwSectionFrame*>(pParent)->SetFollow( nullptr ); | ||||||
394 | if( pSect->GetFollow() ) | ||||||
395 | pParent->InvalidateSize_(); | ||||||
396 | |||||||
397 | const bool bInserted = InsertGroupBefore( pParent, pSibling, pSect ); | ||||||
398 | if (bInserted) | ||||||
399 | { | ||||||
400 | pSect->Init(); | ||||||
401 | aRectFnSet.MakePos( *pSect, pSect->GetUpper(), pSect->GetPrev(), true); | ||||||
402 | } | ||||||
403 | if( !static_cast<SwLayoutFrame*>(pParent)->Lower() ) | ||||||
404 | { | ||||||
405 | SwSectionFrame::MoveContentAndDelete( static_cast<SwSectionFrame*>(pParent), false ); | ||||||
406 | pParent = this; | ||||||
407 | } | ||||||
408 | } | ||||||
409 | else | ||||||
410 | InsertGroupBefore( pParent, pSibling, nullptr ); | ||||||
411 | |||||||
412 | InvalidateAll_(); | ||||||
413 | SwPageFrame *pPage = FindPageFrame(); | ||||||
414 | InvalidatePage( pPage ); | ||||||
415 | |||||||
416 | if ( pSibling ) | ||||||
417 | { | ||||||
418 | pSibling->InvalidatePos_(); | ||||||
419 | pSibling->InvalidatePrt_(); | ||||||
420 | if ( pSibling->IsContentFrame() ) | ||||||
421 | pSibling->InvalidatePage( pPage ); | ||||||
422 | } | ||||||
423 | |||||||
424 | SwTwips nFrameHeight = aRectFnSet.GetHeight(getFrameArea()); | ||||||
425 | if( nFrameHeight ) | ||||||
426 | pParent->Grow( nFrameHeight ); | ||||||
427 | |||||||
428 | if ( GetPrev() && !IsFollow() ) | ||||||
429 | { | ||||||
430 | GetPrev()->InvalidateSize(); | ||||||
431 | if ( GetPrev()->IsContentFrame() ) | ||||||
432 | GetPrev()->InvalidatePage( pPage ); | ||||||
433 | } | ||||||
434 | } | ||||||
435 | |||||||
436 | /** | ||||||
437 | |* Here it's decided whether the this-SectionFrame should break up | ||||||
438 | |* the passed (Section)frm (or not). | ||||||
439 | |* Initially, all superior sections are broken up. Later on that could | ||||||
440 | |* be made configurable. | ||||||
441 | |*/ | ||||||
442 | bool SwSectionFrame::HasToBreak( const SwFrame* pFrame ) const | ||||||
443 | { | ||||||
444 | if( !pFrame->IsSctFrame() ) | ||||||
445 | return false; | ||||||
446 | |||||||
447 | const SwSectionFormat *pTmp = static_cast<const SwSectionFormat*>(GetFormat()); | ||||||
448 | |||||||
449 | const SwFrameFormat *pOtherFormat = static_cast<const SwSectionFrame*>(pFrame)->GetFormat(); | ||||||
450 | do | ||||||
451 | { | ||||||
452 | pTmp = pTmp->GetParent(); | ||||||
453 | if( !pTmp ) | ||||||
454 | return false; | ||||||
455 | if( pTmp == pOtherFormat ) | ||||||
456 | return true; | ||||||
457 | } while( true ); // ( pTmp->GetSect().GetValue() ); | ||||||
458 | } | ||||||
459 | |||||||
460 | /** | ||||||
461 | |* Merges two SectionFrames, in case it's about the same section. | ||||||
462 | |* This can be necessary when a (sub)section is deleted that had | ||||||
463 | |* divided another part into two. | ||||||
464 | |*/ | ||||||
465 | void SwSectionFrame::MergeNext( SwSectionFrame* pNxt ) | ||||||
466 | { | ||||||
467 | if (pNxt->IsDeleteForbidden()) | ||||||
468 | return; | ||||||
469 | |||||||
470 | if (pNxt->IsJoinLocked() || GetSection() != pNxt->GetSection()) | ||||||
471 | return; | ||||||
472 | |||||||
473 | PROTOCOL( this, PROT::Section, DbgAction::Merge, pNxt ) | ||||||
474 | |||||||
475 | SwFrame* pTmp = ::SaveContent( pNxt ); | ||||||
476 | if( pTmp ) | ||||||
477 | { | ||||||
478 | SwFrame* pLast = Lower(); | ||||||
479 | SwLayoutFrame* pLay = this; | ||||||
480 | if( pLast ) | ||||||
481 | { | ||||||
482 | while( pLast->GetNext() ) | ||||||
483 | pLast = pLast->GetNext(); | ||||||
484 | if( pLast->IsColumnFrame() ) | ||||||
485 | { // Columns now with BodyFrame | ||||||
486 | pLay = static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(pLast)->Lower()); | ||||||
487 | pLast = pLay->Lower(); | ||||||
488 | if( pLast ) | ||||||
489 | while( pLast->GetNext() ) | ||||||
490 | pLast = pLast->GetNext(); | ||||||
491 | } | ||||||
492 | } | ||||||
493 | ::RestoreContent( pTmp, pLay, pLast ); | ||||||
494 | } | ||||||
495 | SetFollow( pNxt->GetFollow() ); | ||||||
496 | pNxt->SetFollow( nullptr ); | ||||||
497 | pNxt->Cut(); | ||||||
498 | SwFrame::DestroyFrame(pNxt); | ||||||
499 | InvalidateSize(); | ||||||
500 | } | ||||||
501 | |||||||
502 | /** | ||||||
503 | |* Divides a SectionFrame into two parts. The second one starts with the | ||||||
504 | |* passed frame. | ||||||
505 | |* This is required when inserting an inner section, because the MoveFwd | ||||||
506 | |* cannot have the desired effect within a frame or a table cell. | ||||||
507 | |*/ | ||||||
508 | bool SwSectionFrame::SplitSect( SwFrame* pFrame, bool bApres ) | ||||||
509 | { | ||||||
510 | assert(pFrame && "SplitSect: Why?")(static_cast <bool> (pFrame && "SplitSect: Why?" ) ? void (0) : __assert_fail ("pFrame && \"SplitSect: Why?\"" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 510, __extension__ __PRETTY_FUNCTION__)); | ||||||
511 | SwFrame* pOther = bApres ? pFrame->FindNext() : pFrame->FindPrev(); | ||||||
512 | if( !pOther ) | ||||||
513 | return false; | ||||||
514 | SwSectionFrame* pSect = pOther->FindSctFrame(); | ||||||
515 | if( pSect != this ) | ||||||
516 | return false; | ||||||
517 | // Put the content aside | ||||||
518 | SwFrame* pSav = ::SaveContent( this, bApres ? pOther : pFrame ); | ||||||
519 | OSL_ENSURE( pSav, "SplitSect: What's on?" )do { if (true && (!(pSav))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "519" ": "), "%s", "SplitSect: What's on?"); } } while ( false); | ||||||
520 | if( pSav ) // be robust | ||||||
521 | { // Create a new SctFrame, not as a Follower/master | ||||||
522 | SwSectionFrame* pNew = new SwSectionFrame( *pSect->GetSection(), pSect ); | ||||||
523 | pNew->InsertBehind( pSect->GetUpper(), pSect ); | ||||||
524 | pNew->Init(); | ||||||
525 | SwRectFnSet aRectFnSet(this); | ||||||
526 | aRectFnSet.MakePos( *pNew, nullptr, pSect, true ); | ||||||
527 | // OD 25.03.2003 #108339# - restore content: | ||||||
528 | // determine layout frame for restoring content after the initialization | ||||||
529 | // of the section frame. In the section initialization the columns are | ||||||
530 | // created. | ||||||
531 | { | ||||||
532 | SwLayoutFrame* pLay = pNew; | ||||||
533 | // Search for last layout frame, e.g. for columned sections. | ||||||
534 | while( pLay->Lower() && pLay->Lower()->IsLayoutFrame() ) | ||||||
535 | pLay = static_cast<SwLayoutFrame*>(pLay->Lower()); | ||||||
536 | ::RestoreContent( pSav, pLay, nullptr ); | ||||||
537 | } | ||||||
538 | InvalidateSize_(); | ||||||
539 | if( HasFollow() ) | ||||||
540 | { | ||||||
541 | pNew->SetFollow( GetFollow() ); | ||||||
542 | SetFollow( nullptr ); | ||||||
543 | } | ||||||
544 | return true; | ||||||
545 | } | ||||||
546 | return false; | ||||||
547 | } | ||||||
548 | |||||||
549 | /** | ||||||
550 | |* MoveContent is called for destroying a SectionFrames, due to | ||||||
551 | |* the cancellation or hiding of a section, to handle the content. | ||||||
552 | |* If the SectionFrame hasn't broken up another one, then the content | ||||||
553 | |* is moved to the Upper. Otherwise the content is moved to another | ||||||
554 | |* SectionFrame, which has to be potentially merged. | ||||||
555 | |*/ | ||||||
556 | // If a multi-column section is cancelled, the ContentFrames have to be | ||||||
557 | // invalidated | ||||||
558 | static void lcl_InvalidateInfFlags( SwFrame* pFrame, bool bInva ) | ||||||
559 | { | ||||||
560 | while ( pFrame ) | ||||||
561 | { | ||||||
562 | pFrame->InvalidateInfFlags(); | ||||||
563 | if( bInva ) | ||||||
564 | { | ||||||
565 | pFrame->InvalidatePos_(); | ||||||
566 | pFrame->InvalidateSize_(); | ||||||
567 | pFrame->InvalidatePrt_(); | ||||||
568 | } | ||||||
569 | if( pFrame->IsLayoutFrame() ) | ||||||
570 | lcl_InvalidateInfFlags( static_cast<SwLayoutFrame*>(pFrame)->GetLower(), false ); | ||||||
571 | pFrame = pFrame->GetNext(); | ||||||
572 | } | ||||||
573 | } | ||||||
574 | |||||||
575 | // Works like SwContentFrame::ImplGetNextContentFrame, but starts with a LayoutFrame | ||||||
576 | static SwContentFrame* lcl_GetNextContentFrame( const SwLayoutFrame* pLay, bool bFwd ) | ||||||
577 | { | ||||||
578 | if ( bFwd ) | ||||||
579 | { | ||||||
580 | if ( pLay->GetNext() && pLay->GetNext()->IsContentFrame() ) | ||||||
581 | return const_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pLay->GetNext())); | ||||||
582 | } | ||||||
583 | else | ||||||
584 | { | ||||||
585 | if ( pLay->GetPrev() && pLay->GetPrev()->IsContentFrame() ) | ||||||
586 | return const_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pLay->GetPrev())); | ||||||
587 | } | ||||||
588 | |||||||
589 | const SwFrame* pFrame = pLay; | ||||||
590 | SwContentFrame *pContentFrame = nullptr; | ||||||
591 | bool bGoingUp = true; | ||||||
592 | do { | ||||||
593 | const SwFrame *p = nullptr; | ||||||
594 | bool bGoingFwdOrBwd = false; | ||||||
595 | |||||||
596 | bool bGoingDown = !bGoingUp && pFrame->IsLayoutFrame(); | ||||||
597 | if (bGoingDown) | ||||||
598 | { | ||||||
599 | p = static_cast<const SwLayoutFrame*>(pFrame)->Lower(); | ||||||
600 | bGoingDown = nullptr != p; | ||||||
601 | } | ||||||
602 | if ( !bGoingDown ) | ||||||
603 | { | ||||||
604 | p = pFrame->IsFlyFrame() ? | ||||||
605 | ( bFwd ? static_cast<const SwFlyFrame*>(pFrame)->GetNextLink() : static_cast<const SwFlyFrame*>(pFrame)->GetPrevLink() ) : | ||||||
606 | ( bFwd ? pFrame->GetNext() :pFrame->GetPrev() ); | ||||||
607 | bGoingFwdOrBwd = nullptr != p; | ||||||
608 | if ( !bGoingFwdOrBwd ) | ||||||
609 | { | ||||||
610 | p = pFrame->GetUpper(); | ||||||
611 | bGoingUp = nullptr != p; | ||||||
612 | if ( !bGoingUp ) | ||||||
613 | return nullptr; | ||||||
614 | } | ||||||
615 | } | ||||||
616 | |||||||
617 | bGoingUp = !( bGoingFwdOrBwd || bGoingDown ); | ||||||
618 | assert(p)(static_cast <bool> (p) ? void (0) : __assert_fail ("p" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 618, __extension__ __PRETTY_FUNCTION__)); | ||||||
619 | if (!bFwd && bGoingDown) | ||||||
620 | while ( p->GetNext() ) | ||||||
621 | p = p->GetNext(); | ||||||
622 | |||||||
623 | pFrame = p; | ||||||
624 | } while ( nullptr == (pContentFrame = (pFrame->IsContentFrame() ? const_cast<SwContentFrame*>(static_cast<const SwContentFrame*>(pFrame)) : nullptr) )); | ||||||
625 | |||||||
626 | return pContentFrame; | ||||||
627 | } | ||||||
628 | |||||||
629 | namespace | ||||||
630 | { | ||||||
631 | SwLayoutFrame* FirstLeaf(SwSectionFrame* pLayFrame) | ||||||
632 | { | ||||||
633 | if (pLayFrame->Lower() && pLayFrame->Lower()->IsColumnFrame()) | ||||||
634 | return pLayFrame->GetNextLayoutLeaf(); | ||||||
635 | return pLayFrame; | ||||||
636 | } | ||||||
637 | |||||||
638 | /// Checks if pFrame has a parent that can contain a split section frame. | ||||||
639 | bool CanContainSplitSection(const SwFrame* pFrame) | ||||||
640 | { | ||||||
641 | if (!pFrame->IsInTab()) | ||||||
642 | return true; | ||||||
643 | |||||||
644 | // The frame is in a table, see if the table is in a section. | ||||||
645 | bool bRet = !pFrame->FindTabFrame()->IsInSct(); | ||||||
646 | |||||||
647 | if (bRet) | ||||||
648 | { | ||||||
649 | // Don't try to split if the frame itself is a section frame with | ||||||
650 | // multiple columns. | ||||||
651 | if (pFrame->IsSctFrame()) | ||||||
652 | { | ||||||
653 | const SwFrame* pLower = pFrame->GetLower(); | ||||||
654 | if (pLower && pLower->IsColumnFrame()) | ||||||
655 | bRet = false; | ||||||
656 | } | ||||||
657 | } | ||||||
658 | |||||||
659 | return bRet; | ||||||
660 | } | ||||||
661 | } | ||||||
662 | |||||||
663 | void SwSectionFrame::MoveContentAndDelete( SwSectionFrame* pDel, bool bSave ) | ||||||
664 | { | ||||||
665 | bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrame(); | ||||||
666 | SwFrame* pPrv = pDel->GetPrev(); | ||||||
667 | SwLayoutFrame* pUp = pDel->GetUpper(); | ||||||
668 | // OD 27.03.2003 #i12711# - initialize local pointer variables. | ||||||
669 | SwSectionFrame* pPrvSct = nullptr; | ||||||
670 | SwSectionFrame* pNxtSct = nullptr; | ||||||
671 | SwSectionFormat* pParent = static_cast<SwSectionFormat*>(pDel->GetFormat())->GetParent(); | ||||||
672 | if( pDel->IsInTab() && pParent ) | ||||||
673 | { | ||||||
674 | SwTabFrame *pTab = pDel->FindTabFrame(); | ||||||
675 | // If we are within a table, we can only have broken up sections that | ||||||
676 | // are inside as well, but not a section that contains the whole table. | ||||||
677 | if( pTab->IsInSct() && pParent == pTab->FindSctFrame()->GetFormat() ) | ||||||
678 | pParent = nullptr; | ||||||
679 | } | ||||||
680 | // If our Format has a parent, we have probably broken up another | ||||||
681 | // SectionFrame, which has to be checked. To do so we first acquire the | ||||||
682 | // succeeding and the preceding ContentFrame, let's see if they | ||||||
683 | // lay in the SectionFrames. | ||||||
684 | // OD 27.03.2003 #i12711# - check, if previous and next section belonging | ||||||
685 | // together and can be joined, *not* only if deleted section contains content. | ||||||
686 | if ( pParent ) | ||||||
687 | { | ||||||
688 | SwFrame* pPrvContent = lcl_GetNextContentFrame( pDel, false ); | ||||||
689 | pPrvSct = pPrvContent ? pPrvContent->FindSctFrame() : nullptr; | ||||||
690 | SwFrame* pNxtContent = lcl_GetNextContentFrame( pDel, true ); | ||||||
691 | pNxtSct = pNxtContent ? pNxtContent->FindSctFrame() : nullptr; | ||||||
692 | } | ||||||
693 | else | ||||||
694 | { | ||||||
695 | pParent = nullptr; | ||||||
696 | pPrvSct = pNxtSct = nullptr; | ||||||
697 | } | ||||||
698 | |||||||
699 | // Now the content is put aside and the frame is destroyed | ||||||
700 | SwFrame *pSave = bSave ? ::SaveContent( pDel ) : nullptr; | ||||||
701 | bool bOldFootnote = true; | ||||||
702 | if( pSave && pUp->IsFootnoteFrame() ) | ||||||
703 | { | ||||||
704 | bOldFootnote = static_cast<SwFootnoteFrame*>(pUp)->IsColLocked(); | ||||||
705 | static_cast<SwFootnoteFrame*>(pUp)->ColLock(); | ||||||
706 | } | ||||||
707 | pDel->DelEmpty( true ); | ||||||
708 | SwFrame::DestroyFrame(pDel); | ||||||
709 | if( pParent ) | ||||||
710 | { // Search for the appropriate insert position | ||||||
711 | if( pNxtSct && pNxtSct->GetFormat() == pParent ) | ||||||
712 | { // Here we can insert ourselves at the beginning | ||||||
713 | pUp = FirstLeaf( pNxtSct ); | ||||||
714 | pPrv = nullptr; | ||||||
715 | if( pPrvSct && ( pPrvSct->GetFormat() != pParent ) ) | ||||||
716 | pPrvSct = nullptr; // In order that nothing is merged | ||||||
717 | } | ||||||
718 | else if( pPrvSct && pPrvSct->GetFormat() == pParent ) | ||||||
719 | { // Wonderful, here we can insert ourselves at the end | ||||||
720 | pUp = pPrvSct; | ||||||
721 | if( pUp->Lower() && pUp->Lower()->IsColumnFrame() ) | ||||||
722 | { | ||||||
723 | pUp = static_cast<SwLayoutFrame*>(pUp->GetLastLower()); | ||||||
724 | // The body of the last column | ||||||
725 | pUp = static_cast<SwLayoutFrame*>(pUp->Lower()); | ||||||
726 | } | ||||||
727 | // In order to perform the insertion after the last one | ||||||
728 | pPrv = pUp->GetLastLower(); | ||||||
729 | pPrvSct = nullptr; // Such that nothing is merged | ||||||
730 | } | ||||||
731 | else | ||||||
732 | { | ||||||
733 | if( pSave ) | ||||||
734 | { // Following situations: before and after the section-to-be | ||||||
735 | // deleted there is the section boundary of the enclosing | ||||||
736 | // section, or another (sibling) section connects subsequently, | ||||||
737 | // that derives from the same Parent. | ||||||
738 | // In that case, there's not (yet) a part of our parent available | ||||||
739 | // that can store the content, so we create it here. | ||||||
740 | pPrvSct = new SwSectionFrame( *pParent->GetSection(), pUp ); | ||||||
741 | pPrvSct->InsertBehind( pUp, pPrv ); | ||||||
742 | pPrvSct->Init(); | ||||||
743 | SwRectFnSet aRectFnSet(pUp); | ||||||
744 | aRectFnSet.MakePos( *pPrvSct, pUp, pPrv, true ); | ||||||
745 | pUp = FirstLeaf( pPrvSct ); | ||||||
746 | pPrv = nullptr; | ||||||
747 | } | ||||||
748 | pPrvSct = nullptr; // Such that nothing will be merged | ||||||
749 | } | ||||||
750 | } | ||||||
751 | // The content is going to be inserted... | ||||||
752 | if( pSave ) | ||||||
753 | { | ||||||
754 | lcl_InvalidateInfFlags( pSave, bSize ); | ||||||
755 | ::RestoreContent( pSave, pUp, pPrv ); | ||||||
756 | pUp->FindPageFrame()->InvalidateContent(); | ||||||
757 | if( !bOldFootnote ) | ||||||
758 | static_cast<SwFootnoteFrame*>(pUp)->ColUnlock(); | ||||||
759 | } | ||||||
760 | // Now two parts of the superior section could possibly be merged | ||||||
761 | if( pPrvSct && !pPrvSct->IsJoinLocked() ) | ||||||
762 | { | ||||||
763 | OSL_ENSURE( pNxtSct, "MoveContent: No Merge" )do { if (true && (!(pNxtSct))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "763" ": "), "%s", "MoveContent: No Merge"); } } while ( false); | ||||||
764 | pPrvSct->MergeNext( pNxtSct ); | ||||||
765 | } | ||||||
766 | } | ||||||
767 | |||||||
768 | void SwSectionFrame::MakeAll(vcl::RenderContext* pRenderContext) | ||||||
769 | { | ||||||
770 | if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 ) | ||||||
771 | return; | ||||||
772 | if( !m_pSection ) // Via DelEmpty | ||||||
773 | { | ||||||
774 | #ifdef DBG_UTIL | ||||||
775 | OSL_ENSURE( getRootFrame()->IsInDelList( this ), "SectionFrame without Section" )do { if (true && (!(getRootFrame()->IsInDelList( this )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "775" ": "), "%s", "SectionFrame without Section"); } } while (false); | ||||||
776 | #endif | ||||||
777 | if( !isFrameAreaPositionValid() ) | ||||||
778 | { | ||||||
779 | if( GetUpper() ) | ||||||
780 | { | ||||||
781 | SwRectFnSet aRectFnSet(GetUpper()); | ||||||
782 | aRectFnSet.MakePos( *this, GetUpper(), GetPrev(), false ); | ||||||
783 | } | ||||||
784 | |||||||
785 | if (getFrameArea().Height() == 0) | ||||||
786 | { | ||||||
787 | // SwLayoutFrame::MakeAll() is not called for to-be-deleted | ||||||
788 | // section frames (which would invalidate the position of the | ||||||
789 | // next frame via the SwLayNotify dtor), so call it manually. | ||||||
790 | if (SwFrame* pNext = GetNext()) | ||||||
791 | pNext->InvalidatePos(); | ||||||
792 | } | ||||||
793 | } | ||||||
794 | |||||||
795 | setFrameAreaPositionValid(true); | ||||||
796 | setFrameAreaSizeValid(true); | ||||||
797 | setFramePrintAreaValid(true); | ||||||
798 | return; | ||||||
799 | } | ||||||
800 | LockJoin(); // I don't let myself to be destroyed on the way | ||||||
801 | |||||||
802 | while( GetNext() && GetNext() == GetFollow() ) | ||||||
803 | { | ||||||
804 | const SwFrame* pFoll = GetFollow(); | ||||||
805 | MergeNext( static_cast<SwSectionFrame*>(GetNext()) ); | ||||||
806 | if( pFoll == GetFollow() ) | ||||||
807 | break; | ||||||
808 | } | ||||||
809 | |||||||
810 | // OD 2004-03-15 #116561# - In online layout join the follows, if section | ||||||
811 | // can grow. | ||||||
812 | const SwViewShell *pSh = getRootFrame()->GetCurrShell(); | ||||||
813 | |||||||
814 | // Split sections inside table cells: need to merge all follows of the | ||||||
815 | // section here, as later we won't attempt doing so. | ||||||
816 | bool bCanContainSplitSection = false; | ||||||
817 | if (IsInTab() && GetUpper()) | ||||||
818 | bCanContainSplitSection = CanContainSplitSection(GetUpper()); | ||||||
819 | |||||||
820 | if( pSh && (pSh->GetViewOptions()->getBrowseMode() || bCanContainSplitSection) && | ||||||
821 | ( Grow( LONG_MAX9223372036854775807L, true ) > 0 ) ) | ||||||
822 | { | ||||||
823 | while( GetFollow() ) | ||||||
824 | { | ||||||
825 | const SwFrame* pFoll = GetFollow(); | ||||||
826 | MergeNext( GetFollow() ); | ||||||
827 | if( pFoll == GetFollow() ) | ||||||
828 | break; | ||||||
829 | } | ||||||
830 | } | ||||||
831 | |||||||
832 | // A section with Follow uses all the space until the lower edge of the | ||||||
833 | // Upper. If it moves, its size can grow or decrease... | ||||||
834 | if( !isFrameAreaPositionValid() && ToMaximize( false ) ) | ||||||
835 | { | ||||||
836 | setFrameAreaSizeValid(false); | ||||||
837 | } | ||||||
838 | |||||||
839 | SwLayoutFrame::MakeAll(getRootFrame()->GetCurrShell()->GetOut()); | ||||||
840 | |||||||
841 | if (IsInTab()) | ||||||
842 | { | ||||||
843 | // In case the section is in a table, then calculate the lower right | ||||||
844 | // now. Just setting the valid size flag of the lower to false may not | ||||||
845 | // be enough, as lcl_RecalcRow() can call | ||||||
846 | // SwFrame::ValidateThisAndAllLowers(), and then we don't attempt | ||||||
847 | // calculating the proper position of the lower. | ||||||
848 | SwFrame* pLower = Lower(); | ||||||
849 | if (pLower && !pLower->isFrameAreaPositionValid()) | ||||||
850 | pLower->Calc(pRenderContext); | ||||||
851 | } | ||||||
852 | |||||||
853 | UnlockJoin(); | ||||||
854 | if( m_pSection && IsSuperfluous() ) | ||||||
855 | DelEmpty( false ); | ||||||
856 | } | ||||||
857 | |||||||
858 | bool SwSectionFrame::ShouldBwdMoved( SwLayoutFrame *, bool & ) | ||||||
859 | { | ||||||
860 | OSL_FAIL( "Oops, where is my tinfoil hat?" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "860" ": "), "%s", "Oops, where is my tinfoil hat?"); } } while (false); | ||||||
861 | return false; | ||||||
862 | } | ||||||
863 | |||||||
864 | const SwSectionFormat* SwSectionFrame::GetEndSectFormat_() const | ||||||
865 | { | ||||||
866 | const SwSectionFormat *pFormat = m_pSection->GetFormat(); | ||||||
867 | while( !pFormat->GetEndAtTextEnd().IsAtEnd() ) | ||||||
868 | { | ||||||
869 | if( dynamic_cast< const SwSectionFormat *>( pFormat->GetRegisteredIn()) != nullptr ) | ||||||
870 | pFormat = static_cast<const SwSectionFormat*>(pFormat->GetRegisteredIn()); | ||||||
871 | else | ||||||
872 | return nullptr; | ||||||
873 | } | ||||||
874 | return pFormat; | ||||||
875 | } | ||||||
876 | |||||||
877 | static void lcl_FindContentFrame( SwContentFrame* &rpContentFrame, SwFootnoteFrame* &rpFootnoteFrame, | ||||||
878 | SwFrame* pFrame, bool &rbChkFootnote ) | ||||||
879 | { | ||||||
880 | if( !pFrame ) | ||||||
881 | return; | ||||||
882 | |||||||
883 | while( pFrame->GetNext() ) | ||||||
884 | pFrame = pFrame->GetNext(); | ||||||
885 | while( !rpContentFrame && pFrame ) | ||||||
886 | { | ||||||
887 | if( pFrame->IsContentFrame() ) | ||||||
888 | rpContentFrame = static_cast<SwContentFrame*>(pFrame); | ||||||
889 | else if( pFrame->IsLayoutFrame() ) | ||||||
890 | { | ||||||
891 | if( pFrame->IsFootnoteFrame() ) | ||||||
892 | { | ||||||
893 | if( rbChkFootnote ) | ||||||
894 | { | ||||||
895 | rpFootnoteFrame = static_cast<SwFootnoteFrame*>(pFrame); | ||||||
896 | rbChkFootnote = rpFootnoteFrame->GetAttr()->GetFootnote().IsEndNote(); | ||||||
897 | } | ||||||
898 | } | ||||||
899 | else | ||||||
900 | lcl_FindContentFrame( rpContentFrame, rpFootnoteFrame, | ||||||
901 | static_cast<SwLayoutFrame*>(pFrame)->Lower(), rbChkFootnote ); | ||||||
902 | } | ||||||
903 | pFrame = pFrame->GetPrev(); | ||||||
904 | } | ||||||
905 | } | ||||||
906 | |||||||
907 | SwContentFrame *SwSectionFrame::FindLastContent( SwFindMode nMode ) | ||||||
908 | { | ||||||
909 | SwContentFrame *pRet = nullptr; | ||||||
910 | SwFootnoteFrame *pFootnoteFrame = nullptr; | ||||||
911 | SwSectionFrame *pSect = this; | ||||||
912 | if( nMode != SwFindMode::None ) | ||||||
913 | { | ||||||
914 | const SwSectionFormat *pFormat = IsEndnAtEnd() ? GetEndSectFormat() : | ||||||
915 | m_pSection->GetFormat(); | ||||||
916 | do { | ||||||
917 | while( pSect->HasFollow() ) | ||||||
918 | pSect = pSect->GetFollow(); | ||||||
919 | SwFrame* pTmp = pSect->FindNext(); | ||||||
920 | while( pTmp && pTmp->IsSctFrame() && | ||||||
921 | !static_cast<SwSectionFrame*>(pTmp)->GetSection() ) | ||||||
922 | pTmp = pTmp->FindNext(); | ||||||
923 | if( pTmp && pTmp->IsSctFrame() && | ||||||
924 | static_cast<SwSectionFrame*>(pTmp)->IsDescendantFrom( pFormat ) ) | ||||||
925 | pSect = static_cast<SwSectionFrame*>(pTmp); | ||||||
926 | else | ||||||
927 | break; | ||||||
928 | } while( true ); | ||||||
929 | } | ||||||
930 | bool bFootnoteFound = nMode == SwFindMode::EndNote; | ||||||
931 | do | ||||||
932 | { | ||||||
933 | lcl_FindContentFrame( pRet, pFootnoteFrame, pSect->Lower(), bFootnoteFound ); | ||||||
934 | if( pRet || !pSect->IsFollow() || nMode == SwFindMode::None || | ||||||
935 | ( SwFindMode::MyLast == nMode && this == pSect ) ) | ||||||
936 | break; | ||||||
937 | pSect = pSect->FindMaster(); | ||||||
938 | } while( pSect ); | ||||||
939 | if( ( nMode == SwFindMode::EndNote ) && pFootnoteFrame ) | ||||||
940 | pRet = pFootnoteFrame->ContainsContent(); | ||||||
941 | return pRet; | ||||||
942 | } | ||||||
943 | |||||||
944 | bool SwSectionFrame::CalcMinDiff( SwTwips& rMinDiff ) const | ||||||
945 | { | ||||||
946 | if( ToMaximize( true ) ) | ||||||
947 | { | ||||||
948 | SwRectFnSet aRectFnSet(this); | ||||||
949 | rMinDiff = aRectFnSet.GetPrtBottom(*GetUpper()); | ||||||
950 | rMinDiff = aRectFnSet.BottomDist( getFrameArea(), rMinDiff ); | ||||||
951 | return true; | ||||||
952 | } | ||||||
953 | return false; | ||||||
954 | } | ||||||
955 | |||||||
956 | /** | ||||||
957 | * CollectEndnotes looks for endnotes in the sectionfrm and his follows, | ||||||
958 | * the endnotes will cut off the layout and put into the array. | ||||||
959 | * If the first endnote is not a master-SwFootnoteFrame, the whole sectionfrm | ||||||
960 | * contains only endnotes and it is not necessary to collect them. | ||||||
961 | */ | ||||||
962 | static SwFootnoteFrame* lcl_FindEndnote( SwSectionFrame* &rpSect, bool &rbEmpty, | ||||||
963 | SwLayouter *pLayouter ) | ||||||
964 | { | ||||||
965 | // if rEmpty is set, the rpSect is already searched | ||||||
966 | SwSectionFrame* pSect = rbEmpty ? rpSect->GetFollow() : rpSect; | ||||||
967 | while( pSect ) | ||||||
968 | { | ||||||
969 | OSL_ENSURE( (pSect->Lower() && pSect->Lower()->IsColumnFrame()) || pSect->GetUpper()->IsFootnoteFrame(),do { if (true && (!((pSect->Lower() && pSect ->Lower()->IsColumnFrame()) || pSect->GetUpper()-> IsFootnoteFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "970" ": "), "%s", "InsertEndnotes: Where's my column?") ; } } while (false) | ||||||
970 | "InsertEndnotes: Where's my column?" )do { if (true && (!((pSect->Lower() && pSect ->Lower()->IsColumnFrame()) || pSect->GetUpper()-> IsFootnoteFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "970" ": "), "%s", "InsertEndnotes: Where's my column?") ; } } while (false); | ||||||
971 | |||||||
972 | // i73332: Columned section in endnote | ||||||
973 | SwColumnFrame* pCol = nullptr; | ||||||
974 | if(pSect->Lower() && pSect->Lower()->IsColumnFrame()) | ||||||
975 | pCol = static_cast<SwColumnFrame*>(pSect->Lower()); | ||||||
976 | |||||||
977 | while( pCol ) // check all columns | ||||||
978 | { | ||||||
979 | SwFootnoteContFrame* pFootnoteCont = pCol->FindFootnoteCont(); | ||||||
980 | if( pFootnoteCont ) | ||||||
981 | { | ||||||
982 | SwFootnoteFrame* pRet = static_cast<SwFootnoteFrame*>(pFootnoteCont->Lower()); | ||||||
983 | while( pRet ) // look for endnotes | ||||||
984 | { | ||||||
985 | /* CollectEndNode can destroy pRet so we need to get the | ||||||
986 | next early | ||||||
987 | */ | ||||||
988 | SwFootnoteFrame* pRetNext = static_cast<SwFootnoteFrame*>(pRet->GetNext()); | ||||||
989 | if( pRet->GetAttr()->GetFootnote().IsEndNote() ) | ||||||
990 | { | ||||||
991 | if( pRet->GetMaster() ) | ||||||
992 | { | ||||||
993 | if( pLayouter ) | ||||||
994 | pLayouter->CollectEndnote( pRet ); | ||||||
995 | else | ||||||
996 | return nullptr; | ||||||
997 | } | ||||||
998 | else | ||||||
999 | return pRet; // Found | ||||||
1000 | } | ||||||
1001 | pRet = pRetNext; | ||||||
1002 | } | ||||||
1003 | } | ||||||
1004 | pCol = static_cast<SwColumnFrame*>(pCol->GetNext()); | ||||||
1005 | } | ||||||
1006 | rpSect = pSect; | ||||||
1007 | pSect = pLayouter ? pSect->GetFollow() : nullptr; | ||||||
1008 | rbEmpty = true; | ||||||
1009 | } | ||||||
1010 | return nullptr; | ||||||
1011 | } | ||||||
1012 | |||||||
1013 | static void lcl_ColumnRefresh( SwSectionFrame* pSect, bool bFollow ) | ||||||
1014 | { | ||||||
1015 | vcl::RenderContext* pRenderContext = pSect->getRootFrame()->GetCurrShell()->GetOut(); | ||||||
1016 | while( pSect ) | ||||||
1017 | { | ||||||
1018 | bool bOldLock = pSect->IsColLocked(); | ||||||
1019 | pSect->ColLock(); | ||||||
1020 | if( pSect->Lower() && pSect->Lower()->IsColumnFrame() ) | ||||||
1021 | { | ||||||
1022 | SwColumnFrame *pCol = static_cast<SwColumnFrame*>(pSect->Lower()); | ||||||
1023 | do | ||||||
1024 | { pCol->InvalidateSize_(); | ||||||
1025 | pCol->InvalidatePos_(); | ||||||
1026 | static_cast<SwLayoutFrame*>(pCol)->Lower()->InvalidateSize_(); | ||||||
1027 | pCol->Calc(pRenderContext); // calculation of column and | ||||||
1028 | static_cast<SwLayoutFrame*>(pCol)->Lower()->Calc(pRenderContext); // body | ||||||
1029 | pCol = static_cast<SwColumnFrame*>(pCol->GetNext()); | ||||||
1030 | } while ( pCol ); | ||||||
1031 | } | ||||||
1032 | if( !bOldLock ) | ||||||
1033 | pSect->ColUnlock(); | ||||||
1034 | if( bFollow ) | ||||||
1035 | pSect = pSect->GetFollow(); | ||||||
1036 | else | ||||||
1037 | pSect = nullptr; | ||||||
1038 | } | ||||||
1039 | } | ||||||
1040 | |||||||
1041 | void SwSectionFrame::CollectEndnotes( SwLayouter* pLayouter ) | ||||||
1042 | { | ||||||
1043 | OSL_ENSURE( IsColLocked(), "CollectEndnotes: You love the risk?" )do { if (true && (!(IsColLocked()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1043" ": "), "%s", "CollectEndnotes: You love the risk?" ); } } while (false); | ||||||
1044 | // i73332: Section in footnode does not have columns! | ||||||
1045 | OSL_ENSURE( (Lower() && Lower()->IsColumnFrame()) || GetUpper()->IsFootnoteFrame(), "Where's my column?" )do { if (true && (!((Lower() && Lower()->IsColumnFrame ()) || GetUpper()->IsFootnoteFrame()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1045" ": "), "%s", "Where's my column?"); } } while (false ); | ||||||
1046 | |||||||
1047 | SwSectionFrame* pSect = this; | ||||||
1048 | SwFootnoteFrame* pFootnote; | ||||||
1049 | bool bEmpty = false; | ||||||
1050 | // pSect is the last sectionfrm without endnotes or the this-pointer | ||||||
1051 | // the first sectionfrm with endnotes may be destroyed, when the endnotes | ||||||
1052 | // is cutted | ||||||
1053 | while( nullptr != (pFootnote = lcl_FindEndnote( pSect, bEmpty, pLayouter )) ) | ||||||
1054 | pLayouter->CollectEndnote( pFootnote ); | ||||||
1055 | if( pLayouter->HasEndnotes() ) | ||||||
1056 | lcl_ColumnRefresh( this, true ); | ||||||
1057 | } | ||||||
1058 | |||||||
1059 | /** Fits the size to the surroundings. | ||||||
1060 | |* | ||||||
1061 | |* Those that have a Follow or foot notes, have to extend until | ||||||
1062 | |* the lower edge of a upper (bMaximize) | ||||||
1063 | |* They must not extend above the Upper, as the case may be one can | ||||||
1064 | |* try to grow its upper (bGrow) | ||||||
1065 | |* If the size had to be changed, the content is calculated. | ||||||
1066 | |* | ||||||
1067 | |* @note: perform calculation of content, only if height has changed (OD 18.09.2002 #100522#) | ||||||
1068 | |*/ | ||||||
1069 | void SwSectionFrame::CheckClipping( bool bGrow, bool bMaximize ) | ||||||
1070 | { | ||||||
1071 | SwRectFnSet aRectFnSet(this); | ||||||
1072 | long nDiff; | ||||||
1073 | SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper()); | ||||||
1074 | if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrame() || | ||||||
1075 | !FindFlyFrame()->IsLocked() ) ) | ||||||
1076 | { | ||||||
1077 | nDiff = -aRectFnSet.BottomDist( getFrameArea(), nDeadLine ); | ||||||
1078 | if( !bMaximize ) | ||||||
1079 | nDiff += Undersize(); | ||||||
1080 | if( nDiff > 0 ) | ||||||
1081 | { | ||||||
1082 | long nAdd = GetUpper()->Grow( nDiff ); | ||||||
1083 | if( aRectFnSet.IsVert() ) | ||||||
1084 | nDeadLine -= nAdd; | ||||||
1085 | else | ||||||
1086 | nDeadLine += nAdd; | ||||||
1087 | } | ||||||
1088 | } | ||||||
1089 | nDiff = -aRectFnSet.BottomDist( getFrameArea(), nDeadLine ); | ||||||
1090 | SetUndersized( !bMaximize && nDiff >= 0 ); | ||||||
1091 | const bool bCalc = ( IsUndersized() || bMaximize ) && | ||||||
1092 | ( nDiff || | ||||||
1093 | aRectFnSet.GetTop(getFramePrintArea()) > aRectFnSet.GetHeight(getFrameArea()) ); | ||||||
1094 | // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate | ||||||
1095 | // that a calculation has to be done beside the value of <bCalc>. | ||||||
1096 | bool bExtraCalc = false; | ||||||
1097 | if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFootnote() ) | ||||||
1098 | { | ||||||
1099 | SwSectionFrame *pSect = this; | ||||||
1100 | bool bEmpty = false; | ||||||
1101 | SwLayoutFrame* pFootnote = IsEndnAtEnd() ? | ||||||
1102 | lcl_FindEndnote( pSect, bEmpty, nullptr ) : nullptr; | ||||||
1103 | if( pFootnote ) | ||||||
1104 | { | ||||||
1105 | pFootnote = pFootnote->FindFootnoteBossFrame(); | ||||||
1106 | SwFrame* pTmp = FindLastContent( SwFindMode::LastCnt ); | ||||||
1107 | // OD 08.11.2002 #104840# - use <SwLayoutFrame::IsBefore(..)> | ||||||
1108 | if ( pTmp && pFootnote->IsBefore( pTmp->FindFootnoteBossFrame() ) ) | ||||||
1109 | bExtraCalc = true; | ||||||
1110 | } | ||||||
1111 | else if( GetFollow() && !GetFollow()->ContainsAny() ) | ||||||
1112 | bExtraCalc = true; | ||||||
1113 | } | ||||||
1114 | if ( !(bCalc || bExtraCalc) ) | ||||||
1115 | return; | ||||||
1116 | |||||||
1117 | nDiff = aRectFnSet.YDiff( nDeadLine, aRectFnSet.GetTop(getFrameArea()) ); | ||||||
1118 | if( nDiff < 0 ) | ||||||
1119 | nDeadLine = aRectFnSet.GetTop(getFrameArea()); | ||||||
1120 | const Size aOldSz( getFramePrintArea().SSize() ); | ||||||
1121 | long nTop = aRectFnSet.GetTopMargin(*this); | ||||||
1122 | |||||||
1123 | { | ||||||
1124 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
1125 | aRectFnSet.SetBottom( aFrm, nDeadLine ); | ||||||
1126 | } | ||||||
1127 | |||||||
1128 | nDiff = aRectFnSet.GetHeight(getFrameArea()); | ||||||
1129 | if( nTop > nDiff ) | ||||||
1130 | nTop = nDiff; | ||||||
1131 | aRectFnSet.SetYMargins( *this, nTop, 0 ); | ||||||
1132 | |||||||
1133 | // OD 18.09.2002 #100522# | ||||||
1134 | // Determine, if height has changed. | ||||||
1135 | // Note: In vertical layout the height equals the width value. | ||||||
1136 | bool bHeightChanged = aRectFnSet.IsVert() ? | ||||||
1137 | (aOldSz.Width() != getFramePrintArea().Width()) : | ||||||
1138 | (aOldSz.Height() != getFramePrintArea().Height()); | ||||||
1139 | // Last but not least we have changed the height again, thus the inner | ||||||
1140 | // layout (columns) is calculated and the content as well. | ||||||
1141 | // OD 18.09.2002 #100522# | ||||||
1142 | // calculate content, only if height has changed. | ||||||
1143 | // OD 03.11.2003 #i19737# - restriction of content calculation too strong. | ||||||
1144 | // If an endnote has an incorrect position or a follow section contains | ||||||
1145 | // no content except footnotes/endnotes, the content has also been calculated. | ||||||
1146 | if ( !(( bHeightChanged || bExtraCalc ) && Lower()) ) | ||||||
1147 | return; | ||||||
1148 | |||||||
1149 | if( Lower()->IsColumnFrame() ) | ||||||
1150 | { | ||||||
1151 | lcl_ColumnRefresh( this, false ); | ||||||
1152 | ::CalcContent( this ); | ||||||
1153 | } | ||||||
1154 | else | ||||||
1155 | { | ||||||
1156 | ChgLowersProp( aOldSz ); | ||||||
1157 | if( !bMaximize && !IsContentLocked() ) | ||||||
1158 | ::CalcContent( this ); | ||||||
1159 | } | ||||||
1160 | } | ||||||
1161 | |||||||
1162 | void SwSectionFrame::SimpleFormat() | ||||||
1163 | { | ||||||
1164 | if ( IsJoinLocked() || IsColLocked() ) | ||||||
1165 | return; | ||||||
1166 | LockJoin(); | ||||||
1167 | SwRectFnSet aRectFnSet(this); | ||||||
1168 | if( GetPrev() || GetUpper() ) | ||||||
1169 | { | ||||||
1170 | // assure notifications on position changes. | ||||||
1171 | const SwLayNotify aNotify( this ); | ||||||
1172 | aRectFnSet.MakePos( *this, GetUpper(), GetPrev(), false ); | ||||||
1173 | setFrameAreaPositionValid(true); | ||||||
1174 | } | ||||||
1175 | SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper()); | ||||||
1176 | // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in | ||||||
1177 | // order to get calculated lowers, not only if there space left in its upper. | ||||||
1178 | if( aRectFnSet.BottomDist( getFrameArea(), nDeadLine ) >= 0 ) | ||||||
1179 | { | ||||||
1180 | { | ||||||
1181 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
1182 | aRectFnSet.SetBottom( aFrm, nDeadLine ); | ||||||
1183 | } | ||||||
1184 | |||||||
1185 | long nHeight = aRectFnSet.GetHeight(getFrameArea()); | ||||||
1186 | long nTop = CalcUpperSpace(); | ||||||
1187 | if( nTop > nHeight ) | ||||||
1188 | nTop = nHeight; | ||||||
1189 | aRectFnSet.SetYMargins( *this, nTop, 0 ); | ||||||
1190 | } | ||||||
1191 | lcl_ColumnRefresh( this, false ); | ||||||
1192 | UnlockJoin(); | ||||||
1193 | } | ||||||
1194 | |||||||
1195 | namespace { | ||||||
1196 | |||||||
1197 | // #i40147# - helper class to perform extra section format | ||||||
1198 | // to position anchored objects and to keep the position of whose objects locked. | ||||||
1199 | class ExtraFormatToPositionObjs | ||||||
1200 | { | ||||||
1201 | private: | ||||||
1202 | SwSectionFrame* mpSectFrame; | ||||||
1203 | bool mbExtraFormatPerformed; | ||||||
1204 | |||||||
1205 | public: | ||||||
1206 | explicit ExtraFormatToPositionObjs( SwSectionFrame& _rSectFrame) | ||||||
1207 | : mpSectFrame( &_rSectFrame ), | ||||||
1208 | mbExtraFormatPerformed( false ) | ||||||
1209 | {} | ||||||
1210 | |||||||
1211 | ~ExtraFormatToPositionObjs() | ||||||
1212 | { | ||||||
1213 | if ( !mbExtraFormatPerformed ) | ||||||
1214 | return; | ||||||
1215 | |||||||
1216 | // release keep locked position of lower floating screen objects | ||||||
1217 | SwPageFrame* pPageFrame = mpSectFrame->FindPageFrame(); | ||||||
1218 | SwSortedObjs* pObjs = pPageFrame ? pPageFrame->GetSortedObjs() : nullptr; | ||||||
1219 | if ( pObjs ) | ||||||
1220 | { | ||||||
1221 | for (SwAnchoredObject* pAnchoredObj : *pObjs) | ||||||
1222 | { | ||||||
1223 | if ( mpSectFrame->IsAnLower( pAnchoredObj->GetAnchorFrame() ) ) | ||||||
1224 | { | ||||||
1225 | pAnchoredObj->SetKeepPosLocked( false ); | ||||||
1226 | } | ||||||
1227 | } | ||||||
1228 | } | ||||||
1229 | } | ||||||
1230 | |||||||
1231 | // #i81555# | ||||||
1232 | void InitObjs( SwFrame& rFrame ) | ||||||
1233 | { | ||||||
1234 | SwSortedObjs* pObjs = rFrame.GetDrawObjs(); | ||||||
1235 | if ( pObjs ) | ||||||
1236 | { | ||||||
1237 | for (SwAnchoredObject* pAnchoredObj : *pObjs) | ||||||
1238 | { | ||||||
1239 | pAnchoredObj->UnlockPosition(); | ||||||
1240 | pAnchoredObj->SetClearedEnvironment( false ); | ||||||
1241 | } | ||||||
1242 | } | ||||||
1243 | SwLayoutFrame* pLayoutFrame = dynamic_cast<SwLayoutFrame*>(&rFrame); | ||||||
1244 | if ( pLayoutFrame != nullptr ) | ||||||
1245 | { | ||||||
1246 | SwFrame* pLowerFrame = pLayoutFrame->GetLower(); | ||||||
1247 | while ( pLowerFrame != nullptr ) | ||||||
1248 | { | ||||||
1249 | InitObjs( *pLowerFrame ); | ||||||
1250 | |||||||
1251 | pLowerFrame = pLowerFrame->GetNext(); | ||||||
1252 | } | ||||||
1253 | } | ||||||
1254 | } | ||||||
1255 | |||||||
1256 | void FormatSectionToPositionObjs() | ||||||
1257 | { | ||||||
1258 | vcl::RenderContext* pRenderContext = mpSectFrame->getRootFrame()->GetCurrShell()->GetOut(); | ||||||
1259 | // perform extra format for multi-columned section. | ||||||
1260 | if ( !(mpSectFrame->Lower() && mpSectFrame->Lower()->IsColumnFrame() && | ||||||
1261 | mpSectFrame->Lower()->GetNext()) ) | ||||||
1262 | return; | ||||||
1263 | |||||||
1264 | // grow section till bottom of printing area of upper frame | ||||||
1265 | SwRectFnSet aRectFnSet(mpSectFrame); | ||||||
1266 | SwTwips nTopMargin = aRectFnSet.GetTopMargin(*mpSectFrame); | ||||||
1267 | Size aOldSectPrtSize( mpSectFrame->getFramePrintArea().SSize() ); | ||||||
1268 | SwTwips nDiff = aRectFnSet.BottomDist( mpSectFrame->getFrameArea(), aRectFnSet.GetPrtBottom(*mpSectFrame->GetUpper()) ); | ||||||
1269 | |||||||
1270 | { | ||||||
1271 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*mpSectFrame); | ||||||
1272 | aRectFnSet.AddBottom( aFrm, nDiff ); | ||||||
1273 | } | ||||||
1274 | |||||||
1275 | aRectFnSet.SetYMargins( *mpSectFrame, nTopMargin, 0 ); | ||||||
1276 | // #i59789# | ||||||
1277 | // suppress formatting, if printing area of section is too narrow | ||||||
1278 | if ( aRectFnSet.GetHeight(mpSectFrame->getFramePrintArea()) <= 0 ) | ||||||
1279 | { | ||||||
1280 | return; | ||||||
1281 | } | ||||||
1282 | mpSectFrame->ChgLowersProp( aOldSectPrtSize ); | ||||||
1283 | |||||||
1284 | // format column frames and its body and footnote container | ||||||
1285 | SwColumnFrame* pColFrame = static_cast<SwColumnFrame*>(mpSectFrame->Lower()); | ||||||
1286 | while ( pColFrame ) | ||||||
1287 | { | ||||||
1288 | pColFrame->Calc(pRenderContext); | ||||||
1289 | pColFrame->Lower()->Calc(pRenderContext); | ||||||
1290 | if ( pColFrame->Lower()->GetNext() ) | ||||||
1291 | { | ||||||
1292 | pColFrame->Lower()->GetNext()->Calc(pRenderContext); | ||||||
1293 | } | ||||||
1294 | |||||||
1295 | pColFrame = static_cast<SwColumnFrame*>(pColFrame->GetNext()); | ||||||
1296 | } | ||||||
1297 | |||||||
1298 | // unlock position of lower floating screen objects for the extra format | ||||||
1299 | // #i81555# | ||||||
1300 | // Section frame can already have changed the page and its content | ||||||
1301 | // can still be on the former page. | ||||||
1302 | // Thus, initialize objects via lower-relationship | ||||||
1303 | InitObjs( *mpSectFrame ); | ||||||
1304 | |||||||
1305 | // format content - first with collecting its foot-/endnotes before content | ||||||
1306 | // format, second without collecting its foot-/endnotes. | ||||||
1307 | ::CalcContent( mpSectFrame ); | ||||||
1308 | ::CalcContent( mpSectFrame, true ); | ||||||
1309 | |||||||
1310 | // keep locked position of lower floating screen objects | ||||||
1311 | SwPageFrame* pPageFrame = mpSectFrame->FindPageFrame(); | ||||||
1312 | SwSortedObjs* pObjs = pPageFrame ? pPageFrame->GetSortedObjs() : nullptr; | ||||||
1313 | if ( pObjs ) | ||||||
1314 | { | ||||||
1315 | for (SwAnchoredObject* pAnchoredObj : *pObjs) | ||||||
1316 | { | ||||||
1317 | if ( mpSectFrame->IsAnLower( pAnchoredObj->GetAnchorFrame() ) ) | ||||||
1318 | { | ||||||
1319 | pAnchoredObj->SetKeepPosLocked( true ); | ||||||
1320 | } | ||||||
1321 | } | ||||||
1322 | } | ||||||
1323 | |||||||
1324 | mbExtraFormatPerformed = true; | ||||||
1325 | |||||||
1326 | } | ||||||
1327 | }; | ||||||
1328 | |||||||
1329 | } | ||||||
1330 | |||||||
1331 | /// "formats" the frame; Frame and PrtArea | ||||||
1332 | void SwSectionFrame::Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttr ) | ||||||
1333 | { | ||||||
1334 | if( !m_pSection ) // via DelEmpty | ||||||
1335 | { | ||||||
1336 | #ifdef DBG_UTIL | ||||||
1337 | OSL_ENSURE( getRootFrame()->IsInDelList( this ), "SectionFrame without Section" )do { if (true && (!(getRootFrame()->IsInDelList( this )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1337" ": "), "%s", "SectionFrame without Section"); } } while (false); | ||||||
1338 | #endif | ||||||
1339 | setFrameAreaPositionValid(true); | ||||||
1340 | setFrameAreaSizeValid(true); | ||||||
1341 | setFramePrintAreaValid(true); | ||||||
1342 | return; | ||||||
1343 | } | ||||||
1344 | |||||||
1345 | SwRectFnSet aRectFnSet(this); | ||||||
1346 | |||||||
1347 | if ( !isFramePrintAreaValid() ) | ||||||
1348 | { | ||||||
1349 | PROTOCOL( this, PROT::PrintArea, DbgAction::NONE, nullptr ) | ||||||
1350 | setFramePrintAreaValid(true); | ||||||
1351 | SwTwips nUpper = CalcUpperSpace(); | ||||||
1352 | |||||||
1353 | // #109700# LRSpace for sections | ||||||
1354 | const SvxLRSpaceItem& rLRSpace = GetFormat()->GetLRSpace(); | ||||||
1355 | aRectFnSet.SetXMargins( *this, rLRSpace.GetLeft(), rLRSpace.GetRight() ); | ||||||
1356 | |||||||
1357 | if( nUpper != aRectFnSet.GetTopMargin(*this) ) | ||||||
1358 | { | ||||||
1359 | setFrameAreaSizeValid(false); | ||||||
1360 | SwFrame* pOwn = ContainsAny(); | ||||||
1361 | if( pOwn ) | ||||||
1362 | pOwn->InvalidatePos_(); | ||||||
1363 | } | ||||||
1364 | aRectFnSet.SetYMargins( *this, nUpper, 0 ); | ||||||
1365 | } | ||||||
1366 | |||||||
1367 | if ( isFrameAreaSizeValid() ) | ||||||
1368 | return; | ||||||
1369 | |||||||
1370 | PROTOCOL_ENTER( this, PROT::Size, DbgAction::NONE, nullptr ) | ||||||
1371 | const long nOldHeight = aRectFnSet.GetHeight(getFrameArea()); | ||||||
1372 | bool bOldLock = IsColLocked(); | ||||||
1373 | ColLock(); | ||||||
1374 | |||||||
1375 | setFrameAreaSizeValid(true); | ||||||
1376 | |||||||
1377 | // The size is only determined by the content, if the SectFrame does not have a | ||||||
1378 | // Follow. Otherwise it fills (occupies) the Upper down to the lower edge. | ||||||
1379 | // It is not responsible for the text flow, but the content is. | ||||||
1380 | bool bMaximize = ToMaximize( false ); | ||||||
1381 | |||||||
1382 | // OD 2004-05-17 #i28701# - If the wrapping style has to be considered | ||||||
1383 | // on object positioning, an extra formatting has to be performed | ||||||
1384 | // to determine the correct positions the floating screen objects. | ||||||
1385 | // #i40147# | ||||||
1386 | // use new helper class <ExtraFormatToPositionObjs>. | ||||||
1387 | // This class additionally keep the locked position of the objects | ||||||
1388 | // and releases this position lock keeping on destruction. | ||||||
1389 | ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this ); | ||||||
1390 | if ( !bMaximize && | ||||||
1391 | GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) && | ||||||
1392 | !GetFormat()->GetBalancedColumns().GetValue() ) | ||||||
1393 | { | ||||||
1394 | aExtraFormatToPosObjs.FormatSectionToPositionObjs(); | ||||||
1395 | } | ||||||
1396 | |||||||
1397 | // Column widths have to be adjusted before calling CheckClipping. | ||||||
1398 | // CheckClipping can cause the formatting of the lower frames | ||||||
1399 | // which still have a width of 0. | ||||||
1400 | const bool bHasColumns = Lower() && Lower()->IsColumnFrame(); | ||||||
1401 | if ( bHasColumns
| ||||||
1402 | AdjustColumns( nullptr, false ); | ||||||
1403 | |||||||
1404 | if( GetUpper() ) | ||||||
1405 | { | ||||||
1406 | const long nWidth = aRectFnSet.GetWidth(GetUpper()->getFramePrintArea()); | ||||||
1407 | |||||||
1408 | { | ||||||
1409 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
1410 | aRectFnSet.SetWidth( aFrm, nWidth ); | ||||||
1411 | } | ||||||
1412 | |||||||
1413 | // #109700# LRSpace for sections | ||||||
1414 | { | ||||||
1415 | const SvxLRSpaceItem& rLRSpace = GetFormat()->GetLRSpace(); | ||||||
1416 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | ||||||
1417 | aRectFnSet.SetWidth( aPrt, nWidth - rLRSpace.GetLeft() - rLRSpace.GetRight() ); | ||||||
1418 | } | ||||||
1419 | |||||||
1420 | // OD 15.10.2002 #103517# - allow grow in online layout | ||||||
1421 | // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling | ||||||
1422 | // method <CheckClipping(..)>. | ||||||
1423 | const SwViewShell *pSh = getRootFrame()->GetCurrShell(); | ||||||
1424 | CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize ); | ||||||
1425 | bMaximize = ToMaximize( false ); | ||||||
1426 | setFrameAreaSizeValid(true); | ||||||
1427 | } | ||||||
1428 | |||||||
1429 | // Check the width of the columns and adjust if necessary | ||||||
1430 | if ( bHasColumns
| ||||||
1431 | static_cast<SwColumnFrame*>(Lower())->Lower()->Calc(pRenderContext); | ||||||
1432 | |||||||
1433 | if ( !bMaximize
| ||||||
1434 | { | ||||||
1435 | SwTwips nRemaining = aRectFnSet.GetTopMargin(*this); | ||||||
1436 | SwFrame *pFrame = m_pLower; | ||||||
1437 | if( pFrame ) | ||||||
1438 | { | ||||||
1439 | if( pFrame->IsColumnFrame() && pFrame->GetNext() ) | ||||||
1440 | { | ||||||
1441 | // #i61435# | ||||||
1442 | // suppress formatting, if upper frame has height <= 0 | ||||||
1443 | if ( aRectFnSet.GetHeight(GetUpper()->getFrameArea()) > 0 ) | ||||||
1444 | { | ||||||
1445 | FormatWidthCols( *pAttr, nRemaining, MINLAY23 ); | ||||||
| |||||||
1446 | } | ||||||
1447 | // #126020# - adjust check for empty section | ||||||
1448 | // #130797# - correct fix #126020# | ||||||
1449 | while( HasFollow() && !GetFollow()->ContainsContent() && | ||||||
1450 | !GetFollow()->ContainsAny( true ) ) | ||||||
1451 | { | ||||||
1452 | SwFrame* pOld = GetFollow(); | ||||||
1453 | GetFollow()->DelEmpty( false ); | ||||||
1454 | if( pOld == GetFollow() ) | ||||||
1455 | break; | ||||||
1456 | } | ||||||
1457 | bMaximize = ToMaximize( false ); | ||||||
1458 | nRemaining += aRectFnSet.GetHeight(pFrame->getFrameArea()); | ||||||
1459 | } | ||||||
1460 | else | ||||||
1461 | { | ||||||
1462 | if( pFrame->IsColumnFrame() ) | ||||||
1463 | { | ||||||
1464 | pFrame->Calc(pRenderContext); | ||||||
1465 | pFrame = static_cast<SwColumnFrame*>(pFrame)->Lower(); | ||||||
1466 | pFrame->Calc(pRenderContext); | ||||||
1467 | pFrame = static_cast<SwLayoutFrame*>(pFrame)->Lower(); | ||||||
1468 | CalcFootnoteContent(); | ||||||
1469 | } | ||||||
1470 | // If we are in a columned frame which calls a CalcContent | ||||||
1471 | // in the FormatWidthCols, the content might need calculating | ||||||
1472 | if( pFrame && !pFrame->isFrameAreaDefinitionValid() && IsInFly() && | ||||||
1473 | FindFlyFrame()->IsColLocked() ) | ||||||
1474 | ::CalcContent( this ); | ||||||
1475 | nRemaining += InnerHeight(); | ||||||
1476 | bMaximize = HasFollow(); | ||||||
1477 | } | ||||||
1478 | } | ||||||
1479 | |||||||
1480 | SwTwips nDiff = aRectFnSet.GetHeight(getFrameArea()) - nRemaining; | ||||||
1481 | if( nDiff < 0) | ||||||
1482 | { | ||||||
1483 | SwTwips nDeadLine = aRectFnSet.GetPrtBottom(*GetUpper()); | ||||||
1484 | { | ||||||
1485 | long nBottom = aRectFnSet.GetBottom(getFrameArea()); | ||||||
1486 | nBottom = aRectFnSet.YInc( nBottom, -nDiff ); | ||||||
1487 | long nTmpDiff = aRectFnSet.YDiff( nBottom, nDeadLine ); | ||||||
1488 | if( nTmpDiff > 0 ) | ||||||
1489 | { | ||||||
1490 | nTmpDiff = GetUpper()->Grow( nTmpDiff, true ); | ||||||
1491 | nDeadLine = aRectFnSet.YInc( nDeadLine, nTmpDiff ); | ||||||
1492 | nTmpDiff = aRectFnSet.YDiff( nBottom, nDeadLine ); | ||||||
1493 | if( nTmpDiff > 0 ) | ||||||
1494 | nDiff += nTmpDiff; | ||||||
1495 | if( nDiff > 0 ) | ||||||
1496 | nDiff = 0; | ||||||
1497 | } | ||||||
1498 | } | ||||||
1499 | } | ||||||
1500 | if( nDiff ) | ||||||
1501 | { | ||||||
1502 | long nTmp = nRemaining - aRectFnSet.GetHeight(getFrameArea()); | ||||||
1503 | long nTop = aRectFnSet.GetTopMargin(*this); | ||||||
1504 | |||||||
1505 | { | ||||||
1506 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
1507 | aRectFnSet.AddBottom( aFrm, nTmp ); | ||||||
1508 | } | ||||||
1509 | |||||||
1510 | aRectFnSet.SetYMargins( *this, nTop, 0 ); | ||||||
1511 | InvalidateNextPos(); | ||||||
1512 | |||||||
1513 | if (m_pLower && (!m_pLower->IsColumnFrame() || !m_pLower->GetNext())) | ||||||
1514 | { | ||||||
1515 | // If a single-column section just created the space that | ||||||
1516 | // was requested by the "undersized" paragraphs, then they | ||||||
1517 | // have to be invalidated and calculated, so they fully cover it | ||||||
1518 | pFrame = m_pLower; | ||||||
1519 | if( pFrame->IsColumnFrame() ) | ||||||
1520 | { | ||||||
1521 | pFrame->InvalidateSize_(); | ||||||
1522 | pFrame->InvalidatePos_(); | ||||||
1523 | pFrame->Calc(pRenderContext); | ||||||
1524 | pFrame = static_cast<SwColumnFrame*>(pFrame)->Lower(); | ||||||
1525 | pFrame->Calc(pRenderContext); | ||||||
1526 | pFrame = static_cast<SwLayoutFrame*>(pFrame)->Lower(); | ||||||
1527 | CalcFootnoteContent(); | ||||||
1528 | } | ||||||
1529 | bool bUnderSz = false; | ||||||
1530 | while( pFrame ) | ||||||
1531 | { | ||||||
1532 | if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() ) | ||||||
1533 | { | ||||||
1534 | pFrame->Prepare( PrepareHint::AdjustSizeWithoutFormatting ); | ||||||
1535 | bUnderSz = true; | ||||||
1536 | } | ||||||
1537 | pFrame = pFrame->GetNext(); | ||||||
1538 | } | ||||||
1539 | if( bUnderSz && !IsContentLocked() ) | ||||||
1540 | ::CalcContent( this ); | ||||||
1541 | } | ||||||
1542 | } | ||||||
1543 | } | ||||||
1544 | |||||||
1545 | // Do not exceed the lower edge of the Upper. | ||||||
1546 | // Do not extend below the lower edge with Sections with Follows | ||||||
1547 | if ( GetUpper() ) | ||||||
1548 | CheckClipping( true, bMaximize ); | ||||||
1549 | if( !bOldLock ) | ||||||
1550 | ColUnlock(); | ||||||
1551 | long nDiff = nOldHeight - aRectFnSet.GetHeight(getFrameArea()); | ||||||
1552 | |||||||
1553 | if( nDiff > 0 ) | ||||||
1554 | { | ||||||
1555 | if( !GetNext() ) | ||||||
1556 | SetRetouche(); // Take over the retouching ourselves | ||||||
1557 | if( GetUpper() && !GetUpper()->IsFooterFrame() ) | ||||||
1558 | GetUpper()->Shrink( nDiff ); | ||||||
1559 | } | ||||||
1560 | |||||||
1561 | if( IsUndersized() ) | ||||||
1562 | { | ||||||
1563 | setFramePrintAreaValid(true); | ||||||
1564 | } | ||||||
1565 | |||||||
1566 | } | ||||||
1567 | |||||||
1568 | /// Returns the next layout sheet where the frame can be moved in. | ||||||
1569 | /// New pages are created only if specified by the parameter. | ||||||
1570 | SwLayoutFrame *SwFrame::GetNextSctLeaf( MakePageType eMakePage ) | ||||||
1571 | { | ||||||
1572 | // Attention: Nested sections are currently not supported | ||||||
1573 | |||||||
1574 | PROTOCOL_ENTER( this, PROT::Leaf, DbgAction::NextSect, GetUpper()->FindSctFrame() ) | ||||||
1575 | |||||||
1576 | // Shortcuts for "columned" sections, if we're not in the last column | ||||||
1577 | // Can we slide to the next column of the section? | ||||||
1578 | if( IsColBodyFrame() && GetUpper()->GetNext() ) | ||||||
1579 | return static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(GetUpper()->GetNext())->Lower()); | ||||||
1580 | if( GetUpper()->IsColBodyFrame() && GetUpper()->GetUpper()->GetNext() ) | ||||||
1581 | return static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(GetUpper()->GetUpper()->GetNext())->Lower()); | ||||||
1582 | // Inside a table-in-section, or sections of headers/footers, there can be only | ||||||
1583 | // one column shift be made, one of the above shortcuts should have applied! | ||||||
1584 | if( !CanContainSplitSection(GetUpper()) || FindFooterOrHeader() ) | ||||||
1585 | return nullptr; | ||||||
1586 | |||||||
1587 | SwSectionFrame *pSect = FindSctFrame(); | ||||||
1588 | bool bWrongPage = false; | ||||||
1589 | assert(pSect && "GetNextSctLeaf: Missing SectionFrame")(static_cast <bool> (pSect && "GetNextSctLeaf: Missing SectionFrame" ) ? void (0) : __assert_fail ("pSect && \"GetNextSctLeaf: Missing SectionFrame\"" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1589, __extension__ __PRETTY_FUNCTION__)); | ||||||
1590 | |||||||
1591 | // Shortcut for sections with Follows. That's ok, | ||||||
1592 | // if no columns or pages (except dummy pages) lie in between. | ||||||
1593 | // In case of linked frames and in footnotes the shortcut would get | ||||||
1594 | // even more costly | ||||||
1595 | if( pSect->HasFollow() && pSect->IsInDocBody() && !pSect->IsInTab() ) | ||||||
1596 | { | ||||||
1597 | if( pSect->GetFollow() == pSect->GetNext() ) | ||||||
1598 | { | ||||||
1599 | SwPageFrame *pPg = pSect->GetFollow()->FindPageFrame(); | ||||||
1600 | if( WrongPageDesc( pPg ) ) | ||||||
1601 | bWrongPage = true; | ||||||
1602 | else | ||||||
1603 | return FirstLeaf( pSect->GetFollow() ); | ||||||
1604 | } | ||||||
1605 | else | ||||||
1606 | { | ||||||
1607 | SwFrame* pTmp; | ||||||
1608 | if( !pSect->GetUpper()->IsColBodyFrame() || | ||||||
1609 | nullptr == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) ) | ||||||
1610 | pTmp = pSect->FindPageFrame()->GetNext(); | ||||||
1611 | if( pTmp ) // is now the next column or page | ||||||
1612 | { | ||||||
1613 | SwFrame* pTmpX = pTmp; | ||||||
1614 | if( pTmp->IsPageFrame() && static_cast<SwPageFrame*>(pTmp)->IsEmptyPage() ) | ||||||
1615 | pTmp = pTmp->GetNext(); // skip dummy pages | ||||||
1616 | SwFrame *pUp = pSect->GetFollow()->GetUpper(); | ||||||
1617 | // pUp becomes the next column if the Follow lies in a column | ||||||
1618 | // that is not a "not first" one, otherwise the page | ||||||
1619 | if( !pUp->IsColBodyFrame() || | ||||||
1620 | !( pUp = pUp->GetUpper() )->GetPrev() ) | ||||||
1621 | pUp = pUp->FindPageFrame(); | ||||||
1622 | // Now pUp and pTmp have to be the same page/column, otherwise | ||||||
1623 | // pages or columns lie between Master and Follow | ||||||
1624 | if( pUp == pTmp || pUp->GetNext() == pTmpX ) | ||||||
1625 | { | ||||||
1626 | SwPageFrame* pNxtPg = pUp->IsPageFrame() ? | ||||||
1627 | static_cast<SwPageFrame*>(pUp) : pUp->FindPageFrame(); | ||||||
1628 | if( WrongPageDesc( pNxtPg ) ) | ||||||
1629 | bWrongPage = true; | ||||||
1630 | else | ||||||
1631 | return FirstLeaf( pSect->GetFollow() ); | ||||||
1632 | } | ||||||
1633 | } | ||||||
1634 | } | ||||||
1635 | } | ||||||
1636 | |||||||
1637 | #ifndef NDEBUG | ||||||
1638 | std::vector<SwFrame *> parents; | ||||||
1639 | for (SwFrame * pTmp = GetUpper(); pTmp && !pTmp->IsPageFrame(); pTmp = pTmp->GetUpper()) | ||||||
1640 | { | ||||||
1641 | parents.push_back(pTmp); | ||||||
1642 | } | ||||||
1643 | #endif | ||||||
1644 | |||||||
1645 | // Always end up in the same section: Body again inside Body etc. | ||||||
1646 | const bool bBody = IsInDocBody(); | ||||||
1647 | const bool bFootnotePage = FindPageFrame()->IsFootnotePage(); | ||||||
1648 | |||||||
1649 | // The "pLayLeaf is in a table" case is rejected by default, so that it | ||||||
1650 | // can't happen that we try to move a table to one of its own cells. | ||||||
1651 | bool bLayLeafTableAllowed = false; | ||||||
1652 | SwLayoutFrame *pLayLeaf; | ||||||
1653 | |||||||
1654 | SwLayoutFrame* pCellLeaf = nullptr; | ||||||
1655 | if (GetUpper()->IsInTab()) | ||||||
1656 | { | ||||||
1657 | if (IsTabFrame()) | ||||||
1658 | { | ||||||
1659 | return nullptr; // table in section in table: split disabled for now | ||||||
1660 | } | ||||||
1661 | // We are *in* a table (not an outermost SwTabFrame), see if there | ||||||
1662 | // is a follow cell frame created already. | ||||||
1663 | pCellLeaf = GetNextCellLeaf(); | ||||||
1664 | if (!pCellLeaf) | ||||||
1665 | { | ||||||
1666 | SAL_WARN("sw.layout", "section is in table, but the table is not split")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.layout")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "section is in table, but the table is not split" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1666" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "section is in table, but the table is not split" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "section is in table, but the table is not split"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1666" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "section is in table, but the table is not split" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1666" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "section is in table, but the table is not split" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "section is in table, but the table is not split"; :: sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1666" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
1667 | return nullptr; | ||||||
1668 | } | ||||||
1669 | } | ||||||
1670 | |||||||
1671 | // A shortcut for TabFrames such that not all cells need to be visited | ||||||
1672 | if( bWrongPage ) | ||||||
1673 | pLayLeaf = nullptr; | ||||||
1674 | else if( IsTabFrame() ) | ||||||
1675 | { | ||||||
1676 | SwFrame *const pTmpCnt = static_cast<SwTabFrame*>(this)->FindLastContentOrTable(); | ||||||
1677 | pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : nullptr; | ||||||
1678 | } | ||||||
1679 | else if (pCellLeaf && CanContainSplitSection(this)) | ||||||
1680 | { | ||||||
1681 | // This frame is in a table-not-in-section, its follow should be | ||||||
1682 | // inserted under the follow of the frame's cell. | ||||||
1683 | pLayLeaf = pCellLeaf; | ||||||
1684 | if (pLayLeaf->FindTabFrame() == FindTabFrame()) | ||||||
1685 | SAL_WARN("sw.layout", "my table frame and my follow's table frame is the same")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "sw.layout")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "my table frame and my follow's table frame is the same" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1685" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "my table frame and my follow's table frame is the same" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "my table frame and my follow's table frame is the same" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1685" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "my table frame and my follow's table frame is the same" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1685" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "my table frame and my follow's table frame is the same" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "my table frame and my follow's table frame is the same" ; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sw.layout" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1685" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | ||||||
1686 | // In this case pLayLeaf pointing to an in-table frame is OK. | ||||||
1687 | bLayLeafTableAllowed = true; | ||||||
1688 | } | ||||||
1689 | else | ||||||
1690 | { | ||||||
1691 | pLayLeaf = GetNextLayoutLeaf(); | ||||||
1692 | if( IsColumnFrame() ) | ||||||
1693 | { | ||||||
1694 | while( pLayLeaf && static_cast<SwColumnFrame*>(this)->IsAnLower( pLayLeaf ) ) | ||||||
1695 | pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); | ||||||
1696 | } | ||||||
1697 | } | ||||||
1698 | |||||||
1699 | SwLayoutFrame *pOldLayLeaf = nullptr; // Such that in case of newly | ||||||
1700 | // created pages, the search is | ||||||
1701 | // not started over at the beginning | ||||||
1702 | |||||||
1703 | while( true ) | ||||||
1704 | { | ||||||
1705 | if( pLayLeaf ) | ||||||
1706 | { | ||||||
1707 | // A layout leaf was found, let's see whether it can store me or | ||||||
1708 | // another SectionFrame can be inserted here, or we have to continue | ||||||
1709 | // searching | ||||||
1710 | SwPageFrame* pNxtPg = pLayLeaf->FindPageFrame(); | ||||||
1711 | if ( !bFootnotePage && pNxtPg->IsFootnotePage() ) | ||||||
1712 | { // If I reached the end note pages it's over | ||||||
1713 | pLayLeaf = nullptr; | ||||||
1714 | continue; | ||||||
1715 | } | ||||||
1716 | // Once inBody always inBody, don't step into tables-in-sections and not into other sections | ||||||
1717 | if ( (bBody && !pLayLeaf->IsInDocBody()) || | ||||||
1718 | (IsInFootnote() != pLayLeaf->IsInFootnote() ) || | ||||||
1719 | (pLayLeaf->IsInTab() && !bLayLeafTableAllowed) || | ||||||
1720 | ( pLayLeaf->IsInSct() && ( !pSect->HasFollow() | ||||||
1721 | || pSect->GetFollow() != pLayLeaf->FindSctFrame() ) ) ) | ||||||
1722 | { | ||||||
1723 | // Rejected - try again. | ||||||
1724 | pOldLayLeaf = pLayLeaf; | ||||||
1725 | pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); | ||||||
1726 | continue; | ||||||
1727 | } | ||||||
1728 | // Page desc is never wrong in case of sections-in-tables: in that | ||||||
1729 | // case pLayLeaf points to our section's cell's follow, which is | ||||||
1730 | // fine to be on the same page. New page creation is handled when | ||||||
1731 | // creating / moving the cell frame. | ||||||
1732 | if( WrongPageDesc( pNxtPg ) && !bLayLeafTableAllowed ) | ||||||
1733 | { | ||||||
1734 | if( bWrongPage ) | ||||||
1735 | break; // there's a column between me and my right page | ||||||
1736 | pLayLeaf = nullptr; | ||||||
1737 | bWrongPage = true; | ||||||
1738 | pOldLayLeaf = nullptr; | ||||||
1739 | continue; | ||||||
1740 | } | ||||||
1741 | } | ||||||
1742 | // There is no further LayoutFrame that fits, so a new page | ||||||
1743 | // has to be created, although new pages are worthless within a frame | ||||||
1744 | else if( !pSect->IsInFly() && | ||||||
1745 | ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) ) | ||||||
1746 | { | ||||||
1747 | InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrame() : FindPageFrame(), | ||||||
1748 | false ); | ||||||
1749 | // and again the whole thing | ||||||
1750 | if (pCellLeaf && CanContainSplitSection(this)) | ||||||
1751 | // GetNextLayoutLeaf() would refer to the next cell in the same | ||||||
1752 | // row, avoid that. pCellLeaf points to the correct cell in the | ||||||
1753 | // follow table, and in the next round it'll be used, as we now | ||||||
1754 | // have a next page. | ||||||
1755 | pLayLeaf = pCellLeaf; | ||||||
1756 | else | ||||||
1757 | pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf(); | ||||||
1758 | continue; | ||||||
1759 | } | ||||||
1760 | break; | ||||||
1761 | } | ||||||
1762 | |||||||
1763 | if( pLayLeaf ) | ||||||
1764 | { | ||||||
1765 | // We have found the suitable layout sheet. If there (in the sheet) is | ||||||
1766 | // already a Follow of our section, we take its first layout sheet, | ||||||
1767 | // otherwise it is time to create a section follow | ||||||
1768 | SwSectionFrame* pNew = nullptr; | ||||||
1769 | |||||||
1770 | // This can be omitted if existing Follows were cut short | ||||||
1771 | SwFrame* pFirst = pLayLeaf->Lower(); | ||||||
1772 | // Here SectionFrames that are to be deleted must be ignored | ||||||
1773 | while( pFirst && pFirst->IsSctFrame() && !static_cast<SwSectionFrame*>(pFirst)->GetSection() ) | ||||||
1774 | pFirst = pFirst->GetNext(); | ||||||
1775 | if( pFirst && pFirst->IsSctFrame() && pSect->GetFollow() == pFirst ) | ||||||
1776 | pNew = pSect->GetFollow(); | ||||||
1777 | else if( MAKEPAGE_NOSECTION == eMakePage ) | ||||||
1778 | return pLayLeaf; | ||||||
1779 | else if (pSect->GetSection()) | ||||||
1780 | { | ||||||
1781 | pNew = new SwSectionFrame( *pSect, false ); | ||||||
1782 | pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() ); | ||||||
1783 | pNew->Init(); | ||||||
1784 | SwRectFnSet aRectFnSet(pNew); | ||||||
1785 | aRectFnSet.MakePos( *pNew, pLayLeaf, nullptr, true ); | ||||||
1786 | |||||||
1787 | #ifndef NDEBUG | ||||||
1788 | { // sanity check the parents of the new frame vs. the old frame | ||||||
1789 | SwFrame * pTmp = pNew; | ||||||
1790 | auto iter(parents.begin()); | ||||||
1791 | if (parents.size() >= 2 && | ||||||
1792 | parents[0]->IsBodyFrame() && parents[1]->IsColumnFrame()) | ||||||
1793 | { // this only inserts section frame - remove column | ||||||
1794 | assert(parents[2]->IsSctFrame() || IsSctFrame())(static_cast <bool> (parents[2]->IsSctFrame() || IsSctFrame ()) ? void (0) : __assert_fail ("parents[2]->IsSctFrame() || IsSctFrame()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1794, __extension__ __PRETTY_FUNCTION__)); | ||||||
1795 | if (parents[2]->IsSctFrame()) | ||||||
1796 | std::advance(iter, +2); | ||||||
1797 | else | ||||||
1798 | pTmp = pTmp->GetUpper(); | ||||||
1799 | } | ||||||
1800 | else if (IsBodyFrame() && parents.size() >= 1 | ||||||
1801 | && parents[0]->IsColumnFrame()) | ||||||
1802 | { // same as above, special case: "this" is the body frame | ||||||
1803 | assert(parents[1]->IsSctFrame())(static_cast <bool> (parents[1]->IsSctFrame()) ? void (0) : __assert_fail ("parents[1]->IsSctFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1803, __extension__ __PRETTY_FUNCTION__)); | ||||||
1804 | std::advance(iter, +1); | ||||||
1805 | } | ||||||
1806 | else if (IsSctFrame()) // special case: "this" is the section | ||||||
1807 | { | ||||||
1808 | pTmp = pTmp->GetUpper(); | ||||||
1809 | } | ||||||
1810 | |||||||
1811 | for ( ; iter != parents.end(); ++iter) | ||||||
1812 | { | ||||||
1813 | if (pTmp->IsPageFrame()) | ||||||
1814 | { | ||||||
1815 | if ((*iter)->IsColumnFrame() && | ||||||
1816 | (iter + 1) != parents.end() && (*(iter + 1))->IsBodyFrame()) | ||||||
1817 | { // page style has columns - evidently these are | ||||||
1818 | break; // added later? | ||||||
1819 | } | ||||||
1820 | assert(!pTmp->IsPageFrame())(static_cast <bool> (!pTmp->IsPageFrame()) ? void (0 ) : __assert_fail ("!pTmp->IsPageFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1820, __extension__ __PRETTY_FUNCTION__)); | ||||||
1821 | } | ||||||
1822 | assert(pTmp->GetType() == (*iter)->GetType())(static_cast <bool> (pTmp->GetType() == (*iter)-> GetType()) ? void (0) : __assert_fail ("pTmp->GetType() == (*iter)->GetType()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1822, __extension__ __PRETTY_FUNCTION__)); | ||||||
1823 | // for cell frames and table frames: | ||||||
1824 | // 1) there may be multiple follow frames of the old one | ||||||
1825 | // 2) the new frame may be identical to the old one | ||||||
1826 | // (not sure if this is allowed, but it happens now | ||||||
1827 | // for the outer table of a nested table) | ||||||
1828 | if (pTmp->IsCellFrame()) | ||||||
1829 | { | ||||||
1830 | SwCellFrame const*const pNewF(static_cast<SwCellFrame*>(pTmp)); | ||||||
1831 | SwCellFrame const*const pOldF(static_cast<SwCellFrame*>(*iter)); | ||||||
1832 | bool bFollowFound(false); | ||||||
1833 | for (SwCellFrame const* pOldIter = pOldF; | ||||||
1834 | pOldIter; pOldIter = pOldIter->GetFollowCell()) | ||||||
1835 | { | ||||||
1836 | if (pOldIter == pNewF) | ||||||
1837 | { | ||||||
1838 | bFollowFound = true; | ||||||
1839 | break; | ||||||
1840 | } | ||||||
1841 | } | ||||||
1842 | assert(bFollowFound)(static_cast <bool> (bFollowFound) ? void (0) : __assert_fail ("bFollowFound", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1842, __extension__ __PRETTY_FUNCTION__)); | ||||||
1843 | } | ||||||
1844 | else if (pTmp->IsFlowFrame()) | ||||||
1845 | { | ||||||
1846 | SwFlowFrame const*const pNewF(SwFlowFrame::CastFlowFrame(pTmp)); | ||||||
1847 | SwFlowFrame const*const pOldF(SwFlowFrame::CastFlowFrame(*iter)); | ||||||
1848 | bool bFollowFound(false); | ||||||
1849 | for (SwFlowFrame const* pOldIter = pOldF; | ||||||
1850 | pOldIter; pOldIter = pOldIter->GetFollow()) | ||||||
1851 | { | ||||||
1852 | if (pOldIter == pNewF) | ||||||
1853 | { | ||||||
1854 | bFollowFound = true; | ||||||
1855 | break; | ||||||
1856 | } | ||||||
1857 | } | ||||||
1858 | assert(bFollowFound)(static_cast <bool> (bFollowFound) ? void (0) : __assert_fail ("bFollowFound", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1858, __extension__ __PRETTY_FUNCTION__)); | ||||||
1859 | } | ||||||
1860 | pTmp = pTmp->GetUpper(); | ||||||
1861 | } | ||||||
1862 | assert(pTmp == nullptr /* SwFlyAtContentFrame case */(static_cast <bool> (pTmp == nullptr || pTmp->IsPageFrame () || (pTmp->IsColumnFrame() && pTmp->GetUpper( )->IsBodyFrame() && pTmp->GetUpper()->GetUpper ()->IsPageFrame())) ? void (0) : __assert_fail ("pTmp == nullptr || pTmp->IsPageFrame() || (pTmp->IsColumnFrame() && pTmp->GetUpper()->IsBodyFrame() && pTmp->GetUpper()->GetUpper()->IsPageFrame())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1866, __extension__ __PRETTY_FUNCTION__)) | ||||||
1863 | || pTmp->IsPageFrame() // usual case(static_cast <bool> (pTmp == nullptr || pTmp->IsPageFrame () || (pTmp->IsColumnFrame() && pTmp->GetUpper( )->IsBodyFrame() && pTmp->GetUpper()->GetUpper ()->IsPageFrame())) ? void (0) : __assert_fail ("pTmp == nullptr || pTmp->IsPageFrame() || (pTmp->IsColumnFrame() && pTmp->GetUpper()->IsBodyFrame() && pTmp->GetUpper()->GetUpper()->IsPageFrame())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1866, __extension__ __PRETTY_FUNCTION__)) | ||||||
1864 | // the new page has columns, but the old page did not(static_cast <bool> (pTmp == nullptr || pTmp->IsPageFrame () || (pTmp->IsColumnFrame() && pTmp->GetUpper( )->IsBodyFrame() && pTmp->GetUpper()->GetUpper ()->IsPageFrame())) ? void (0) : __assert_fail ("pTmp == nullptr || pTmp->IsPageFrame() || (pTmp->IsColumnFrame() && pTmp->GetUpper()->IsBodyFrame() && pTmp->GetUpper()->GetUpper()->IsPageFrame())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1866, __extension__ __PRETTY_FUNCTION__)) | ||||||
1865 | || (pTmp->IsColumnFrame() && pTmp->GetUpper()->IsBodyFrame()(static_cast <bool> (pTmp == nullptr || pTmp->IsPageFrame () || (pTmp->IsColumnFrame() && pTmp->GetUpper( )->IsBodyFrame() && pTmp->GetUpper()->GetUpper ()->IsPageFrame())) ? void (0) : __assert_fail ("pTmp == nullptr || pTmp->IsPageFrame() || (pTmp->IsColumnFrame() && pTmp->GetUpper()->IsBodyFrame() && pTmp->GetUpper()->GetUpper()->IsPageFrame())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1866, __extension__ __PRETTY_FUNCTION__)) | ||||||
1866 | && pTmp->GetUpper()->GetUpper()->IsPageFrame()))(static_cast <bool> (pTmp == nullptr || pTmp->IsPageFrame () || (pTmp->IsColumnFrame() && pTmp->GetUpper( )->IsBodyFrame() && pTmp->GetUpper()->GetUpper ()->IsPageFrame())) ? void (0) : __assert_fail ("pTmp == nullptr || pTmp->IsPageFrame() || (pTmp->IsColumnFrame() && pTmp->GetUpper()->IsBodyFrame() && pTmp->GetUpper()->GetUpper()->IsPageFrame())" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1866, __extension__ __PRETTY_FUNCTION__)); | ||||||
1867 | } | ||||||
1868 | #endif | ||||||
1869 | |||||||
1870 | // If our section frame has a successor then that has to be | ||||||
1871 | // moved behind the new Follow of the section frames | ||||||
1872 | SwFrame* pTmp = pSect->GetNext(); | ||||||
1873 | if( pTmp && pTmp != pSect->GetFollow() ) | ||||||
1874 | { | ||||||
1875 | SwFlowFrame* pNxt; | ||||||
1876 | SwContentFrame* pNxtContent = nullptr; | ||||||
1877 | if( pTmp->IsContentFrame() ) | ||||||
1878 | { | ||||||
1879 | pNxt = static_cast<SwContentFrame*>(pTmp); | ||||||
1880 | pNxtContent = static_cast<SwContentFrame*>(pTmp); | ||||||
1881 | } | ||||||
1882 | else | ||||||
1883 | { | ||||||
1884 | pNxtContent = static_cast<SwLayoutFrame*>(pTmp)->ContainsContent(); | ||||||
1885 | if( pTmp->IsSctFrame() ) | ||||||
1886 | pNxt = static_cast<SwSectionFrame*>(pTmp); | ||||||
1887 | else | ||||||
1888 | { | ||||||
1889 | assert(pTmp->IsTabFrame())(static_cast <bool> (pTmp->IsTabFrame()) ? void (0) : __assert_fail ("pTmp->IsTabFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 1889, __extension__ __PRETTY_FUNCTION__)); | ||||||
1890 | pNxt = static_cast<SwTabFrame*>(pTmp); | ||||||
1891 | } | ||||||
1892 | while( !pNxtContent && nullptr != ( pTmp = pTmp->GetNext() ) ) | ||||||
1893 | { | ||||||
1894 | if( pTmp->IsContentFrame() ) | ||||||
1895 | pNxtContent = static_cast<SwContentFrame*>(pTmp); | ||||||
1896 | else | ||||||
1897 | pNxtContent = static_cast<SwLayoutFrame*>(pTmp)->ContainsContent(); | ||||||
1898 | } | ||||||
1899 | } | ||||||
1900 | if( pNxtContent ) | ||||||
1901 | { | ||||||
1902 | SwFootnoteBossFrame* pOldBoss = pSect->FindFootnoteBossFrame( true ); | ||||||
1903 | if( pOldBoss == pNxtContent->FindFootnoteBossFrame( true ) ) | ||||||
1904 | { | ||||||
1905 | SwSaveFootnoteHeight aHeight( pOldBoss, | ||||||
1906 | pOldBoss->getFrameArea().Top() + pOldBoss->getFrameArea().Height() ); | ||||||
1907 | pSect->GetUpper()->MoveLowerFootnotes( pNxtContent, pOldBoss, | ||||||
1908 | pLayLeaf->FindFootnoteBossFrame( true ), false ); | ||||||
1909 | } | ||||||
1910 | } | ||||||
1911 | pNxt->MoveSubTree( pLayLeaf, pNew->GetNext() ); | ||||||
1912 | } | ||||||
1913 | if( pNew->GetFollow() ) | ||||||
1914 | pNew->SimpleFormat(); | ||||||
1915 | } | ||||||
1916 | // The wanted layout sheet is now the first of the determined SctFrames: | ||||||
1917 | pLayLeaf = pNew ? FirstLeaf(pNew) : nullptr; | ||||||
1918 | } | ||||||
1919 | return pLayLeaf; | ||||||
1920 | } | ||||||
1921 | |||||||
1922 | /// Returns the preceding layout sheet where the frame can be moved into | ||||||
1923 | SwLayoutFrame *SwFrame::GetPrevSctLeaf() | ||||||
1924 | { | ||||||
1925 | PROTOCOL_ENTER( this, PROT::Leaf, DbgAction::PrevSect, GetUpper()->FindSctFrame() ) | ||||||
1926 | |||||||
1927 | SwLayoutFrame* pCol; | ||||||
1928 | // ColumnFrame always contain a BodyFrame now | ||||||
1929 | if( IsColBodyFrame() ) | ||||||
| |||||||
1930 | pCol = GetUpper(); | ||||||
1931 | else if( GetUpper()->IsColBodyFrame() ) | ||||||
1932 | pCol = GetUpper()->GetUpper(); | ||||||
1933 | else | ||||||
1934 | pCol = nullptr; | ||||||
1935 | bool bJump = false; | ||||||
1936 | if( pCol
| ||||||
1937 | { | ||||||
1938 | if( pCol->GetPrev() ) | ||||||
1939 | { | ||||||
1940 | do | ||||||
1941 | { | ||||||
1942 | pCol = static_cast<SwLayoutFrame*>(pCol->GetPrev()); | ||||||
1943 | // Is there any content? | ||||||
1944 | if( static_cast<SwLayoutFrame*>(pCol->Lower())->Lower() ) | ||||||
1945 | { | ||||||
1946 | if( bJump ) // Did we skip a blank page? | ||||||
1947 | SwFlowFrame::SetMoveBwdJump( true ); | ||||||
1948 | return static_cast<SwLayoutFrame*>(pCol->Lower()); // The columnm body | ||||||
1949 | } | ||||||
1950 | bJump = true; | ||||||
1951 | } while( pCol->GetPrev() ); | ||||||
1952 | |||||||
1953 | // We get here when all columns are empty, pCol is now the | ||||||
1954 | // first column, we need the body though | ||||||
1955 | pCol = static_cast<SwLayoutFrame*>(pCol->Lower()); | ||||||
1956 | } | ||||||
1957 | else | ||||||
1958 | pCol = nullptr; | ||||||
1959 | } | ||||||
1960 | |||||||
1961 | if( bJump
| ||||||
1962 | SwFlowFrame::SetMoveBwdJump( true ); | ||||||
1963 | |||||||
1964 | SwSectionFrame *pSect = FindSctFrame(); | ||||||
1965 | if (!pCol
| ||||||
1966 | { | ||||||
1967 | // We don't have a previous section yet, and we're in a | ||||||
1968 | // section-in-table. | ||||||
1969 | if (SwFlowFrame* pPrecede = pSect->GetPrecede()) | ||||||
1970 | { | ||||||
1971 | // Our section has a precede, work with that. | ||||||
1972 | if (pPrecede->GetFrame().IsLayoutFrame()) | ||||||
1973 | pCol = static_cast<SwLayoutFrame*>(&pPrecede->GetFrame()); | ||||||
1974 | } | ||||||
1975 | } | ||||||
1976 | |||||||
1977 | // Within sections in tables or section in headers/footers there can | ||||||
1978 | // be only one column change be made, one of the above shortcuts should | ||||||
1979 | // have applied, also when the section has a pPrev. | ||||||
1980 | // Now we even consider an empty column... | ||||||
1981 | OSL_ENSURE( pSect, "GetNextSctLeaf: Missing SectionFrame" )do { if (true && (!(pSect))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "1981" ": "), "%s", "GetNextSctLeaf: Missing SectionFrame" ); } } while (false); | ||||||
1982 | if (!pSect
| ||||||
1983 | return pCol; | ||||||
1984 | |||||||
1985 | // === IMPORTANT === | ||||||
1986 | // Precondition, which needs to be hold, is that the <this> frame can be | ||||||
1987 | // inside a table, but then the found section frame <pSect> is also inside | ||||||
1988 | // this table. | ||||||
1989 | |||||||
1990 | // #i95698# | ||||||
1991 | // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..) | ||||||
1992 | // Thus, a table inside a section, which is inside another table can only | ||||||
1993 | // flow backward in the columns of its section. | ||||||
1994 | // Note: The table cell, which contains the section, can not have a master table cell. | ||||||
1995 | if ( IsTabFrame() && pSect->IsInTab() ) | ||||||
1996 | { | ||||||
1997 | return pCol; | ||||||
1998 | } | ||||||
1999 | |||||||
2000 | { | ||||||
2001 | if (SwFrame *pPrv = pSect->GetIndPrev()) | ||||||
2002 | { | ||||||
2003 | // Mooching, half dead SectionFrames shouldn't confuse us | ||||||
2004 | while( pPrv && pPrv->IsSctFrame() && !static_cast<SwSectionFrame*>(pPrv)->GetSection() ) | ||||||
2005 | pPrv = pPrv->GetPrev(); | ||||||
2006 | if( pPrv ) | ||||||
2007 | return pCol; | ||||||
2008 | } | ||||||
2009 | } | ||||||
2010 | |||||||
2011 | const bool bBody = IsInDocBody(); | ||||||
2012 | const bool bFly = IsInFly(); | ||||||
2013 | |||||||
2014 | SwLayoutFrame *pLayLeaf = GetPrevLayoutLeaf(); | ||||||
2015 | SwLayoutFrame *pPrevLeaf = nullptr; | ||||||
2016 | |||||||
2017 | while ( pLayLeaf ) | ||||||
2018 | { | ||||||
2019 | // Never step into tables or sections | ||||||
2020 | if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() ) | ||||||
2021 | { | ||||||
2022 | pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); | ||||||
2023 | } | ||||||
2024 | else if ( bBody && pLayLeaf->IsInDocBody() ) | ||||||
2025 | { | ||||||
2026 | // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for. | ||||||
2027 | // Exception: pLayLeaf->Lower() is a zombie section frame | ||||||
2028 | const SwFrame* pTmp = pLayLeaf->Lower(); | ||||||
2029 | // OD 11.04.2003 #108824# - consider, that the zombie section frame | ||||||
2030 | // can have frame below it in the found layout leaf. | ||||||
2031 | // Thus, skipping zombie section frame, if possible. | ||||||
2032 | while ( pTmp && pTmp->IsSctFrame() && | ||||||
2033 | !( static_cast<const SwSectionFrame*>(pTmp)->GetSection() ) && | ||||||
2034 | pTmp->GetNext() | ||||||
2035 | ) | ||||||
2036 | { | ||||||
2037 | pTmp = pTmp->GetNext(); | ||||||
2038 | } | ||||||
2039 | if ( pTmp && | ||||||
2040 | ( !pTmp->IsSctFrame() || | ||||||
2041 | ( static_cast<const SwSectionFrame*>(pTmp)->GetSection() ) | ||||||
2042 | ) | ||||||
2043 | ) | ||||||
2044 | { | ||||||
2045 | break; | ||||||
2046 | } | ||||||
2047 | pPrevLeaf = pLayLeaf; | ||||||
2048 | pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); | ||||||
2049 | if ( pLayLeaf ) | ||||||
2050 | SwFlowFrame::SetMoveBwdJump( true ); | ||||||
2051 | } | ||||||
2052 | else if ( bFly ) | ||||||
2053 | break; // Contents in Flys every layout sheet should be right. Why? | ||||||
2054 | else | ||||||
2055 | pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); | ||||||
2056 | } | ||||||
2057 | if( !pLayLeaf
| ||||||
2058 | { | ||||||
2059 | if( !pPrevLeaf ) | ||||||
2060 | return pCol; | ||||||
2061 | pLayLeaf = pPrevLeaf; | ||||||
2062 | } | ||||||
2063 | |||||||
2064 | SwSectionFrame* pNew = nullptr; | ||||||
2065 | // At first go to the end of the layout sheet | ||||||
2066 | SwFrame *pTmp = pLayLeaf->Lower(); | ||||||
2067 | if( pTmp ) | ||||||
2068 | { | ||||||
2069 | while( pTmp->GetNext() ) | ||||||
2070 | pTmp = pTmp->GetNext(); | ||||||
2071 | if( pTmp->IsSctFrame() ) | ||||||
2072 | { | ||||||
2073 | // Half dead ones only interfere here | ||||||
2074 | while( !static_cast<SwSectionFrame*>(pTmp)->GetSection() && pTmp->GetPrev() && | ||||||
2075 | pTmp->GetPrev()->IsSctFrame() ) | ||||||
2076 | pTmp = pTmp->GetPrev(); | ||||||
2077 | if( static_cast<SwSectionFrame*>(pTmp)->GetFollow() == pSect ) | ||||||
2078 | pNew = static_cast<SwSectionFrame*>(pTmp); | ||||||
2079 | } | ||||||
2080 | } | ||||||
2081 | if( !pNew
| ||||||
2082 | { | ||||||
2083 | pNew = new SwSectionFrame( *pSect, true ); | ||||||
2084 | pNew->InsertBefore( pLayLeaf, nullptr ); | ||||||
2085 | pNew->Init(); | ||||||
2086 | SwRectFnSet aRectFnSet(pNew); | ||||||
2087 | aRectFnSet.MakePos( *pNew, pLayLeaf, pNew->GetPrev(), true ); | ||||||
2088 | |||||||
2089 | pLayLeaf = FirstLeaf( pNew ); | ||||||
2090 | if( !pNew->Lower() ) // Format single column sections | ||||||
2091 | { | ||||||
2092 | pNew->MakePos(); | ||||||
2093 | pLayLeaf->Format(getRootFrame()->GetCurrShell()->GetOut()); // In order that the PrtArea is correct for the MoveBwd | ||||||
2094 | } | ||||||
2095 | else | ||||||
2096 | pNew->SimpleFormat(); | ||||||
2097 | } | ||||||
2098 | else | ||||||
2099 | { | ||||||
2100 | pLayLeaf = FirstLeaf( pNew ); | ||||||
2101 | if( pLayLeaf->IsColBodyFrame() ) | ||||||
2102 | { | ||||||
2103 | // In existent section columns we're looking for the last not empty | ||||||
2104 | // column. | ||||||
2105 | SwLayoutFrame *pTmpLay = pLayLeaf; | ||||||
2106 | while( pLayLeaf->GetUpper()->GetNext() ) | ||||||
2107 | { | ||||||
2108 | pLayLeaf = static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(pLayLeaf->GetUpper()->GetNext())->Lower()); | ||||||
2109 | if( pLayLeaf->Lower() ) | ||||||
2110 | pTmpLay = pLayLeaf; | ||||||
2111 | } | ||||||
2112 | // If we skipped an empty column, we've to set the jump-flag | ||||||
2113 | if( pLayLeaf != pTmpLay ) | ||||||
2114 | { | ||||||
2115 | pLayLeaf = pTmpLay; | ||||||
2116 | SwFlowFrame::SetMoveBwdJump( true ); | ||||||
2117 | } | ||||||
2118 | } | ||||||
2119 | } | ||||||
2120 | return pLayLeaf; | ||||||
2121 | } | ||||||
2122 | |||||||
2123 | static SwTwips lcl_DeadLine( const SwFrame* pFrame ) | ||||||
2124 | { | ||||||
2125 | const SwLayoutFrame* pUp = pFrame->GetUpper(); | ||||||
2126 | while( pUp && pUp->IsInSct() ) | ||||||
2127 | { | ||||||
2128 | if( pUp->IsSctFrame() ) | ||||||
2129 | pUp = pUp->GetUpper(); | ||||||
2130 | // Columns now with BodyFrame | ||||||
2131 | else if( pUp->IsColBodyFrame() && pUp->GetUpper()->GetUpper()->IsSctFrame() ) | ||||||
2132 | pUp = pUp->GetUpper()->GetUpper(); | ||||||
2133 | else | ||||||
2134 | break; | ||||||
2135 | } | ||||||
2136 | SwRectFnSet aRectFnSet(pFrame); | ||||||
2137 | return pUp ? aRectFnSet.GetPrtBottom(*pUp) : | ||||||
2138 | aRectFnSet.GetBottom(pFrame->getFrameArea()); | ||||||
2139 | } | ||||||
2140 | |||||||
2141 | /// checks whether the SectionFrame is still able to grow, as case may be the environment has to be asked | ||||||
2142 | bool SwSectionFrame::Growable() const | ||||||
2143 | { | ||||||
2144 | SwRectFnSet aRectFnSet(this); | ||||||
2145 | if( aRectFnSet.YDiff( lcl_DeadLine( this ), | ||||||
2146 | aRectFnSet.GetBottom(getFrameArea()) ) > 0 ) | ||||||
2147 | return true; | ||||||
2148 | |||||||
2149 | return ( GetUpper() && const_cast<SwFrame*>(static_cast<SwFrame const *>(GetUpper()))->Grow( LONG_MAX9223372036854775807L, true ) ); | ||||||
2150 | } | ||||||
2151 | |||||||
2152 | SwTwips SwSectionFrame::Grow_( SwTwips nDist, bool bTst ) | ||||||
2153 | { | ||||||
2154 | if ( !IsColLocked() && !HasFixSize() ) | ||||||
2155 | { | ||||||
2156 | SwRectFnSet aRectFnSet(this); | ||||||
2157 | long nFrameHeight = aRectFnSet.GetHeight(getFrameArea()); | ||||||
2158 | if( nFrameHeight > 0 && nDist > (LONG_MAX9223372036854775807L - nFrameHeight) ) | ||||||
2159 | nDist = LONG_MAX9223372036854775807L - nFrameHeight; | ||||||
2160 | |||||||
2161 | if ( nDist <= 0 ) | ||||||
2162 | return 0; | ||||||
2163 | |||||||
2164 | bool bInCalcContent = GetUpper() && IsInFly() && FindFlyFrame()->IsLocked(); | ||||||
2165 | // OD 2004-03-15 #116561# - allow grow in online layout | ||||||
2166 | bool bGrow = !Lower() || !Lower()->IsColumnFrame() || !Lower()->GetNext(); | ||||||
2167 | if (!bGrow) | ||||||
2168 | { | ||||||
2169 | SwSection* pSection = GetSection(); | ||||||
2170 | bGrow = pSection && pSection->GetFormat()->GetBalancedColumns().GetValue(); | ||||||
2171 | } | ||||||
2172 | if( !bGrow ) | ||||||
2173 | { | ||||||
2174 | const SwViewShell *pSh = getRootFrame()->GetCurrShell(); | ||||||
2175 | bGrow = pSh && pSh->GetViewOptions()->getBrowseMode(); | ||||||
2176 | } | ||||||
2177 | if( bGrow ) | ||||||
2178 | { | ||||||
2179 | SwTwips nGrow; | ||||||
2180 | if( IsInFootnote() ) | ||||||
2181 | nGrow = 0; | ||||||
2182 | else | ||||||
2183 | { | ||||||
2184 | nGrow = lcl_DeadLine( this ); | ||||||
2185 | nGrow = aRectFnSet.YDiff( nGrow, aRectFnSet.GetBottom(getFrameArea()) ); | ||||||
2186 | } | ||||||
2187 | SwTwips nSpace = nGrow; | ||||||
2188 | if( !bInCalcContent && nGrow < nDist && GetUpper() ) | ||||||
2189 | nGrow = o3tl::saturating_add( | ||||||
2190 | nGrow, GetUpper()->Grow( LONG_MAX9223372036854775807L, true )); | ||||||
2191 | |||||||
2192 | if( nGrow > nDist ) | ||||||
2193 | nGrow = nDist; | ||||||
2194 | if( nGrow <= 0 ) | ||||||
2195 | { | ||||||
2196 | nGrow = 0; | ||||||
2197 | if (!bTst) | ||||||
2198 | { | ||||||
2199 | if( bInCalcContent ) | ||||||
2200 | InvalidateSize_(); | ||||||
2201 | else | ||||||
2202 | InvalidateSize(); | ||||||
2203 | } | ||||||
2204 | } | ||||||
2205 | else if( !bTst ) | ||||||
2206 | { | ||||||
2207 | if( bInCalcContent ) | ||||||
2208 | InvalidateSize_(); | ||||||
2209 | else if( nSpace < nGrow && nDist != nSpace + GetUpper()-> | ||||||
2210 | Grow( nGrow - nSpace ) ) | ||||||
2211 | InvalidateSize(); | ||||||
2212 | else | ||||||
2213 | { | ||||||
2214 | const SvxGraphicPosition ePos = | ||||||
2215 | GetAttrSet()->GetBackground().GetGraphicPos(); | ||||||
2216 | if ( GPOS_RT < ePos && GPOS_TILED != ePos ) | ||||||
2217 | { | ||||||
2218 | SetCompletePaint(); | ||||||
2219 | InvalidatePage(); | ||||||
2220 | } | ||||||
2221 | if( GetUpper() && GetUpper()->IsHeaderFrame() ) | ||||||
2222 | GetUpper()->InvalidateSize(); | ||||||
2223 | } | ||||||
2224 | |||||||
2225 | { | ||||||
2226 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
2227 | aRectFnSet.AddBottom( aFrm, nGrow ); | ||||||
2228 | } | ||||||
2229 | |||||||
2230 | { | ||||||
2231 | const long nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea()) + nGrow; | ||||||
2232 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | ||||||
2233 | aRectFnSet.SetHeight( aPrt, nPrtHeight ); | ||||||
2234 | } | ||||||
2235 | |||||||
2236 | if( Lower() && Lower()->IsColumnFrame() && Lower()->GetNext() ) | ||||||
2237 | { | ||||||
2238 | SwFrame* pTmp = Lower(); | ||||||
2239 | do | ||||||
2240 | { | ||||||
2241 | pTmp->InvalidateSize_(); | ||||||
2242 | pTmp = pTmp->GetNext(); | ||||||
2243 | } while ( pTmp ); | ||||||
2244 | InvalidateSize_(); | ||||||
2245 | } | ||||||
2246 | if( GetNext() ) | ||||||
2247 | { | ||||||
2248 | // Own height changed, need to invalidate the position of | ||||||
2249 | // next frames. | ||||||
2250 | SwFrame *pFrame = GetNext(); | ||||||
2251 | while( pFrame && pFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pFrame)->GetSection() ) | ||||||
2252 | { | ||||||
2253 | // Invalidate all in-between frames, otherwise position | ||||||
2254 | // calculation (which only looks back to one relative | ||||||
2255 | // frame) will have an incorrect result. | ||||||
2256 | InvalidateFramePos(pFrame, bInCalcContent); | ||||||
2257 | pFrame = pFrame->GetNext(); | ||||||
2258 | } | ||||||
2259 | if( pFrame ) | ||||||
2260 | { | ||||||
2261 | InvalidateFramePos(pFrame, bInCalcContent); | ||||||
2262 | } | ||||||
2263 | } | ||||||
2264 | // #i28701# - Due to the new object positioning | ||||||
2265 | // the frame on the next page/column can flow backward (e.g. it | ||||||
2266 | // was moved forward due to the positioning of its objects ). | ||||||
2267 | // Thus, invalivate this next frame, if document compatibility | ||||||
2268 | // option 'Consider wrapping style influence on object positioning' is ON. | ||||||
2269 | else if ( GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) ) | ||||||
2270 | { | ||||||
2271 | InvalidateNextPos(); | ||||||
2272 | } | ||||||
2273 | } | ||||||
2274 | return nGrow; | ||||||
2275 | } | ||||||
2276 | if ( !bTst ) | ||||||
2277 | { | ||||||
2278 | if( bInCalcContent ) | ||||||
2279 | InvalidateSize_(); | ||||||
2280 | else | ||||||
2281 | InvalidateSize(); | ||||||
2282 | } | ||||||
2283 | } | ||||||
2284 | return 0; | ||||||
2285 | } | ||||||
2286 | |||||||
2287 | SwTwips SwSectionFrame::Shrink_( SwTwips nDist, bool bTst ) | ||||||
2288 | { | ||||||
2289 | if ( Lower() && !IsColLocked() && !HasFixSize() ) | ||||||
2290 | { | ||||||
2291 | if( ToMaximize( false ) ) | ||||||
2292 | { | ||||||
2293 | if( !bTst ) | ||||||
2294 | InvalidateSize(); | ||||||
2295 | } | ||||||
2296 | else | ||||||
2297 | { | ||||||
2298 | SwRectFnSet aRectFnSet(this); | ||||||
2299 | long nFrameHeight = aRectFnSet.GetHeight(getFrameArea()); | ||||||
2300 | if ( nDist > nFrameHeight ) | ||||||
2301 | nDist = nFrameHeight; | ||||||
2302 | |||||||
2303 | if ( Lower()->IsColumnFrame() && Lower()->GetNext() && // FootnoteAtEnd | ||||||
2304 | !GetSection()->GetFormat()->GetBalancedColumns().GetValue() ) | ||||||
2305 | { // With column bases the format takes over the control of the | ||||||
2306 | // growth (because of the balance) | ||||||
2307 | if ( !bTst ) | ||||||
2308 | InvalidateSize(); | ||||||
2309 | return nDist; | ||||||
2310 | } | ||||||
2311 | else if( !bTst ) | ||||||
2312 | { | ||||||
2313 | const SvxGraphicPosition ePos = | ||||||
2314 | GetAttrSet()->GetBackground().GetGraphicPos(); | ||||||
2315 | if ( GPOS_RT < ePos && GPOS_TILED != ePos ) | ||||||
2316 | { | ||||||
2317 | SetCompletePaint(); | ||||||
2318 | InvalidatePage(); | ||||||
2319 | } | ||||||
2320 | |||||||
2321 | { | ||||||
2322 | SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); | ||||||
2323 | aRectFnSet.AddBottom( aFrm, -nDist ); | ||||||
2324 | } | ||||||
2325 | |||||||
2326 | { | ||||||
2327 | const long nPrtHeight = aRectFnSet.GetHeight(getFramePrintArea()) - nDist; | ||||||
2328 | SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); | ||||||
2329 | aRectFnSet.SetHeight( aPrt, nPrtHeight ); | ||||||
2330 | } | ||||||
2331 | |||||||
2332 | // We do not allow a section frame to shrink the its upper | ||||||
2333 | // footer frame. This is because in the calculation of a | ||||||
2334 | // footer frame, the content of the section frame is _not_ | ||||||
2335 | // calculated. If there is a fly frame overlapping with the | ||||||
2336 | // footer frame, the section frame is not affected by this | ||||||
2337 | // during the calculation of the footer frame size. | ||||||
2338 | // The footer frame does not grow in its FormatSize function | ||||||
2339 | // but during the calculation of the content of the section | ||||||
2340 | // frame. The section frame grows until some of its text is | ||||||
2341 | // located on top of the fly frame. The next call of CalcContent | ||||||
2342 | // tries to shrink the section and here it would also shrink | ||||||
2343 | // the footer. This may not happen, because shrinking the footer | ||||||
2344 | // would cause the top of the section frame to overlap with the | ||||||
2345 | // fly frame again, this would result in a perfect loop. | ||||||
2346 | if( GetUpper() && !GetUpper()->IsFooterFrame() ) | ||||||
2347 | GetUpper()->Shrink( nDist, bTst ); | ||||||
2348 | |||||||
2349 | if( Lower() && Lower()->IsColumnFrame() && Lower()->GetNext() ) | ||||||
2350 | { | ||||||
2351 | SwFrame* pTmp = Lower(); | ||||||
2352 | do | ||||||
2353 | { | ||||||
2354 | pTmp->InvalidateSize_(); | ||||||
2355 | pTmp = pTmp->GetNext(); | ||||||
2356 | } while ( pTmp ); | ||||||
2357 | } | ||||||
2358 | if( GetNext() ) | ||||||
2359 | { | ||||||
2360 | SwFrame* pFrame = GetNext(); | ||||||
2361 | while( pFrame && pFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pFrame)->GetSection() ) | ||||||
2362 | pFrame = pFrame->GetNext(); | ||||||
2363 | if( pFrame ) | ||||||
2364 | pFrame->InvalidatePos(); | ||||||
2365 | else | ||||||
2366 | SetRetouche(); | ||||||
2367 | } | ||||||
2368 | else | ||||||
2369 | SetRetouche(); | ||||||
2370 | return nDist; | ||||||
2371 | } | ||||||
2372 | } | ||||||
2373 | } | ||||||
2374 | return 0; | ||||||
2375 | } | ||||||
2376 | |||||||
2377 | /* | ||||||
2378 | |* When are Frames within a SectionFrames moveable? | ||||||
2379 | |* If they are not in the last column of a SectionFrames yet, | ||||||
2380 | |* if there is no Follow, | ||||||
2381 | |* if the SectionFrame cannot grow anymore, then it gets more complicated, | ||||||
2382 | |* in that case it depends on whether the SectionFrame can find a next | ||||||
2383 | |* layout sheet. In (column based/chained) Flys this is checked via | ||||||
2384 | |* GetNextLayout, in tables and headers/footers there is none, however in the | ||||||
2385 | |* DocBody and in foot notes there is always one. | ||||||
2386 | |* | ||||||
2387 | |* This routine is used in the TextFormatter to decided whether it's allowed to | ||||||
2388 | |* create a (paragraph-)Follow or whether the paragraph has to stick together | ||||||
2389 | |*/ | ||||||
2390 | bool SwSectionFrame::MoveAllowed( const SwFrame* pFrame) const | ||||||
2391 | { | ||||||
2392 | // Is there a Follow or is the Frame not in the last column? | ||||||
2393 | if( HasFollow() || ( pFrame->GetUpper()->IsColBodyFrame() && | ||||||
2394 | pFrame->GetUpper()->GetUpper()->GetNext() ) ) | ||||||
2395 | return true; | ||||||
2396 | if( pFrame->IsInFootnote() ) | ||||||
2397 | { | ||||||
2398 | if( IsInFootnote() ) | ||||||
2399 | { | ||||||
2400 | if( GetUpper()->IsInSct() ) | ||||||
2401 | { | ||||||
2402 | if( Growable() ) | ||||||
2403 | return false; | ||||||
2404 | return GetUpper()->FindSctFrame()->MoveAllowed( this ); | ||||||
2405 | } | ||||||
2406 | else | ||||||
2407 | return true; | ||||||
2408 | } | ||||||
2409 | // The content of footnote inside a columned sectionfrm is moveable | ||||||
2410 | // except in the last column | ||||||
2411 | const SwLayoutFrame *pLay = pFrame->FindFootnoteFrame()->GetUpper()->GetUpper(); | ||||||
2412 | if( pLay->IsColumnFrame() && pLay->GetNext() ) | ||||||
2413 | { | ||||||
2414 | // The first paragraph in the first footnote in the first column | ||||||
2415 | // in the sectionfrm at the top of the page is not moveable, | ||||||
2416 | // if the columnbody is empty. | ||||||
2417 | bool bRet = false; | ||||||
2418 | if( pLay->GetIndPrev() || pFrame->GetIndPrev() || | ||||||
2419 | pFrame->FindFootnoteFrame()->GetPrev() ) | ||||||
2420 | bRet = true; | ||||||
2421 | else | ||||||
2422 | { | ||||||
2423 | const SwLayoutFrame* pBody = static_cast<const SwColumnFrame*>(pLay)->FindBodyCont(); | ||||||
2424 | if( pBody && pBody->Lower() ) | ||||||
2425 | bRet = true; | ||||||
2426 | } | ||||||
2427 | if( bRet && ( IsFootnoteAtEnd() || !Growable() ) ) | ||||||
2428 | return true; | ||||||
2429 | } | ||||||
2430 | } | ||||||
2431 | // Or can the section still grow? | ||||||
2432 | if( !IsColLocked() && Growable() ) | ||||||
2433 | return false; | ||||||
2434 | // Now it has to be examined whether there is a layout sheet wherein | ||||||
2435 | // a section Follow can be created | ||||||
2436 | if( !CanContainSplitSection(this) || ( !IsInDocBody() && FindFooterOrHeader() ) ) | ||||||
2437 | return false; // It doesn't work in table-in-sections/nested tables/headers/footers | ||||||
2438 | if( IsInFly() ) // In column based or chained frames | ||||||
2439 | return nullptr != const_cast<SwFrame*>(static_cast<SwFrame const *>(GetUpper()))->GetNextLeaf( MAKEPAGE_NONE ); | ||||||
2440 | return true; | ||||||
2441 | } | ||||||
2442 | |||||||
2443 | /** Called for a frame inside a section with no direct previous frame (or only | ||||||
2444 | previous empty section frames) the previous frame of the outer section is | ||||||
2445 | returned, if the frame is the first flowing content of this section. | ||||||
2446 | |||||||
2447 | Note: For a frame inside a table frame, which is inside a section frame, | ||||||
2448 | NULL is returned. | ||||||
2449 | */ | ||||||
2450 | SwFrame* SwFrame::GetIndPrev_() const | ||||||
2451 | { | ||||||
2452 | SwFrame *pRet = nullptr; | ||||||
2453 | // #i79774# | ||||||
2454 | // Do not assert, if the frame has a direct previous frame, because it | ||||||
2455 | // could be an empty section frame. The caller has to assure, that the | ||||||
2456 | // frame has no direct previous frame or only empty section frames as | ||||||
2457 | // previous frames. | ||||||
2458 | OSL_ENSURE( /*!pPrev &&*/ IsInSct(), "Why?" )do { if (true && (!(IsInSct()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2458" ": "), "%s", "Why?"); } } while (false); | ||||||
2459 | const SwFrame* pSct = GetUpper(); | ||||||
2460 | if( !pSct ) | ||||||
2461 | return nullptr; | ||||||
2462 | if( pSct->IsSctFrame() ) | ||||||
2463 | pRet = pSct->GetIndPrev(); | ||||||
2464 | else if( pSct->IsColBodyFrame() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrame() ) | ||||||
2465 | { | ||||||
2466 | // Do not return the previous frame of the outer section, if in one | ||||||
2467 | // of the previous columns is content. | ||||||
2468 | const SwFrame* pCol = GetUpper()->GetUpper()->GetPrev(); | ||||||
2469 | while( pCol ) | ||||||
2470 | { | ||||||
2471 | assert(pCol->IsColumnFrame())(static_cast <bool> (pCol->IsColumnFrame()) ? void ( 0) : __assert_fail ("pCol->IsColumnFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 2471, __extension__ __PRETTY_FUNCTION__)); | ||||||
2472 | assert(pCol->GetLower() && pCol->GetLower()->IsBodyFrame())(static_cast <bool> (pCol->GetLower() && pCol ->GetLower()->IsBodyFrame()) ? void (0) : __assert_fail ("pCol->GetLower() && pCol->GetLower()->IsBodyFrame()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 2472, __extension__ __PRETTY_FUNCTION__)); | ||||||
2473 | if( static_cast<const SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pCol)->Lower())->Lower() ) | ||||||
2474 | return nullptr; | ||||||
2475 | pCol = pCol->GetPrev(); | ||||||
2476 | } | ||||||
2477 | pRet = pSct->GetIndPrev(); | ||||||
2478 | } | ||||||
2479 | |||||||
2480 | // skip empty section frames | ||||||
2481 | while( pRet && pRet->IsSctFrame() && !static_cast<SwSectionFrame*>(pRet)->GetSection() ) | ||||||
2482 | pRet = pRet->GetIndPrev(); | ||||||
2483 | return pRet; | ||||||
2484 | } | ||||||
2485 | |||||||
2486 | SwFrame* SwFrame::GetIndNext_() | ||||||
2487 | { | ||||||
2488 | OSL_ENSURE( !mpNext && IsInSct(), "Why?" )do { if (true && (!(!mpNext && IsInSct()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2488" ": "), "%s", "Why?"); } } while (false); | ||||||
2489 | SwFrame* pSct = GetUpper(); | ||||||
2490 | if( !pSct ) | ||||||
2491 | return nullptr; | ||||||
2492 | if( pSct->IsSctFrame() ) | ||||||
2493 | return pSct->GetIndNext(); | ||||||
2494 | if( pSct->IsColBodyFrame() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrame() ) | ||||||
2495 | { // We can only return the successor of the SectionFrames if there is no | ||||||
2496 | // content in the successive columns | ||||||
2497 | SwFrame* pCol = GetUpper()->GetUpper()->GetNext(); | ||||||
2498 | while( pCol ) | ||||||
2499 | { | ||||||
2500 | assert(pCol->IsColumnFrame())(static_cast <bool> (pCol->IsColumnFrame()) ? void ( 0) : __assert_fail ("pCol->IsColumnFrame()", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 2500, __extension__ __PRETTY_FUNCTION__)); | ||||||
2501 | assert(pCol->GetLower() && pCol->GetLower()->IsBodyFrame())(static_cast <bool> (pCol->GetLower() && pCol ->GetLower()->IsBodyFrame()) ? void (0) : __assert_fail ("pCol->GetLower() && pCol->GetLower()->IsBodyFrame()" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 2501, __extension__ __PRETTY_FUNCTION__)); | ||||||
2502 | if( static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(pCol)->Lower())->Lower() ) | ||||||
2503 | return nullptr; | ||||||
2504 | pCol = pCol->GetNext(); | ||||||
2505 | } | ||||||
2506 | return pSct->GetIndNext(); | ||||||
2507 | } | ||||||
2508 | return nullptr; | ||||||
2509 | } | ||||||
2510 | |||||||
2511 | bool SwSectionFrame::IsDescendantFrom( const SwSectionFormat* pFormat ) const | ||||||
2512 | { | ||||||
2513 | if( !m_pSection || !pFormat ) | ||||||
2514 | return false; | ||||||
2515 | const SwSectionFormat *pMyFormat = m_pSection->GetFormat(); | ||||||
2516 | while( pFormat != pMyFormat ) | ||||||
2517 | { | ||||||
2518 | if( dynamic_cast< const SwSectionFormat *>( pMyFormat->GetRegisteredIn()) != nullptr ) | ||||||
2519 | pMyFormat = static_cast<const SwSectionFormat*>(pMyFormat->GetRegisteredIn()); | ||||||
2520 | else | ||||||
2521 | return false; | ||||||
2522 | } | ||||||
2523 | return true; | ||||||
2524 | } | ||||||
2525 | |||||||
2526 | void SwSectionFrame::CalcFootnoteAtEndFlag() | ||||||
2527 | { | ||||||
2528 | SwSectionFormat *pFormat = GetSection()->GetFormat(); | ||||||
2529 | sal_uInt16 nVal = pFormat->GetFootnoteAtTextEnd( false ).GetValue(); | ||||||
2530 | m_bFootnoteAtEnd = FTNEND_ATPGORDOCEND != nVal; | ||||||
2531 | m_bOwnFootnoteNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal || | ||||||
2532 | FTNEND_ATTXTEND_OWNNUMANDFMT == nVal; | ||||||
2533 | while( !m_bFootnoteAtEnd && !m_bOwnFootnoteNum ) | ||||||
2534 | { | ||||||
2535 | if( dynamic_cast< const SwSectionFormat *>( pFormat->GetRegisteredIn()) != nullptr ) | ||||||
2536 | pFormat = static_cast<SwSectionFormat*>(pFormat->GetRegisteredIn()); | ||||||
2537 | else | ||||||
2538 | break; | ||||||
2539 | nVal = pFormat->GetFootnoteAtTextEnd( false ).GetValue(); | ||||||
2540 | if( FTNEND_ATPGORDOCEND != nVal ) | ||||||
2541 | { | ||||||
2542 | m_bFootnoteAtEnd = true; | ||||||
2543 | m_bOwnFootnoteNum = m_bOwnFootnoteNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal || | ||||||
2544 | FTNEND_ATTXTEND_OWNNUMANDFMT == nVal; | ||||||
2545 | } | ||||||
2546 | } | ||||||
2547 | } | ||||||
2548 | |||||||
2549 | bool SwSectionFrame::IsEndnoteAtMyEnd() const | ||||||
2550 | { | ||||||
2551 | return m_pSection->GetFormat()->GetEndAtTextEnd( false ).IsAtEnd(); | ||||||
2552 | } | ||||||
2553 | |||||||
2554 | void SwSectionFrame::CalcEndAtEndFlag() | ||||||
2555 | { | ||||||
2556 | SwSectionFormat *pFormat = GetSection()->GetFormat(); | ||||||
2557 | m_bEndnAtEnd = pFormat->GetEndAtTextEnd( false ).IsAtEnd(); | ||||||
2558 | while( !m_bEndnAtEnd ) | ||||||
2559 | { | ||||||
2560 | if( dynamic_cast< const SwSectionFormat *>( pFormat->GetRegisteredIn()) != nullptr ) | ||||||
2561 | pFormat = static_cast<SwSectionFormat*>(pFormat->GetRegisteredIn()); | ||||||
2562 | else | ||||||
2563 | break; | ||||||
2564 | m_bEndnAtEnd = pFormat->GetEndAtTextEnd( false ).IsAtEnd(); | ||||||
2565 | } | ||||||
2566 | } | ||||||
2567 | |||||||
2568 | void SwSectionFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) | ||||||
2569 | { | ||||||
2570 | sal_uInt8 nInvFlags = 0; | ||||||
2571 | |||||||
2572 | if( pNew && RES_ATTRSET_CHG == pNew->Which() ) | ||||||
2573 | { | ||||||
2574 | SfxItemIter aNIter( *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet() ); | ||||||
2575 | SfxItemIter aOIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() ); | ||||||
2576 | const SfxPoolItem* pNItem = aNIter.GetCurItem(); | ||||||
2577 | const SfxPoolItem* pOItem = aOIter.GetCurItem(); | ||||||
2578 | SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) ); | ||||||
2579 | SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) ); | ||||||
2580 | do | ||||||
2581 | { | ||||||
2582 | UpdateAttr_(pOItem, pNItem, nInvFlags, &aOldSet, &aNewSet); | ||||||
2583 | pNItem = aNIter.NextItem(); | ||||||
2584 | pOItem = aOIter.NextItem(); | ||||||
2585 | } while (pNItem); | ||||||
2586 | if ( aOldSet.Count() || aNewSet.Count() ) | ||||||
2587 | SwLayoutFrame::Modify( &aOldSet, &aNewSet ); | ||||||
2588 | } | ||||||
2589 | else | ||||||
2590 | UpdateAttr_( pOld, pNew, nInvFlags ); | ||||||
2591 | |||||||
2592 | if ( nInvFlags != 0 ) | ||||||
2593 | { | ||||||
2594 | if ( nInvFlags & 0x01 ) | ||||||
2595 | InvalidateSize(); | ||||||
2596 | if ( nInvFlags & 0x10 ) | ||||||
2597 | SetCompletePaint(); | ||||||
2598 | } | ||||||
2599 | } | ||||||
2600 | |||||||
2601 | void SwSectionFrame::SwClientNotify( const SwModify& rMod, const SfxHint& rHint ) | ||||||
2602 | { | ||||||
2603 | SwFrame::SwClientNotify(rMod, rHint); | ||||||
2604 | // #i117863# | ||||||
2605 | if(&rMod != GetDep()) | ||||||
2606 | return; | ||||||
2607 | const auto pHint = dynamic_cast<const SwSectionFrameMoveAndDeleteHint*>(&rHint); | ||||||
2608 | if(!pHint) | ||||||
2609 | return; | ||||||
2610 | SwSectionFrame::MoveContentAndDelete( this, pHint->IsSaveContent() ); | ||||||
2611 | } | ||||||
2612 | |||||||
2613 | void SwSectionFrame::UpdateAttr_( const SfxPoolItem *pOld, const SfxPoolItem *pNew, | ||||||
2614 | sal_uInt8 &rInvFlags, | ||||||
2615 | SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet ) | ||||||
2616 | { | ||||||
2617 | bool bClear = true; | ||||||
2618 | const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; | ||||||
2619 | switch( nWhich ) | ||||||
2620 | { // Suppress multi columns in foot notes | ||||||
2621 | case RES_FMT_CHG: | ||||||
2622 | { | ||||||
2623 | const SwFormatCol& rNewCol = GetFormat()->GetCol(); | ||||||
2624 | if( !IsInFootnote() ) | ||||||
2625 | { | ||||||
2626 | // Nasty case. When allocating a template we can not count | ||||||
2627 | // on the old column attribute. We're left with creating a | ||||||
2628 | // temporary attribute here. | ||||||
2629 | SwFormatCol aCol; | ||||||
2630 | if ( Lower() && Lower()->IsColumnFrame() ) | ||||||
2631 | { | ||||||
2632 | sal_uInt16 nCol = 0; | ||||||
2633 | SwFrame *pTmp = Lower(); | ||||||
2634 | do | ||||||
2635 | { ++nCol; | ||||||
2636 | pTmp = pTmp->GetNext(); | ||||||
2637 | } while ( pTmp ); | ||||||
2638 | aCol.Init( nCol, 0, 1000 ); | ||||||
2639 | } | ||||||
2640 | bool bChgFootnote = IsFootnoteAtEnd(); | ||||||
2641 | bool const bChgEndn = IsEndnAtEnd(); | ||||||
2642 | bool const bChgMyEndn = IsEndnoteAtMyEnd(); | ||||||
2643 | CalcFootnoteAtEndFlag(); | ||||||
2644 | CalcEndAtEndFlag(); | ||||||
2645 | bChgFootnote = ( bChgFootnote != IsFootnoteAtEnd() ) || | ||||||
2646 | ( bChgEndn != IsEndnAtEnd() ) || | ||||||
2647 | ( bChgMyEndn != IsEndnoteAtMyEnd() ); | ||||||
2648 | ChgColumns( aCol, rNewCol, bChgFootnote ); | ||||||
2649 | rInvFlags |= 0x10; | ||||||
2650 | } | ||||||
2651 | rInvFlags |= 0x01; | ||||||
2652 | bClear = false; | ||||||
2653 | } | ||||||
2654 | break; | ||||||
2655 | |||||||
2656 | case RES_COL: | ||||||
2657 | if( !IsInFootnote() ) | ||||||
2658 | { | ||||||
2659 | assert(pOld && pNew)(static_cast <bool> (pOld && pNew) ? void (0) : __assert_fail ("pOld && pNew", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 2659, __extension__ __PRETTY_FUNCTION__)); | ||||||
2660 | if (pOld && pNew) | ||||||
2661 | { | ||||||
2662 | ChgColumns( *static_cast<const SwFormatCol*>(pOld), *static_cast<const SwFormatCol*>(pNew) ); | ||||||
2663 | rInvFlags |= 0x11; | ||||||
2664 | } | ||||||
2665 | } | ||||||
2666 | break; | ||||||
2667 | |||||||
2668 | case RES_FTN_AT_TXTEND: | ||||||
2669 | if( !IsInFootnote() ) | ||||||
2670 | { | ||||||
2671 | bool const bOld = IsFootnoteAtEnd(); | ||||||
2672 | CalcFootnoteAtEndFlag(); | ||||||
2673 | if (bOld != IsFootnoteAtEnd()) | ||||||
2674 | { | ||||||
2675 | const SwFormatCol& rNewCol = GetFormat()->GetCol(); | ||||||
2676 | ChgColumns( rNewCol, rNewCol, true ); | ||||||
2677 | rInvFlags |= 0x01; | ||||||
2678 | } | ||||||
2679 | } | ||||||
2680 | break; | ||||||
2681 | |||||||
2682 | case RES_END_AT_TXTEND: | ||||||
2683 | if( !IsInFootnote() ) | ||||||
2684 | { | ||||||
2685 | bool const bOld = IsEndnAtEnd(); | ||||||
2686 | bool const bMyOld = IsEndnoteAtMyEnd(); | ||||||
2687 | CalcEndAtEndFlag(); | ||||||
2688 | if (bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd()) | ||||||
2689 | { | ||||||
2690 | const SwFormatCol& rNewCol = GetFormat()->GetCol(); | ||||||
2691 | ChgColumns( rNewCol, rNewCol, true ); | ||||||
2692 | rInvFlags |= 0x01; | ||||||
2693 | } | ||||||
2694 | } | ||||||
2695 | break; | ||||||
2696 | case RES_COLUMNBALANCE: | ||||||
2697 | rInvFlags |= 0x01; | ||||||
2698 | break; | ||||||
2699 | |||||||
2700 | case RES_FRAMEDIR : | ||||||
2701 | SetDerivedR2L( false ); | ||||||
2702 | CheckDirChange(); | ||||||
2703 | break; | ||||||
2704 | |||||||
2705 | case RES_PROTECT: | ||||||
2706 | { | ||||||
2707 | SwViewShell *pSh = getRootFrame()->GetCurrShell(); | ||||||
2708 | if( pSh && pSh->GetLayout()->IsAnyShellAccessible() ) | ||||||
2709 | pSh->Imp()->InvalidateAccessibleEditableState( true, this ); | ||||||
2710 | } | ||||||
2711 | break; | ||||||
2712 | |||||||
2713 | default: | ||||||
2714 | bClear = false; | ||||||
2715 | } | ||||||
2716 | if ( bClear ) | ||||||
2717 | { | ||||||
2718 | if ( pOldSet || pNewSet ) | ||||||
2719 | { | ||||||
2720 | if ( pOldSet ) | ||||||
2721 | pOldSet->ClearItem( nWhich ); | ||||||
2722 | if ( pNewSet ) | ||||||
2723 | pNewSet->ClearItem( nWhich ); | ||||||
2724 | } | ||||||
2725 | else | ||||||
2726 | SwLayoutFrame::Modify( pOld, pNew ); | ||||||
2727 | } | ||||||
2728 | } | ||||||
2729 | |||||||
2730 | /// A follow or a ftncontainer at the end of the page causes a maximal Size of the sectionframe. | ||||||
2731 | bool SwSectionFrame::ToMaximize( bool bCheckFollow ) const | ||||||
2732 | { | ||||||
2733 | if( HasFollow() ) | ||||||
2734 | { | ||||||
2735 | if( !bCheckFollow ) // Don't check superfluous follows | ||||||
2736 | return true; | ||||||
2737 | const SwSectionFrame* pFoll = GetFollow(); | ||||||
2738 | while( pFoll && pFoll->IsSuperfluous() ) | ||||||
2739 | pFoll = pFoll->GetFollow(); | ||||||
2740 | if( pFoll ) | ||||||
2741 | return true; | ||||||
2742 | } | ||||||
2743 | if( IsFootnoteAtEnd() ) | ||||||
2744 | return false; | ||||||
2745 | const SwFootnoteContFrame* pCont = ContainsFootnoteCont(); | ||||||
2746 | if( !IsEndnAtEnd() ) | ||||||
2747 | return nullptr != pCont; | ||||||
2748 | bool bRet = false; | ||||||
2749 | while( pCont && !bRet ) | ||||||
2750 | { | ||||||
2751 | if( pCont->FindFootNote() ) | ||||||
2752 | bRet = true; | ||||||
2753 | else | ||||||
2754 | pCont = ContainsFootnoteCont( pCont ); | ||||||
2755 | } | ||||||
2756 | return bRet; | ||||||
2757 | } | ||||||
2758 | |||||||
2759 | /// Check every Column for FootnoteContFrames. | ||||||
2760 | SwFootnoteContFrame* SwSectionFrame::ContainsFootnoteCont( const SwFootnoteContFrame* pCont ) const | ||||||
2761 | { | ||||||
2762 | SwFootnoteContFrame* pRet = nullptr; | ||||||
2763 | const SwLayoutFrame* pLay; | ||||||
2764 | if( pCont ) | ||||||
2765 | { | ||||||
2766 | pLay = pCont->FindFootnoteBossFrame(); | ||||||
2767 | OSL_ENSURE( IsAnLower( pLay ), "ContainsFootnoteCont: Wrong FootnoteContainer" )do { if (true && (!(IsAnLower( pLay )))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2767" ": "), "%s", "ContainsFootnoteCont: Wrong FootnoteContainer" ); } } while (false); | ||||||
2768 | pLay = static_cast<const SwLayoutFrame*>(pLay->GetNext()); | ||||||
2769 | } | ||||||
2770 | else if( Lower() && Lower()->IsColumnFrame() ) | ||||||
2771 | pLay = static_cast<const SwLayoutFrame*>(Lower()); | ||||||
2772 | else | ||||||
2773 | pLay = nullptr; | ||||||
2774 | while ( !pRet && pLay ) | ||||||
2775 | { | ||||||
2776 | if( pLay->Lower() && pLay->Lower()->GetNext() ) | ||||||
2777 | { | ||||||
2778 | OSL_ENSURE( pLay->Lower()->GetNext()->IsFootnoteContFrame(),do { if (true && (!(pLay->Lower()->GetNext()-> IsFootnoteContFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2779" ": "), "%s", "ToMaximize: Unexpected Frame"); } } while (false) | ||||||
2779 | "ToMaximize: Unexpected Frame" )do { if (true && (!(pLay->Lower()->GetNext()-> IsFootnoteContFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2779" ": "), "%s", "ToMaximize: Unexpected Frame"); } } while (false); | ||||||
2780 | pRet = const_cast<SwFootnoteContFrame*>(static_cast<const SwFootnoteContFrame*>(pLay->Lower()->GetNext())); | ||||||
2781 | } | ||||||
2782 | OSL_ENSURE( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrame(),do { if (true && (!(!pLay->GetNext() || pLay->GetNext ()->IsLayoutFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2783" ": "), "%s", "ToMaximize: ColFrame expected"); } } while (false) | ||||||
2783 | "ToMaximize: ColFrame expected" )do { if (true && (!(!pLay->GetNext() || pLay->GetNext ()->IsLayoutFrame()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2783" ": "), "%s", "ToMaximize: ColFrame expected"); } } while (false); | ||||||
2784 | pLay = static_cast<const SwLayoutFrame*>(pLay->GetNext()); | ||||||
2785 | } | ||||||
2786 | return pRet; | ||||||
2787 | } | ||||||
2788 | |||||||
2789 | void SwSectionFrame::InvalidateFootnotePos() | ||||||
2790 | { | ||||||
2791 | SwFootnoteContFrame* pCont = ContainsFootnoteCont(); | ||||||
2792 | if( pCont ) | ||||||
2793 | { | ||||||
2794 | SwFrame *pTmp = pCont->ContainsContent(); | ||||||
2795 | if( pTmp ) | ||||||
2796 | pTmp->InvalidatePos_(); | ||||||
2797 | } | ||||||
2798 | } | ||||||
2799 | |||||||
2800 | SwTwips SwSectionFrame::CalcUndersize() const | ||||||
2801 | { | ||||||
2802 | SwRectFnSet aRectFnSet(this); | ||||||
2803 | return InnerHeight() - aRectFnSet.GetHeight(getFramePrintArea()); | ||||||
2804 | } | ||||||
2805 | |||||||
2806 | SwTwips SwSectionFrame::Undersize() | ||||||
2807 | { | ||||||
2808 | const auto nRet = CalcUndersize(); | ||||||
2809 | m_bUndersized = (nRet > 0); | ||||||
2810 | return nRet <= 0 ? 0 : nRet; | ||||||
2811 | } | ||||||
2812 | |||||||
2813 | void SwSectionFrame::CalcFootnoteContent() | ||||||
2814 | { | ||||||
2815 | vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut(); | ||||||
2816 | SwFootnoteContFrame* pCont = ContainsFootnoteCont(); | ||||||
2817 | if( !pCont ) | ||||||
2818 | return; | ||||||
2819 | |||||||
2820 | SwFrame* pFrame = pCont->ContainsAny(); | ||||||
2821 | if( pFrame ) | ||||||
2822 | pCont->Calc(pRenderContext); | ||||||
2823 | while( pFrame && IsAnLower( pFrame ) ) | ||||||
2824 | { | ||||||
2825 | SwFootnoteFrame* pFootnote = pFrame->FindFootnoteFrame(); | ||||||
2826 | if( pFootnote ) | ||||||
2827 | pFootnote->Calc(pRenderContext); | ||||||
2828 | pFrame->Calc(pRenderContext); | ||||||
2829 | if( pFrame->IsSctFrame() ) | ||||||
2830 | { | ||||||
2831 | SwFrame *pTmp = static_cast<SwSectionFrame*>(pFrame)->ContainsAny(); | ||||||
2832 | if( pTmp ) | ||||||
2833 | { | ||||||
2834 | pFrame = pTmp; | ||||||
2835 | continue; | ||||||
2836 | } | ||||||
2837 | } | ||||||
2838 | pFrame = pFrame->FindNext(); | ||||||
2839 | } | ||||||
2840 | } | ||||||
2841 | |||||||
2842 | /* | ||||||
2843 | * If a SectionFrame gets empty, e.g. because its content changes the page/column, | ||||||
2844 | * it is not destroyed immediately (there could be a pointer left to it on the | ||||||
2845 | * stack), instead it puts itself in a list at the RootFrame, which is processed | ||||||
2846 | * later on (in Layaction::Action among others). Its size is set to Null and | ||||||
2847 | * the pointer to its page as well. Such SectionFrames that are to be deleted | ||||||
2848 | * must be ignored by the layout/during formatting. | ||||||
2849 | * | ||||||
2850 | * With InsertEmptySct the RootFrame stores a SectionFrame in the list, | ||||||
2851 | * with RemoveFromList it can be removed from the list (Dtor), | ||||||
2852 | * with DeleteEmptySct the list is processed and the SectionFrames are destroyed. | ||||||
2853 | */ | ||||||
2854 | void SwRootFrame::InsertEmptySct( SwSectionFrame* pDel ) | ||||||
2855 | { | ||||||
2856 | if( !mpDestroy ) | ||||||
2857 | mpDestroy.reset( new SwDestroyList ); | ||||||
2858 | mpDestroy->insert( pDel ); | ||||||
2859 | } | ||||||
2860 | |||||||
2861 | void SwRootFrame::DeleteEmptySct_() | ||||||
2862 | { | ||||||
2863 | assert(mpDestroy)(static_cast <bool> (mpDestroy) ? void (0) : __assert_fail ("mpDestroy", "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 2863, __extension__ __PRETTY_FUNCTION__)); | ||||||
2864 | while( !mpDestroy->empty() ) | ||||||
2865 | { | ||||||
2866 | SwSectionFrame* pSect = *mpDestroy->begin(); | ||||||
2867 | mpDestroy->erase( mpDestroy->begin() ); | ||||||
2868 | OSL_ENSURE( !pSect->IsColLocked() && !pSect->IsJoinLocked(),do { if (true && (!(!pSect->IsColLocked() && !pSect->IsJoinLocked()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2869" ": "), "%s", "DeleteEmptySct: Locked SectionFrame" ); } } while (false) | ||||||
2869 | "DeleteEmptySct: Locked SectionFrame" )do { if (true && (!(!pSect->IsColLocked() && !pSect->IsJoinLocked()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2869" ": "), "%s", "DeleteEmptySct: Locked SectionFrame" ); } } while (false); | ||||||
2870 | if( !pSect->getFrameArea().HasArea() && !pSect->ContainsContent() ) | ||||||
2871 | { | ||||||
2872 | SwLayoutFrame* pUp = pSect->GetUpper(); | ||||||
2873 | pSect->RemoveFromLayout(); | ||||||
2874 | SwFrame::DestroyFrame(pSect); | ||||||
2875 | if( pUp && !pUp->Lower() ) | ||||||
2876 | { | ||||||
2877 | if( pUp->IsPageBodyFrame() ) | ||||||
2878 | pUp->getRootFrame()->SetSuperfluous(); | ||||||
2879 | else if( pUp->IsFootnoteFrame() && !pUp->IsColLocked() && | ||||||
2880 | pUp->GetUpper() ) | ||||||
2881 | { | ||||||
2882 | pUp->Cut(); | ||||||
2883 | SwFrame::DestroyFrame(pUp); | ||||||
2884 | } | ||||||
2885 | } | ||||||
2886 | } | ||||||
2887 | else { | ||||||
2888 | OSL_ENSURE( pSect->GetSection(), "DeleteEmptySct: Half-dead SectionFrame?!" )do { if (true && (!(pSect->GetSection()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" ":" "2888" ": "), "%s", "DeleteEmptySct: Half-dead SectionFrame?!" ); } } while (false); | ||||||
2889 | } | ||||||
2890 | } | ||||||
2891 | } | ||||||
2892 | |||||||
2893 | void SwRootFrame::RemoveFromList_( SwSectionFrame* pSct ) | ||||||
2894 | { | ||||||
2895 | assert(mpDestroy && "Where's my list?")(static_cast <bool> (mpDestroy && "Where's my list?" ) ? void (0) : __assert_fail ("mpDestroy && \"Where's my list?\"" , "/home/maarten/src/libreoffice/core/sw/source/core/layout/sectfrm.cxx" , 2895, __extension__ __PRETTY_FUNCTION__)); | ||||||
2896 | mpDestroy->erase( pSct ); | ||||||
2897 | } | ||||||
2898 | |||||||
2899 | #ifdef DBG_UTIL | ||||||
2900 | bool SwRootFrame::IsInDelList( SwSectionFrame* pSct ) const | ||||||
2901 | { | ||||||
2902 | return mpDestroy && mpDestroy->find( pSct ) != mpDestroy->end(); | ||||||
2903 | } | ||||||
2904 | #endif | ||||||
2905 | |||||||
2906 | bool SwSectionFrame::IsBalancedSection() const | ||||||
2907 | { | ||||||
2908 | bool bRet = false; | ||||||
2909 | if ( GetSection() && Lower() && Lower()->IsColumnFrame() && Lower()->GetNext() ) | ||||||
2910 | { | ||||||
2911 | bRet = !GetSection()->GetFormat()->GetBalancedColumns().GetValue(); | ||||||
2912 | } | ||||||
2913 | return bRet; | ||||||
2914 | } | ||||||
2915 | |||||||
2916 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | /* |
3 | * This file is part of the LibreOffice project. |
4 | * |
5 | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | * |
9 | * This file incorporates work covered by the following license notice: |
10 | * |
11 | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | * contributor license agreements. See the NOTICE file distributed |
13 | * with this work for additional information regarding copyright |
14 | * ownership. The ASF licenses this file to you under the Apache |
15 | * License, Version 2.0 (the "License"); you may not use this file |
16 | * except in compliance with the License. You may obtain a copy of |
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | */ |
19 | #ifndef INCLUDED_SW_SOURCE_CORE_INC_LAYFRM_HXX |
20 | #define INCLUDED_SW_SOURCE_CORE_INC_LAYFRM_HXX |
21 | |
22 | #include "frame.hxx" |
23 | #include <swdllapi.h> |
24 | |
25 | class SwAnchoredObject; |
26 | class SwContentFrame; |
27 | class SwFormatCol; |
28 | struct SwCursorMoveState; |
29 | class SwFrameFormat; |
30 | class SwBorderAttrs; |
31 | class SwFormatFrameSize; |
32 | class SwCellFrame; |
33 | |
34 | /// A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame. |
35 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwLayoutFrame: public SwFrame |
36 | { |
37 | // The SwFrame in disguise |
38 | friend class SwFlowFrame; |
39 | friend class SwFrame; |
40 | |
41 | // Releases the Lower while restructuring columns |
42 | friend SwFrame* SaveContent( SwLayoutFrame *, SwFrame * ); |
43 | friend void RestoreContent( SwFrame *, SwLayoutFrame *, SwFrame *pSibling ); |
44 | |
45 | protected: |
46 | |
47 | virtual void DestroyImpl() override; |
48 | virtual ~SwLayoutFrame() override; |
49 | |
50 | virtual void Format( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ) override; |
51 | virtual void MakeAll(vcl::RenderContext* pRenderContext) override; |
52 | |
53 | SwFrame * m_pLower; |
54 | std::vector<SwAnchoredObject*> m_VertPosOrientFramesFor; |
55 | |
56 | virtual SwTwips ShrinkFrame( SwTwips, bool bTst = false, bool bInfo = false ) override; |
57 | virtual SwTwips GrowFrame ( SwTwips, bool bTst = false, bool bInfo = false ) override; |
58 | |
59 | long CalcRel( const SwFormatFrameSize &rSz ) const; |
60 | |
61 | public: |
62 | // --> #i28701# |
63 | |
64 | virtual void PaintSubsidiaryLines( const SwPageFrame*, const SwRect& ) const; |
65 | void RefreshLaySubsidiary( const SwPageFrame*, const SwRect& ) const; |
66 | void RefreshExtraData( const SwRect & ) const; |
67 | |
68 | /// Change size of lowers proportionally |
69 | void ChgLowersProp( const Size& rOldSize ); |
70 | |
71 | void AdjustColumns( const SwFormatCol *pCol, bool bAdjustAttributes ); |
72 | |
73 | void ChgColumns( const SwFormatCol &rOld, const SwFormatCol &rNew, |
74 | const bool bChgFootnote = false ); |
75 | |
76 | /// Paints the column separation line for the inner columns |
77 | void PaintColLines( const SwRect &, const SwFormatCol &, |
78 | const SwPageFrame * ) const; |
79 | |
80 | virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const override; |
81 | |
82 | virtual bool GetModelPositionForViewPoint( SwPosition *, Point&, |
83 | SwCursorMoveState* = nullptr, bool bTestBackground = false ) const override; |
84 | |
85 | virtual void Cut() override; |
86 | virtual void Paste( SwFrame* pParent, SwFrame* pSibling = nullptr ) override; |
87 | |
88 | /** |
89 | * Finds the closest Content for the SPoint |
90 | * Is used for Pages, Flys and Cells if GetModelPositionForViewPoint failed |
91 | */ |
92 | const SwContentFrame* GetContentPos( Point &rPoint, const bool bDontLeave, |
93 | const bool bBodyOnly = false, |
94 | SwCursorMoveState *pCMS = nullptr, |
95 | const bool bDefaultExpand = true ) const; |
96 | |
97 | SwLayoutFrame( SwFrameFormat*, SwFrame* ); |
98 | |
99 | virtual void PaintSwFrame( vcl::RenderContext& rRenderContext, SwRect const&, |
100 | SwPrintData const*const pPrintData = nullptr ) const override; |
101 | const SwFrame *Lower() const { return m_pLower; } |
102 | SwFrame *Lower() { return m_pLower; } |
103 | const SwContentFrame *ContainsContent() const; |
104 | inline SwContentFrame *ContainsContent(); |
105 | const SwCellFrame *FirstCell() const; |
106 | inline SwCellFrame *FirstCell(); |
107 | |
108 | /** |
109 | * Method <ContainsAny()> doesn't investigate content of footnotes by default. |
110 | * But under certain circumstances this investigation is intended. |
111 | * Thus, introduce new optional parameter <_bInvestigateFootnoteForSections>. |
112 | * It's default is <false>, still indicating that content of footnotes isn't |
113 | * investigated for sections. |
114 | */ |
115 | const SwFrame *ContainsAny( const bool _bInvestigateFootnoteForSections = false ) const; |
116 | inline SwFrame *ContainsAny( const bool _bInvestigateFootnoteForSections = false ); |
117 | bool IsAnLower( const SwFrame * ) const; |
118 | |
119 | virtual const SwFrameFormat *GetFormat() const; |
120 | virtual SwFrameFormat *GetFormat(); |
121 | void SetFrameFormat( SwFrameFormat* ); |
122 | |
123 | /** |
124 | * Moving the Footnotes of all Lowers - starting from StartContent |
125 | * |
126 | * @returns true if at least one Footnote was moved |
127 | * Calls the page number update if bFootnoteNums is set |
128 | */ |
129 | bool MoveLowerFootnotes( SwContentFrame *pStart, SwFootnoteBossFrame *pOldBoss, |
130 | SwFootnoteBossFrame *pNewBoss, const bool bFootnoteNums ); |
131 | |
132 | // --> #i28701# - change purpose of method and its name |
133 | // --> #i44016# - add parameter <_bUnlockPosOfObjs> to |
134 | /// force an unlockposition call for the lower objects. |
135 | void NotifyLowerObjs( const bool _bUnlockPosOfObjs = false ); |
136 | |
137 | /** |
138 | * Invalidates the inner Frames, whose width and/or height are |
139 | * calculated using percentages. |
140 | * Frames that are anchored to this or inner Frames, are also invalidated. |
141 | */ |
142 | void InvaPercentLowers( SwTwips nDiff = 0 ); |
143 | |
144 | /// Called by Format for Frames and Areas with columns |
145 | void FormatWidthCols( const SwBorderAttrs &, const SwTwips nBorder, |
146 | const SwTwips nMinHeight ); |
147 | |
148 | /** |
149 | * InnerHeight returns the height of the content and may be bigger or |
150 | * less than the PrtArea-Height of the layoutframe himself |
151 | */ |
152 | SwTwips InnerHeight() const; |
153 | |
154 | /** method to check relative position of layout frame to |
155 | a given layout frame. |
156 | |
157 | refactoring of pseudo-local method <lcl_Apres(..)> in |
158 | <txtftn.cxx> for #104840#. |
159 | |
160 | @param _aCheckRefLayFrame |
161 | constant reference of an instance of class <SwLayoutFrame> which |
162 | is used as the reference for the relative position check. |
163 | |
164 | @return true, if <this> is positioned before the layout frame <p> |
165 | */ |
166 | bool IsBefore( const SwLayoutFrame* _pCheckRefLayFrame ) const; |
167 | |
168 | const SwFrame* GetLastLower() const; |
169 | inline SwFrame* GetLastLower(); |
170 | |
171 | virtual void PaintBreak() const; |
172 | |
173 | void SetVertPosOrientFrameFor(SwAnchoredObject *pObj) |
174 | { |
175 | m_VertPosOrientFramesFor.push_back(pObj); |
176 | } |
177 | |
178 | void ClearVertPosOrientFrameFor(SwAnchoredObject *pObj) |
179 | { |
180 | m_VertPosOrientFramesFor.erase( |
181 | std::remove(m_VertPosOrientFramesFor.begin(), |
182 | m_VertPosOrientFramesFor.end(), pObj), |
183 | m_VertPosOrientFramesFor.end()); |
184 | } |
185 | }; |
186 | |
187 | /** |
188 | * In order to save us from duplicating implementations, we cast here |
189 | * a little. |
190 | */ |
191 | inline SwContentFrame* SwLayoutFrame::ContainsContent() |
192 | { |
193 | return const_cast<SwContentFrame*>(static_cast<const SwLayoutFrame*>(this)->ContainsContent()); |
194 | } |
195 | |
196 | inline SwCellFrame* SwLayoutFrame::FirstCell() |
197 | { |
198 | return const_cast<SwCellFrame*>(static_cast<const SwLayoutFrame*>(this)->FirstCell()); |
199 | } |
200 | |
201 | inline SwFrame* SwLayoutFrame::ContainsAny( const bool _bInvestigateFootnoteForSections ) |
202 | { |
203 | return const_cast<SwFrame*>(static_cast<const SwLayoutFrame*>(this)->ContainsAny( _bInvestigateFootnoteForSections )); |
204 | } |
205 | |
206 | /** |
207 | * These SwFrame inlines are here, so that frame.hxx does not need to include layfrm.hxx |
208 | */ |
209 | inline bool SwFrame::IsColBodyFrame() const |
210 | { |
211 | return mnFrameType == SwFrameType::Body && GetUpper()->IsColumnFrame(); |
212 | } |
213 | |
214 | inline bool SwFrame::IsPageBodyFrame() const |
215 | { |
216 | return mnFrameType == SwFrameType::Body && GetUpper()->IsPageFrame(); |
217 | } |
218 | |
219 | inline SwFrame* SwLayoutFrame::GetLastLower() |
220 | { |
221 | return const_cast<SwFrame*>(static_cast<const SwLayoutFrame*>(this)->GetLastLower()); |
222 | } |
223 | |
224 | #endif // INCLUDED_SW_SOURCE_CORE_INC_LAYFRM_HXX |
225 | |
226 | /* 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: */ |