merged tag ooo/OOO330_m14
[LibreOffice.git] / sc / source / filter / lotus / op.cxx
blob4ab0c8bb3b1469d48bbbceb2b57611426fc7cb82
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
31 //------------------------------------------------------------------------
33 #include <tools/solar.h>
34 #include <rtl/math.hxx>
36 #include <stdio.h>
37 #include <string.h>
38 #include <math.h>
39 #include <ctype.h>
40 #if defined( ICC )
41 #include <stdlib.h>
42 #endif
44 #include "scitems.hxx"
45 #include "patattr.hxx"
46 #include "docpool.hxx"
47 #include <svx/algitem.hxx>
48 #include <editeng/postitem.hxx>
49 #include <editeng/udlnitem.hxx>
50 #include <editeng/wghtitem.hxx>
52 #include "cell.hxx"
53 #include "rangenam.hxx"
54 #include "document.hxx"
55 #include "postit.hxx"
57 #include "op.h"
58 #include "optab.h"
59 #include "tool.h"
60 //#include "math.h"
61 #include "decl.h"
62 #include "lotform.hxx"
63 #include "lotrange.hxx"
65 #include "root.hxx"
67 #include "ftools.hxx"
69 #include <vector>
70 #include <map>
72 #include <stdio.h>
73 #include <string.h>
74 #include <math.h>
75 #include <ctype.h>
76 #if defined( MAC ) || defined( ICC )
77 #include <stdlib.h>
78 #endif
80 extern sal_Char* pAnsi; // -> memory.cxx, Puffer zum Umwandeln von OEM->ANSI
81 extern sal_Char* pErgebnis; // -> memory.cxx, Ergebnispuffer
82 extern WKTYP eTyp; // -> filter.cxx, aktueller Dateityp
83 extern BOOL bEOF; // -> filter.cxx, zeigt Dateiende an
84 extern sal_Char* pPuffer0; // -> memory.cxx
85 extern sal_Char* pPuffer1;
86 extern BYTE nDefaultFormat; // -> tool.cxx, Default-Zellenformat
87 extern ScDocument* pDoc; // -> filter.cxx, Aufhaenger zum Dokumentzugriff
88 extern BYTE* pFormelBuffer; // -> memory.cxx, fuer
89 extern CharSet eCharVon; // -> filter.cxx, character set specified
91 static UINT16 nDefWidth = ( UINT16 ) ( TWIPS_PER_CHAR * 10 );
93 extern std::map<UINT16, ScPatternAttr> aLotusPatternPool;
95 void NI( SvStream& r, UINT16 n )
97 r.SeekRel( n );
101 void OP_BOF( SvStream& r, UINT16 /*n*/ )
103 r.SeekRel( 2 ); // Versionsnummer ueberlesen
107 void OP_EOF( SvStream& /*r*/, UINT16 /*n*/ )
109 bEOF = TRUE;
113 void OP_Integer( SvStream& r, UINT16 /*n*/ )
115 BYTE nFormat;
116 UINT16 nCol, nRow;
117 SCTAB nTab = 0;
118 INT16 nValue;
120 r >> nFormat >> nCol >> nRow >> nValue;
122 ScValueCell* pZelle = new ScValueCell( ( double ) nValue );
123 pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( BOOL ) TRUE );
125 // 0 Stellen nach'm Komma!
126 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, 0 );
130 void OP_Number( SvStream& r, UINT16 /*n*/ )
132 BYTE nFormat;
133 UINT16 nCol, nRow;
134 SCTAB nTab = 0;
135 double fValue;
137 r >> nFormat >> nCol >> nRow >> fValue;
139 fValue = ::rtl::math::round( fValue, 15 );
140 ScValueCell* pZelle = new ScValueCell( fValue );
141 pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( BOOL ) TRUE );
143 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezFloat );
147 void OP_Label( SvStream& r, UINT16 n )
149 BYTE nFormat;
150 UINT16 nCol, nRow;
151 SCTAB nTab = 0;
153 r >> nFormat >> nCol >> nRow;
154 n -= 5;
156 sal_Char* pText = new sal_Char[n + 1];
157 r.Read( pText, n );
158 pText[n] = 0;
160 nFormat &= 0x80; // Bit 7 belassen
161 nFormat |= 0x75; // protected egal, special-text gesetzt
163 PutFormString( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pText );
165 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezStd );
167 delete [] pText;
171 //UNUSED2009-05 void OP_Text( SvStream& r, UINT16 n ) // WK3
172 //UNUSED2009-05 {
173 //UNUSED2009-05 UINT16 nRow;
174 //UNUSED2009-05 BYTE nCol, nTab;
175 //UNUSED2009-05 sal_Char pText[ 256 ];
176 //UNUSED2009-05
177 //UNUSED2009-05 r >> nRow >> nTab >> nCol;
178 //UNUSED2009-05 n -= 4;
179 //UNUSED2009-05
180 //UNUSED2009-05 r.Read( pText, n );
181 //UNUSED2009-05 pText[ n ] = 0; // zur Sicherheit Nullterminator anhaengen
182 //UNUSED2009-05
183 //UNUSED2009-05 PutFormString( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), static_cast<SCTAB> (nTab), pText );
184 //UNUSED2009-05 }
187 void OP_Formula( SvStream& r, UINT16 /*n*/ )
189 BYTE nFormat;
190 UINT16 nCol, nRow, nFormulaSize;
191 SCTAB nTab = 0;
193 r >> nFormat >> nCol >> nRow;
194 r.SeekRel( 8 ); // Ergebnis ueberspringen
195 r >> nFormulaSize;
197 const ScTokenArray* pErg;
198 INT32 nBytesLeft = nFormulaSize;
199 ScAddress aAddress( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab );
201 LotusToSc aConv( r, pLotusRoot->eCharsetQ, FALSE );
202 aConv.Reset( aAddress );
203 aConv.Convert( pErg, nBytesLeft );
205 ScFormulaCell* pZelle = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
207 pZelle->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
209 pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( BOOL ) TRUE );
211 // nFormat = Standard -> Nachkommastellen wie Float
212 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezFloat );
216 void OP_ColumnWidth( SvStream& r, UINT16 /*n*/ )
218 UINT16 nCol, nBreite;
219 BYTE nWidthSpaces;
220 SCTAB nTab = 0;
222 r >> nCol >> nWidthSpaces;
224 if( nWidthSpaces )
225 // Annahme: 10cpi-Zeichensatz
226 nBreite = ( UINT16 ) ( TWIPS_PER_CHAR * nWidthSpaces );
227 else
229 pDoc->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), 0, true);
230 nBreite = nDefWidth;
233 pDoc->SetColWidth( static_cast<SCCOL> (nCol), nTab, nBreite );
237 void OP_NamedRange( SvStream& r, UINT16 /*n*/ )
239 // POST: waren Koordinaten ungueltig, wird nicht gespeichert
240 UINT16 nColSt, nRowSt, nColEnd, nRowEnd;
241 sal_Char cPuffer[ 32 ];
243 r.Read( cPuffer, 16 );
245 r >> nColSt >> nRowSt >> nColEnd >> nRowEnd;
247 LotusRange* pRange;
249 if( nColSt == nColEnd && nRowSt == nRowEnd )
250 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) );
251 else
252 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt), static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) );
254 if( isdigit( *cPuffer ) )
255 { // erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen
256 *pAnsi = 'A';
257 strcpy( pAnsi + 1, cPuffer ); // #100211# - checked
259 else
260 strcpy( pAnsi, cPuffer ); // #100211# - checked
262 String aTmp( pAnsi, pLotusRoot->eCharsetQ );
264 ScfTools::ConvertToScDefinedName( aTmp );
266 pLotusRoot->pRangeNames->Append( pRange, aTmp );
270 void OP_SymphNamedRange( SvStream& r, UINT16 /*n*/ )
272 // POST: waren Koordinaten ungueltig, wird nicht gespeichert
273 UINT16 nColSt, nRowSt, nColEnd, nRowEnd;
274 BYTE nType;
275 sal_Char* pName;
276 sal_Char cPuffer[ 32 ];
278 r.Read( cPuffer, 16 );
279 cPuffer[ 16 ] = 0;
280 pName = cPuffer;
282 r >> nColSt >> nRowSt >> nColEnd >> nRowEnd >> nType;
284 LotusRange* pRange;
286 if( nType )
287 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) );
288 else
289 pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt), static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) );
291 if( isdigit( *cPuffer ) )
292 { // erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen
293 *pAnsi = 'A';
294 strcpy( pAnsi + 1, cPuffer ); // #100211# - checked
296 else
297 strcpy( pAnsi, cPuffer ); // #100211# - checked
299 String aTmp( pAnsi, pLotusRoot->eCharsetQ );
300 ScfTools::ConvertToScDefinedName( aTmp );
302 pLotusRoot->pRangeNames->Append( pRange, aTmp );
306 void OP_Footer( SvStream& r, UINT16 n )
308 r.SeekRel( n );
312 void OP_Header( SvStream& r, UINT16 n )
314 r.SeekRel( n );
318 void OP_Margins( SvStream& r, UINT16 n )
320 r.SeekRel( n );
324 void OP_HiddenCols( SvStream& r, UINT16 /*n*/ )
326 UINT16 nByte, nBit;
327 SCCOL nCount;
328 BYTE nAkt;
329 nCount = 0;
331 for( nByte = 0 ; nByte < 32 ; nByte++ ) // 32 Bytes mit ...
333 r >> nAkt;
334 for( nBit = 0 ; nBit < 8 ; nBit++ ) // ...jeweils 8 Bits = 256 Bits
336 if( nAkt & 0x01 ) // unterstes Bit gesetzt?
337 // -> Hidden Col
338 pDoc->SetColHidden(nCount, nCount, 0, true);
340 nCount++;
341 nAkt = nAkt / 2; // der Naechste bitte...
347 void OP_Window1( SvStream& r, UINT16 n )
349 r.SeekRel( 4 ); // Cursor Pos ueberspringen
351 r >> nDefaultFormat;
353 r.SeekRel( 1 ); // 'unused' ueberspringen
355 r >> nDefWidth;
357 r.SeekRel( n - 8 ); // und den Rest ueberspringen
359 nDefWidth = ( UINT16 ) ( TWIPS_PER_CHAR * nDefWidth );
361 // statt Defaulteinstellung in SC alle Cols zu Fuss setzen
362 for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
363 pDoc->SetColWidth( nCol, 0, nDefWidth );
367 void OP_Blank( SvStream& r, UINT16 /*n*/ )
369 UINT16 nCol, nRow;
370 BYTE nFormat;
371 r >> nFormat >> nCol >> nRow;
373 SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), 0, nFormat, nDezFloat );
376 void OP_BOF123( SvStream& r, UINT16 /*n*/ )
378 r.SeekRel( 26 );
382 void OP_EOF123( SvStream& /*r*/, UINT16 /*n*/ )
384 bEOF = TRUE;
387 void OP_Label123( SvStream& r, UINT16 n )
389 BYTE nTab, nCol;
390 UINT16 nRow;
391 r >> nRow >> nTab >> nCol;
392 n -= 4;
394 sal_Char* pText = new sal_Char[n + 1];
395 r.Read( pText, n );
396 pText[ n ] = 0;
398 PutFormString( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pText );
400 delete []pText;
403 void OP_Number123( SvStream& r, UINT16 /*n*/ )
405 BYTE nCol,nTab;
406 UINT16 nRow;
407 UINT32 nValue;
409 r >> nRow >> nTab >> nCol >> nValue;
410 double fValue = Snum32ToDouble( nValue );
412 ScValueCell *pCell = new ScValueCell( fValue );
413 pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (BOOL) TRUE );
416 void OP_Formula123( SvStream& r, UINT16 n )
418 BYTE nCol,nTab;
419 UINT16 nRow;
421 r >> nRow >> nTab >> nCol;
422 r.SeekRel( 8 ); // Result- jump over
424 const ScTokenArray* pErg;
425 INT32 nBytesLeft = n - 12;
426 ScAddress aAddress( nCol, nRow, nTab );
428 LotusToSc aConv( r, pLotusRoot->eCharsetQ, TRUE );
429 aConv.Reset( aAddress );
430 aConv.Convert( pErg, nBytesLeft );
432 ScFormulaCell* pCell = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
434 pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
436 pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (BOOL) TRUE );
439 void OP_IEEENumber123( SvStream& r, UINT16 /*n*/ )
441 BYTE nCol,nTab;
442 UINT16 nRow;
443 double dValue;
445 r >> nRow >> nTab >> nCol >> dValue;
447 ScValueCell *pCell = new ScValueCell(dValue);
448 pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (BOOL) TRUE );
451 void OP_Note123( SvStream& r, UINT16 n)
453 BYTE nTab, nCol;
454 UINT16 nRow;
455 r >> nRow >> nTab >> nCol;
456 n -= 4;
458 sal_Char* pText = new sal_Char[n + 1];
459 r.Read( pText, n );
460 pText[ n ] = 0;
462 String aNoteText(pText,pLotusRoot->eCharsetQ);
463 delete [] pText;
465 ScAddress aPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab) );
466 ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false, false );
469 void OP_HorAlign123( BYTE nAlignPattern, SfxItemSet& rPatternItemSet )
471 // pre: Pattern is stored in the last 3 bites of the 21st byte
472 // post: Appropriate Horizontal Alignement is set in rPattern according to the bit pattern.
474 // LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
475 // LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
477 nAlignPattern = ( nAlignPattern & 0x07);
479 switch (nAlignPattern)
481 case 1:
482 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
483 break;
484 case 2:
485 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY ) );
486 break;
487 case 3:
488 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY) );
489 break;
490 case 4:
491 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) );
492 break;
493 case 6:
494 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_BLOCK, ATTR_HOR_JUSTIFY ) );
495 break;
496 default:
497 rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) );
498 break;
502 void OP_VerAlign123( BYTE nAlignPattern,SfxItemSet& rPatternItemSet )
504 // pre: Pattern is stored in the last 3 bites of the 22nd byte
505 // post: Appropriate Verticle Alignement is set in rPattern according to the bit pattern.
507 // TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
509 nAlignPattern = ( nAlignPattern & 0x07);
511 switch (nAlignPattern)
513 case 0:
514 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) );
515 break;
516 case 1:
517 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_TOP, ATTR_VER_JUSTIFY) );
518 break;
519 case 2:
520 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY) );
521 break;
522 case 4:
523 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_BOTTOM, ATTR_VER_JUSTIFY) );
524 break;
525 default:
526 rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) );
527 break;
531 void OP_CreatePattern123( SvStream& r, UINT16 n)
533 UINT16 nCode,nPatternId;
535 ScPatternAttr aPattern(pDoc->GetPool());
536 SfxItemSet& rItemSet = aPattern.GetItemSet();
538 r >> nCode;
539 n = n - 2;
541 if ( nCode == 0x0fd2 )
543 r >> nPatternId;
545 BYTE Hor_Align, Ver_Align, temp;
546 BOOL bIsBold,bIsUnderLine,bIsItalics;
548 r.SeekRel(12);
550 // Read 17th Byte
551 r >> temp;
553 bIsBold = (temp & 0x01);
554 bIsItalics = (temp & 0x02);
555 bIsUnderLine = (temp & 0x04);
557 if ( bIsBold )
558 rItemSet.Put( SvxWeightItem(WEIGHT_BOLD,ATTR_FONT_WEIGHT) );
559 if ( bIsItalics )
560 rItemSet.Put( SvxPostureItem(ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
561 if ( bIsUnderLine )
562 rItemSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE, ATTR_FONT_UNDERLINE ) );
564 r.SeekRel(3);
566 // Read 21st Byte
567 r >> Hor_Align;
568 OP_HorAlign123( Hor_Align, rItemSet );
570 r >> Ver_Align;
571 OP_VerAlign123( Ver_Align, rItemSet );
573 aLotusPatternPool.insert( std::map<UINT16, ScPatternAttr>::value_type( nPatternId, aPattern ) );
574 n = n - 20;
576 r.SeekRel(n);
579 void OP_SheetName123( SvStream& rStream, USHORT nLength )
581 if (nLength <= 4)
583 rStream.SeekRel(nLength);
584 return;
587 // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
589 sal_uInt16 nDummy;
590 rStream >> nDummy; // ignore the first 2 bytes (B0 36).
591 rStream >> nDummy;
592 SCTAB nSheetNum = static_cast<SCTAB>(nDummy);
593 pDoc->MakeTable(nSheetNum);
595 ::std::vector<sal_Char> sSheetName;
596 sSheetName.reserve(nLength-4);
597 for (USHORT i = 4; i < nLength; ++i)
599 sal_Char c;
600 rStream >> c;
601 sSheetName.push_back(c);
604 if (!sSheetName.empty())
606 String aName(&sSheetName[0], eCharVon);
607 pDoc->RenameTab(nSheetNum, aName);
611 void OP_ApplyPatternArea123( SvStream& rStream )
613 UINT16 nOpcode, nLength;
614 UINT16 nCol = 0, nColCount = 0, nRow = 0, nRowCount = 0, nTab = 0, nData, nTabCount = 0, nLevel = 0;
618 rStream >> nOpcode >> nLength;
619 switch ( nOpcode )
621 case ROW_FORMAT_MARKER:
622 nLevel++;
623 break;
624 case COL_FORMAT_MARKER:
625 nLevel--;
626 if( nLevel == 1 )
628 nTab = nTab + nTabCount;
629 nCol = 0; nColCount = 0;
630 nRow = 0; nRowCount = 0;
632 break;
633 case LOTUS_FORMAT_INDEX:
634 if( nLength >= 2 )
636 rStream >> nData;
637 rStream.SeekRel( nLength - 2 );
638 if( nLevel == 1 )
639 nTabCount = nData;
640 else if( nLevel == 2 )
642 nCol = nCol + nColCount;
643 nColCount = nData;
644 if ( nCol > 0xff ) // 256 is the max col size supported by 123
645 nCol = 0;
647 else if( nLevel == 3 )
649 nRow = nRow + nRowCount;
650 nRowCount = nData;
651 if ( nRow > 0x1fff ) // 8192 is the max row size supported by 123
652 nRow = 0;
655 else
656 rStream.SeekRel( nLength );
657 break;
658 case LOTUS_FORMAT_INFO:
659 if( nLength >= 2 )
661 rStream >> nData;
662 rStream.SeekRel( nLength - 2 );
663 for( int i = 0; i < nTabCount; i++)
665 std::map<UINT16, ScPatternAttr>::iterator loc = aLotusPatternPool.find( nData );
667 // #126338# apparently, files with invalid index occur in the wild -> don't crash then
668 DBG_ASSERT( loc != aLotusPatternPool.end(), "invalid format index" );
669 if ( loc != aLotusPatternPool.end() )
670 pDoc->ApplyPatternAreaTab( nCol, nRow, nCol + nColCount - 1, nRow + nRowCount - 1, static_cast< SCTAB >( nTab + i ), loc->second );
673 else
674 rStream.SeekRel( nLength );
675 break;
676 default:
677 rStream.SeekRel( nLength );
678 break;
681 while( nLevel && !rStream.IsEof() );
683 aLotusPatternPool.clear();