Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <hintids.hxx>
30 : : #include <editeng/brkitem.hxx>
31 : : #include <tools/stream.hxx>
32 : : #include <doc.hxx>
33 : : #include <docstat.hxx>
34 : : #include <docary.hxx>
35 : : #include <fmtpdsc.hxx>
36 : : #include <laycache.hxx>
37 : : #include <layhelp.hxx>
38 : : #include <pagefrm.hxx>
39 : : #include <rootfrm.hxx>
40 : : #include <txtfrm.hxx>
41 : : #include <ndtxt.hxx>
42 : : #include <swtable.hxx>
43 : : #include <tabfrm.hxx>
44 : : #include <rowfrm.hxx>
45 : : #include <colfrm.hxx>
46 : : #include <bodyfrm.hxx>
47 : : #include <ndindex.hxx>
48 : : #include <sectfrm.hxx>
49 : : #include <frmfmt.hxx>
50 : : #include <fmtcntnt.hxx>
51 : : #include <pagedesc.hxx>
52 : : #include <frmtool.hxx>
53 : : #include <dflyobj.hxx>
54 : : #include <dcontact.hxx>
55 : : #include "viewopt.hxx"
56 : : #include "viewsh.hxx"
57 : : #include <flyfrm.hxx>
58 : : // OD 2004-05-24 #i28701#
59 : : #include <sortedobjs.hxx>
60 : : //
61 : : #include <pam.hxx>
62 : : #include <docsh.hxx>
63 : : #include <poolfmt.hxx>
64 : : #include <com/sun/star/document/XDocumentInfoSupplier.hpp>
65 : : #include <com/sun/star/beans/XPropertySet.hpp>
66 : :
67 : : #include <set>
68 : :
69 : :
70 : : using namespace ::com::sun::star;
71 : :
72 : : /*
73 : : * Reading and writing of the layout cache.
74 : : * The layout cache is not necessary, but it improves
75 : : * the performance and reduces the text flow during
76 : : * the formatting.
77 : : * The layout cache contains the index of the paragraphs/tables
78 : : * at the top of every page, so it's possible to create
79 : : * the right count of pages and to distribute the document content
80 : : * to this pages before the formatting starts.
81 : : */
82 : :
83 : 12 : void SwLayoutCache::Read( SvStream &rStream )
84 : : {
85 [ + - ]: 12 : if( !pImpl )
86 : : {
87 [ + - ]: 12 : pImpl = new SwLayCacheImpl;
88 [ - + ]: 12 : if( !pImpl->Read( rStream ) )
89 : : {
90 [ # # ]: 0 : delete pImpl;
91 : 0 : pImpl = 0;
92 : : }
93 : : }
94 : 12 : }
95 : :
96 : : //-----------------------------------------------------------------------------
97 : :
98 : 42 : void SwLayCacheImpl::Insert( sal_uInt16 nType, sal_uLong nIndex, xub_StrLen nOffset )
99 : : {
100 : 42 : aType.push_back( nType );
101 : 42 : std::vector<sal_uLong>::push_back( nIndex );
102 : 42 : aOffset.push_back( nOffset );
103 : 42 : }
104 : :
105 : 12 : sal_Bool SwLayCacheImpl::Read( SvStream& rStream )
106 : : {
107 [ + - ]: 12 : SwLayCacheIoImpl aIo( rStream, sal_False );
108 [ - + ]: 12 : if( aIo.GetMajorVersion() > SW_LAYCACHE_IO_VERSION_MAJOR )
109 : 0 : return sal_False;
110 : :
111 : : // Due to an evil bug in the layout cache (#102759#), we cannot trust the
112 : : // sizes of fly frames which have been written using the "old" layout cache.
113 : : // This flag should indicate that we do not want to trust the width and
114 : : // height of fly frames
115 : 12 : bUseFlyCache = aIo.GetMinorVersion() >= 1;
116 : :
117 : : sal_uInt8 cFlags;
118 : : sal_uInt32 nIndex, nOffset;
119 : :
120 [ + - ]: 12 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
121 [ + - ]: 12 : aIo.OpenFlagRec();
122 [ + - ]: 12 : aIo.CloseFlagRec();
123 [ + - ][ + + ]: 62 : while( aIo.BytesLeft() && !aIo.HasError() )
[ + - ][ + + ]
124 : : {
125 [ + - ]: 50 : switch( aIo.Peek() )
[ + - + - ]
126 : : {
127 : : case SW_LAYCACHE_IO_REC_PARA:
128 [ + - ]: 42 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
129 [ + - ]: 42 : cFlags = aIo.OpenFlagRec();
130 [ + - ]: 42 : aIo.GetStream() >> nIndex;
131 [ + + ]: 42 : if( (cFlags & 0x01) != 0 )
132 [ + - ]: 8 : aIo.GetStream() >> nOffset;
133 : : else
134 : 34 : nOffset = STRING_LEN;
135 [ + - ]: 42 : aIo.CloseFlagRec();
136 [ + - ]: 42 : Insert( SW_LAYCACHE_IO_REC_PARA, nIndex, (xub_StrLen)nOffset );
137 [ + - ]: 42 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
138 : 42 : break;
139 : : case SW_LAYCACHE_IO_REC_TABLE:
140 [ # # ]: 0 : aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
141 [ # # ]: 0 : aIo.OpenFlagRec();
142 [ # # ]: 0 : aIo.GetStream() >> nIndex
143 [ # # ]: 0 : >> nOffset;
144 [ # # ]: 0 : Insert( SW_LAYCACHE_IO_REC_TABLE, nIndex, (xub_StrLen)nOffset );
145 [ # # ]: 0 : aIo.CloseFlagRec();
146 [ # # ]: 0 : aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
147 : 0 : break;
148 : : case SW_LAYCACHE_IO_REC_FLY:
149 : : {
150 [ + - ]: 8 : aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
151 [ + - ]: 8 : aIo.OpenFlagRec();
152 [ + - ]: 8 : aIo.CloseFlagRec();
153 : : sal_Int32 nX, nY, nW, nH;
154 : : sal_uInt16 nPgNum;
155 [ + - ][ + - ]: 8 : aIo.GetStream() >> nPgNum >> nIndex
156 [ + - ][ + - ]: 8 : >> nX >> nY >> nW >> nH;
[ + - ][ + - ]
157 [ + - ]: 8 : SwFlyCache* pFly = new SwFlyCache( nPgNum, nIndex, nX, nY, nW, nH );
158 [ + - ]: 8 : aFlyCache.push_back( pFly );
159 [ + - ]: 8 : aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
160 : : break;
161 : : }
162 : : default:
163 [ # # ]: 0 : aIo.SkipRec();
164 : 0 : break;
165 : : }
166 : : }
167 [ + - ]: 12 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
168 : :
169 : 12 : return !aIo.HasError();
170 : : }
171 : :
172 : : /*
173 : : * SwLayoutCache::Write(..)
174 : : * writes the index (more precise: the difference between
175 : : * the index and the first index of the document content)
176 : : * of the first paragraph/table at the top of every page.
177 : : * If at the top of a page is the rest of a paragraph/table
178 : : * from the bottom of the previous page, the character/row
179 : : * number is stored, too.
180 : : * The position, size and page number of the text frames
181 : : * are stored, too
182 : : */
183 : :
184 : 4 : void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc )
185 : : {
186 [ + - ]: 4 : if( rDoc.GetCurrentLayout() ) // the layout itself .. //swmod 080218
187 : : {
188 [ + - ]: 4 : SwLayCacheIoImpl aIo( rStream, sal_True );
189 : : // We want to save the relative index, so we need the index
190 : : // of the first content
191 [ + - ]: 4 : sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
192 : 4 : StartOfSectionNode()->GetIndex();
193 : : // The first page..
194 [ + - ]: 4 : SwPageFrm* pPage = (SwPageFrm*)rDoc.GetCurrentLayout()->Lower(); //swmod 080218
195 : :
196 [ + - ]: 4 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
197 [ + - ]: 4 : aIo.OpenFlagRec( 0, 0 );
198 [ + - ]: 4 : aIo.CloseFlagRec();
199 [ + + ]: 18 : while( pPage )
200 : : {
201 [ + + ]: 14 : if( pPage->GetPrev() )
202 : : {
203 [ + - ]: 10 : SwLayoutFrm* pLay = pPage->FindBodyCont();
204 [ + - ][ + - ]: 10 : SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
205 : : // We are only interested in paragraph or table frames,
206 : : // a section frames contains paragraphs/tables.
207 [ + - ][ + + ]: 10 : if( pTmp && pTmp->IsSctFrm() )
[ + + ]
208 [ + - ]: 2 : pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
209 : :
210 [ + - ]: 10 : if( pTmp ) // any content
211 : : {
212 [ + - ]: 10 : if( pTmp->IsTxtFrm() )
213 : : {
214 : 10 : sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
215 [ + - ]: 10 : if( nNdIdx > nStartOfContent )
216 : : {
217 : : /* Open Paragraph Record */
218 [ + - ]: 10 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
219 : 10 : sal_Bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
220 : : aIo.OpenFlagRec( bFollow ? 0x01 : 0x00,
221 [ + + ][ + - ]: 10 : bFollow ? 8 : 4 );
[ + + ]
222 : 10 : nNdIdx -= nStartOfContent;
223 [ + - ]: 10 : aIo.GetStream() << static_cast<sal_uInt32>(nNdIdx);
224 [ + + ]: 10 : if( bFollow )
225 [ + - ]: 8 : aIo.GetStream() << static_cast<sal_uInt32>(((SwTxtFrm*)pTmp)->GetOfst());
226 [ + - ]: 10 : aIo.CloseFlagRec();
227 : : /* Close Paragraph Record */
228 [ + - ]: 10 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
229 : : }
230 : : }
231 [ # # ]: 0 : else if( pTmp->IsTabFrm() )
232 : : {
233 : 0 : SwTabFrm* pTab = (SwTabFrm*)pTmp;
234 : 0 : sal_uLong nOfst = STRING_LEN;
235 [ # # ]: 0 : if( pTab->IsFollow() )
236 : : {
237 : : // If the table is a follow, we have to look for the
238 : : // master and to count all rows to get the row number
239 : 0 : nOfst = 0;
240 [ # # ]: 0 : if( pTab->IsFollow() )
241 [ # # ]: 0 : pTab = pTab->FindMaster( true );
242 [ # # ]: 0 : while( pTab != pTmp )
243 : : {
244 : 0 : SwFrm* pSub = pTab->Lower();
245 [ # # ]: 0 : while( pSub )
246 : : {
247 : 0 : ++nOfst;
248 : 0 : pSub = pSub->GetNext();
249 : : }
250 : 0 : pTab = pTab->GetFollow();
251 : : OSL_ENSURE( pTab, "Table follow without master" );
252 : : }
253 : : }
254 [ # # ]: 0 : do
255 : : {
256 : : sal_uLong nNdIdx =
257 [ # # ]: 0 : pTab->GetTable()->GetTableNode()->GetIndex();
258 [ # # ]: 0 : if( nNdIdx > nStartOfContent )
259 : : {
260 : : /* Open Table Record */
261 [ # # ]: 0 : aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
262 [ # # ]: 0 : aIo.OpenFlagRec( 0, 8 );
263 : 0 : nNdIdx -= nStartOfContent;
264 [ # # ]: 0 : aIo.GetStream() << static_cast<sal_uInt32>(nNdIdx)
265 [ # # ]: 0 : << static_cast<sal_uInt32>(nOfst);
266 [ # # ]: 0 : aIo.CloseFlagRec();
267 : : /* Close Table Record */
268 [ # # ]: 0 : aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
269 : : }
270 : : // If the table has a follow on the next page,
271 : : // we know already the row number and store this
272 : : // immediately.
273 [ # # ]: 0 : if( pTab->GetFollow() )
274 : : {
275 [ # # ]: 0 : if( nOfst == STRING_LEN )
276 : 0 : nOfst = 0;
277 [ # # ]: 0 : do
278 : : {
279 : 0 : SwFrm* pSub = pTab->Lower();
280 [ # # ]: 0 : while( pSub )
281 : : {
282 : 0 : ++nOfst;
283 : 0 : pSub = pSub->GetNext();
284 : : }
285 : 0 : pTab = pTab->GetFollow();
286 [ # # ]: 0 : SwPageFrm *pTabPage = pTab->FindPageFrm();
287 [ # # ]: 0 : if( pTabPage != pPage )
288 : : {
289 : : OSL_ENSURE( pPage->GetPhyPageNum() <
290 : : pTabPage->GetPhyPageNum(),
291 : : "Looping Tableframes" );
292 : 0 : pPage = pTabPage;
293 : 0 : break;
294 : : }
295 : 0 : } while ( pTab->GetFollow() );
296 : : }
297 : : else
298 : 0 : break;
299 : : } while( pTab );
300 : : }
301 : : }
302 : : }
303 [ - + ]: 14 : if( pPage->GetSortedObjs() )
304 : : {
305 : 0 : SwSortedObjs &rObjs = *pPage->GetSortedObjs();
306 [ # # ][ # # ]: 0 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
307 : : {
308 [ # # ]: 0 : SwAnchoredObject* pAnchoredObj = rObjs[i];
309 [ # # ][ # # ]: 0 : if ( pAnchoredObj->ISA(SwFlyFrm) )
[ # # ]
310 : : {
311 [ # # ]: 0 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
312 [ # # ][ # # ]: 0 : if( pFly->Frm().Left() != FAR_AWAY &&
[ # # ]
313 [ # # ][ # # ]: 0 : !pFly->GetAnchorFrm()->FindFooterOrHeader() )
314 : : {
315 : : const SwContact *pC =
316 [ # # ][ # # ]: 0 : ::GetUserCall(pAnchoredObj->GetDrawObj());
317 [ # # ]: 0 : if( pC )
318 : : {
319 [ # # ][ # # ]: 0 : sal_uInt32 nOrdNum = pAnchoredObj->GetDrawObj()->GetOrdNum();
320 : 0 : sal_uInt16 nPageNum = pPage->GetPhyPageNum();
321 : : /* Open Fly Record */
322 [ # # ]: 0 : aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
323 [ # # ]: 0 : aIo.OpenFlagRec( 0, 0 );
324 [ # # ]: 0 : aIo.CloseFlagRec();
325 : 0 : SwRect &rRct = pFly->Frm();
326 : 0 : sal_Int32 nX = rRct.Left() - pPage->Frm().Left();
327 : 0 : sal_Int32 nY = rRct.Top() - pPage->Frm().Top();
328 [ # # ][ # # ]: 0 : aIo.GetStream() << nPageNum << nOrdNum
329 [ # # ][ # # ]: 0 : << nX << nY
330 [ # # ]: 0 : << static_cast<sal_Int32>(rRct.Width())
331 [ # # ]: 0 : << static_cast<sal_Int32>(rRct.Height());
332 : : /* Close Fly Record */
333 [ # # ]: 0 : aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
334 : : }
335 : : }
336 : : }
337 : : }
338 : : }
339 : 14 : pPage = (SwPageFrm*)pPage->GetNext();
340 : : }
341 [ + - ]: 4 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
342 : : }
343 : 4 : }
344 : :
345 : : #ifdef DBG_UTIL
346 : : sal_Bool SwLayoutCache::CompareLayout( const SwDoc& rDoc ) const
347 : : {
348 : : if( !pImpl )
349 : : return sal_True;
350 : : const SwRootFrm *pRootFrm = rDoc.GetCurrentLayout();
351 : : sal_Bool bRet = sal_True;
352 : : if( pRootFrm )
353 : : {
354 : : sal_uInt16 nIndex = 0;
355 : : sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
356 : : StartOfSectionNode()->GetIndex();
357 : : SwPageFrm* pPage = (SwPageFrm*)pRootFrm->Lower();
358 : : if( pPage )
359 : : pPage = (SwPageFrm*)pPage->GetNext();
360 : : while( pPage )
361 : : {
362 : : if( nIndex >= pImpl->size() )
363 : : {
364 : : if( bRet )
365 : : bRet = sal_False;
366 : : break;
367 : : }
368 : : SwLayoutFrm* pLay = pPage->FindBodyCont();
369 : : SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
370 : : if( pTmp && pTmp->IsSctFrm() )
371 : : pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
372 : : if( pTmp )
373 : : {
374 : : if( pTmp->IsTxtFrm() )
375 : : {
376 : : sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
377 : : if( nNdIdx > nStartOfContent )
378 : : {
379 : : sal_Bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
380 : : nNdIdx -= nStartOfContent;
381 : : if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
382 : : SW_LAYCACHE_IO_REC_PARA !=
383 : : pImpl->GetBreakType( nIndex ) ||
384 : : ( bFollow ? ((SwTxtFrm*)pTmp)->GetOfst()
385 : : : STRING_LEN ) != pImpl->GetBreakOfst( nIndex ) )
386 : : {
387 : : if( bRet )
388 : : bRet = sal_False;
389 : : }
390 : : ++nIndex;
391 : : }
392 : : }
393 : : else if( pTmp->IsTabFrm() )
394 : : {
395 : : SwTabFrm* pTab = (SwTabFrm*)pTmp;
396 : : sal_uLong nOfst = STRING_LEN;
397 : : if( pTab->IsFollow() )
398 : : {
399 : : nOfst = 0;
400 : : if( pTab->IsFollow() )
401 : : pTab = pTab->FindMaster( true );
402 : : while( pTab != pTmp )
403 : : {
404 : : SwFrm* pSub = pTab->Lower();
405 : : while( pSub )
406 : : {
407 : : ++nOfst;
408 : : pSub = pSub->GetNext();
409 : : }
410 : : pTab = pTab->GetFollow();
411 : : }
412 : : }
413 : : do
414 : : {
415 : : sal_uLong nNdIdx =
416 : : pTab->GetTable()->GetTableNode()->GetIndex();
417 : : if( nNdIdx > nStartOfContent )
418 : : {
419 : : nNdIdx -= nStartOfContent;
420 : : if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
421 : : SW_LAYCACHE_IO_REC_TABLE !=
422 : : pImpl->GetBreakType( nIndex ) ||
423 : : nOfst != pImpl->GetBreakOfst( nIndex ) )
424 : : {
425 : : if( bRet )
426 : : bRet = sal_False;
427 : : }
428 : : ++nIndex;
429 : : }
430 : : if( pTab->GetFollow() )
431 : : {
432 : : if( nOfst == STRING_LEN )
433 : : nOfst = 0;
434 : : do
435 : : {
436 : : SwFrm* pSub = pTab->Lower();
437 : : while( pSub )
438 : : {
439 : : ++nOfst;
440 : : pSub = pSub->GetNext();
441 : : }
442 : : pTab = pTab->GetFollow();
443 : : SwPageFrm *pTabPage = pTab->FindPageFrm();
444 : : if( pTabPage != pPage )
445 : : {
446 : : pPage = pTabPage;
447 : : break;
448 : : }
449 : : } while ( pTab->GetFollow() );
450 : : }
451 : : else
452 : : break;
453 : : } while( pTab );
454 : : }
455 : : }
456 : : pPage = (SwPageFrm*)pPage->GetNext();
457 : : }
458 : : }
459 : : return bRet;
460 : : }
461 : : #endif
462 : :
463 : 12 : void SwLayoutCache::ClearImpl()
464 : : {
465 [ + - ]: 12 : if( !IsLocked() )
466 : : {
467 [ + - ]: 12 : delete pImpl;
468 : 12 : pImpl = 0;
469 : : }
470 : 12 : }
471 : :
472 : :
473 : 9 : SwLayoutCache::~SwLayoutCache()
474 : : {
475 : : OSL_ENSURE( !nLockCount, "Deleting a locked SwLayoutCache!?" );
476 [ - + ]: 9 : delete pImpl;
477 : 9 : }
478 : :
479 : : /*
480 : : * SwActualSection,
481 : : * a help class to create not nested section frames
482 : : * for nested sections.
483 : : */
484 : :
485 : 126 : SwActualSection::SwActualSection( SwActualSection *pUp,
486 : : SwSectionFrm *pSect,
487 : : SwSectionNode *pNd ) :
488 : : pUpper( pUp ),
489 : : pSectFrm( pSect ),
490 : 126 : pSectNode( pNd )
491 : : {
492 [ + + ]: 126 : if ( !pSectNode )
493 : : {
494 : 6 : const SwNodeIndex *pIndex = pSect->GetFmt()->GetCntnt().GetCntntIdx();
495 : 6 : pSectNode = pIndex->GetNode().FindSectionNode();
496 : : }
497 : 126 : }
498 : :
499 : : /*
500 : : * SwLayHelper
501 : : * is the helper class, which utilizes the layout cache information
502 : : * to distribute the document content to the rigth pages.
503 : : * It's used by the _InsertCnt(..)-function.
504 : : * If there's no layout cache, the distibution to the pages is more
505 : : * a guess, but a guess with statistical background.
506 : : */
507 : :
508 : 1318 : SwLayHelper::SwLayHelper( SwDoc *pD, SwFrm* &rpF, SwFrm* &rpP, SwPageFrm* &rpPg,
509 : : SwLayoutFrm* &rpL, SwActualSection* &rpA, sal_Bool &rB,
510 : : sal_uLong nNodeIndex, sal_Bool bCache )
511 : : : rpFrm( rpF ), rpPrv( rpP ), rpPage( rpPg ), rpLay( rpL ),
512 : : rpActualSection( rpA ), rbBreakAfter(rB), pDoc(pD), nMaxParaPerPage( 25 ),
513 [ + - ]: 1318 : nParagraphCnt( bCache ? 0 : USHRT_MAX ), bFirst( bCache )
514 : : {
515 [ + + ]: 1318 : pImpl = pDoc->GetLayoutCache() ? pDoc->GetLayoutCache()->LockImpl() : NULL;
516 [ + + ]: 1318 : if( pImpl )
517 : : {
518 : 12 : nMaxParaPerPage = 1000;
519 : 12 : nStartOfContent = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()
520 : 12 : ->GetIndex();
521 : 12 : nNodeIndex -= nStartOfContent;
522 : 12 : nIndex = 0;
523 : 12 : nFlyIdx = 0;
524 [ + - ][ - + ]: 12 : while( nIndex < pImpl->size() && (*pImpl)[ nIndex ] < nNodeIndex )
[ - + ]
525 : 0 : ++nIndex;
526 [ - + ]: 12 : if( nIndex >= pImpl->size() )
527 : : {
528 : 0 : pDoc->GetLayoutCache()->UnlockImpl();
529 : 0 : pImpl = NULL;
530 : : }
531 : : }
532 : : else
533 : : {
534 : 1306 : nIndex = USHRT_MAX;
535 : 1306 : nStartOfContent = ULONG_MAX;
536 : : }
537 : 1318 : }
538 : :
539 : 1318 : SwLayHelper::~SwLayHelper()
540 : : {
541 [ + + ]: 1318 : if( pImpl )
542 : : {
543 : : OSL_ENSURE( pDoc && pDoc->GetLayoutCache(), "Missing layoutcache" );
544 : 12 : pDoc->GetLayoutCache()->UnlockImpl();
545 : : }
546 : 1318 : }
547 : :
548 : : /*
549 : : * SwLayHelper::CalcPageCount() does not really calculate the page count,
550 : : * it returns the page count value from the layout cache, if available,
551 : : * otherwise it estimates the page count.
552 : : */
553 : :
554 : 1318 : sal_uLong SwLayHelper::CalcPageCount()
555 : : {
556 : : sal_uLong nPgCount;
557 : 1318 : SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
558 [ + + ]: 1318 : pDoc->GetLayoutCache()->LockImpl() : NULL;
559 [ + + ]: 1318 : if( pCache )
560 : : {
561 : 12 : nPgCount = pCache->size() + 1;
562 : 12 : pDoc->GetLayoutCache()->UnlockImpl();
563 : : }
564 : : else
565 : : {
566 : 1306 : nPgCount = pDoc->GetDocStat().nPage;
567 [ + - ]: 1306 : if ( nPgCount <= 10 ) // no page insertion for less than 10 pages
568 : 1306 : nPgCount = 0;
569 : 1306 : sal_uLong nNdCount = pDoc->GetDocStat().nPara;
570 [ + + ]: 1306 : if ( nNdCount <= 1 )
571 : : {
572 : : //Estimates the number of paragraphs.
573 : 1281 : sal_uLong nTmp = pDoc->GetNodes().GetEndOfContent().GetIndex() -
574 : 1281 : pDoc->GetNodes().GetEndOfExtras().GetIndex();
575 : : //Tables have a little overhead..
576 : 1281 : nTmp -= pDoc->GetTblFrmFmts()->size() * 25;
577 : : //Fly frames, too ..
578 : 1281 : nTmp -= (pDoc->GetNodes().GetEndOfAutotext().GetIndex() -
579 : 1281 : pDoc->GetNodes().GetEndOfInserts().GetIndex()) / 3 * 5;
580 [ + - ]: 1281 : if ( nTmp > 0 )
581 : 1281 : nNdCount = nTmp;
582 : : }
583 [ + + ]: 1306 : if ( nNdCount > 100 ) // no estimation below this value
584 : : {
585 [ - + ]: 252 : if ( nPgCount > 0 )
586 : 0 : nMaxParaPerPage = nNdCount / nPgCount;
587 : : else
588 : : {
589 : : nMaxParaPerPage = Max( sal_uLong(20),
590 : 252 : sal_uLong(20 + nNdCount / 1000 * 3) );
591 : 252 : const sal_uLong nMax = 53;
592 : 252 : nMaxParaPerPage = Min( nMaxParaPerPage, nMax );
593 : 252 : nPgCount = nNdCount / nMaxParaPerPage;
594 : : }
595 [ - + ]: 252 : if ( nNdCount < 1000 )
596 : 0 : nPgCount = 0;// no progress bar for small documents
597 : 252 : ViewShell *pSh = 0;
598 [ + - ][ + - ]: 252 : if( rpLay && rpLay->getRootFrm() )
[ + - ]
599 : 252 : pSh = rpLay->getRootFrm()->GetCurrShell();
600 [ + - ][ - + ]: 252 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
[ - + ]
601 : 0 : nMaxParaPerPage *= 6;
602 : : }
603 : : }
604 : 1318 : return nPgCount;
605 : : }
606 : :
607 : : /*
608 : : * SwLayHelper::CheckInsertPage()
609 : : * inserts a page and return sal_True, if
610 : : * - the break after flag is set
611 : : * - the actual content wants a break before
612 : : * - the maximum count of paragraph/rows is reached
613 : : *
614 : : * The break after flag is set, if the actual content
615 : : * wants a break after.
616 : : */
617 : :
618 : 1147 : sal_Bool SwLayHelper::CheckInsertPage()
619 : : {
620 : 1147 : sal_Bool bEnd = 0 == rpPage->GetNext();
621 : 1147 : const SwAttrSet* pAttr = rpFrm->GetAttrSet();
622 : 1147 : const SvxFmtBreakItem& rBrk = pAttr->GetBreak();
623 : 1147 : const SwFmtPageDesc& rDesc = pAttr->GetPageDesc();
624 : : // #118195# Do not evaluate page description if frame
625 : : // is a follow frame!
626 : 1147 : const SwPageDesc* pDesc = rpFrm->IsFlowFrm() &&
627 : 1147 : SwFlowFrm::CastFlowFrm( rpFrm )->IsFollow() ?
628 : : 0 :
629 [ + - + + ]: 2294 : rDesc.GetPageDesc();
630 : :
631 [ + + ][ + + ]: 1147 : sal_Bool bBrk = nParagraphCnt > nMaxParaPerPage || rbBreakAfter;
632 : 1147 : rbBreakAfter = rBrk.GetBreak() == SVX_BREAK_PAGE_AFTER ||
633 [ - + ][ + - ]: 1147 : rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
634 [ + + ]: 1147 : if ( !bBrk )
635 : 1125 : bBrk = rBrk.GetBreak() == SVX_BREAK_PAGE_BEFORE ||
636 [ - + ][ + + ]: 1125 : rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
637 : :
638 [ + + ][ + + ]: 1147 : if ( bBrk || pDesc )
639 : : {
640 : 61 : sal_uInt16 nPgNum = 0;
641 [ + + ]: 61 : if ( !pDesc )
642 : 28 : pDesc = rpPage->GetPageDesc()->GetFollow();
643 : : else
644 : : {
645 [ - + ]: 33 : if ( 0 != (nPgNum = rDesc.GetNumOffset()) )
646 : 0 : ((SwRootFrm*)rpPage->GetUpper())->SetVirtPageNum(sal_True);
647 : : }
648 : 61 : sal_Bool bNextPageOdd = !rpPage->OnRightPage();
649 : 61 : sal_Bool bInsertEmpty = sal_False;
650 [ # # ][ - + ]: 61 : if( nPgNum && bNextPageOdd != ( ( nPgNum % 2 ) != 0 ) )
651 : : {
652 : 0 : bNextPageOdd = !bNextPageOdd;
653 : 0 : bInsertEmpty = sal_True;
654 : : }
655 : : // If the page style is changing, we'll have a first page.
656 : 61 : bool bNextPageFirst = pDesc != rpPage->GetPageDesc();
657 : 61 : ::InsertNewPage( (SwPageDesc&)*pDesc, rpPage->GetUpper(),
658 : 122 : bNextPageOdd, bNextPageFirst, bInsertEmpty, sal_False, rpPage->GetNext() );
659 [ + - ]: 61 : if ( bEnd )
660 : : {
661 : : OSL_ENSURE( rpPage->GetNext(), "No new page?" );
662 [ + + ]: 64 : do
663 : 64 : { rpPage = (SwPageFrm*)rpPage->GetNext();
664 : 64 : } while ( rpPage->GetNext() );
665 : : }
666 : : else
667 : : {
668 : : OSL_ENSURE( rpPage->GetNext(), "No new page?" );
669 : 0 : rpPage = (SwPageFrm*)rpPage->GetNext();
670 [ # # ]: 0 : if ( rpPage->IsEmptyPage() )
671 : : {
672 : : OSL_ENSURE( rpPage->GetNext(), "No new page?" );
673 : 0 : rpPage = (SwPageFrm*)rpPage->GetNext();
674 : : }
675 : : }
676 : 61 : rpLay = rpPage->FindBodyCont();
677 [ - + ]: 61 : while( rpLay->Lower() )
678 : 0 : rpLay = (SwLayoutFrm*)rpLay->Lower();
679 : 61 : return sal_True;
680 : : }
681 : 1147 : return sal_False;
682 : : }
683 : :
684 : : //
685 : 0 : bool lcl_HasTextFrmAnchoredObjs( SwTxtFrm* p_pTxtFrm )
686 : : {
687 : 0 : bool bHasTextFrmAnchoredObjs( false );
688 : :
689 : 0 : const SwFrmFmts* pSpzFrmFmts = p_pTxtFrm->GetTxtNode()->GetDoc()->GetSpzFrmFmts();
690 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < pSpzFrmFmts->size(); ++i )
691 : : {
692 : 0 : SwFrmFmt *pFmt = (SwFrmFmt*)(*pSpzFrmFmts)[i];
693 : 0 : const SwFmtAnchor &rAnch = pFmt->GetAnchor();
694 [ # # ][ # # : 0 : if ( rAnch.GetCntntAnchor() &&
# # # # #
# ]
695 : 0 : ((rAnch.GetAnchorId() == FLY_AT_PARA) ||
696 : 0 : (rAnch.GetAnchorId() == FLY_AT_CHAR)) &&
697 : 0 : rAnch.GetCntntAnchor()->nNode.GetIndex() ==
698 : 0 : p_pTxtFrm->GetTxtNode()->GetIndex() )
699 : : {
700 : 0 : bHasTextFrmAnchoredObjs = true;
701 : 0 : break;
702 : : }
703 : : }
704 : :
705 : 0 : return bHasTextFrmAnchoredObjs;
706 : : }
707 : :
708 : 0 : void lcl_ApplyWorkaroundForB6375613( SwFrm* p_pFirstFrmOnNewPage )
709 : : {
710 [ # # ]: 0 : SwTxtFrm* pFirstTextFrmOnNewPage = dynamic_cast<SwTxtFrm*>(p_pFirstFrmOnNewPage);
711 : : //
712 [ # # # # : 0 : if ( pFirstTextFrmOnNewPage &&
# # # # ]
[ # # ]
713 : 0 : !pFirstTextFrmOnNewPage->IsFollow() &&
714 : 0 : pFirstTextFrmOnNewPage->GetTxt().Len() == 0 &&
715 : 0 : lcl_HasTextFrmAnchoredObjs( pFirstTextFrmOnNewPage ) )
716 : : {
717 : : // apply page break before at this text frame to assure, that it doesn't flow backward.
718 : : const SvxBreak eBreak =
719 : 0 : pFirstTextFrmOnNewPage->GetAttrSet()->GetBreak().GetBreak();
720 [ # # ]: 0 : if ( eBreak == SVX_BREAK_NONE )
721 : : {
722 : 0 : pFirstTextFrmOnNewPage->GetTxtNode()->LockModify();
723 : 0 : SwDoc* pDoc( pFirstTextFrmOnNewPage->GetTxtNode()->GetDoc() );
724 [ # # ]: 0 : IDocumentContentOperations* pIDCO = pFirstTextFrmOnNewPage->GetTxtNode()->getIDocumentContentOperations();
725 [ # # ]: 0 : const SwPaM aTmpPaM( *(pFirstTextFrmOnNewPage->GetTxtNode()) );
726 : : pIDCO->InsertPoolItem( aTmpPaM,
727 [ # # ][ # # ]: 0 : SvxFmtBreakItem( SVX_BREAK_PAGE_BEFORE, RES_BREAK ), 0 );
[ # # ]
728 : 0 : pFirstTextFrmOnNewPage->GetTxtNode()->UnlockModify();
729 : :
730 : : uno::Reference< document::XDocumentInfoSupplier > xDoc(
731 : 0 : pDoc->GetDocShell()->GetBaseModel(),
732 [ # # ][ # # ]: 0 : uno::UNO_QUERY);
733 : : uno::Reference< beans::XPropertySet > xDocInfo(
734 [ # # ]: 0 : xDoc->getDocumentInfo(),
735 [ # # ][ # # ]: 0 : uno::UNO_QUERY );
736 : : try
737 : : {
738 [ # # ][ # # ]: 0 : xDocInfo->setPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WorkaroundForB6375613Applied")), uno::makeAny( true ) );
[ # # ][ # # ]
[ # # ]
739 : : }
740 [ # # ]: 0 : catch( uno::Exception& )
741 : : {
742 [ # # ]: 0 : }
743 : : }
744 : : }
745 : 0 : }
746 : :
747 : : /*
748 : : * SwLayHelper::CheckInsert
749 : : * is the entry point for the _InsertCnt-function.
750 : : * The document content index is checked either it is
751 : : * in the layout cache either it's time to insert a page
752 : : * cause the maximal estimation of content per page is reached.
753 : : * A really big table or long paragraph may contains more than
754 : : * one page, in this case the needed count of pages will inserted.
755 : : */
756 : :
757 : 2463 : sal_Bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex )
758 : : {
759 : 2463 : sal_Bool bRet = sal_False;
760 : 2463 : sal_Bool bLongTab = sal_False;
761 : 2463 : sal_uLong nMaxRowPerPage( 0 );
762 : 2463 : nNodeIndex -= nStartOfContent;
763 : 2463 : sal_uInt16 nRows( 0 );
764 [ + + ]: 2463 : if( rpFrm->IsTabFrm() )
765 : : {
766 : : //Inside a table counts every row as a paragraph
767 : 99 : SwFrm *pLow = ((SwTabFrm*)rpFrm)->Lower();
768 : 99 : nRows = 0;
769 [ + + ]: 172 : do
770 : : {
771 : 172 : ++nRows;
772 : 172 : pLow = pLow->GetNext();
773 : : } while ( pLow );
774 : 99 : nParagraphCnt += nRows;
775 [ + - ][ - + ]: 99 : if( !pImpl && nParagraphCnt > nMaxParaPerPage + 10 )
776 : : {
777 : : // OD 09.04.2003 #108698# - improve heuristics:
778 : : // Assume that a table, which has more than three times the quantity
779 : : // of maximal paragraphs per page rows, consists of rows, which have
780 : : // the height of a normal paragraph. Thus, allow as much rows per page
781 : : // as much paragraphs are allowed.
782 [ # # ]: 0 : if ( nRows > ( 3*nMaxParaPerPage ) )
783 : : {
784 : 0 : nMaxRowPerPage = nMaxParaPerPage;
785 : : }
786 : : else
787 : : {
788 : 0 : SwFrm *pTmp = ((SwTabFrm*)rpFrm)->Lower();
789 [ # # ]: 0 : if( pTmp->GetNext() )
790 : 0 : pTmp = pTmp->GetNext();
791 : 0 : pTmp = ((SwRowFrm*)pTmp)->Lower();
792 : 0 : sal_uInt16 nCnt = 0;
793 [ # # ]: 0 : do
794 : : {
795 : 0 : ++nCnt;
796 : 0 : pTmp = pTmp->GetNext();
797 : : } while( pTmp );
798 : 0 : nMaxRowPerPage = Max( sal_uLong(2), nMaxParaPerPage / nCnt );
799 : : }
800 : 0 : bLongTab = sal_True;
801 : : }
802 : : }
803 : : else
804 : 2364 : ++nParagraphCnt;
805 [ + + ][ + + ]: 2475 : if( bFirst && pImpl && nIndex < pImpl->size() &&
[ + - - +
# # # # #
# ][ - + ]
806 : 12 : pImpl->GetBreakIndex( nIndex ) == nNodeIndex &&
807 : 0 : ( pImpl->GetBreakOfst( nIndex ) < STRING_LEN ||
808 : 0 : ( ++nIndex < pImpl->size() &&
809 : 0 : pImpl->GetBreakIndex( nIndex ) == nNodeIndex ) ) )
810 : 0 : bFirst = sal_False;
811 : : #if OSL_DEBUG_LEVEL > 1
812 : : sal_uLong nBreakIndex = ( pImpl && nIndex < pImpl->size() ) ?
813 : : pImpl->GetBreakIndex(nIndex) : 0xffff;
814 : : (void)nBreakIndex;
815 : : #endif
816 : : // OD 09.04.2003 #108698# - always split a big tables.
817 [ + + + + ]: 3781 : if ( !bFirst ||
[ - + ][ + + ]
818 : 1318 : ( rpFrm->IsTabFrm() && bLongTab )
819 : : )
820 : : {
821 : 1145 : sal_uLong nRowCount = 0;
822 [ + - ][ + + : 1364 : do
+ + + + ]
[ + + ]
823 : : {
824 [ + + ][ - + ]: 1147 : if( pImpl || bLongTab )
825 : : {
826 : : #if OSL_DEBUG_LEVEL > 1
827 : : sal_uLong nBrkIndex = ( pImpl && nIndex < pImpl->size() ) ?
828 : : pImpl->GetBreakIndex(nIndex) : 0xffff;
829 : : (void)nBrkIndex;
830 : : #endif
831 : 129 : xub_StrLen nOfst = STRING_LEN;
832 : 129 : sal_uInt16 nType = SW_LAYCACHE_IO_REC_PAGES;
833 [ - + ]: 129 : if( bLongTab )
834 : : {
835 : 0 : rbBreakAfter = sal_True;
836 : 0 : nOfst = static_cast<xub_StrLen>(nRowCount + nMaxRowPerPage);
837 : : }
838 : : else
839 : : {
840 [ + + - + ]: 226 : while( nIndex < pImpl->size() &&
[ - + ]
841 : 97 : pImpl->GetBreakIndex(nIndex) < nNodeIndex)
842 : 0 : ++nIndex;
843 [ + + + + ]: 226 : if( nIndex < pImpl->size() &&
[ + + ]
844 : 97 : pImpl->GetBreakIndex(nIndex) == nNodeIndex )
845 : : {
846 : 18 : nType = pImpl->GetBreakType( nIndex );
847 : 18 : nOfst = pImpl->GetBreakOfst( nIndex++ );
848 : 18 : rbBreakAfter = sal_True;
849 : : }
850 : : }
851 : :
852 [ + + ]: 129 : if( nOfst < STRING_LEN )
853 : : {
854 : 8 : sal_Bool bSplit = sal_False;
855 : 8 : sal_uInt16 nRepeat( 0 );
856 [ + - ][ + - ]: 16 : if( !bLongTab && rpFrm->IsTxtFrm() &&
[ + - + - ]
[ + - ]
857 : : SW_LAYCACHE_IO_REC_PARA == nType &&
858 : 8 : nOfst<((SwTxtFrm*)rpFrm)->GetTxtNode()->GetTxt().Len() )
859 : 8 : bSplit = sal_True;
860 [ # # ][ # # ]: 0 : else if( rpFrm->IsTabFrm() && nRowCount < nOfst &&
[ # # ][ # # ]
[ # # ]
861 : : ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) )
862 : : {
863 : : nRepeat = ((SwTabFrm*)rpFrm)->
864 : 0 : GetTable()->GetRowsToRepeat();
865 [ # # ][ # # ]: 0 : bSplit = nOfst < nRows && nRowCount + nRepeat < nOfst;
866 [ # # ][ # # ]: 0 : bLongTab = bLongTab && bSplit;
867 : : }
868 [ + - ]: 8 : if( bSplit )
869 : : {
870 : 8 : rpFrm->InsertBehind( rpLay, rpPrv );
871 : 8 : rpFrm->Frm().Pos() = rpLay->Frm().Pos();
872 : 8 : rpFrm->Frm().Pos().Y() += 1;
873 : 8 : rpPrv = rpFrm;
874 [ - + ]: 8 : if( rpFrm->IsTabFrm() )
875 : : {
876 : 0 : SwTabFrm* pTab = (SwTabFrm*)rpFrm;
877 : : // #i33629#, #i29955#
878 : 0 : ::RegistFlys( pTab->FindPageFrm(), pTab );
879 : 0 : SwFrm *pRow = pTab->Lower();
880 [ # # ]: 0 : SwTabFrm *pFoll = new SwTabFrm( *pTab );
881 : :
882 : : SwFrm *pPrv;
883 [ # # ]: 0 : if( nRepeat > 0 )
884 : : {
885 : 0 : bDontCreateObjects = sal_True; //frmtool
886 : :
887 : : // Insert new headlines:
888 : 0 : sal_uInt16 nRowIdx = 0;
889 : 0 : SwRowFrm* pHeadline = 0;
890 [ # # ]: 0 : while( nRowIdx < nRepeat )
891 : : {
892 : : OSL_ENSURE( pTab->GetTable()->GetTabLines()[ nRowIdx ], "Table ohne Zeilen?" );
893 : : pHeadline =
894 [ # # ]: 0 : new SwRowFrm( *pTab->GetTable()->GetTabLines()[ nRowIdx ], pTab );
895 : 0 : pHeadline->SetRepeatedHeadline( true );
896 : 0 : pHeadline->InsertBefore( pFoll, 0 );
897 : 0 : pHeadline->RegistFlys();
898 : :
899 : 0 : ++nRowIdx;
900 : : }
901 : :
902 : 0 : bDontCreateObjects = sal_False;
903 : 0 : pPrv = pHeadline;
904 : 0 : nRows = nRows + nRepeat;
905 : : }
906 : : else
907 : 0 : pPrv = 0;
908 [ # # ][ # # ]: 0 : while( pRow && nRowCount < nOfst )
[ # # ]
909 : : {
910 : 0 : pRow = pRow->GetNext();
911 : 0 : ++nRowCount;
912 : : }
913 [ # # ]: 0 : while ( pRow )
914 : : {
915 : 0 : SwFrm* pNxt = pRow->GetNext();
916 : 0 : pRow->Remove();
917 : 0 : pRow->InsertBehind( pFoll, pPrv );
918 : 0 : pPrv = pRow;
919 : 0 : pRow = pNxt;
920 : : }
921 : 0 : rpFrm = pFoll;
922 : : }
923 : : else
924 : : {
925 : : SwTxtFrm *pNew = new SwTxtFrm( ((SwTxtFrm*)rpFrm)->
926 [ + - ]: 8 : GetTxtNode(), rpFrm );
927 : 8 : pNew->ManipOfst( nOfst );
928 [ - + ]: 8 : pNew->SetFollow( ((SwTxtFrm*)rpFrm)->GetFollow() );
929 [ + - ]: 8 : ((SwTxtFrm*)rpFrm)->SetFollow( pNew );
930 : 8 : rpFrm = pNew;
931 : : }
932 : : }
933 : : }
934 : : }
935 : :
936 : 1147 : SwPageFrm* pLastPage = rpPage;
937 [ + + ]: 1147 : if( CheckInsertPage() )
938 : : {
939 : : //
940 [ - + ]: 61 : if ( pDoc->ApplyWorkaroundForB6375613() )
941 : : {
942 : 0 : lcl_ApplyWorkaroundForB6375613( rpFrm );
943 : : }
944 : 61 : _CheckFlyCache( pLastPage );
945 [ + + ][ + - ]: 61 : if( rpPrv && rpPrv->IsTxtFrm() && !rpPrv->GetValidSizeFlag() )
[ + + ][ + + ]
946 : 56 : rpPrv->Frm().Height( rpPrv->GetUpper()->Prt().Height() );
947 : :
948 : 61 : bRet = sal_True;
949 : 61 : rpPrv = 0;
950 : 61 : nParagraphCnt = 0;
951 : :
952 [ + + ]: 61 : if ( rpActualSection )
953 : : {
954 : : //Did the SectionFrm even have a content? If not, we can
955 : : //directly put it somewhere else
956 : : SwSectionFrm *pSct;
957 : 2 : bool bInit = false;
958 [ + - ]: 2 : if ( !rpActualSection->GetSectionFrm()->ContainsCntnt())
959 : : {
960 : 2 : pSct = rpActualSection->GetSectionFrm();
961 : 2 : pSct->Remove();
962 : : }
963 : : else
964 : : {
965 : : pSct = new SwSectionFrm(
966 [ # # ]: 0 : *rpActualSection->GetSectionFrm(), sal_False );
967 : 0 : rpActualSection->GetSectionFrm()->SimpleFormat();
968 : 0 : bInit = true;
969 : : }
970 : 2 : rpActualSection->SetSectionFrm( pSct );
971 : 2 : pSct->InsertBehind( rpLay, 0 );
972 [ - + ]: 2 : if( bInit )
973 : 0 : pSct->Init();
974 : 2 : pSct->Frm().Pos() = rpLay->Frm().Pos();
975 : 2 : pSct->Frm().Pos().Y() += 1; //because of the notifications
976 : :
977 : 2 : rpLay = pSct;
978 [ + - ][ + - ]: 2 : if ( rpLay->Lower() && rpLay->Lower()->IsLayoutFrm() )
[ + - ]
979 : 2 : rpLay = rpLay->GetNextLayoutLeaf();
980 : : }
981 : : }
982 : 129 : } while( bLongTab || ( pImpl && nIndex < pImpl->size() &&
983 : 88 : (*pImpl)[ nIndex ] == nNodeIndex ) );
984 : : }
985 : 2463 : bFirst = sal_False;
986 : 2463 : return bRet;
987 : : }
988 : :
989 : : struct SdrObjectCompare
990 : : {
991 : 0 : bool operator()( const SdrObject* pF1, const SdrObject* pF2 ) const
992 : : {
993 : 0 : return pF1->GetOrdNum() < pF2->GetOrdNum();
994 : : }
995 : : };
996 : :
997 : : struct FlyCacheCompare
998 : : {
999 : 14 : bool operator()( const SwFlyCache* pC1, const SwFlyCache* pC2 ) const
1000 : : {
1001 : 14 : return pC1->nOrdNum < pC2->nOrdNum;
1002 : : }
1003 : : };
1004 : :
1005 : : /*
1006 : : * SwLayHelper::_CheckFlyCache(..)
1007 : : * If a new page is inserted, the last page is analysed.
1008 : : * If there are text frames with default position, the fly cache
1009 : : * is checked, if these frames are stored in the cache.
1010 : : */
1011 : :
1012 : 63 : void SwLayHelper::_CheckFlyCache( SwPageFrm* pPage )
1013 : : {
1014 [ + + ][ - + ]: 63 : if( !pImpl || !pPage )
1015 : 63 : return;
1016 : 20 : sal_uInt16 nFlyCount = pImpl->GetFlyCount();
1017 : : // Any text frames at the page, fly cache avaiable?
1018 [ + - ][ + + ]: 20 : if( pPage->GetSortedObjs() && nFlyIdx < nFlyCount )
[ + + ]
1019 : : {
1020 : 4 : SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1021 : 4 : sal_uInt16 nPgNum = pPage->GetPhyPageNum();
1022 : :
1023 : : //
1024 : : // NOTE: Here we do not use the absolute ordnums but
1025 : : // relative ordnums for the objects on this page.
1026 : :
1027 : : // skip fly frames from pages before the current page
1028 : : SwFlyCache* pFlyC;
1029 [ + - ][ + - ]: 10 : while( nFlyIdx < nFlyCount && ( pFlyC = pImpl->
[ + + ][ + + ]
1030 : 10 : GetFlyCache(nFlyIdx) )->nPageNum < nPgNum)
1031 : 6 : ++nFlyIdx;
1032 : :
1033 : : // sort cached objects on this page by ordnum
1034 [ + - ]: 4 : std::set< const SwFlyCache*, FlyCacheCompare > aFlyCacheSet;
1035 : 4 : sal_uInt16 nIdx = nFlyIdx;
1036 : :
1037 [ + + ][ + - ]: 12 : while( nIdx < nFlyCount && ( pFlyC = pImpl->
[ + + ][ + + ]
1038 : 10 : GetFlyCache( nIdx ) )->nPageNum == nPgNum )
1039 : : {
1040 [ + - ]: 8 : aFlyCacheSet.insert( pFlyC );
1041 : 8 : ++nIdx;
1042 : : }
1043 : :
1044 : : // sort objects on this page by ordnum
1045 [ + - ]: 4 : std::set< const SdrObject*, SdrObjectCompare > aFlySet;
1046 [ + - ][ + + ]: 8 : for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
1047 : : {
1048 [ + - ]: 4 : SwAnchoredObject* pAnchoredObj = rObjs[i];
1049 [ + - ][ + - ]: 4 : if ( pAnchoredObj->ISA(SwFlyFrm) ) // a text frame?
[ + - ]
1050 : : {
1051 [ + - ]: 4 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1052 [ + - ][ + - ]: 8 : if( pFly->GetAnchorFrm() &&
[ + - ][ + - ]
1053 [ + - ][ + - ]: 4 : !pFly->GetAnchorFrm()->FindFooterOrHeader() )
1054 : : {
1055 [ + - ][ + - ]: 4 : const SwContact *pC = ::GetUserCall( pAnchoredObj->GetDrawObj() );
1056 [ + - ]: 4 : if( pC )
1057 : : {
1058 [ + - ][ + - ]: 4 : aFlySet.insert( pAnchoredObj->GetDrawObj() );
1059 : : }
1060 : : }
1061 : : }
1062 : : }
1063 : :
1064 [ + + ]: 4 : if ( aFlyCacheSet.size() == aFlySet.size() )
1065 : : {
1066 : : std::set< const SwFlyCache*, FlyCacheCompare >::iterator aFlyCacheSetIt =
1067 : 2 : aFlyCacheSet.begin();
1068 : : std::set< const SdrObject*, SdrObjectCompare >::iterator aFlySetIt =
1069 : 2 : aFlySet.begin();
1070 : :
1071 [ + + ]: 4 : while ( aFlyCacheSetIt != aFlyCacheSet.end() )
1072 : : {
1073 : 2 : const SwFlyCache* pFlyCache = *aFlyCacheSetIt;
1074 [ + - ]: 2 : SwFlyFrm* pFly = ((SwVirtFlyDrawObj*)*aFlySetIt)->GetFlyFrm();
1075 : :
1076 [ - + ]: 2 : if ( pFly->Frm().Left() == FAR_AWAY )
1077 : : {
1078 : : // we get the stored information
1079 : 0 : pFly->Frm().Pos().X() = pFlyCache->Left() +
1080 : 0 : pPage->Frm().Left();
1081 : 0 : pFly->Frm().Pos().Y() = pFlyCache->Top() +
1082 : 0 : pPage->Frm().Top();
1083 [ # # ]: 0 : if ( pImpl->IsUseFlyCache() )
1084 : : {
1085 : 0 : pFly->Frm().Width( pFlyCache->Width() );
1086 : 0 : pFly->Frm().Height( pFlyCache->Height() );
1087 : : }
1088 : : }
1089 : :
1090 : 2 : ++aFlyCacheSetIt;
1091 [ + - ]: 2 : ++aFlySetIt;
1092 : : }
1093 : 4 : }
1094 : : }
1095 : : }
1096 : :
1097 : : /*
1098 : : * SwLayHelper::CheckPageFlyCache(..)
1099 : : * looks for the given text frame in the fly cache and sets
1100 : : * the position and size, if possible.
1101 : : * The fly cache is sorted by pages and we start searching with the given page.
1102 : : * If we found the page number in the fly cache, we set
1103 : : * the rpPage parameter to the right page, if possible.
1104 : : */
1105 : :
1106 : 123 : sal_Bool SwLayHelper::CheckPageFlyCache( SwPageFrm* &rpPage, SwFlyFrm* pFly )
1107 : : {
1108 [ + - ]: 246 : if( !pFly->GetAnchorFrm() || !pFly->GetVirtDrawObj() ||
[ + - - + ]
[ - + ]
1109 : 123 : pFly->GetAnchorFrm()->FindFooterOrHeader() )
1110 : 0 : return sal_False;
1111 : 123 : sal_Bool bRet = sal_False;
1112 : 123 : SwDoc* pDoc = rpPage->GetFmt()->GetDoc();
1113 : 123 : SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
1114 [ + + ]: 123 : pDoc->GetLayoutCache()->LockImpl() : NULL;
1115 [ + + ]: 123 : if( pCache )
1116 : : {
1117 : 6 : sal_uInt16 nPgNum = rpPage->GetPhyPageNum();
1118 : 6 : sal_uInt16 nIdx = 0;
1119 : 6 : sal_uInt16 nCnt = pCache->GetFlyCount();
1120 : 6 : sal_uLong nOrdNum = pFly->GetVirtDrawObj()->GetOrdNum();
1121 : 6 : SwFlyCache* pFlyC = 0;
1122 : :
1123 : : // skip fly frames from pages before the current page
1124 [ + - ][ + + ]: 12 : while( nIdx < nCnt &&
[ + + ]
1125 : 12 : nPgNum > (pFlyC = pCache->GetFlyCache( nIdx ))->nPageNum )
1126 : 6 : ++nIdx;
1127 : :
1128 [ + - ][ + + ]: 12 : while( nIdx < nCnt &&
[ + + ]
1129 : 12 : nOrdNum != (pFlyC = pCache->GetFlyCache( nIdx ))->nOrdNum )
1130 : 6 : ++nIdx;
1131 [ + - ]: 6 : if( nIdx < nCnt )
1132 : : {
1133 : 6 : SwPageFrm *pPage = rpPage;
1134 [ + - ][ - + ]: 6 : while( pPage && pPage->GetPhyPageNum() < pFlyC->nPageNum )
[ - + ]
1135 : 0 : pPage = (SwPageFrm*)pPage->GetNext();
1136 : : // #i43266# - if the found page is an empty page,
1137 : : // take the previous one (take next one, if previous one doesn't exists)
1138 [ + - ][ - + ]: 6 : if ( pPage && pPage->IsEmptyPage() )
[ - + ]
1139 : : {
1140 : 0 : pPage = static_cast<SwPageFrm*>( pPage->GetPrev()
1141 : 0 : ? pPage->GetPrev()
1142 [ # # ]: 0 : : pPage->GetNext() );
1143 : : }
1144 [ + - ]: 6 : if( pPage )
1145 : : {
1146 : 6 : rpPage = pPage;
1147 : 6 : pFly->Frm().Pos().X() = pFlyC->Left() + pPage->Frm().Left();
1148 : 6 : pFly->Frm().Pos().Y() = pFlyC->Top() + pPage->Frm().Top();
1149 [ + - ]: 6 : if ( pCache->IsUseFlyCache() )
1150 : : {
1151 : 6 : pFly->Frm().Width( pFlyC->Width() );
1152 : 6 : pFly->Frm().Height( pFlyC->Height() );
1153 : : }
1154 : 6 : bRet = sal_True;
1155 : : }
1156 : : }
1157 : 6 : pDoc->GetLayoutCache()->UnlockImpl();
1158 : : }
1159 : 123 : return bRet;
1160 : : }
1161 : :
1162 : : // -----------------------------------------------------------------------------
1163 : :
1164 : 16 : SwLayCacheIoImpl::SwLayCacheIoImpl( SvStream& rStrm, sal_Bool bWrtMd ) :
1165 : : pStream( &rStrm ),
1166 : : nMajorVersion(SW_LAYCACHE_IO_VERSION_MAJOR),
1167 : : nMinorVersion(SW_LAYCACHE_IO_VERSION_MINOR),
1168 : : bWriteMode( bWrtMd ),
1169 : 16 : bError( sal_False )
1170 : : {
1171 [ + + ]: 16 : if( bWriteMode )
1172 [ + - ]: 4 : *pStream << nMajorVersion
1173 [ + - ]: 4 : << nMinorVersion;
1174 : :
1175 : : else
1176 [ + - ]: 12 : *pStream >> nMajorVersion
1177 [ + - ]: 12 : >> nMinorVersion;
1178 : 16 : }
1179 : :
1180 : 76 : sal_Bool SwLayCacheIoImpl::OpenRec( sal_uInt8 cType )
1181 : : {
1182 : 76 : sal_Bool bRes = sal_True;
1183 : 76 : sal_uInt32 nPos = pStream->Tell();
1184 [ + + ]: 76 : if( bWriteMode )
1185 : : {
1186 [ + - ]: 14 : aRecords.push_back( RecTypeSize(cType, nPos) );
1187 : 14 : *pStream << (sal_uInt32) 0;
1188 : : }
1189 : : else
1190 : : {
1191 : : sal_uInt32 nVal;
1192 [ + - ]: 62 : *pStream >> nVal;
1193 : 62 : sal_uInt8 cRecTyp = (sal_uInt8)nVal;
1194 [ + - ][ + - : 186 : if( !nVal || cRecTyp != cType ||
+ - - + ]
[ - + ]
1195 : 124 : pStream->GetErrorCode() != SVSTREAM_OK || pStream->IsEof() )
1196 : : {
1197 : : OSL_ENSURE( nVal, "OpenRec: Record-Header is 0" );
1198 : : OSL_ENSURE( cRecTyp == cType, "OpenRec: Wrong Record Type" );
1199 [ # # ]: 0 : aRecords.push_back( RecTypeSize(0, pStream->Tell()) );
1200 : 0 : bRes = sal_False;
1201 : 0 : bError = sal_True;
1202 : : }
1203 : : else
1204 : : {
1205 : 62 : sal_uInt32 nSize = nVal >> 8;
1206 [ + - ]: 62 : aRecords.push_back( RecTypeSize(cRecTyp, nPos+nSize) );
1207 : : }
1208 : : }
1209 : 76 : return bRes;
1210 : : }
1211 : :
1212 : : // Close record
1213 : :
1214 : 76 : sal_Bool SwLayCacheIoImpl::CloseRec( sal_uInt8 )
1215 : : {
1216 : 76 : sal_Bool bRes = sal_True;
1217 : : OSL_ENSURE( !aRecords.empty(), "CloseRec: no levels" );
1218 [ + - ]: 76 : if( !aRecords.empty() )
1219 : : {
1220 : 76 : sal_uInt32 nPos = pStream->Tell();
1221 [ + + ]: 76 : if( bWriteMode )
1222 : : {
1223 : 14 : sal_uInt32 nBgn = aRecords.back().size;
1224 : 14 : pStream->Seek( nBgn );
1225 : 14 : sal_uInt32 nSize = nPos - nBgn;
1226 : 14 : sal_uInt32 nVal = ( nSize << 8 ) | aRecords.back().type;
1227 : 14 : *pStream << nVal;
1228 : 14 : pStream->Seek( nPos );
1229 [ - + ]: 14 : if( pStream->GetError() != SVSTREAM_OK )
1230 : 0 : bRes = sal_False;
1231 : : }
1232 : : else
1233 : : {
1234 : 62 : sal_uInt32 n = aRecords.back().size;
1235 : : OSL_ENSURE( n >= nPos, "CloseRec: to much data read" );
1236 [ - + ]: 62 : if( n != nPos )
1237 : : {
1238 : 0 : pStream->Seek( n );
1239 [ # # ]: 0 : if( n < nPos )
1240 : 0 : bRes = sal_False;
1241 : : }
1242 [ - + ]: 62 : if( pStream->GetErrorCode() != SVSTREAM_OK )
1243 : 0 : bRes = sal_False;
1244 : : }
1245 : 76 : aRecords.pop_back();
1246 : : }
1247 : :
1248 [ - + ]: 76 : if( !bRes )
1249 : 0 : bError = sal_True;
1250 : :
1251 : 76 : return bRes;
1252 : : }
1253 : :
1254 : 62 : sal_uInt32 SwLayCacheIoImpl::BytesLeft()
1255 : : {
1256 : 62 : sal_uInt32 n = 0;
1257 [ + - ][ + - ]: 62 : if( !bError && !aRecords.empty() )
[ + - ]
1258 : : {
1259 : 62 : sal_uInt32 nEndPos = aRecords.back().size;
1260 : 62 : sal_uInt32 nPos = pStream->Tell();
1261 [ + + ]: 62 : if( nEndPos > nPos )
1262 : 50 : n = nEndPos - nPos;
1263 : : }
1264 : 62 : return n;
1265 : : }
1266 : :
1267 : 50 : sal_uInt8 SwLayCacheIoImpl::Peek()
1268 : : {
1269 : 50 : sal_uInt8 c = 0;
1270 [ + - ]: 50 : if( !bError )
1271 : : {
1272 : 50 : sal_uInt32 nPos = pStream->Tell();
1273 [ + - ]: 50 : *pStream >> c;
1274 [ + - ]: 50 : pStream->Seek( nPos );
1275 [ - + ]: 50 : if( pStream->GetErrorCode() != SVSTREAM_OK )
1276 : : {
1277 : 0 : c = 0;
1278 : 0 : bError = sal_True;
1279 : : }
1280 : : }
1281 : 50 : return c;
1282 : : }
1283 : :
1284 : 0 : void SwLayCacheIoImpl::SkipRec()
1285 : : {
1286 : 0 : sal_uInt8 c = Peek();
1287 : 0 : OpenRec( c );
1288 : 0 : pStream->Seek( aRecords.back().size );
1289 : 0 : CloseRec( c );
1290 : 0 : }
1291 : :
1292 : 62 : sal_uInt8 SwLayCacheIoImpl::OpenFlagRec()
1293 : : {
1294 : : OSL_ENSURE( !bWriteMode, "OpenFlagRec illegal in write mode" );
1295 : : sal_uInt8 cFlags;
1296 [ + - ]: 62 : *pStream >> cFlags;
1297 : 62 : nFlagRecEnd = pStream->Tell() + ( cFlags & 0x0F );
1298 : 62 : return (cFlags >> 4);
1299 : : }
1300 : :
1301 : 14 : void SwLayCacheIoImpl::OpenFlagRec( sal_uInt8 nFlags, sal_uInt8 nLen )
1302 : : {
1303 : : OSL_ENSURE( bWriteMode, "OpenFlagRec illegal in read mode" );
1304 : : OSL_ENSURE( (nFlags & 0xF0) == 0, "illegal flags set" );
1305 : : OSL_ENSURE( nLen < 16, "wrong flag record length" );
1306 : 14 : sal_uInt8 cFlags = (nFlags << 4) + nLen;
1307 : 14 : *pStream << cFlags;
1308 : 14 : nFlagRecEnd = pStream->Tell() + nLen;
1309 : 14 : }
1310 : :
1311 : 76 : void SwLayCacheIoImpl::CloseFlagRec()
1312 : : {
1313 [ + + ]: 76 : if( bWriteMode )
1314 : : {
1315 : : OSL_ENSURE( pStream->Tell() == nFlagRecEnd, "Wrong amount of data written" );
1316 : : }
1317 : : else
1318 : : {
1319 : : OSL_ENSURE( pStream->Tell() <= nFlagRecEnd, "To many data read" );
1320 [ - + ]: 62 : if( pStream->Tell() != nFlagRecEnd )
1321 : 0 : pStream->Seek( nFlagRecEnd );
1322 : : }
1323 : 76 : }
1324 : :
1325 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|