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 32 : void SwLayoutCache::Read( SvStream &rStream )
61 : {
62 32 : if( !pImpl )
63 : {
64 32 : pImpl = new SwLayCacheImpl;
65 32 : if( !pImpl->Read( rStream ) )
66 : {
67 0 : delete pImpl;
68 0 : pImpl = 0;
69 : }
70 : }
71 32 : }
72 :
73 104 : void SwLayCacheImpl::Insert( sal_uInt16 nType, sal_uLong nIndex, sal_Int32 nOffset )
74 : {
75 104 : aType.push_back( nType );
76 104 : mIndices.push_back( nIndex );
77 104 : aOffset.push_back( nOffset );
78 104 : }
79 :
80 32 : bool SwLayCacheImpl::Read( SvStream& rStream )
81 : {
82 32 : SwLayCacheIoImpl aIo( rStream, false );
83 32 : 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 32 : bUseFlyCache = aIo.GetMinorVersion() >= 1;
91 :
92 32 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
93 32 : aIo.OpenFlagRec();
94 32 : aIo.CloseFlagRec();
95 178 : while( aIo.BytesLeft() && !aIo.HasError() )
96 : {
97 114 : sal_uInt32 nIndex(0), nOffset(0);
98 :
99 114 : switch( aIo.Peek() )
100 : {
101 : case SW_LAYCACHE_IO_REC_PARA:
102 : {
103 102 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
104 102 : sal_uInt8 cFlags = aIo.OpenFlagRec();
105 102 : aIo.GetStream().ReadUInt32( nIndex );
106 102 : if( (cFlags & 0x01) != 0 )
107 10 : aIo.GetStream().ReadUInt32( nOffset );
108 : else
109 92 : nOffset = COMPLETE_STRING;
110 102 : aIo.CloseFlagRec();
111 102 : Insert( SW_LAYCACHE_IO_REC_PARA, nIndex, (sal_Int32)nOffset );
112 102 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
113 102 : break;
114 : }
115 : case SW_LAYCACHE_IO_REC_TABLE:
116 2 : aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
117 2 : aIo.OpenFlagRec();
118 2 : aIo.GetStream().ReadUInt32( nIndex )
119 2 : .ReadUInt32( nOffset );
120 2 : Insert( SW_LAYCACHE_IO_REC_TABLE, nIndex, (sal_Int32)nOffset );
121 2 : aIo.CloseFlagRec();
122 2 : aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
123 2 : break;
124 : case SW_LAYCACHE_IO_REC_FLY:
125 : {
126 10 : aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
127 10 : aIo.OpenFlagRec();
128 10 : aIo.CloseFlagRec();
129 10 : sal_Int32 nX(0), nY(0), nW(0), nH(0);
130 10 : sal_uInt16 nPgNum(0);
131 10 : aIo.GetStream().ReadUInt16( nPgNum ).ReadUInt32( nIndex )
132 10 : .ReadInt32( nX ).ReadInt32( nY ).ReadInt32( nW ).ReadInt32( nH );
133 10 : SwFlyCache* pFly = new SwFlyCache( nPgNum, nIndex, nX, nY, nW, nH );
134 10 : aFlyCache.push_back( pFly );
135 10 : aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
136 10 : break;
137 : }
138 : default:
139 0 : aIo.SkipRec();
140 0 : break;
141 : }
142 : }
143 32 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
144 :
145 32 : 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 6 : void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc )
158 : {
159 6 : if( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ) // the layout itself ..
160 : {
161 6 : SwLayCacheIoImpl aIo( rStream, true );
162 : // We want to save the relative index, so we need the index
163 : // of the first content
164 6 : sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
165 6 : StartOfSectionNode()->GetIndex();
166 : // The first page..
167 6 : SwPageFrm* pPage = (SwPageFrm*)rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->Lower();
168 :
169 6 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
170 6 : aIo.OpenFlagRec( 0, 0 );
171 6 : aIo.CloseFlagRec();
172 40 : while( pPage )
173 : {
174 28 : if( pPage->GetPrev() )
175 : {
176 22 : SwLayoutFrm* pLay = pPage->FindBodyCont();
177 22 : SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
178 : // We are only interested in paragraph or table frames,
179 : // a section frames contains paragraphs/tables.
180 22 : if( pTmp && pTmp->IsSctFrm() )
181 0 : pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
182 :
183 22 : if( pTmp ) // any content
184 : {
185 22 : if( pTmp->IsTxtFrm() )
186 : {
187 22 : sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
188 22 : if( nNdIdx > nStartOfContent )
189 : {
190 : /* Open Paragraph Record */
191 22 : aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
192 22 : bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
193 : aIo.OpenFlagRec( bFollow ? 0x01 : 0x00,
194 22 : bFollow ? 8 : 4 );
195 22 : nNdIdx -= nStartOfContent;
196 22 : aIo.GetStream().WriteUInt32( nNdIdx );
197 22 : if( bFollow )
198 8 : aIo.GetStream().WriteUInt32( ((SwTxtFrm*)pTmp)->GetOfst() );
199 22 : aIo.CloseFlagRec();
200 : /* Close Paragraph Record */
201 22 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
202 : }
203 : }
204 0 : else if( pTmp->IsTabFrm() )
205 : {
206 0 : SwTabFrm* pTab = (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 28 : if( pPage->GetSortedObjs() )
277 : {
278 4 : SwSortedObjs &rObjs = *pPage->GetSortedObjs();
279 8 : for ( size_t i = 0; i < rObjs.size(); ++i )
280 : {
281 4 : SwAnchoredObject* pAnchoredObj = rObjs[i];
282 4 : 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 28 : pPage = (SwPageFrm*)pPage->GetNext();
313 : }
314 6 : aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
315 : }
316 6 : }
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 : SwPageFrm* pPage = (SwPageFrm*)pRootFrm->Lower();
330 : if( pPage )
331 : pPage = (SwPageFrm*)pPage->GetNext();
332 : while( pPage )
333 : {
334 : if( nIndex >= pImpl->size() )
335 : return false;
336 :
337 : SwLayoutFrm* pLay = pPage->FindBodyCont();
338 : SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
339 : if( pTmp && pTmp->IsSctFrm() )
340 : pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
341 : if( pTmp )
342 : {
343 : if( pTmp->IsTxtFrm() )
344 : {
345 : sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
346 : if( nNdIdx > nStartOfContent )
347 : {
348 : bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
349 : nNdIdx -= nStartOfContent;
350 : if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
351 : SW_LAYCACHE_IO_REC_PARA !=
352 : pImpl->GetBreakType( nIndex ) ||
353 : ( bFollow ? ((SwTxtFrm*)pTmp)->GetOfst()
354 : : COMPLETE_STRING ) != pImpl->GetBreakOfst( nIndex ) )
355 : {
356 : return false;
357 : }
358 : ++nIndex;
359 : }
360 : }
361 : else if( pTmp->IsTabFrm() )
362 : {
363 : SwTabFrm* pTab = (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 : 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 : SwFrm* pSub = pTab->Lower();
404 : while( pSub )
405 : {
406 : ++nOfst;
407 : pSub = pSub->GetNext();
408 : }
409 : pTab = pTab->GetFollow();
410 : 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 = (SwPageFrm*)pPage->GetNext();
424 : }
425 : }
426 : return true;
427 : }
428 : #endif
429 :
430 28 : void SwLayoutCache::ClearImpl()
431 : {
432 28 : if( !IsLocked() )
433 : {
434 28 : delete pImpl;
435 28 : pImpl = 0;
436 : }
437 28 : }
438 :
439 32 : SwLayoutCache::~SwLayoutCache()
440 : {
441 : OSL_ENSURE( !nLockCount, "Deleting a locked SwLayoutCache!?" );
442 32 : delete pImpl;
443 32 : }
444 :
445 : /// helper class to create not nested section frames for nested sections.
446 592 : SwActualSection::SwActualSection( SwActualSection *pUp,
447 : SwSectionFrm *pSect,
448 : SwSectionNode *pNd ) :
449 : pUpper( pUp ),
450 : pSectFrm( pSect ),
451 592 : pSectNode( pNd )
452 : {
453 592 : if ( !pSectNode )
454 : {
455 6 : const SwNodeIndex *pIndex = pSect->GetFmt()->GetCntnt().GetCntntIdx();
456 6 : pSectNode = pIndex->GetNode().FindSectionNode();
457 : }
458 592 : }
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 5266 : 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 5266 : , bFirst( bCache )
480 : {
481 5266 : pImpl = pDoc->GetLayoutCache() ? pDoc->GetLayoutCache()->LockImpl() : NULL;
482 5266 : if( pImpl )
483 : {
484 28 : nMaxParaPerPage = 1000;
485 28 : nStartOfContent = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()
486 28 : ->GetIndex();
487 28 : nNodeIndex -= nStartOfContent;
488 28 : nIndex = 0;
489 56 : while( nIndex < pImpl->size() && pImpl->GetBreakIndex( nIndex ) < nNodeIndex )
490 : {
491 0 : ++nIndex;
492 : }
493 28 : if( nIndex >= pImpl->size() )
494 : {
495 0 : pDoc->GetLayoutCache()->UnlockImpl();
496 0 : pImpl = NULL;
497 : }
498 : }
499 : else
500 : {
501 5238 : nIndex = USHRT_MAX;
502 5238 : nStartOfContent = ULONG_MAX;
503 : }
504 5266 : }
505 :
506 5266 : SwLayHelper::~SwLayHelper()
507 : {
508 5266 : if( pImpl )
509 : {
510 : OSL_ENSURE( pDoc && pDoc->GetLayoutCache(), "Missing layoutcache" );
511 28 : pDoc->GetLayoutCache()->UnlockImpl();
512 : }
513 5266 : }
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 5266 : sal_uLong SwLayHelper::CalcPageCount()
520 : {
521 : sal_uLong nPgCount;
522 5266 : SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
523 5266 : pDoc->GetLayoutCache()->LockImpl() : NULL;
524 5266 : if( pCache )
525 : {
526 28 : nPgCount = pCache->size() + 1;
527 28 : pDoc->GetLayoutCache()->UnlockImpl();
528 : }
529 : else
530 : {
531 5238 : nPgCount = pDoc->getIDocumentStatistics().GetDocStat().nPage;
532 5238 : if ( nPgCount <= 10 ) // no page insertion for less than 10 pages
533 5238 : nPgCount = 0;
534 5238 : sal_uLong nNdCount = pDoc->getIDocumentStatistics().GetDocStat().nPara;
535 5238 : if ( nNdCount <= 1 )
536 : {
537 : //Estimates the number of paragraphs.
538 5108 : sal_uLong nTmp = pDoc->GetNodes().GetEndOfContent().GetIndex() -
539 5108 : pDoc->GetNodes().GetEndOfExtras().GetIndex();
540 : //Tables have a little overhead..
541 5108 : nTmp -= pDoc->GetTblFrmFmts()->size() * 25;
542 : //Fly frames, too ..
543 10216 : nTmp -= (pDoc->GetNodes().GetEndOfAutotext().GetIndex() -
544 10216 : pDoc->GetNodes().GetEndOfInserts().GetIndex()) / 3 * 5;
545 5108 : if ( nTmp > 0 )
546 5070 : nNdCount = nTmp;
547 : }
548 5238 : if ( nNdCount > 100 ) // no estimation below this value
549 : {
550 1910 : if ( nPgCount > 0 )
551 0 : nMaxParaPerPage = nNdCount / nPgCount;
552 : else
553 : {
554 : nMaxParaPerPage = std::max( sal_uLong(20),
555 1910 : sal_uLong(20 + nNdCount / 1000 * 3) );
556 1910 : const sal_uLong nMax = 53;
557 1910 : nMaxParaPerPage = std::min( nMaxParaPerPage, nMax );
558 1910 : nPgCount = nNdCount / nMaxParaPerPage;
559 : }
560 1910 : if ( nNdCount < 1000 )
561 90 : nPgCount = 0;// no progress bar for small documents
562 1910 : SwViewShell *pSh = 0;
563 1910 : if( rpLay && rpLay->getRootFrm() )
564 1910 : pSh = rpLay->getRootFrm()->GetCurrShell();
565 1910 : if( pSh && pSh->GetViewOptions()->getBrowseMode() )
566 0 : nMaxParaPerPage *= 6;
567 : }
568 : }
569 5266 : 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 24940 : bool SwLayHelper::CheckInsertPage()
582 : {
583 24940 : bool bEnd = 0 == rpPage->GetNext();
584 24940 : const SwAttrSet* pAttr = rpFrm->GetAttrSet();
585 24940 : const SvxFmtBreakItem& rBrk = pAttr->GetBreak();
586 24940 : const SwFmtPageDesc& rDesc = pAttr->GetPageDesc();
587 : // #118195# Do not evaluate page description if frame
588 : // is a follow frame!
589 49880 : const SwPageDesc* pDesc = rpFrm->IsFlowFrm() &&
590 24940 : SwFlowFrm::CastFlowFrm( rpFrm )->IsFollow() ?
591 : 0 :
592 49730 : rDesc.GetPageDesc();
593 :
594 24940 : bool bBrk = nParagraphCnt > nMaxParaPerPage || rbBreakAfter;
595 49880 : rbBreakAfter = rBrk.GetBreak() == SVX_BREAK_PAGE_AFTER ||
596 74820 : rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
597 24940 : if ( !bBrk )
598 47652 : bBrk = rBrk.GetBreak() == SVX_BREAK_PAGE_BEFORE ||
599 47652 : rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
600 :
601 24940 : if ( bBrk || pDesc )
602 : {
603 1662 : ::boost::optional<sal_uInt16> oPgNum;
604 1662 : if ( !pDesc )
605 : {
606 1432 : pDesc = rpPage->GetPageDesc()->GetFollow();
607 :
608 1432 : SwFmtPageDesc aFollowDesc( pDesc );
609 1432 : oPgNum = aFollowDesc.GetNumOffset();
610 1432 : if ( oPgNum )
611 0 : ((SwRootFrm*)rpPage->GetUpper())->SetVirtPageNum(true);
612 : }
613 : else
614 : {
615 230 : oPgNum = rDesc.GetNumOffset();
616 230 : if ( oPgNum )
617 30 : ((SwRootFrm*)rpPage->GetUpper())->SetVirtPageNum(true);
618 : }
619 1662 : bool bNextPageOdd = !rpPage->OnRightPage();
620 1662 : bool bInsertEmpty = false;
621 1662 : if( oPgNum && bNextPageOdd != ( ( oPgNum.get() % 2 ) != 0 ) )
622 : {
623 18 : bNextPageOdd = !bNextPageOdd;
624 18 : bInsertEmpty = true;
625 : }
626 : // If the page style is changing, we'll have a first page.
627 1662 : bool bNextPageFirst = pDesc != rpPage->GetPageDesc();
628 1662 : ::InsertNewPage( (SwPageDesc&)*pDesc, rpPage->GetUpper(),
629 3324 : bNextPageOdd, bNextPageFirst, bInsertEmpty, false, rpPage->GetNext() );
630 1662 : if ( bEnd )
631 : {
632 : OSL_ENSURE( rpPage->GetNext(), "No new page?" );
633 1684 : do
634 1684 : { rpPage = (SwPageFrm*)rpPage->GetNext();
635 1684 : } while ( rpPage->GetNext() );
636 : }
637 : else
638 : {
639 : OSL_ENSURE( rpPage->GetNext(), "No new page?" );
640 0 : rpPage = (SwPageFrm*)rpPage->GetNext();
641 0 : if ( rpPage->IsEmptyPage() )
642 : {
643 : OSL_ENSURE( rpPage->GetNext(), "No new page?" );
644 0 : rpPage = (SwPageFrm*)rpPage->GetNext();
645 : }
646 : }
647 1662 : rpLay = rpPage->FindBodyCont();
648 3344 : while( rpLay->Lower() )
649 20 : rpLay = (SwLayoutFrm*)rpLay->Lower();
650 1662 : return true;
651 : }
652 23278 : 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 30072 : bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex )
663 : {
664 30072 : bool bRet = false;
665 30072 : bool bLongTab = false;
666 30072 : sal_uLong nMaxRowPerPage( 0 );
667 30072 : nNodeIndex -= nStartOfContent;
668 30072 : sal_uInt16 nRows( 0 );
669 30072 : if( rpFrm->IsTabFrm() )
670 : {
671 : //Inside a table counts every row as a paragraph
672 784 : SwFrm *pLow = ((SwTabFrm*)rpFrm)->Lower();
673 784 : nRows = 0;
674 4392 : do
675 : {
676 4392 : ++nRows;
677 4392 : pLow = pLow->GetNext();
678 : } while ( pLow );
679 784 : nParagraphCnt += nRows;
680 784 : 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 30 : if ( nRows > ( 3*nMaxParaPerPage ) )
688 : {
689 8 : nMaxRowPerPage = nMaxParaPerPage;
690 : }
691 : else
692 : {
693 22 : SwFrm *pTmp = ((SwTabFrm*)rpFrm)->Lower();
694 22 : if( pTmp->GetNext() )
695 22 : pTmp = pTmp->GetNext();
696 22 : pTmp = ((SwRowFrm*)pTmp)->Lower();
697 22 : sal_uInt16 nCnt = 0;
698 62 : do
699 : {
700 62 : ++nCnt;
701 62 : pTmp = pTmp->GetNext();
702 : } while( pTmp );
703 22 : nMaxRowPerPage = std::max( sal_uLong(2), nMaxParaPerPage / nCnt );
704 : }
705 30 : bLongTab = true;
706 : }
707 : }
708 : else
709 29288 : ++nParagraphCnt;
710 35366 : if( bFirst && pImpl && nIndex < pImpl->size() &&
711 30102 : pImpl->GetBreakIndex( nIndex ) == nNodeIndex &&
712 6 : ( pImpl->GetBreakOfst( nIndex ) < COMPLETE_STRING ||
713 6 : ( ++nIndex < pImpl->size() &&
714 2 : 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 60156 : if ( !bFirst ||
723 5630 : ( rpFrm->IsTabFrm() && bLongTab )
724 : )
725 : {
726 24818 : sal_Int32 nRowCount = 0;
727 24940 : do
728 : {
729 24940 : 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 322 : sal_Int32 nOfst = COMPLETE_STRING;
737 322 : sal_uInt16 nType = SW_LAYCACHE_IO_REC_PAGES;
738 322 : if( bLongTab )
739 : {
740 150 : rbBreakAfter = true;
741 150 : nOfst = static_cast<sal_Int32>(nRowCount + nMaxRowPerPage);
742 : }
743 : else
744 : {
745 506 : while( nIndex < pImpl->size() &&
746 162 : pImpl->GetBreakIndex(nIndex) < nNodeIndex)
747 0 : ++nIndex;
748 334 : if( nIndex < pImpl->size() &&
749 162 : pImpl->GetBreakIndex(nIndex) == nNodeIndex )
750 : {
751 64 : nType = pImpl->GetBreakType( nIndex );
752 64 : nOfst = pImpl->GetBreakOfst( nIndex++ );
753 64 : rbBreakAfter = true;
754 : }
755 : }
756 :
757 322 : if( nOfst < COMPLETE_STRING )
758 : {
759 158 : bool bSplit = false;
760 158 : sal_uInt16 nRepeat( 0 );
761 324 : if( !bLongTab && rpFrm->IsTxtFrm() &&
762 166 : SW_LAYCACHE_IO_REC_PARA == nType &&
763 8 : nOfst<((SwTxtFrm*)rpFrm)->GetTxtNode()->GetTxt().getLength())
764 8 : bSplit = true;
765 300 : else if( rpFrm->IsTabFrm() && nRowCount < nOfst &&
766 0 : ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) )
767 : {
768 : nRepeat = ((SwTabFrm*)rpFrm)->
769 150 : GetTable()->GetRowsToRepeat();
770 150 : bSplit = nOfst < nRows && nRowCount + nRepeat < nOfst;
771 150 : bLongTab = bLongTab && bSplit;
772 : }
773 158 : if( bSplit )
774 : {
775 128 : rpFrm->InsertBehind( rpLay, rpPrv );
776 128 : rpFrm->Frm().Pos() = rpLay->Frm().Pos();
777 128 : rpFrm->Frm().Pos().Y() += 1;
778 128 : rpPrv = rpFrm;
779 128 : if( rpFrm->IsTabFrm() )
780 : {
781 120 : SwTabFrm* pTab = (SwTabFrm*)rpFrm;
782 : // #i33629#, #i29955#
783 120 : ::RegistFlys( pTab->FindPageFrm(), pTab );
784 120 : SwFrm *pRow = pTab->Lower();
785 120 : SwTabFrm *pFoll = new SwTabFrm( *pTab );
786 :
787 : SwFrm *pPrv;
788 120 : 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 120 : pPrv = 0;
813 1788 : while( pRow && nRowCount < nOfst )
814 : {
815 1548 : pRow = pRow->GetNext();
816 1548 : ++nRowCount;
817 : }
818 6728 : while ( pRow )
819 : {
820 6488 : SwFrm* pNxt = pRow->GetNext();
821 6488 : pRow->Remove();
822 6488 : pRow->InsertBehind( pFoll, pPrv );
823 6488 : pPrv = pRow;
824 6488 : pRow = pNxt;
825 : }
826 120 : rpFrm = pFoll;
827 : }
828 : else
829 : {
830 : SwTxtFrm *const pNew = static_cast<SwTxtFrm*>(
831 : static_cast<SwTxtFrm*>(rpFrm)
832 8 : ->GetTxtNode()->MakeFrm(rpFrm));
833 8 : pNew->ManipOfst( nOfst );
834 8 : pNew->SetFollow( ((SwTxtFrm*)rpFrm)->GetFollow() );
835 8 : ((SwTxtFrm*)rpFrm)->SetFollow( pNew );
836 8 : rpFrm = pNew;
837 : }
838 : }
839 : }
840 : }
841 :
842 24940 : SwPageFrm* pLastPage = rpPage;
843 24940 : if( CheckInsertPage() )
844 : {
845 1662 : _CheckFlyCache( pLastPage );
846 1662 : if( rpPrv && rpPrv->IsTxtFrm() && !rpPrv->GetValidSizeFlag() )
847 1444 : rpPrv->Frm().Height( rpPrv->GetUpper()->Prt().Height() );
848 :
849 1662 : bRet = true;
850 1662 : rpPrv = 0;
851 1662 : nParagraphCnt = 0;
852 :
853 1662 : 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 106 : bool bInit = false;
859 106 : if ( !rpActualSection->GetSectionFrm()->ContainsCntnt())
860 : {
861 22 : pSct = rpActualSection->GetSectionFrm();
862 22 : pSct->Remove();
863 : }
864 : else
865 : {
866 : pSct = new SwSectionFrm(
867 84 : *rpActualSection->GetSectionFrm(), false );
868 84 : rpActualSection->GetSectionFrm()->SimpleFormat();
869 84 : bInit = true;
870 : }
871 106 : rpActualSection->SetSectionFrm( pSct );
872 106 : pSct->InsertBehind( rpLay, 0 );
873 106 : if( bInit )
874 84 : pSct->Init();
875 106 : pSct->Frm().Pos() = rpLay->Frm().Pos();
876 106 : pSct->Frm().Pos().Y() += 1; //because of the notifications
877 :
878 106 : rpLay = pSct;
879 106 : if ( rpLay->Lower() && rpLay->Lower()->IsLayoutFrm() )
880 28 : rpLay = rpLay->GetNextLayoutLeaf();
881 : }
882 : }
883 25076 : } while( bLongTab || ( pImpl && nIndex < pImpl->size() &&
884 136 : pImpl->GetBreakIndex( nIndex ) == nNodeIndex ) );
885 : }
886 30072 : bFirst = false;
887 30072 : 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 14 : bool operator()( const SwFlyCache* pC1, const SwFlyCache* pC2 ) const
901 : {
902 14 : 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 1664 : void SwLayHelper::_CheckFlyCache( SwPageFrm* pPage )
912 : {
913 1664 : if( !pImpl || !pPage )
914 3262 : return;
915 66 : sal_uInt16 nFlyCount = pImpl->GetFlyCount();
916 : // Any text frames at the page, fly cache available?
917 66 : if( pPage->GetSortedObjs() && nFlyIdx < nFlyCount )
918 : {
919 4 : SwSortedObjs &rObjs = *pPage->GetSortedObjs();
920 4 : 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 24 : while( nFlyIdx < nFlyCount &&
927 10 : pImpl->GetFlyCache(nFlyIdx).nPageNum < nPgNum )
928 6 : ++nFlyIdx;
929 :
930 : // sort cached objects on this page by ordnum
931 4 : std::set< const SwFlyCache*, FlyCacheCompare > aFlyCacheSet;
932 4 : sal_uInt16 nIdx = nFlyIdx;
933 :
934 : SwFlyCache* pFlyC;
935 36 : while( nIdx < nFlyCount &&
936 20 : ( pFlyC = &pImpl->GetFlyCache( nIdx ) )->nPageNum == nPgNum )
937 : {
938 8 : aFlyCacheSet.insert( pFlyC );
939 8 : ++nIdx;
940 : }
941 :
942 : // sort objects on this page by ordnum
943 8 : std::set< const SdrObject*, SdrObjectCompare > aFlySet;
944 8 : for ( size_t i = 0; i < rObjs.size(); ++i )
945 : {
946 4 : SwAnchoredObject* pAnchoredObj = rObjs[i];
947 4 : if ( pAnchoredObj->ISA(SwFlyFrm) ) // a text frame?
948 : {
949 4 : SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
950 8 : if( pFly->GetAnchorFrm() &&
951 4 : !pFly->GetAnchorFrm()->FindFooterOrHeader() )
952 : {
953 4 : const SwContact *pC = ::GetUserCall( pAnchoredObj->GetDrawObj() );
954 4 : if( pC )
955 : {
956 4 : aFlySet.insert( pAnchoredObj->GetDrawObj() );
957 : }
958 : }
959 : }
960 : }
961 :
962 4 : 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 = ((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 4 : }
992 : }
993 : }
994 :
995 38 : 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 38 : bError( false )
1002 : {
1003 38 : if( bWriteMode )
1004 6 : pStream->WriteUInt16( nMajorVersion )
1005 12 : .WriteUInt16( nMinorVersion );
1006 :
1007 : else
1008 32 : pStream->ReadUInt16( nMajorVersion )
1009 64 : .ReadUInt16( nMinorVersion );
1010 38 : }
1011 :
1012 174 : bool SwLayCacheIoImpl::OpenRec( sal_uInt8 cType )
1013 : {
1014 174 : bool bRes = true;
1015 174 : sal_uInt32 nPos = pStream->Tell();
1016 174 : if( bWriteMode )
1017 : {
1018 28 : aRecords.push_back( RecTypeSize(cType, nPos) );
1019 28 : pStream->WriteUInt32( 0 );
1020 : }
1021 : else
1022 : {
1023 146 : sal_uInt32 nVal(0);
1024 146 : pStream->ReadUInt32( nVal );
1025 146 : sal_uInt8 cRecTyp = (sal_uInt8)nVal;
1026 584 : if( !nVal || cRecTyp != cType ||
1027 438 : 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 146 : sal_uInt32 nSize = nVal >> 8;
1038 146 : aRecords.push_back( RecTypeSize(cRecTyp, nPos+nSize) );
1039 : }
1040 : }
1041 174 : return bRes;
1042 : }
1043 :
1044 : // Close record
1045 174 : bool SwLayCacheIoImpl::CloseRec( sal_uInt8 )
1046 : {
1047 174 : bool bRes = true;
1048 : OSL_ENSURE( !aRecords.empty(), "CloseRec: no levels" );
1049 174 : if( !aRecords.empty() )
1050 : {
1051 174 : sal_uInt32 nPos = pStream->Tell();
1052 174 : if( bWriteMode )
1053 : {
1054 28 : sal_uInt32 nBgn = aRecords.back().size;
1055 28 : pStream->Seek( nBgn );
1056 28 : sal_uInt32 nSize = nPos - nBgn;
1057 28 : sal_uInt32 nVal = ( nSize << 8 ) | aRecords.back().type;
1058 28 : pStream->WriteUInt32( nVal );
1059 28 : pStream->Seek( nPos );
1060 28 : if( pStream->GetError() != SVSTREAM_OK )
1061 0 : bRes = false;
1062 : }
1063 : else
1064 : {
1065 146 : sal_uInt32 n = aRecords.back().size;
1066 : OSL_ENSURE( n >= nPos, "CloseRec: to much data read" );
1067 146 : if( n != nPos )
1068 : {
1069 0 : pStream->Seek( n );
1070 0 : if( n < nPos )
1071 0 : bRes = false;
1072 : }
1073 146 : if( pStream->GetErrorCode() != SVSTREAM_OK )
1074 0 : bRes = false;
1075 : }
1076 174 : aRecords.pop_back();
1077 : }
1078 :
1079 174 : if( !bRes )
1080 0 : bError = true;
1081 :
1082 174 : return bRes;
1083 : }
1084 :
1085 146 : sal_uInt32 SwLayCacheIoImpl::BytesLeft()
1086 : {
1087 146 : sal_uInt32 n = 0;
1088 146 : if( !bError && !aRecords.empty() )
1089 : {
1090 146 : sal_uInt32 nEndPos = aRecords.back().size;
1091 146 : sal_uInt32 nPos = pStream->Tell();
1092 146 : if( nEndPos > nPos )
1093 114 : n = nEndPos - nPos;
1094 : }
1095 146 : return n;
1096 : }
1097 :
1098 114 : sal_uInt8 SwLayCacheIoImpl::Peek()
1099 : {
1100 114 : sal_uInt8 c(0);
1101 114 : if( !bError )
1102 : {
1103 114 : sal_uInt32 nPos = pStream->Tell();
1104 114 : pStream->ReadUChar( c );
1105 114 : pStream->Seek( nPos );
1106 114 : if( pStream->GetErrorCode() != SVSTREAM_OK )
1107 : {
1108 0 : c = 0;
1109 0 : bError = true;
1110 : }
1111 : }
1112 114 : 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 146 : sal_uInt8 SwLayCacheIoImpl::OpenFlagRec()
1124 : {
1125 : OSL_ENSURE( !bWriteMode, "OpenFlagRec illegal in write mode" );
1126 146 : sal_uInt8 cFlags(0);
1127 146 : pStream->ReadUChar( cFlags );
1128 146 : nFlagRecEnd = pStream->Tell() + ( cFlags & 0x0F );
1129 146 : return (cFlags >> 4);
1130 : }
1131 :
1132 28 : 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 28 : sal_uInt8 cFlags = (nFlags << 4) + nLen;
1138 28 : pStream->WriteUChar( cFlags );
1139 28 : nFlagRecEnd = pStream->Tell() + nLen;
1140 28 : }
1141 :
1142 174 : void SwLayCacheIoImpl::CloseFlagRec()
1143 : {
1144 174 : 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 146 : if( pStream->Tell() != nFlagRecEnd )
1152 0 : pStream->Seek( nFlagRecEnd );
1153 : }
1154 444 : }
1155 :
1156 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|