xref: /trunk/main/sc/source/filter/lotus/op.cxx (revision b77af630)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scfilt.hxx"
26 
27 //------------------------------------------------------------------------
28 
29 #include <tools/solar.h>
30 #include <rtl/math.hxx>
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37 
38 #include "scitems.hxx"
39 #include "patattr.hxx"
40 #include "docpool.hxx"
41 #include <svx/algitem.hxx>
42 #include <editeng/postitem.hxx>
43 #include <editeng/udlnitem.hxx>
44 #include <editeng/wghtitem.hxx>
45 
46 #include "cell.hxx"
47 #include "rangenam.hxx"
48 #include "document.hxx"
49 #include "postit.hxx"
50 
51 #include "op.h"
52 #include "optab.h"
53 #include "tool.h"
54 #include "decl.h"
55 #include "lotform.hxx"
56 #include "lotrange.hxx"
57 
58 #include "root.hxx"
59 
60 #include "ftools.hxx"
61 
62 #include <vector>
63 #include <map>
64 
65 extern WKTYP		eTyp;			// -> filter.cxx, aktueller Dateityp
66 extern sal_Bool			bEOF;			// -> filter.cxx, zeigt Dateiende an
67 extern sal_uInt8			nDefaultFormat;	// -> tool.cxx, Default-Zellenformat
68 extern ScDocument*	pDoc;			// -> filter.cxx, Aufhaenger zum Dokumentzugriff
69 extern CharSet		eCharVon;       // -> filter.cxx, character set specified
70 
71 static sal_uInt16		nDefWidth = ( sal_uInt16 ) ( TWIPS_PER_CHAR * 10 );
72 
73 extern std::map<sal_uInt16, ScPatternAttr> aLotusPatternPool;
74 
NI(SvStream & r,sal_uInt16 n)75 void NI( SvStream& r, sal_uInt16 n )
76 {
77 	r.SeekRel( n );
78 }
79 
80 
OP_BOF(SvStream & r,sal_uInt16)81 void OP_BOF( SvStream& r, sal_uInt16 /*n*/ )
82 {
83 	r.SeekRel( 2 );        // Versionsnummer ueberlesen
84 }
85 
86 
OP_EOF(SvStream &,sal_uInt16)87 void OP_EOF( SvStream& /*r*/, sal_uInt16 /*n*/ )
88 {
89 	bEOF = sal_True;
90 }
91 
92 
OP_Integer(SvStream & r,sal_uInt16)93 void OP_Integer( SvStream& r, sal_uInt16 /*n*/ )
94 {
95 	sal_uInt8			nFormat;
96 	sal_uInt16			nCol, nRow;
97 	SCTAB			nTab = 0;
98 	sal_Int16			nValue;
99 
100 	r >> nFormat >> nCol >> nRow >> nValue;
101 
102     if (ValidColRow( static_cast<SCCOL>(nCol), nRow))
103     {
104         ScValueCell*	pZelle = new ScValueCell( ( double ) nValue );
105         pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( sal_Bool ) sal_True );
106 
107         // 0 Stellen nach'm Komma!
108         SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, 0 );
109     }
110 }
111 
112 
OP_Number(SvStream & r,sal_uInt16)113 void OP_Number( SvStream& r, sal_uInt16 /*n*/ )
114 {
115 	sal_uInt8			nFormat;
116 	sal_uInt16			nCol, nRow;
117 	SCTAB			nTab = 0;
118 	double			fValue;
119 
120 	r >> nFormat >> nCol >> nRow >> fValue;
121 
122     if (ValidColRow( static_cast<SCCOL>(nCol), nRow))
123     {
124         fValue = ::rtl::math::round( fValue, 15 );
125         ScValueCell*	pZelle = new ScValueCell( fValue );
126         pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( sal_Bool ) sal_True );
127 
128         SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezFloat );
129     }
130 }
131 
132 
OP_Label(SvStream & r,sal_uInt16 n)133 void OP_Label( SvStream& r, sal_uInt16 n )
134 {
135 	sal_uInt8			nFormat;
136 	sal_uInt16			nCol, nRow;
137 	SCTAB			nTab = 0;
138 
139 	r >> nFormat >> nCol >> nRow;
140 
141     n -= (n > 5) ? 5 : n;
142 
143     sal_Char* pText = new sal_Char[n + 1];
144     r.Read( pText, n );
145     pText[n] = 0;
146 
147     if (ValidColRow( static_cast<SCCOL>(nCol), nRow))
148     {
149         nFormat &= 0x80;    // Bit 7 belassen
150         nFormat |= 0x75;    // protected egal, special-text gesetzt
151 
152         PutFormString( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pText );
153 
154         SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezStd );
155     }
156 
157     delete [] pText;
158 }
159 
160 
OP_Formula(SvStream & r,sal_uInt16)161 void OP_Formula( SvStream& r, sal_uInt16 /*n*/ )
162 {
163 	sal_uInt8				nFormat;
164 	sal_uInt16				nCol, nRow, nFormulaSize;
165 	SCTAB			        nTab = 0;
166 
167 	r >> nFormat >> nCol >> nRow;
168 	r.SeekRel( 8 );    // Ergebnis ueberspringen
169 	r >> nFormulaSize;
170 
171 	const ScTokenArray*	pErg;
172 	sal_Int32				nBytesLeft = nFormulaSize;
173 	ScAddress			aAddress( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab );
174 
175 	LotusToSc			aConv( r, pLotusRoot->eCharsetQ, sal_False );
176 	aConv.Reset( aAddress );
177 	aConv.Convert( pErg, nBytesLeft );
178 
179     if (ValidColRow( static_cast<SCCOL>(nCol), nRow))
180     {
181         ScFormulaCell*		pZelle = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
182 
183         pZelle->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
184 
185         pDoc->PutCell( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, pZelle, ( sal_Bool ) sal_True );
186 
187         // nFormat = Standard -> Nachkommastellen wie Float
188         SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), nTab, nFormat, nDezFloat );
189     }
190 }
191 
192 
OP_ColumnWidth(SvStream & r,sal_uInt16)193 void OP_ColumnWidth( SvStream& r, sal_uInt16 /*n*/ )
194 {
195 	sal_uInt16				nCol, nBreite;
196 	sal_uInt8				nWidthSpaces;
197 	SCTAB			        nTab = 0;
198 
199 	r >> nCol >> nWidthSpaces;
200 
201     if (ValidCol( static_cast<SCCOL>(nCol)))
202     {
203         if( nWidthSpaces )
204             // Annahme: 10cpi-Zeichensatz
205             nBreite = ( sal_uInt16 ) ( TWIPS_PER_CHAR * nWidthSpaces );
206         else
207         {
208             pDoc->SetColHidden(static_cast<SCCOL>(nCol), static_cast<SCCOL>(nCol), 0, true);
209             nBreite = nDefWidth;
210         }
211 
212         pDoc->SetColWidth( static_cast<SCCOL> (nCol), nTab, nBreite );
213     }
214 }
215 
216 
OP_NamedRange(SvStream & r,sal_uInt16)217 void OP_NamedRange( SvStream& r, sal_uInt16 /*n*/ )
218 	{
219 	// POST:    waren Koordinaten ungueltig, wird nicht gespeichert
220 	sal_uInt16				nColSt, nRowSt, nColEnd, nRowEnd;
221 
222     sal_Char cPuffer[ 16+1 ];
223 	r.Read( cPuffer, 16 );
224 	cPuffer[ 16 ] = 0;
225 
226 	r >> nColSt >> nRowSt >> nColEnd >> nRowEnd;
227 
228     if (ValidColRow( static_cast<SCCOL>(nColSt), nRowSt) && ValidColRow( static_cast<SCCOL>(nColEnd), nRowEnd))
229     {
230         LotusRange*			pRange;
231 
232         if( nColSt == nColEnd && nRowSt == nRowEnd )
233             pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) );
234         else
235             pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
236                     static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) );
237 
238         sal_Char cBuf[sizeof(cPuffer)+1];
239         if( isdigit( *cPuffer ) )
240         {	// erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen
241             cBuf[0] = 'A';
242             strcpy( cBuf + 1, cPuffer );       // #100211# - checked
243         }
244         else
245             strcpy( cBuf, cPuffer );           // #100211# - checked
246 
247         String				aTmp( cBuf, pLotusRoot->eCharsetQ );
248 
249         ScfTools::ConvertToScDefinedName( aTmp );
250 
251         pLotusRoot->pRangeNames->Append( pRange, aTmp );
252     }
253 }
254 
255 
OP_SymphNamedRange(SvStream & r,sal_uInt16)256 void OP_SymphNamedRange( SvStream& r, sal_uInt16 /*n*/ )
257 {
258 	// POST:    waren Koordinaten ungueltig, wird nicht gespeichert
259 	sal_uInt16				nColSt, nRowSt, nColEnd, nRowEnd;
260 	sal_uInt8				nType;
261 
262     sal_Char cPuffer[ 16+1 ];
263 	r.Read( cPuffer, 16 );
264 	cPuffer[ 16 ] = 0;
265 
266 	r >> nColSt >> nRowSt >> nColEnd >> nRowEnd >> nType;
267 
268     if (ValidColRow( static_cast<SCCOL>(nColSt), nRowSt) && ValidColRow( static_cast<SCCOL>(nColEnd), nRowEnd))
269     {
270         LotusRange*			pRange;
271 
272         if( nType )
273             pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) );
274         else
275             pRange = new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
276                     static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) );
277 
278         sal_Char cBuf[sizeof(cPuffer)+1];
279         if( isdigit( *cPuffer ) )
280         {	// erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen
281             cBuf[0] = 'A';
282             strcpy( cBuf + 1, cPuffer );       // #100211# - checked
283         }
284         else
285             strcpy( cBuf, cPuffer );           // #100211# - checked
286 
287         String		aTmp( cBuf, pLotusRoot->eCharsetQ );
288         ScfTools::ConvertToScDefinedName( aTmp );
289 
290         pLotusRoot->pRangeNames->Append( pRange, aTmp );
291     }
292 }
293 
294 
OP_Footer(SvStream & r,sal_uInt16 n)295 void OP_Footer( SvStream& r, sal_uInt16 n )
296 {
297 	r.SeekRel( n );
298 }
299 
300 
OP_Header(SvStream & r,sal_uInt16 n)301 void OP_Header( SvStream& r, sal_uInt16 n )
302 {
303 	r.SeekRel( n );
304 }
305 
306 
OP_Margins(SvStream & r,sal_uInt16 n)307 void OP_Margins( SvStream& r, sal_uInt16 n )
308 {
309 	r.SeekRel( n );
310 }
311 
312 
OP_HiddenCols(SvStream & r,sal_uInt16)313 void OP_HiddenCols( SvStream& r, sal_uInt16 /*n*/ )
314 {
315 	sal_uInt16		nByte, nBit;
316 	SCCOL		nCount;
317 	sal_uInt8		nAkt;
318 	nCount = 0;
319 
320 	for( nByte = 0 ; nByte < 32 ; nByte++ ) // 32 Bytes mit ...
321 	{
322 		r >> nAkt;
323 		for( nBit = 0 ; nBit < 8 ; nBit++ ) // ...jeweils 8 Bits = 256 Bits
324 		{
325 			if( nAkt & 0x01 )   // unterstes Bit gesetzt?
326 				// -> Hidden Col
327                 pDoc->SetColHidden(nCount, nCount, 0, true);
328 
329 			nCount++;
330             nAkt = nAkt / 2;    // der Naechste bitte...
331 		}
332 	}
333 }
334 
335 
OP_Window1(SvStream & r,sal_uInt16 n)336 void OP_Window1( SvStream& r, sal_uInt16 n )
337 {
338 	r.SeekRel( 4 );    // Cursor Pos ueberspringen
339 
340 	r >> nDefaultFormat;
341 
342 	r.SeekRel( 1 );    // 'unused' ueberspringen
343 
344 	r >> nDefWidth;
345 
346 	r.SeekRel( n - 8 );  // und den Rest ueberspringen
347 
348 	nDefWidth = ( sal_uInt16 ) ( TWIPS_PER_CHAR * nDefWidth );
349 
350 	// statt Defaulteinstellung in SC alle Cols zu Fuss setzen
351 	for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ )
352 		pDoc->SetColWidth( nCol, 0, nDefWidth );
353 }
354 
355 
OP_Blank(SvStream & r,sal_uInt16)356 void OP_Blank( SvStream& r, sal_uInt16 /*n*/ )
357 {
358 	sal_uInt16		nCol, nRow;
359 	sal_uInt8		nFormat;
360 	r >> nFormat >> nCol >> nRow;
361 
362 	SetFormat( static_cast<SCCOL> (nCol), static_cast<SCROW> (nRow), 0, nFormat, nDezFloat );
363 }
364 
OP_BOF123(SvStream & r,sal_uInt16)365 void OP_BOF123( SvStream& r, sal_uInt16 /*n*/ )
366 {
367 	r.SeekRel( 26 );
368 }
369 
370 
OP_EOF123(SvStream &,sal_uInt16)371 void OP_EOF123( SvStream& /*r*/, sal_uInt16 /*n*/ )
372 {
373 	bEOF = sal_True;
374 }
375 
OP_Label123(SvStream & r,sal_uInt16 n)376 void OP_Label123( SvStream& r, sal_uInt16 n )
377 {
378 	sal_uInt8      nTab, nCol;
379 	sal_uInt16    nRow;
380 	r >> nRow >> nTab >> nCol;
381     n -= (n > 4) ? 4 : n;
382 
383 	sal_Char* pText = new sal_Char[n + 1];
384 	r.Read( pText, n );
385 	pText[ n ] = 0;
386 
387 	PutFormString( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pText );
388 
389 	delete []pText;
390 }
391 
OP_Number123(SvStream & r,sal_uInt16)392 void OP_Number123( SvStream& r, sal_uInt16 /*n*/ )
393 {
394 	sal_uInt8    nCol,nTab;
395 	sal_uInt16  nRow;
396 	sal_uInt32   nValue;
397 
398 	r >> nRow >> nTab >> nCol >> nValue;
399 
400     if (ValidColRow( static_cast<SCCOL>(nCol), nRow) && nTab < pDoc->GetMaxTableNumber())
401     {
402         double fValue = Snum32ToDouble( nValue );
403 
404         ScValueCell *pCell = new ScValueCell( fValue );
405         pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (sal_Bool) sal_True );
406     }
407 }
408 
OP_Formula123(SvStream & r,sal_uInt16 n)409 void OP_Formula123( SvStream& r, sal_uInt16 n )
410 {
411     sal_uInt8 nCol,nTab;
412     sal_uInt16 nRow;
413 
414     r >> nRow >> nTab >> nCol;
415     r.SeekRel( 8 );    // Result- jump over
416 
417     const ScTokenArray*	pErg;
418     sal_Int32				nBytesLeft = (n > 12) ? n - 12 : 0;
419     ScAddress			aAddress( nCol, nRow, nTab );
420 
421     LotusToSc			aConv( r, pLotusRoot->eCharsetQ, sal_True );
422     aConv.Reset( aAddress );
423     aConv.Convert( pErg, nBytesLeft );
424 
425     if (ValidColRow( static_cast<SCCOL>(nCol), nRow) && nTab < pDoc->GetMaxTableNumber())
426     {
427         ScFormulaCell*		pCell = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
428 
429         pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
430 
431         pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (sal_Bool) sal_True );
432     }
433 }
434 
OP_IEEENumber123(SvStream & r,sal_uInt16)435 void OP_IEEENumber123( SvStream& r, sal_uInt16 /*n*/ )
436 {
437     sal_uInt8 nCol,nTab;
438     sal_uInt16 nRow;
439     double dValue;
440 
441     r >> nRow >> nTab >> nCol >> dValue;
442 
443     if (ValidColRow( static_cast<SCCOL>(nCol), nRow) && nTab < pDoc->GetMaxTableNumber())
444     {
445         ScValueCell *pCell = new ScValueCell(dValue);
446         pDoc->PutCell( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab), pCell, (sal_Bool) sal_True );
447     }
448 }
449 
OP_Note123(SvStream & r,sal_uInt16 n)450 void OP_Note123( SvStream& r, sal_uInt16 n)
451 {
452     sal_uInt8      nTab, nCol;
453     sal_uInt16    nRow;
454     r >> nRow >> nTab >> nCol;
455     n -= (n > 4) ? 4 : n;
456 
457     sal_Char* pText = new sal_Char[n + 1];
458     r.Read( pText, n );
459     pText[ n ] = 0;
460 
461     String aNoteText(pText,pLotusRoot->eCharsetQ);
462     delete [] pText;
463 
464     ScAddress aPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab) );
465     ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false, false );
466 }
467 
OP_HorAlign123(sal_uInt8 nAlignPattern,SfxItemSet & rPatternItemSet)468 void OP_HorAlign123( sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet )
469 {
470 //      pre:  Pattern is stored in the last 3 bites of the 21st byte
471 //      post: Appropriate Horizontal Alignement is set in rPattern according to the bit pattern.
472 //
473 //      LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
474 //      LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
475 
476 	nAlignPattern = ( nAlignPattern & 0x07);
477 
478 	switch (nAlignPattern)
479  	{
480 		case 1:
481             rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
482 			break;
483 	  	case 2:
484             rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY ) );
485             break;
486 		case 3:
487             rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY) );
488             break;
489   		case 4:
490             rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) );
491             break;
492 		case 6:
493             rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_BLOCK, ATTR_HOR_JUSTIFY ) );
494             break;
495   		default:
496             rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) );
497             break;
498   	}
499 }
500 
OP_VerAlign123(sal_uInt8 nAlignPattern,SfxItemSet & rPatternItemSet)501 void OP_VerAlign123( sal_uInt8 nAlignPattern,SfxItemSet& rPatternItemSet  )
502 {
503 //      pre:  Pattern is stored in the last 3 bites of the 22nd byte
504 //      post: Appropriate Verticle Alignement is set in rPattern according to the bit pattern.
505 //
506 //      TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
507 
508 	nAlignPattern = ( nAlignPattern & 0x07);
509 
510     switch (nAlignPattern)
511     {
512         case 0:
513             rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) );
514             break;
515         case 1:
516             rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_TOP, ATTR_VER_JUSTIFY) );
517             break;
518         case 2:
519             rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY) );
520             break;
521         case 4:
522             rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_BOTTOM, ATTR_VER_JUSTIFY) );
523             break;
524         default:
525             rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) );
526             break;
527     }
528 }
529 
OP_CreatePattern123(SvStream & r,sal_uInt16 n)530 void OP_CreatePattern123( SvStream& r, sal_uInt16 n)
531 {
532     sal_uInt16 nCode,nPatternId;
533 
534     ScPatternAttr aPattern(pDoc->GetPool());
535     SfxItemSet& rItemSet = aPattern.GetItemSet();
536 
537     r >> nCode;
538     n -= (n > 2) ? 2 : n;
539 
540     if ( nCode == 0x0fd2 )
541     {
542         r >> nPatternId;
543 
544         sal_uInt8 Hor_Align, Ver_Align, temp;
545         sal_Bool bIsBold,bIsUnderLine,bIsItalics;
546 
547         r.SeekRel(12);
548 
549         // Read 17th Byte
550         r >> temp;
551 
552         bIsBold = (temp & 0x01);
553         bIsItalics = (temp & 0x02);
554         bIsUnderLine = (temp & 0x04);
555 
556         if ( bIsBold )
557             rItemSet.Put( SvxWeightItem(WEIGHT_BOLD,ATTR_FONT_WEIGHT) );
558         if ( bIsItalics )
559             rItemSet.Put( SvxPostureItem(ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
560         if ( bIsUnderLine )
561             rItemSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE, ATTR_FONT_UNDERLINE ) );
562 
563         r.SeekRel(3);
564 
565         // Read 21st Byte
566         r >> Hor_Align;
567         OP_HorAlign123( Hor_Align, rItemSet );
568 
569         r >> Ver_Align;
570         OP_VerAlign123( Ver_Align, rItemSet );
571 
572         aLotusPatternPool.insert( std::map<sal_uInt16, ScPatternAttr>::value_type( nPatternId, aPattern ) );
573         n -= (n > 20) ? 20 : n;
574     }
575     r.SeekRel(n);
576 }
577 
OP_SheetName123(SvStream & rStream,sal_uInt16 nLength)578 void OP_SheetName123( SvStream& rStream, sal_uInt16 nLength )
579 {
580     if (nLength <= 4)
581     {
582         rStream.SeekRel(nLength);
583         return;
584     }
585 
586     // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
587 
588     sal_uInt16 nDummy;
589     rStream >> nDummy; // ignore the first 2 bytes (B0 36).
590     rStream >> nDummy;
591     SCTAB nSheetNum = static_cast<SCTAB>(nDummy);
592     pDoc->MakeTable(nSheetNum);
593 
594     ::std::vector<sal_Char> sSheetName;
595     sSheetName.reserve(nLength-4);
596     for (sal_uInt16 i = 4; i < nLength; ++i)
597     {
598         sal_Char c;
599         rStream >> c;
600         sSheetName.push_back(c);
601     }
602 
603     if (!sSheetName.empty())
604     {
605         String aName(&sSheetName[0], eCharVon);
606         pDoc->RenameTab(nSheetNum, aName);
607     }
608 }
609 
OP_ApplyPatternArea123(SvStream & rStream)610 void OP_ApplyPatternArea123( SvStream& rStream )
611 {
612     sal_uInt16 nOpcode, nLength;
613     sal_uInt16 nCol = 0, nColCount = 0, nRow = 0, nRowCount = 0, nTab = 0, nData, nTabCount = 0, nLevel = 0;
614 
615     do
616     {
617         rStream >> nOpcode >> nLength;
618         switch ( nOpcode )
619         {
620             case ROW_FORMAT_MARKER:
621                 nLevel++;
622                 break;
623             case COL_FORMAT_MARKER:
624                 nLevel--;
625                 if( nLevel == 1 )
626                 {
627                     nTab = nTab + nTabCount;
628                     nCol = 0; nColCount = 0;
629                     nRow = 0; nRowCount = 0;
630                 }
631                 break;
632             case LOTUS_FORMAT_INDEX:
633 				if( nLength >= 2 )
634                 {
635                     rStream >> nData;
636                     rStream.SeekRel( nLength - 2 );
637                     if( nLevel == 1 )
638                         nTabCount = nData;
639                     else if( nLevel == 2 )
640                     {
641                         nCol = nCol + nColCount;
642                         nColCount = nData;
643                         if ( nCol > 0xff ) // 256 is the max col size supported by 123
644                             nCol = 0;
645                     }
646                     else if( nLevel == 3 )
647                     {
648                         nRow = nRow + nRowCount;
649                         nRowCount = nData;
650                         if ( nRow > 0x1fff ) // 8192 is the max row size supported by 123
651                             nRow = 0;
652                     }
653                 }
654                 else
655                     rStream.SeekRel( nLength );
656                 break;
657             case LOTUS_FORMAT_INFO:
658 				if( nLength >= 2 )
659                 {
660                     rStream >> nData;
661                     rStream.SeekRel( nLength - 2 );
662                     std::map<sal_uInt16, ScPatternAttr>::iterator loc = aLotusPatternPool.find( nData );
663                     // #126338# apparently, files with invalid index occur in the wild -> don't crash then
664                     if ( loc != aLotusPatternPool.end() )
665                         for( int i = 0; i < nTabCount; i++)
666                         {
667                             pDoc->ApplyPatternAreaTab( nCol, nRow, nCol +  nColCount - 1, nRow + nRowCount - 1, static_cast< SCTAB >( nTab + i ), loc->second );
668                         }
669                 }
670                 else
671                     rStream.SeekRel( nLength );
672                 break;
673             default:
674                 rStream.SeekRel( nLength );
675                 break;
676         }
677     }
678     while( nLevel && !rStream.IsEof() );
679 
680     aLotusPatternPool.clear();
681 }
682