LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sc / source / filter / lotus / op.cxx
blobf95bff7e18cedc9dd8036ce8f928f936d58d8c27
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 <ftools.hxx>
46 #include <vector>
47 #include <map>
48 #include <memory>
50 static sal_uInt16 nDefWidth = sal_uInt16( TWIPS_PER_CHAR * 10 );
52 void NI(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
54 r.SeekRel( n );
57 void OP_BOF(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 /*n*/)
59 r.SeekRel( 2 ); // skip version number
62 void OP_EOF(LotusContext& rContext, SvStream& /*r*/, sal_uInt16 /*n*/)
64 rContext.bEOF = true;
67 void OP_Integer(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
69 sal_uInt8 nFormat(0);
70 sal_uInt16 nTmpCol(0), nTmpRow(0);
71 sal_Int16 nValue(0);
72 r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow).ReadInt16(nValue);
73 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
74 SCROW nRow(static_cast<SCROW>(nTmpRow));
76 ScAddress aAddr(nCol, nRow, 0);
77 if (rContext.rDoc.ValidAddress(aAddr))
79 rContext.rDoc.EnsureTable(0);
80 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
81 rContext.rDoc.SetValue(aAddr, static_cast<double>(nValue));
83 // 0 digits in fractional part!
84 SetFormat(rContext, nCol, nRow, 0, nFormat, 0);
88 void OP_Number(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
90 sal_uInt8 nFormat(0);
91 sal_uInt16 nTmpCol(0), nTmpRow(0);
92 double fValue(0.0);
93 r.ReadUChar( nFormat ).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow).ReadDouble(fValue);
94 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
95 SCROW nRow(static_cast<SCROW>(nTmpRow));
97 ScAddress aAddr(nCol, nRow, 0);
98 if (rContext.rDoc.ValidAddress(aAddr))
100 fValue = ::rtl::math::round( fValue, 15 );
101 rContext.rDoc.EnsureTable(0);
102 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
103 rContext.rDoc.SetValue(aAddr, fValue);
105 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
109 void OP_Label(LotusContext& rContext, SvStream& r, sal_uInt16 n)
111 sal_uInt8 nFormat(0);
112 sal_uInt16 nTmpCol(0), nTmpRow(0);
113 r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
114 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
115 SCROW nRow(static_cast<SCROW>(nTmpRow));
117 n -= std::min<sal_uInt16>(n, 5);
119 std::vector<char> aText(n + 1);
120 n = r.ReadBytes(aText.data(), n);
121 aText[n] = 0;
123 if (rContext.rDoc.ValidColRow(nCol, nRow))
125 nFormat &= 0x80; // don't change Bit 7
126 nFormat |= 0x75; // protected does not matter, special-text is set
128 PutFormString(rContext, nCol, nRow, 0, aText.data());
130 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalStd);
134 void OP_Formula(LotusContext &rContext, SvStream& r, sal_uInt16 /*n*/)
136 sal_uInt8 nFormat(0);
137 sal_uInt16 nTmpCol(0), nTmpRow(0);
138 r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
139 r.SeekRel(8); // skip result
140 sal_uInt16 nFormulaSize(0);
141 r.ReadUInt16(nFormulaSize);
143 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
144 SCROW nRow(static_cast<SCROW>(nTmpRow));
146 std::unique_ptr<ScTokenArray> pResult;
147 sal_Int32 nBytesLeft = nFormulaSize;
148 ScAddress aAddress(nCol, nRow, 0);
150 svl::SharedStringPool& rSPool = rContext.rDoc.GetSharedStringPool();
151 LotusToSc aConv(rContext, r, rSPool, rContext.eCharset, false);
152 aConv.Reset( aAddress );
153 aConv.Convert( pResult, nBytesLeft );
154 if (!aConv.good())
155 return;
157 if (rContext.rDoc.ValidColRow(nCol, nRow))
159 ScFormulaCell* pCell = new ScFormulaCell(rContext.rDoc, aAddress, std::move(pResult));
160 pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
161 rContext.rDoc.EnsureTable(0);
162 rContext.rDoc.SetFormulaCell(ScAddress(nCol, nRow, 0), pCell);
164 // nFormat = Default -> number of digits in fractional part like Float
165 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
169 void OP_ColumnWidth(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
171 sal_uInt16 nTmpCol(0);
172 sal_uInt8 nWidthSpaces(0);
173 r.ReadUInt16(nTmpCol).ReadUChar(nWidthSpaces);
174 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
176 if (!rContext.rDoc.ValidCol(nCol))
177 return;
179 nCol = rContext.rDoc.SanitizeCol(nCol);
181 sal_uInt16 nBreite;
182 if( nWidthSpaces )
183 // assuming 10cpi character set
184 nBreite = static_cast<sal_uInt16>( TWIPS_PER_CHAR * nWidthSpaces );
185 else
187 rContext.rDoc.SetColHidden(nCol, nCol, 0, true);
188 nBreite = nDefWidth;
191 rContext.rDoc.SetColWidth(nCol, 0, nBreite);
194 void OP_NamedRange(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
196 // POST: don't save for invalid coordinates
197 sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd;
199 char cBuffer[ 16+1 ];
200 r.ReadBytes(cBuffer, 16);
201 cBuffer[ 16 ] = 0;
203 r.ReadUInt16( nColSt ).ReadUInt16( nRowSt ).ReadUInt16( nColEnd ).ReadUInt16( nRowEnd );
205 if (!r.good())
206 return;
208 if (!rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColSt), nRowSt) || !rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColEnd), nRowEnd))
209 return;
211 std::unique_ptr<LotusRange> pRange;
213 if( nColSt == nColEnd && nRowSt == nRowEnd )
214 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) ));
215 else
216 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
217 static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) ));
219 char cBuf[sizeof(cBuffer)+1];
220 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer) ) )
221 { // first char in name is a number -> prepend 'A'
222 cBuf[0] = 'A';
223 strcpy( cBuf + 1, cBuffer ); // #100211# - checked
225 else
226 strcpy( cBuf, cBuffer ); // #100211# - checked
228 OUString aTmp( cBuf, strlen(cBuf), rContext.eCharset );
230 aTmp = ScfTools::ConvertToScDefinedName( aTmp );
232 rContext.maRangeNames.Append( &rContext.rDoc, std::move(pRange) );
235 void OP_SymphNamedRange(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
237 // POST:don't save for invalid coordinates
238 sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd;
239 sal_uInt8 nType;
241 char cBuffer[ 16+1 ];
242 r.ReadBytes(cBuffer, 16);
243 cBuffer[ 16 ] = 0;
245 r.ReadUInt16( nColSt ).ReadUInt16( nRowSt ).ReadUInt16( nColEnd ).ReadUInt16( nRowEnd ).ReadUChar( nType );
247 if (!r.good())
248 return;
250 if (!rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColSt), nRowSt) || !rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColEnd), nRowEnd))
251 return;
253 std::unique_ptr<LotusRange> pRange;
255 if( nType )
256 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) ));
257 else
258 pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
259 static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) ));
261 char cBuf[sizeof(cBuffer)+1];
262 if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer) ) )
263 { // first char in name is a number -> prepend 'A'
264 cBuf[0] = 'A';
265 strcpy( cBuf + 1, cBuffer ); // #100211# - checked
267 else
268 strcpy( cBuf, cBuffer ); // #100211# - checked
270 OUString aTmp( cBuf, strlen(cBuf), rContext.eCharset );
271 aTmp = ScfTools::ConvertToScDefinedName( aTmp );
273 rContext.maRangeNames.Append( &rContext.rDoc, std::move(pRange) );
276 void OP_Footer(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
278 r.SeekRel( n );
281 void OP_Header(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
283 r.SeekRel( n );
286 void OP_Margins(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
288 r.SeekRel( n );
291 void OP_HiddenCols(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
293 SCCOL nCount = 0;
294 for (sal_uInt16 nByte = 0; nByte < 32; ++nByte) // 32 Bytes with ...
296 sal_uInt8 nCurrent(0);
297 r.ReadUChar(nCurrent);
298 for (sal_uInt16 nBit = 0; nBit < 8; ++nBit) // ...each 8 Bits = 256 Bits
300 if( nCurrent & 0x01 ) // is lowest Bit set?
302 // -> Hidden Col
303 rContext.rDoc.SetColHidden(nCount, nCount, 0, true);
306 nCount++;
307 nCurrent = nCurrent / 2; // the next please...
312 void OP_Window1(LotusContext& rContext, SvStream& r, sal_uInt16 n)
314 r.SeekRel( 4 ); // skip Cursor Pos
316 sal_uInt8 nDefaultFormat; // -> op.cpp, standard cell format
317 r.ReadUChar(nDefaultFormat);
319 r.SeekRel( 1 ); // skip 'unused'
321 r.ReadUInt16( nDefWidth );
322 if (!r.good())
323 return;
325 r.SeekRel( n - 8 ); // skip the rest
327 nDefWidth = static_cast<sal_uInt16>( TWIPS_PER_CHAR * nDefWidth );
329 const bool bFuzzing = utl::ConfigManager::IsFuzzing();
331 // instead of default, set all Cols in SC by hand
332 for (SCCOL nCol = 0 ; nCol <= rContext.rDoc.MaxCol() ; nCol++)
334 rContext.rDoc.SetColWidth( nCol, 0, nDefWidth );
335 if (bFuzzing)
336 break;
340 void OP_Blank(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
342 sal_uInt8 nFormat(0);
343 sal_uInt16 nTmpCol(0), nTmpRow(0);
344 r.ReadUChar( nFormat ).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
345 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
346 SCROW nRow(static_cast<SCROW>(nTmpRow));
348 SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
351 void OP_BOF123(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 /*n*/)
353 r.SeekRel( 26 );
356 void OP_EOF123(LotusContext& rContext, SvStream& /*r*/, sal_uInt16 /*n*/)
358 rContext.bEOF = true;
361 void OP_Label123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
363 sal_uInt8 nTmpTab(0), nTmpCol(0);
364 sal_uInt16 nTmpRow(0);
365 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
366 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
367 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
368 SCROW nRow(static_cast<SCROW>(nTmpRow));
370 n -= std::min<sal_uInt16>(n, 4);
372 std::unique_ptr<char[]> pText(new char[n + 1]);
373 r.ReadBytes(pText.get(), n);
374 pText[ n ] = 0;
376 PutFormString(rContext, nCol, nRow, nTab, pText.get());
379 void OP_Number123(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
381 sal_uInt16 nTmpRow(0);
382 sal_uInt8 nTmpCol(0), nTmpTab(0);
383 sal_uInt32 nValue(0);
384 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol).ReadUInt32(nValue);
385 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
386 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
387 SCROW nRow(static_cast<SCROW>(nTmpRow));
389 ScAddress aAddr(nCol, nRow, nTab);
390 if (rContext.rDoc.ValidAddress(aAddr) && nTab <= rContext.rDoc.GetMaxTableNumber())
392 double fValue = Snum32ToDouble( nValue );
393 rContext.rDoc.EnsureTable(nTab);
394 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
395 rContext.rDoc.SetValue(aAddr, fValue);
399 void OP_Formula123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
401 sal_uInt16 nTmpRow(0);
402 sal_uInt8 nTmpCol(0), nTmpTab(0);
403 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
404 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
405 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
406 SCROW nRow(static_cast<SCROW>(nTmpRow));
407 r.SeekRel( 8 ); // skip Result
409 std::unique_ptr<ScTokenArray> pResult;
410 sal_Int32 nBytesLeft = (n > 12) ? n - 12 : 0;
411 ScAddress aAddress(nCol, nRow, nTab);
413 svl::SharedStringPool& rSPool = rContext.rDoc.GetSharedStringPool();
414 LotusToSc aConv(rContext, r, rSPool, rContext.eCharset, true);
415 aConv.Reset( aAddress );
416 aConv.Convert( pResult, nBytesLeft );
417 if (!aConv.good())
418 return;
420 if (rContext.rDoc.ValidAddress(aAddress) && nTab <= rContext.rDoc.GetMaxTableNumber())
422 ScFormulaCell* pCell = new ScFormulaCell(rContext.rDoc, aAddress, std::move(pResult));
423 pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
424 rContext.rDoc.EnsureTable(nTab);
425 rContext.rDoc.SetFormulaCell(aAddress, pCell);
429 void OP_IEEENumber123(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
431 sal_uInt16 nTmpRow(0);
432 sal_uInt8 nTmpCol(0), nTmpTab(0);
433 double dValue(0.0);
434 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol).ReadDouble(dValue);
435 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
436 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
437 SCROW nRow(static_cast<SCROW>(nTmpRow));
439 ScAddress aAddr(nCol, nRow, nTab);
440 if (rContext.rDoc.ValidAddress(aAddr) && nTab <= rContext.rDoc.GetMaxTableNumber())
442 rContext.rDoc.EnsureTable(nTab);
443 // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
444 rContext.rDoc.SetValue(aAddr, dValue);
448 void OP_Note123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
450 sal_uInt16 nTmpRow(0);
451 sal_uInt8 nTmpTab(0), nTmpCol(0);
452 r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
453 SCTAB nTab(static_cast<SCTAB>(nTmpTab));
454 SCCOL nCol(static_cast<SCCOL>(nTmpCol));
455 SCROW nRow(static_cast<SCROW>(nTmpRow));
457 n -= std::min<sal_uInt16>(n, 4);
459 std::unique_ptr<char[]> pText(new char[n + 1]);
460 r.ReadBytes(pText.get(), n);
461 pText[ n ] = 0;
463 OUString aNoteText(pText.get(), strlen(pText.get()), rContext.eCharset);
464 pText.reset();
466 ScAddress aPos(nCol, nRow, nTab);
467 ScNoteUtil::CreateNoteFromString( rContext.rDoc, aPos, aNoteText, false, false );
470 void OP_HorAlign123(LotusContext& /*rContext*/, sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet)
472 // pre: Pattern is stored in the last 3 bites of the 21st byte
473 // post: Appropriate Horizontal Alignment is set in rPattern according to the bit pattern.
475 // LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
476 // LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
478 nAlignPattern = ( nAlignPattern & 0x07);
480 switch (nAlignPattern)
482 case 1:
483 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Left, ATTR_HOR_JUSTIFY ) );
484 break;
485 case 2:
486 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Right, ATTR_HOR_JUSTIFY ) );
487 break;
488 case 3:
489 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY) );
490 break;
491 case 4:
492 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard, ATTR_HOR_JUSTIFY ) );
493 break;
494 case 6:
495 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Block, ATTR_HOR_JUSTIFY ) );
496 break;
497 default:
498 rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard, ATTR_HOR_JUSTIFY ) );
499 break;
503 void OP_VerAlign123(LotusContext& /*rContext*/, sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet)
505 // pre: Pattern is stored in the last 3 bites of the 22nd byte
506 // post: Appropriate Vertical Alignment is set in rPattern according to the bit pattern.
508 // TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
510 nAlignPattern = ( nAlignPattern & 0x07);
512 switch (nAlignPattern)
514 case 0:
515 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard, ATTR_VER_JUSTIFY) );
516 break;
517 case 1:
518 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Top, ATTR_VER_JUSTIFY) );
519 break;
520 case 2:
521 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Center, ATTR_VER_JUSTIFY) );
522 break;
523 case 4:
524 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Bottom, ATTR_VER_JUSTIFY) );
525 break;
526 default:
527 rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard, ATTR_VER_JUSTIFY) );
528 break;
532 void OP_CreatePattern123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
534 sal_uInt16 nCode;
536 ScPatternAttr aPattern(rContext.rDoc.GetPool());
537 SfxItemSet& rItemSet = aPattern.GetItemSet();
539 r.ReadUInt16( nCode );
540 n -= std::min<sal_uInt16>(n, 2);
542 if ( nCode == 0x0fd2 )
544 sal_uInt16 nPatternId;
545 r.ReadUInt16( nPatternId );
547 sal_uInt8 Hor_Align, Ver_Align, temp;
548 bool bIsBold,bIsUnderLine,bIsItalics;
550 r.SeekRel(12);
552 // Read 17th Byte
553 r.ReadUChar( temp );
555 bIsBold = (temp & 0x01);
556 bIsItalics = (temp & 0x02);
557 bIsUnderLine = (temp & 0x04);
559 if ( bIsBold )
560 rItemSet.Put( SvxWeightItem(WEIGHT_BOLD,ATTR_FONT_WEIGHT) );
561 if ( bIsItalics )
562 rItemSet.Put( SvxPostureItem(ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
563 if ( bIsUnderLine )
564 rItemSet.Put( SvxUnderlineItem( LINESTYLE_SINGLE, ATTR_FONT_UNDERLINE ) );
566 r.SeekRel(3);
568 // Read 21st Byte
569 r.ReadUChar( Hor_Align );
570 OP_HorAlign123(rContext, Hor_Align, rItemSet );
572 r.ReadUChar( Ver_Align );
573 OP_VerAlign123(rContext, Ver_Align, rItemSet );
575 rContext.aLotusPatternPool.emplace( nPatternId, aPattern );
576 n -= std::min<sal_uInt16>(n, 20);
578 r.SeekRel(n);
581 void OP_SheetName123(LotusContext& rContext, SvStream& rStream, sal_uInt16 nLength)
583 if (nLength <= 4)
585 rStream.SeekRel(nLength);
586 return;
589 // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
590 rStream.SeekRel(2); // ignore the first 2 bytes (B0 36).
591 sal_uInt16 nSheetNum(0);
592 rStream.ReadUInt16(nSheetNum);
594 const size_t nStrLen = nLength - 4;
595 std::vector<char> sSheetName(nStrLen + 1);
596 sSheetName[rStream.ReadBytes(sSheetName.data(), nStrLen)] = 0;
598 if (!ValidTab(nSheetNum))
599 return;
600 // coverity[tainted_data : FALSE] - ValidTab has sanitized nSheetNum
601 rContext.rDoc.MakeTable(nSheetNum);
602 if (!sSheetName.empty())
604 OUString aName(sSheetName.data(), strlen(sSheetName.data()), rContext.eCharset);
605 rContext.rDoc.RenameTab(nSheetNum, aName);
609 void OP_ApplyPatternArea123(LotusContext& rContext, SvStream& rStream)
611 sal_uInt16 nOpcode, nLength;
612 sal_uInt16 nCol = 0, nColCount = 0, nRow = 0, nRowCount = 0, nTab = 0, nData, nTabCount = 0, nLevel = 0;
616 rStream.ReadUInt16( nOpcode ).ReadUInt16( nLength );
617 switch ( nOpcode )
619 case ROW_FORMAT_MARKER:
620 nLevel++;
621 break;
622 case COL_FORMAT_MARKER:
623 nLevel--;
624 if( nLevel == 1 )
626 nTab = nTab + nTabCount;
627 nCol = 0; nColCount = 0;
628 nRow = 0; nRowCount = 0;
630 break;
631 case LOTUS_FORMAT_INDEX:
632 if( nLength >= 2 )
634 rStream.ReadUInt16( nData );
635 rStream.SeekRel( nLength - 2 );
636 if( nLevel == 1 )
637 nTabCount = SanitizeTab(nData);
638 else if( nLevel == 2 )
640 nCol = nCol + nColCount;
641 nColCount = nData;
642 if ( nCol > 0xff ) // 256 is the max col size supported by 123
643 nCol = 0;
645 else if( nLevel == 3 )
647 nRow = nRow + nRowCount;
648 nRowCount = nData;
649 if ( nRow > 0x1fff ) // 8192 is the max row size supported by 123
650 nRow = 0;
653 else
654 rStream.SeekRel( nLength );
655 break;
656 case LOTUS_FORMAT_INFO:
657 if( nLength >= 2 )
659 rStream.ReadUInt16( nData );
660 rStream.SeekRel( nLength - 2 );
661 std::map<sal_uInt16, ScPatternAttr>::iterator loc = rContext.aLotusPatternPool.find( nData );
662 // #126338# apparently, files with invalid index occur in the wild -> don't crash then
663 if ( loc != rContext.aLotusPatternPool.end() )
664 for( int i = 0; i < nTabCount; i++)
666 rContext.rDoc.ApplyPatternAreaTab( nCol, nRow, nCol + nColCount - 1, nRow + nRowCount - 1, static_cast< SCTAB >( nTab + i ), loc->second );
669 else
670 rStream.SeekRel( nLength );
671 break;
672 default:
673 rStream.SeekRel( nLength );
674 break;
677 while( nLevel && rStream.good() );
679 rContext.aLotusPatternPool.clear();
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */