Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / lotus / op.cxx
blob02cd9b0e014d932fdcad248db912b99a18b7117d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <rtl/math.hxx>
21 #include <rtl/character.hxx>
23 #include <string.h>
25 #include <scitems.hxx>
26 #include <patattr.hxx>
27 #include <docpool.hxx>
28 #include <editeng/postitem.hxx>
29 #include <editeng/udlnitem.hxx>
30 #include <editeng/wghtitem.hxx>
31 #include <editeng/justifyitem.hxx>
32 #include <unotools/configmgr.hxx>
34 #include <formulacell.hxx>
35 #include <document.hxx>
36 #include <postit.hxx>
38 #include <op.h>
39 #include <optab.h>
40 #include <tool.h>
41 #include "lotfilter.hxx"
42 #include <lotform.hxx>
43 #include <lotrange.hxx>
44 #include <root.hxx>
45 #include <ftools.hxx>
47 #include <vector>
48 #include <map>
49 #include <memory>
51 static sal_uInt16 nDefWidth = sal_uInt16( TWIPS_PER_CHAR * 10 );
53 void NI(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
55 r.SeekRel( n );
58 void OP_BOF(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 /*n*/)
60 r.SeekRel( 2 ); // skip version number
63 void OP_EOF(LotusContext& rContext, SvStream& /*r*/, sal_uInt16 /*n*/)
65 rContext.bEOF = true;
68 void OP_Integer(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
70 sal_uInt8 nFormat(0);
71 sal_uInt16 nTmpCol(0), nTmpRow(0);
72 sal_Int16 nValue(0);
73 r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow).ReadInt16(nValue);
74 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
75 SCROW nRow(static_cast<SCROW>(nTmpRow));
77 if (ValidColRow(nCol, nRow))
79 rContext.pDoc->EnsureTable(0);
80 rContext.pDoc->SetValue(ScAddress(nCol, nRow, 0), static_cast<double>(nValue));
82 // 0 digits in fractional part!
83 SetFormat(rContext, nCol, nRow, 0, nFormat, 0);
87 void OP_Number(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
89 sal_uInt8 nFormat(0);
90 sal_uInt16 nTmpCol(0), nTmpRow(0);
91 double fValue(0.0);
92 r.ReadUChar( nFormat ).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow).ReadDouble(fValue);
93 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
94 SCROW nRow(static_cast<SCROW>(nTmpRow));
96 if (ValidColRow(nCol, nRow))
98 fValue = ::rtl::math::round( fValue, 15 );
99 rContext.pDoc->EnsureTable(0);
100 rContext.pDoc->SetValue(ScAddress(nCol, nRow, 0), fValue);
102 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
106 void OP_Label(LotusContext& rContext, SvStream& r, sal_uInt16 n)
108 sal_uInt8 nFormat(0);
109 sal_uInt16 nTmpCol(0), nTmpRow(0);
110 r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
111 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
112 SCROW nRow(static_cast<SCROW>(nTmpRow));
114 n -= std::min<sal_uInt16>(n, 5);
116 std::unique_ptr<sal_Char[]> pText(new sal_Char[n + 1]);
117 r.ReadBytes(pText.get(), n);
118 pText[n] = 0;
120 if (ValidColRow(nCol, nRow))
122 nFormat &= 0x80; // don't change Bit 7
123 nFormat |= 0x75; // protected does not matter, special-text is set
125 PutFormString(rContext, nCol, nRow, 0, pText.get());
127 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalStd);
131 void OP_Formula(LotusContext &rContext, SvStream& r, sal_uInt16 /*n*/)
133 sal_uInt8 nFormat(0);
134 sal_uInt16 nTmpCol(0), nTmpRow(0);
135 r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
136 r.SeekRel(8); // skip result
137 sal_uInt16 nFormulaSize(0);
138 r.ReadUInt16(nFormulaSize);
140 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
141 SCROW nRow(static_cast<SCROW>(nTmpRow));
143 std::unique_ptr<ScTokenArray> pResult;
144 sal_Int32 nBytesLeft = nFormulaSize;
145 ScAddress aAddress(nCol, nRow, 0);
147 svl::SharedStringPool& rSPool = rContext.pLotusRoot->pDoc->GetSharedStringPool();
148 LotusToSc aConv(rContext, r, rSPool, rContext.pLotusRoot->eCharsetQ, false);
149 aConv.Reset( aAddress );
150 aConv.Convert( pResult, nBytesLeft );
151 if (!aConv.good())
152 return;
154 if (ValidColRow(nCol, nRow))
156 ScFormulaCell* pCell = new ScFormulaCell(rContext.pLotusRoot->pDoc, aAddress, std::move(pResult));
157 pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
158 rContext.pDoc->EnsureTable(0);
159 rContext.pDoc->SetFormulaCell(ScAddress(nCol, nRow, 0), pCell);
161 // nFormat = Default -> number of digits in fractional part like Float
162 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
166 void OP_ColumnWidth(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
168 sal_uInt16 nTmpCol(0);
169 sal_uInt8 nWidthSpaces(0);
170 r.ReadUInt16(nTmpCol).ReadUChar(nWidthSpaces);
171 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
173 if (ValidCol(nCol))
175 nCol = SanitizeCol(nCol);
177 sal_uInt16 nBreite;
178 if( nWidthSpaces )
179 // assuming 10cpi character set
180 nBreite = static_cast<sal_uInt16>( TWIPS_PER_CHAR * nWidthSpaces );
181 else
183 rContext.pDoc->SetColHidden(nCol, nCol, 0, true);
184 nBreite = nDefWidth;
187 rContext.pDoc->SetColWidth(nCol, 0, nBreite);
191 void OP_NamedRange(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
193 // POST: don't save for invalid coordinates
194 sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd;
196 sal_Char cBuffer[ 16+1 ];
197 r.ReadBytes(cBuffer, 16);
198 cBuffer[ 16 ] = 0;
200 r.ReadUInt16( nColSt ).ReadUInt16( nRowSt ).ReadUInt16( nColEnd ).ReadUInt16( nRowEnd );
202 if (ValidColRow( static_cast<SCCOL>(nColSt), nRowSt) && ValidColRow( static_cast<SCCOL>(nColEnd), nRowEnd))
204 std::unique_ptr<LotusRange> pRange;
206 if( nColSt == nColEnd && nRowSt == nRowEnd )
207 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) ));
208 else
209 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
210 static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) ));
212 sal_Char cBuf[sizeof(cBuffer)+1];
213 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer) ) )
214 { // first char in name is a number -> prepend 'A'
215 cBuf[0] = 'A';
216 strcpy( cBuf + 1, cBuffer ); // #100211# - checked
218 else
219 strcpy( cBuf, cBuffer ); // #100211# - checked
221 OUString aTmp( cBuf, strlen(cBuf), rContext.pLotusRoot->eCharsetQ );
223 aTmp = ScfTools::ConvertToScDefinedName( aTmp );
225 rContext.pLotusRoot->maRangeNames.Append( std::move(pRange) );
229 void OP_SymphNamedRange(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
231 // POST:don't save for invalid coordinates
232 sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd;
233 sal_uInt8 nType;
235 sal_Char cBuffer[ 16+1 ];
236 r.ReadBytes(cBuffer, 16);
237 cBuffer[ 16 ] = 0;
239 r.ReadUInt16( nColSt ).ReadUInt16( nRowSt ).ReadUInt16( nColEnd ).ReadUInt16( nRowEnd ).ReadUChar( nType );
241 if (ValidColRow( static_cast<SCCOL>(nColSt), nRowSt) && ValidColRow( static_cast<SCCOL>(nColEnd), nRowEnd))
243 std::unique_ptr<LotusRange> pRange;
245 if( nType )
246 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) ));
247 else
248 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
249 static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) ));
251 sal_Char cBuf[sizeof(cBuffer)+1];
252 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer) ) )
253 { // first char in name is a number -> prepend 'A'
254 cBuf[0] = 'A';
255 strcpy( cBuf + 1, cBuffer ); // #100211# - checked
257 else
258 strcpy( cBuf, cBuffer ); // #100211# - checked
260 OUString aTmp( cBuf, strlen(cBuf), rContext.pLotusRoot->eCharsetQ );
261 aTmp = ScfTools::ConvertToScDefinedName( aTmp );
263 rContext.pLotusRoot->maRangeNames.Append( std::move(pRange) );
267 void OP_Footer(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
269 r.SeekRel( n );
272 void OP_Header(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
274 r.SeekRel( n );
277 void OP_Margins(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
279 r.SeekRel( n );
282 void OP_HiddenCols(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
284 sal_uInt16 nByte, nBit;
285 SCCOL nCount;
286 sal_uInt8 nCurrent;
287 nCount = 0;
289 for( nByte = 0 ; nByte < 32 ; nByte++ ) // 32 Bytes with ...
291 r.ReadUChar( nCurrent );
292 for( nBit = 0 ; nBit < 8 ; nBit++ ) // ...each 8 Bits = 256 Bits
294 if( nCurrent & 0x01 ) // is lowest Bit set?
296 // -> Hidden Col
297 rContext.pDoc->SetColHidden(nCount, nCount, 0, true);
300 nCount++;
301 nCurrent = nCurrent / 2; // the next please...
306 void OP_Window1(LotusContext& rContext, SvStream& r, sal_uInt16 n)
308 r.SeekRel( 4 ); // skip Cursor Pos
310 sal_uInt8 nDefaultFormat; // -> op.cpp, standard cell format
311 r.ReadUChar(nDefaultFormat);
313 r.SeekRel( 1 ); // skip 'unused'
315 r.ReadUInt16( nDefWidth );
316 if (!r.good())
317 return;
319 r.SeekRel( n - 8 ); // skip the rest
321 nDefWidth = static_cast<sal_uInt16>( TWIPS_PER_CHAR * nDefWidth );
323 const bool bFuzzing = utl::ConfigManager::IsFuzzing();
325 // instead of default, set all Cols in SC by hand
326 for (SCCOL nCol = 0 ; nCol <= rContext.pDoc->MaxCol() ; nCol++)
328 rContext.pDoc->SetColWidth( nCol, 0, nDefWidth );
329 if (bFuzzing)
330 break;
334 void OP_Blank(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
336 sal_uInt8 nFormat(0);
337 sal_uInt16 nTmpCol(0), nTmpRow(0);
338 r.ReadUChar( nFormat ).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
339 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
340 SCROW nRow(static_cast<SCROW>(nTmpRow));
342 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
345 void OP_BOF123(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 /*n*/)
347 r.SeekRel( 26 );
350 void OP_EOF123(LotusContext& rContext, SvStream& /*r*/, sal_uInt16 /*n*/)
352 rContext.bEOF = true;
355 void OP_Label123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
357 sal_uInt8 nTmpTab(0), nTmpCol(0);
358 sal_uInt16 nTmpRow(0);
359 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
360 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
361 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
362 SCROW nRow(static_cast<SCROW>(nTmpRow));
364 n -= std::min<sal_uInt16>(n, 4);
366 std::unique_ptr<sal_Char[]> pText(new sal_Char[n + 1]);
367 r.ReadBytes(pText.get(), n);
368 pText[ n ] = 0;
370 PutFormString(rContext, nCol, nRow, nTab, pText.get());
373 void OP_Number123(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
375 sal_uInt16 nTmpRow(0);
376 sal_uInt8 nTmpCol(0), nTmpTab(0);
377 sal_uInt32 nValue(0);
378 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol).ReadUInt32(nValue);
379 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
380 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
381 SCROW nRow(static_cast<SCROW>(nTmpRow));
383 if (ValidColRow(nCol, nRow) && nTab <= rContext.pDoc->GetMaxTableNumber())
385 double fValue = Snum32ToDouble( nValue );
386 rContext.pDoc->EnsureTable(nTab);
387 rContext.pDoc->SetValue(ScAddress(nCol,nRow,nTab), fValue);
391 void OP_Formula123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
393 sal_uInt16 nTmpRow(0);
394 sal_uInt8 nTmpCol(0), nTmpTab(0);
395 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
396 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
397 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
398 SCROW nRow(static_cast<SCROW>(nTmpRow));
399 r.SeekRel( 8 ); // skip Result
401 std::unique_ptr<ScTokenArray> pResult;
402 sal_Int32 nBytesLeft = (n > 12) ? n - 12 : 0;
403 ScAddress aAddress( nCol, nRow, nTab );
405 svl::SharedStringPool& rSPool = rContext.pLotusRoot->pDoc->GetSharedStringPool();
406 LotusToSc aConv(rContext, r, rSPool, rContext.pLotusRoot->eCharsetQ, true);
407 aConv.Reset( aAddress );
408 aConv.Convert( pResult, nBytesLeft );
409 if (!aConv.good())
410 return;
412 if (ValidColRow(nCol, nRow) && nTab <= rContext.pDoc->GetMaxTableNumber())
414 ScFormulaCell* pCell = new ScFormulaCell(rContext.pLotusRoot->pDoc, aAddress, std::move(pResult));
415 pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
416 rContext.pDoc->EnsureTable(nTab);
417 rContext.pDoc->SetFormulaCell(ScAddress(nCol,nRow,nTab), pCell);
421 void OP_IEEENumber123(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
423 sal_uInt16 nTmpRow(0);
424 sal_uInt8 nTmpCol(0), nTmpTab(0);
425 double dValue(0.0);
426 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol).ReadDouble(dValue);
427 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
428 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
429 SCROW nRow(static_cast<SCROW>(nTmpRow));
431 if (ValidColRow(nCol, nRow) && nTab <= rContext.pDoc->GetMaxTableNumber())
433 rContext.pDoc->EnsureTable(nTab);
434 rContext.pDoc->SetValue(ScAddress(nCol,nRow,nTab), dValue);
438 void OP_Note123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
440 sal_uInt16 nTmpRow(0);
441 sal_uInt8 nTmpTab(0), nTmpCol(0);
442 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
443 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
444 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
445 SCROW nRow(static_cast<SCROW>(nTmpRow));
447 n -= std::min<sal_uInt16>(n, 4);
449 std::unique_ptr<sal_Char[]> pText(new sal_Char[n + 1]);
450 r.ReadBytes(pText.get(), n);
451 pText[ n ] = 0;
453 OUString aNoteText(pText.get(), strlen(pText.get()), rContext.pLotusRoot->eCharsetQ);
454 pText.reset();
456 ScAddress aPos(nCol, nRow, nTab);
457 ScNoteUtil::CreateNoteFromString( *rContext.pDoc, aPos, aNoteText, false, false );
460 void OP_HorAlign123(LotusContext& /*rContext*/, sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet)
462 // pre: Pattern is stored in the last 3 bites of the 21st byte
463 // post: Appropriate Horizontal Alignment is set in rPattern according to the bit pattern.
465 // LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
466 // LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
468 nAlignPattern = ( nAlignPattern & 0x07);
470 switch (nAlignPattern)
472 case 1:
473 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Left, ATTR_HOR_JUSTIFY ) );
474 break;
475 case 2:
476 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Right, ATTR_HOR_JUSTIFY ) );
477 break;
478 case 3:
479 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY) );
480 break;
481 case 4:
482 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard, ATTR_HOR_JUSTIFY ) );
483 break;
484 case 6:
485 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Block, ATTR_HOR_JUSTIFY ) );
486 break;
487 default:
488 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard, ATTR_HOR_JUSTIFY ) );
489 break;
493 void OP_VerAlign123(LotusContext& /*rContext*/, sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet)
495 // pre: Pattern is stored in the last 3 bites of the 22nd byte
496 // post: Appropriate Vertical Alignment is set in rPattern according to the bit pattern.
498 // TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
500 nAlignPattern = ( nAlignPattern & 0x07);
502 switch (nAlignPattern)
504 case 0:
505 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard, ATTR_VER_JUSTIFY) );
506 break;
507 case 1:
508 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Top, ATTR_VER_JUSTIFY) );
509 break;
510 case 2:
511 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Center, ATTR_VER_JUSTIFY) );
512 break;
513 case 4:
514 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Bottom, ATTR_VER_JUSTIFY) );
515 break;
516 default:
517 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard, ATTR_VER_JUSTIFY) );
518 break;
522 void OP_CreatePattern123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
524 sal_uInt16 nCode,nPatternId;
526 ScPatternAttr aPattern(rContext.pDoc->GetPool());
527 SfxItemSet& rItemSet = aPattern.GetItemSet();
529 r.ReadUInt16( nCode );
530 n -= std::min<sal_uInt16>(n, 2);
532 if ( nCode == 0x0fd2 )
534 r.ReadUInt16( nPatternId );
536 sal_uInt8 Hor_Align, Ver_Align, temp;
537 bool bIsBold,bIsUnderLine,bIsItalics;
539 r.SeekRel(12);
541 // Read 17th Byte
542 r.ReadUChar( temp );
544 bIsBold = (temp & 0x01);
545 bIsItalics = (temp & 0x02);
546 bIsUnderLine = (temp & 0x04);
548 if ( bIsBold )
549 rItemSet.Put( SvxWeightItem(WEIGHT_BOLD,ATTR_FONT_WEIGHT) );
550 if ( bIsItalics )
551 rItemSet.Put( SvxPostureItem(ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
552 if ( bIsUnderLine )
553 rItemSet.Put( SvxUnderlineItem( LINESTYLE_SINGLE, ATTR_FONT_UNDERLINE ) );
555 r.SeekRel(3);
557 // Read 21st Byte
558 r.ReadUChar( Hor_Align );
559 OP_HorAlign123(rContext, Hor_Align, rItemSet );
561 r.ReadUChar( Ver_Align );
562 OP_VerAlign123(rContext, Ver_Align, rItemSet );
564 rContext.aLotusPatternPool.emplace( nPatternId, aPattern );
565 n -= std::min<sal_uInt16>(n, 20);
567 r.SeekRel(n);
570 void OP_SheetName123(LotusContext& rContext, SvStream& rStream, sal_uInt16 nLength)
572 if (nLength <= 4)
574 rStream.SeekRel(nLength);
575 return;
578 // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
579 rStream.SeekRel(2); // ignore the first 2 bytes (B0 36).
580 sal_uInt16 nSheetNum(0);
581 rStream.ReadUInt16(nSheetNum);
583 ::std::vector<sal_Char> sSheetName;
584 sSheetName.reserve(nLength-4);
585 for (sal_uInt16 i = 4; i < nLength; ++i)
587 sal_Char c;
588 rStream.ReadChar( c );
589 sSheetName.push_back(c);
592 if (!ValidTab(nSheetNum))
593 return;
594 // coverity[tainted_data : FALSE] - ValidTab has sanitized nSheetNum
595 rContext.pDoc->MakeTable(nSheetNum);
596 if (!sSheetName.empty())
598 OUString aName(sSheetName.data(), strlen(sSheetName.data()), rContext.eCharVon);
599 rContext.pDoc->RenameTab(nSheetNum, aName);
603 void OP_ApplyPatternArea123(LotusContext& rContext, SvStream& rStream)
605 sal_uInt16 nOpcode, nLength;
606 sal_uInt16 nCol = 0, nColCount = 0, nRow = 0, nRowCount = 0, nTab = 0, nData, nTabCount = 0, nLevel = 0;
610 rStream.ReadUInt16( nOpcode ).ReadUInt16( nLength );
611 switch ( nOpcode )
613 case ROW_FORMAT_MARKER:
614 nLevel++;
615 break;
616 case COL_FORMAT_MARKER:
617 nLevel--;
618 if( nLevel == 1 )
620 nTab = nTab + nTabCount;
621 nCol = 0; nColCount = 0;
622 nRow = 0; nRowCount = 0;
624 break;
625 case LOTUS_FORMAT_INDEX:
626 if( nLength >= 2 )
628 rStream.ReadUInt16( nData );
629 rStream.SeekRel( nLength - 2 );
630 if( nLevel == 1 )
631 nTabCount = SanitizeTab(nData);
632 else if( nLevel == 2 )
634 nCol = nCol + nColCount;
635 nColCount = nData;
636 if ( nCol > 0xff ) // 256 is the max col size supported by 123
637 nCol = 0;
639 else if( nLevel == 3 )
641 nRow = nRow + nRowCount;
642 nRowCount = nData;
643 if ( nRow > 0x1fff ) // 8192 is the max row size supported by 123
644 nRow = 0;
647 else
648 rStream.SeekRel( nLength );
649 break;
650 case LOTUS_FORMAT_INFO:
651 if( nLength >= 2 )
653 rStream.ReadUInt16( nData );
654 rStream.SeekRel( nLength - 2 );
655 std::map<sal_uInt16, ScPatternAttr>::iterator loc = rContext.aLotusPatternPool.find( nData );
656 // #126338# apparently, files with invalid index occur in the wild -> don't crash then
657 if ( loc != rContext.aLotusPatternPool.end() )
658 for( int i = 0; i < nTabCount; i++)
660 rContext.pDoc->ApplyPatternAreaTab( nCol, nRow, nCol + nColCount - 1, nRow + nRowCount - 1, static_cast< SCTAB >( nTab + i ), loc->second );
663 else
664 rStream.SeekRel( nLength );
665 break;
666 default:
667 rStream.SeekRel( nLength );
668 break;
671 while( nLevel && rStream.good() );
673 rContext.aLotusPatternPool.clear();
676 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */