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