update dev300-m58
[ooovba.git] / sc / source / filter / lotus / op.cxx
blobeb7d043f80c5a4826fb6420c98c223059e314070
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: op.cxx,v $
10 * $Revision: 1.18.126.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 //------------------------------------------------------------------------
36 #include <tools/solar.h>
37 #include <rtl/math.hxx>
39 #include <stdio.h>
40 #include <string.h>
41 #include <math.h>
42 #include <ctype.h>
43 #if defined( ICC )
44 #include <stdlib.h>
45 #endif
47 #include "scitems.hxx"
48 #include "patattr.hxx"
49 #include "docpool.hxx"
50 #include <svx/algitem.hxx>
51 #include <svx/postitem.hxx>
52 #include <svx/udlnitem.hxx>
53 #include <svx/wghtitem.hxx>
55 #include "cell.hxx"
56 #include "rangenam.hxx"
57 #include "document.hxx"
58 #include "postit.hxx"
60 #include "op.h"
61 #include "optab.h"
62 #include "tool.h"
63 //#include "math.h"
64 #include "decl.h"
65 #include "lotform.hxx"
66 #include "lotrange.hxx"
68 #include "root.hxx"
70 #include "ftools.hxx"
72 #include <vector>
73 #include <map>
75 #include <stdio.h>
76 #include <string.h>
77 #include <math.h>
78 #include <ctype.h>
79 #if defined( MAC ) || defined( ICC )
80 #include <stdlib.h>
81 #endif
83 extern sal_Char* pAnsi; // -> memory.cxx, Puffer zum Umwandeln von OEM->ANSI
84 extern sal_Char* pErgebnis; // -> memory.cxx, Ergebnispuffer
85 extern WKTYP eTyp; // -> filter.cxx, aktueller Dateityp
86 extern BOOL bEOF; // -> filter.cxx, zeigt Dateiende an
87 extern sal_Char* pPuffer0; // -> memory.cxx
88 extern sal_Char* pPuffer1;
89 extern BYTE nDefaultFormat; // -> tool.cxx, Default-Zellenformat
90 extern ScDocument* pDoc; // -> filter.cxx, Aufhaenger zum Dokumentzugriff
91 extern BYTE* pFormelBuffer; // -> memory.cxx, fuer
92 extern CharSet eCharVon; // -> filter.cxx, character set specified
94 static UINT16 nDefWidth = ( UINT16 ) ( TWIPS_PER_CHAR * 10 );
96 extern std::map<UINT16, ScPatternAttr> aLotusPatternPool;
98 void NI( SvStream& r, UINT16 n )
100 r.SeekRel( n );
104 void OP_BOF( SvStream& r, UINT16 /*n*/ )
106 r.SeekRel( 2 ); // Versionsnummer ueberlesen
110 void OP_EOF( SvStream& /*r*/, UINT16 /*n*/ )
112 bEOF = TRUE;
116 void OP_Integer( SvStream& r, UINT16 /*n*/ )
118 BYTE nFormat;
119 UINT16 nCol, nRow;
120 SCTAB nTab = 0;
121 INT16 nValue;
123 r >> nFormat >> nCol >> nRow >> nValue;
125 ScValueCell* pZelle = new ScValueCell( ( double ) nValue );
126 pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( BOOL ) TRUE );
128 // 0 Stellen nach'm Komma!
129 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, 0 );
133 void OP_Number( SvStream& r, UINT16 /*n*/ )
135 BYTE nFormat;
136 UINT16 nCol, nRow;
137 SCTAB nTab = 0;
138 double fValue;
140 r >> nFormat >> nCol >> nRow >> fValue;
142 fValue = ::rtl::math::round( fValue, 15 );
143 ScValueCell* pZelle = new ScValueCell( fValue );
144 pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( BOOL ) TRUE );
146 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezFloat );
150 void OP_Label( SvStream& r, UINT16 n )
152 BYTE nFormat;
153 UINT16 nCol, nRow;
154 SCTAB nTab = 0;
156 r >> nFormat >> nCol >> nRow;
157 n -= 5;
159 sal_Char* pText = new sal_Char[n + 1];
160 r.Read( pText, n );
161 pText[n] = 0;
163 nFormat &= 0x80; // Bit 7 belassen
164 nFormat |= 0x75; // protected egal, special-text gesetzt
166 PutFormString( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pText );
168 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezStd );
170 delete [] pText;
174 //UNUSED2009-05 void OP_Text( SvStream& r, UINT16 n ) // WK3
175 //UNUSED2009-05 {
176 //UNUSED2009-05 UINT16 nRow;
177 //UNUSED2009-05 BYTE nCol, nTab;
178 //UNUSED2009-05 sal_Char pText[ 256 ];
179 //UNUSED2009-05
180 //UNUSED2009-05 r >> nRow >> nTab >> nCol;
181 //UNUSED2009-05 n -= 4;
182 //UNUSED2009-05
183 //UNUSED2009-05 r.Read( pText, n );
184 //UNUSED2009-05 pText[ n ] = 0; // zur Sicherheit Nullterminator anhaengen
185 //UNUSED2009-05
186 //UNUSED2009-05 PutFormString( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), static_cast<SCTAB> (nTab), pText );
187 //UNUSED2009-05 }
190 void OP_Formula( SvStream& r, UINT16 /*n*/ )
192 BYTE nFormat;
193 UINT16 nCol, nRow, nFormulaSize;
194 SCTAB nTab = 0;
196 r >> nFormat >> nCol >> nRow;
197 r.SeekRel( 8 ); // Ergebnis ueberspringen
198 r >> nFormulaSize;
200 const ScTokenArray* pErg;
201 INT32 nBytesLeft = nFormulaSize;
202 ScAddress aAddress( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab );
204 LotusToSc aConv( r, pLotusRoot->eCharsetQ, FALSE );
205 aConv.Reset( aAddress );
206 aConv.Convert( pErg, nBytesLeft );
208 ScFormulaCell* pZelle = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
210 pZelle->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
212 pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( BOOL ) TRUE );
214 // nFormat = Standard -> Nachkommastellen wie Float
215 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezFloat );
219 void OP_ColumnWidth( SvStream& r, UINT16 /*n*/ )
221 UINT16 nCol, nBreite;
222 BYTE nWidthSpaces;
223 SCTAB nTab = 0;
225 r >> nCol >> nWidthSpaces;
227 if( nWidthSpaces )
228 // Annahme: 10cpi-Zeichensatz
229 nBreite = ( UINT16 ) ( TWIPS_PER_CHAR * nWidthSpaces );
230 else
232 pDoc->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), 0, true);
233 nBreite = nDefWidth;
236 pDoc->SetColWidth( static_cast<SCCOL> (nCol), nTab, nBreite );
240 void OP_NamedRange( SvStream& r, UINT16 /*n*/ )
242 // POST: waren Koordinaten ungueltig, wird nicht gespeichert
243 UINT16 nColSt, nRowSt, nColEnd, nRowEnd;
244 sal_Char cPuffer[ 32 ];
246 r.Read( cPuffer, 16 );
248 r >> nColSt >> nRowSt >> nColEnd >> nRowEnd;
250 LotusRange* pRange;
252 if( nColSt == nColEnd && nRowSt == nRowEnd )
253 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) );
254 else
255 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt), static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) );
257 if( isdigit( *cPuffer ) )
258 { // erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen
259 *pAnsi = 'A';
260 strcpy( pAnsi + 1, cPuffer ); // #100211# - checked
262 else
263 strcpy( pAnsi, cPuffer ); // #100211# - checked
265 String aTmp( pAnsi, pLotusRoot->eCharsetQ );
267 ScfTools::ConvertToScDefinedName( aTmp );
269 pLotusRoot->pRangeNames->Append( pRange, aTmp );
273 void OP_SymphNamedRange( SvStream& r, UINT16 /*n*/ )
275 // POST: waren Koordinaten ungueltig, wird nicht gespeichert
276 UINT16 nColSt, nRowSt, nColEnd, nRowEnd;
277 BYTE nType;
278 sal_Char* pName;
279 sal_Char cPuffer[ 32 ];
281 r.Read( cPuffer, 16 );
282 cPuffer[ 16 ] = 0;
283 pName = cPuffer;
285 r >> nColSt >> nRowSt >> nColEnd >> nRowEnd >> nType;
287 LotusRange* pRange;
289 if( nType )
290 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) );
291 else
292 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt), static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) );
294 if( isdigit( *cPuffer ) )
295 { // erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen
296 *pAnsi = 'A';
297 strcpy( pAnsi + 1, cPuffer ); // #100211# - checked
299 else
300 strcpy( pAnsi, cPuffer ); // #100211# - checked
302 String aTmp( pAnsi, pLotusRoot->eCharsetQ );
303 ScfTools::ConvertToScDefinedName( aTmp );
305 pLotusRoot->pRangeNames->Append( pRange, aTmp );
309 void OP_Footer( SvStream& r, UINT16 n )
311 r.SeekRel( n );
315 void OP_Header( SvStream& r, UINT16 n )
317 r.SeekRel( n );
321 void OP_Margins( SvStream& r, UINT16 n )
323 r.SeekRel( n );
327 void OP_HiddenCols( SvStream& r, UINT16 /*n*/ )
329 UINT16 nByte, nBit;
330 SCCOL nCount;
331 BYTE nAkt;
332 nCount = 0;
334 for( nByte = 0 ; nByte < 32 ; nByte++ ) // 32 Bytes mit ...
336 r >> nAkt;
337 for( nBit = 0 ; nBit < 8 ; nBit++ ) // ...jeweils 8 Bits = 256 Bits
339 if( nAkt & 0x01 ) // unterstes Bit gesetzt?
340 // -> Hidden Col
341 pDoc->SetColHidden(nCount, nCount, 0, true);
343 nCount++;
344 nAkt = nAkt / 2; // der Naechste bitte...
350 void OP_Window1( SvStream& r, UINT16 n )
352 r.SeekRel( 4 ); // Cursor Pos ueberspringen
354 r >> nDefaultFormat;
356 r.SeekRel( 1 ); // 'unused' ueberspringen
358 r >> nDefWidth;
360 r.SeekRel( n - 8 ); // und den Rest ueberspringen
362 nDefWidth = ( UINT16 ) ( TWIPS_PER_CHAR * nDefWidth );
364 // statt Defaulteinstellung in SC alle Cols zu Fuss setzen
365 for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
366 pDoc->SetColWidth( nCol, 0, nDefWidth );
370 void OP_Blank( SvStream& r, UINT16 /*n*/ )
372 UINT16 nCol, nRow;
373 BYTE nFormat;
374 r >> nFormat >> nCol >> nRow;
376 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), 0, nFormat, nDezFloat );
379 void OP_BOF123( SvStream& r, UINT16 /*n*/ )
381 r.SeekRel( 26 );
385 void OP_EOF123( SvStream& /*r*/, UINT16 /*n*/ )
387 bEOF = TRUE;
390 void OP_Label123( SvStream& r, UINT16 n )
392 BYTE nTab, nCol;
393 UINT16 nRow;
394 r >> nRow >> nTab >> nCol;
395 n -= 4;
397 sal_Char* pText = new sal_Char[n + 1];
398 r.Read( pText, n );
399 pText[ n ] = 0;
401 PutFormString( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pText );
403 delete []pText;
406 void OP_Number123( SvStream& r, UINT16 /*n*/ )
408 BYTE nCol,nTab;
409 UINT16 nRow;
410 UINT32 nValue;
412 r >> nRow >> nTab >> nCol >> nValue;
413 double fValue = Snum32ToDouble( nValue );
415 ScValueCell *pCell = new ScValueCell( fValue );
416 pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (BOOL) TRUE );
419 void OP_Formula123( SvStream& r, UINT16 n )
421 BYTE nCol,nTab;
422 UINT16 nRow;
424 r >> nRow >> nTab >> nCol;
425 r.SeekRel( 8 ); // Result- jump over
427 const ScTokenArray* pErg;
428 INT32 nBytesLeft = n - 12;
429 ScAddress aAddress( nCol, nRow, nTab );
431 LotusToSc aConv( r, pLotusRoot->eCharsetQ, TRUE );
432 aConv.Reset( aAddress );
433 aConv.Convert( pErg, nBytesLeft );
435 ScFormulaCell* pCell = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
437 pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
439 pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (BOOL) TRUE );
442 void OP_IEEENumber123( SvStream& r, UINT16 /*n*/ )
444 BYTE nCol,nTab;
445 UINT16 nRow;
446 double dValue;
448 r >> nRow >> nTab >> nCol >> dValue;
450 ScValueCell *pCell = new ScValueCell(dValue);
451 pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (BOOL) TRUE );
454 void OP_Note123( SvStream& r, UINT16 n)
456 BYTE nTab, nCol;
457 UINT16 nRow;
458 r >> nRow >> nTab >> nCol;
459 n -= 4;
461 sal_Char* pText = new sal_Char[n + 1];
462 r.Read( pText, n );
463 pText[ n ] = 0;
465 String aNoteText(pText,pLotusRoot->eCharsetQ);
466 delete [] pText;
468 ScAddress aPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab) );
469 ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false, false );
472 void OP_HorAlign123( BYTE nAlignPattern, SfxItemSet& rPatternItemSet )
474 // pre: Pattern is stored in the last 3 bites of the 21st byte
475 // post: Appropriate Horizontal Alignement is set in rPattern according to the bit pattern.
477 // LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
478 // LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
480 nAlignPattern = ( nAlignPattern & 0x07);
482 switch (nAlignPattern)
484 case 1:
485 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
486 break;
487 case 2:
488 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY ) );
489 break;
490 case 3:
491 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY) );
492 break;
493 case 4:
494 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) );
495 break;
496 case 6:
497 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_BLOCK, ATTR_HOR_JUSTIFY ) );
498 break;
499 default:
500 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) );
501 break;
505 void OP_VerAlign123( BYTE nAlignPattern,SfxItemSet& rPatternItemSet )
507 // pre: Pattern is stored in the last 3 bites of the 22nd byte
508 // post: Appropriate Verticle Alignement is set in rPattern according to the bit pattern.
510 // TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
512 nAlignPattern = ( nAlignPattern & 0x07);
514 switch (nAlignPattern)
516 case 0:
517 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) );
518 break;
519 case 1:
520 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_TOP, ATTR_VER_JUSTIFY) );
521 break;
522 case 2:
523 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY) );
524 break;
525 case 4:
526 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_BOTTOM, ATTR_VER_JUSTIFY) );
527 break;
528 default:
529 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) );
530 break;
534 void OP_CreatePattern123( SvStream& r, UINT16 n)
536 UINT16 nCode,nPatternId;
538 ScPatternAttr aPattern(pDoc->GetPool());
539 SfxItemSet& rItemSet = aPattern.GetItemSet();
541 r >> nCode;
542 n = n - 2;
544 if ( nCode == 0x0fd2 )
546 r >> nPatternId;
548 BYTE Hor_Align, Ver_Align, temp;
549 BOOL bIsBold,bIsUnderLine,bIsItalics;
551 r.SeekRel(12);
553 // Read 17th Byte
554 r >> temp;
556 bIsBold = (temp & 0x01);
557 bIsItalics = (temp & 0x02);
558 bIsUnderLine = (temp & 0x04);
560 if ( bIsBold )
561 rItemSet.Put( SvxWeightItem(WEIGHT_BOLD,ATTR_FONT_WEIGHT) );
562 if ( bIsItalics )
563 rItemSet.Put( SvxPostureItem(ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
564 if ( bIsUnderLine )
565 rItemSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE, ATTR_FONT_UNDERLINE ) );
567 r.SeekRel(3);
569 // Read 21st Byte
570 r >> Hor_Align;
571 OP_HorAlign123( Hor_Align, rItemSet );
573 r >> Ver_Align;
574 OP_VerAlign123( Ver_Align, rItemSet );
576 aLotusPatternPool.insert( std::map<UINT16, ScPatternAttr>::value_type( nPatternId, aPattern ) );
577 n = n - 20;
579 r.SeekRel(n);
582 void OP_SheetName123( SvStream& rStream, USHORT nLength )
584 if (nLength <= 4)
586 rStream.SeekRel(nLength);
587 return;
590 // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
592 sal_uInt16 nDummy;
593 rStream >> nDummy; // ignore the first 2 bytes (B0 36).
594 rStream >> nDummy;
595 SCTAB nSheetNum = static_cast<SCTAB>(nDummy);
596 pDoc->MakeTable(nSheetNum);
598 ::std::vector<sal_Char> sSheetName;
599 sSheetName.reserve(nLength-4);
600 for (USHORT i = 4; i < nLength; ++i)
602 sal_Char c;
603 rStream >> c;
604 sSheetName.push_back(c);
607 if (!sSheetName.empty())
609 String aName(&sSheetName[0], eCharVon);
610 pDoc->RenameTab(nSheetNum, aName);
614 void OP_ApplyPatternArea123( SvStream& rStream )
616 UINT16 nOpcode, nLength;
617 UINT16 nCol = 0, nColCount = 0, nRow = 0, nRowCount = 0, nTab = 0, nData, nTabCount = 0, nLevel = 0;
621 rStream >> nOpcode >> nLength;
622 switch ( nOpcode )
624 case ROW_FORMAT_MARKER:
625 nLevel++;
626 break;
627 case COL_FORMAT_MARKER:
628 nLevel--;
629 if( nLevel == 1 )
631 nTab = nTab + nTabCount;
632 nCol = 0; nColCount = 0;
633 nRow = 0; nRowCount = 0;
635 break;
636 case LOTUS_FORMAT_INDEX:
637 if( nLength >= 2 )
639 rStream >> nData;
640 rStream.SeekRel( nLength - 2 );
641 if( nLevel == 1 )
642 nTabCount = nData;
643 else if( nLevel == 2 )
645 nCol = nCol + nColCount;
646 nColCount = nData;
647 if ( nCol > 0xff ) // 256 is the max col size supported by 123
648 nCol = 0;
650 else if( nLevel == 3 )
652 nRow = nRow + nRowCount;
653 nRowCount = nData;
654 if ( nRow > 0x1fff ) // 8192 is the max row size supported by 123
655 nRow = 0;
658 else
659 rStream.SeekRel( nLength );
660 break;
661 case LOTUS_FORMAT_INFO:
662 if( nLength >= 2 )
664 rStream >> nData;
665 rStream.SeekRel( nLength - 2 );
666 for( int i = 0; i < nTabCount; i++)
668 std::map<UINT16, ScPatternAttr>::iterator loc = aLotusPatternPool.find( nData );
670 // #126338# apparently, files with invalid index occur in the wild -> don't crash then
671 DBG_ASSERT( loc != aLotusPatternPool.end(), "invalid format index" );
672 if ( loc != aLotusPatternPool.end() )
673 pDoc->ApplyPatternAreaTab( nCol, nRow, nCol + nColCount - 1, nRow + nRowCount - 1, static_cast< SCTAB >( nTab + i ), loc->second );
676 else
677 rStream.SeekRel( nLength );
678 break;
679 default:
680 rStream.SeekRel( nLength );
681 break;
684 while( nLevel && !rStream.IsEof() );
686 aLotusPatternPool.clear();