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