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