summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/lotus/op.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/lotus/op.cxx')
-rw-r--r--sc/source/filter/lotus/op.cxx684
1 files changed, 684 insertions, 0 deletions
diff --git a/sc/source/filter/lotus/op.cxx b/sc/source/filter/lotus/op.cxx
new file mode 100644
index 000000000..58007a518
--- /dev/null
+++ b/sc/source/filter/lotus/op.cxx
@@ -0,0 +1,684 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <rtl/math.hxx>
+#include <rtl/character.hxx>
+
+#include <string.h>
+
+#include <scitems.hxx>
+#include <patattr.hxx>
+#include <docpool.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/justifyitem.hxx>
+#include <unotools/configmgr.hxx>
+
+#include <formulacell.hxx>
+#include <document.hxx>
+#include <postit.hxx>
+
+#include <op.h>
+#include <optab.h>
+#include <tool.h>
+#include "lotfilter.hxx"
+#include <lotform.hxx>
+#include <lotrange.hxx>
+#include <ftools.hxx>
+
+#include <vector>
+#include <map>
+#include <memory>
+
+static sal_uInt16 nDefWidth = sal_uInt16( TWIPS_PER_CHAR * 10 );
+
+void NI(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
+{
+ r.SeekRel( n );
+}
+
+void OP_BOF(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 /*n*/)
+{
+ r.SeekRel( 2 ); // skip version number
+}
+
+void OP_EOF(LotusContext& rContext, SvStream& /*r*/, sal_uInt16 /*n*/)
+{
+ rContext.bEOF = true;
+}
+
+void OP_Integer(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ sal_uInt8 nFormat(0);
+ sal_uInt16 nTmpCol(0), nTmpRow(0);
+ sal_Int16 nValue(0);
+ r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow).ReadInt16(nValue);
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ ScAddress aAddr(nCol, nRow, 0);
+ if (rContext.rDoc.ValidAddress(aAddr))
+ {
+ rContext.rDoc.EnsureTable(0);
+ // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
+ rContext.rDoc.SetValue(aAddr, static_cast<double>(nValue));
+
+ // 0 digits in fractional part!
+ SetFormat(rContext, nCol, nRow, 0, nFormat, 0);
+ }
+}
+
+void OP_Number(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ sal_uInt8 nFormat(0);
+ sal_uInt16 nTmpCol(0), nTmpRow(0);
+ double fValue(0.0);
+ r.ReadUChar( nFormat ).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow).ReadDouble(fValue);
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ ScAddress aAddr(nCol, nRow, 0);
+ if (rContext.rDoc.ValidAddress(aAddr))
+ {
+ fValue = ::rtl::math::round( fValue, 15 );
+ rContext.rDoc.EnsureTable(0);
+ // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
+ rContext.rDoc.SetValue(aAddr, fValue);
+
+ SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
+ }
+}
+
+void OP_Label(LotusContext& rContext, SvStream& r, sal_uInt16 n)
+{
+ sal_uInt8 nFormat(0);
+ sal_uInt16 nTmpCol(0), nTmpRow(0);
+ r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ n -= std::min<sal_uInt16>(n, 5);
+
+ std::vector<char> aText(n + 1);
+ n = r.ReadBytes(aText.data(), n);
+ aText[n] = 0;
+
+ if (rContext.rDoc.ValidColRow(nCol, nRow))
+ {
+ nFormat &= 0x80; // don't change Bit 7
+ nFormat |= 0x75; // protected does not matter, special-text is set
+
+ PutFormString(rContext, nCol, nRow, 0, aText.data());
+
+ SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalStd);
+ }
+}
+
+void OP_Formula(LotusContext &rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ sal_uInt8 nFormat(0);
+ sal_uInt16 nTmpCol(0), nTmpRow(0);
+ r.ReadUChar(nFormat).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
+ r.SeekRel(8); // skip result
+ sal_uInt16 nFormulaSize(0);
+ r.ReadUInt16(nFormulaSize);
+
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ std::unique_ptr<ScTokenArray> pResult;
+ sal_Int32 nBytesLeft = nFormulaSize;
+ ScAddress aAddress(nCol, nRow, 0);
+
+ svl::SharedStringPool& rSPool = rContext.rDoc.GetSharedStringPool();
+ LotusToSc aConv(rContext, r, rSPool, rContext.eCharset, false);
+ aConv.Reset( aAddress );
+ aConv.Convert( pResult, nBytesLeft );
+ if (!aConv.good())
+ return;
+
+ if (rContext.rDoc.ValidColRow(nCol, nRow))
+ {
+ ScFormulaCell* pCell = new ScFormulaCell(rContext.rDoc, aAddress, std::move(pResult));
+ pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
+ rContext.rDoc.EnsureTable(0);
+ // coverity[tainted_data : FALSE] - ValidColRow has sanitized aAddr
+ rContext.rDoc.SetFormulaCell(ScAddress(nCol, nRow, 0), pCell);
+
+ // nFormat = Default -> number of digits in fractional part like Float
+ SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
+ }
+}
+
+void OP_ColumnWidth(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ sal_uInt16 nTmpCol(0);
+ sal_uInt8 nWidthSpaces(0);
+ r.ReadUInt16(nTmpCol).ReadUChar(nWidthSpaces);
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+
+ if (!rContext.rDoc.ValidCol(nCol))
+ return;
+
+ nCol = rContext.rDoc.SanitizeCol(nCol);
+
+ sal_uInt16 nBreite;
+ if( nWidthSpaces )
+ // assuming 10cpi character set
+ nBreite = static_cast<sal_uInt16>( TWIPS_PER_CHAR * nWidthSpaces );
+ else
+ {
+ rContext.rDoc.SetColHidden(nCol, nCol, 0, true);
+ nBreite = nDefWidth;
+ }
+
+ rContext.rDoc.SetColWidth(nCol, 0, nBreite);
+}
+
+void OP_NamedRange(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ // POST: don't save for invalid coordinates
+ sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd;
+
+ char cBuffer[ 16+1 ];
+ r.ReadBytes(cBuffer, 16);
+ cBuffer[ 16 ] = 0;
+
+ r.ReadUInt16( nColSt ).ReadUInt16( nRowSt ).ReadUInt16( nColEnd ).ReadUInt16( nRowEnd );
+
+ if (!r.good())
+ return;
+
+ if (!rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColSt), nRowSt) || !rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColEnd), nRowEnd))
+ return;
+
+ std::unique_ptr<LotusRange> pRange;
+
+ if( nColSt == nColEnd && nRowSt == nRowEnd )
+ pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) ));
+ else
+ pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
+ static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) ));
+
+ char cBuf[sizeof(cBuffer)+1];
+ if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer) ) )
+ { // first char in name is a number -> prepend 'A'
+ cBuf[0] = 'A';
+ strcpy( cBuf + 1, cBuffer ); // #100211# - checked
+ }
+ else
+ strcpy( cBuf, cBuffer ); // #100211# - checked
+
+ OUString aTmp( cBuf, strlen(cBuf), rContext.eCharset );
+
+ aTmp = ScfTools::ConvertToScDefinedName( aTmp );
+
+ rContext.maRangeNames.Append( &rContext.rDoc, std::move(pRange) );
+}
+
+void OP_SymphNamedRange(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ // POST:don't save for invalid coordinates
+ sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd;
+ sal_uInt8 nType;
+
+ char cBuffer[ 16+1 ];
+ r.ReadBytes(cBuffer, 16);
+ cBuffer[ 16 ] = 0;
+
+ r.ReadUInt16( nColSt ).ReadUInt16( nRowSt ).ReadUInt16( nColEnd ).ReadUInt16( nRowEnd ).ReadUChar( nType );
+
+ if (!r.good())
+ return;
+
+ if (!rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColSt), nRowSt) || !rContext.rDoc.ValidColRow(static_cast<SCCOL>(nColEnd), nRowEnd))
+ return;
+
+ std::unique_ptr<LotusRange> pRange;
+
+ if( nType )
+ pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt) ));
+ else
+ pRange.reset(new LotusRange( static_cast<SCCOL> (nColSt), static_cast<SCROW> (nRowSt),
+ static_cast<SCCOL> (nColEnd), static_cast<SCROW> (nRowEnd) ));
+
+ char cBuf[sizeof(cBuffer)+1];
+ if( rtl::isAsciiDigit( static_cast<unsigned char>(*cBuffer) ) )
+ { // first char in name is a number -> prepend 'A'
+ cBuf[0] = 'A';
+ strcpy( cBuf + 1, cBuffer ); // #100211# - checked
+ }
+ else
+ strcpy( cBuf, cBuffer ); // #100211# - checked
+
+ OUString aTmp( cBuf, strlen(cBuf), rContext.eCharset );
+ aTmp = ScfTools::ConvertToScDefinedName( aTmp );
+
+ rContext.maRangeNames.Append( &rContext.rDoc, std::move(pRange) );
+}
+
+void OP_Footer(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
+{
+ r.SeekRel( n );
+}
+
+void OP_Header(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
+{
+ r.SeekRel( n );
+}
+
+void OP_Margins(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 n)
+{
+ r.SeekRel( n );
+}
+
+void OP_HiddenCols(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ SCCOL nCount = 0;
+ for (sal_uInt16 nByte = 0; nByte < 32; ++nByte) // 32 Bytes with ...
+ {
+ sal_uInt8 nCurrent(0);
+ r.ReadUChar(nCurrent);
+ for (sal_uInt16 nBit = 0; nBit < 8; ++nBit) // ...each 8 Bits = 256 Bits
+ {
+ if( nCurrent & 0x01 ) // is lowest Bit set?
+ {
+ // -> Hidden Col
+ rContext.rDoc.SetColHidden(nCount, nCount, 0, true);
+ }
+
+ nCount++;
+ nCurrent = nCurrent / 2; // the next please...
+ }
+ }
+}
+
+void OP_Window1(LotusContext& rContext, SvStream& r, sal_uInt16 n)
+{
+ r.SeekRel( 4 ); // skip Cursor Pos
+
+ sal_uInt8 nDefaultFormat; // -> op.cpp, standard cell format
+ r.ReadUChar(nDefaultFormat);
+
+ r.SeekRel( 1 ); // skip 'unused'
+
+ r.ReadUInt16( nDefWidth );
+ if (!r.good())
+ return;
+
+ r.SeekRel( n - 8 ); // skip the rest
+
+ nDefWidth = static_cast<sal_uInt16>( TWIPS_PER_CHAR * nDefWidth );
+
+ const bool bFuzzing = utl::ConfigManager::IsFuzzing();
+
+ // instead of default, set all Cols in SC by hand
+ for (SCCOL nCol = 0 ; nCol <= rContext.rDoc.MaxCol() ; nCol++)
+ {
+ rContext.rDoc.SetColWidth( nCol, 0, nDefWidth );
+ if (bFuzzing)
+ break;
+ }
+}
+
+void OP_Blank(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ sal_uInt8 nFormat(0);
+ sal_uInt16 nTmpCol(0), nTmpRow(0);
+ r.ReadUChar( nFormat ).ReadUInt16(nTmpCol).ReadUInt16(nTmpRow);
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ SetFormat(rContext, nCol, nRow, 0, nFormat, nFractionalFloat);
+}
+
+void OP_BOF123(LotusContext& /*rContext*/, SvStream& r, sal_uInt16 /*n*/)
+{
+ r.SeekRel( 26 );
+}
+
+void OP_EOF123(LotusContext& rContext, SvStream& /*r*/, sal_uInt16 /*n*/)
+{
+ rContext.bEOF = true;
+}
+
+void OP_Label123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
+{
+ sal_uInt8 nTmpTab(0), nTmpCol(0);
+ sal_uInt16 nTmpRow(0);
+ r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
+ SCTAB nTab(static_cast<SCTAB>(nTmpTab));
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ n -= std::min<sal_uInt16>(n, 4);
+
+ std::unique_ptr<char[]> pText(new char[n + 1]);
+ r.ReadBytes(pText.get(), n);
+ pText[ n ] = 0;
+
+ PutFormString(rContext, nCol, nRow, nTab, pText.get());
+}
+
+void OP_Number123(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ sal_uInt16 nTmpRow(0);
+ sal_uInt8 nTmpCol(0), nTmpTab(0);
+ sal_uInt32 nValue(0);
+ r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol).ReadUInt32(nValue);
+ SCTAB nTab(static_cast<SCTAB>(nTmpTab));
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ ScAddress aAddr(nCol, nRow, nTab);
+ if (rContext.rDoc.ValidAddress(aAddr) && nTab <= rContext.rDoc.GetMaxTableNumber())
+ {
+ double fValue = Snum32ToDouble( nValue );
+ rContext.rDoc.EnsureTable(nTab);
+ // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
+ rContext.rDoc.SetValue(aAddr, fValue);
+ }
+}
+
+void OP_Formula123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
+{
+ sal_uInt16 nTmpRow(0);
+ sal_uInt8 nTmpCol(0), nTmpTab(0);
+ r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
+ SCTAB nTab(static_cast<SCTAB>(nTmpTab));
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+ r.SeekRel( 8 ); // skip Result
+
+ std::unique_ptr<ScTokenArray> pResult;
+ sal_Int32 nBytesLeft = (n > 12) ? n - 12 : 0;
+ ScAddress aAddress(nCol, nRow, nTab);
+
+ svl::SharedStringPool& rSPool = rContext.rDoc.GetSharedStringPool();
+ LotusToSc aConv(rContext, r, rSPool, rContext.eCharset, true);
+ aConv.Reset( aAddress );
+ aConv.Convert( pResult, nBytesLeft );
+ if (!aConv.good())
+ return;
+
+ if (rContext.rDoc.ValidAddress(aAddress) && nTab <= rContext.rDoc.GetMaxTableNumber())
+ {
+ ScFormulaCell* pCell = new ScFormulaCell(rContext.rDoc, aAddress, std::move(pResult));
+ pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
+ rContext.rDoc.EnsureTable(nTab);
+ // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
+ rContext.rDoc.SetFormulaCell(aAddress, pCell);
+ }
+}
+
+void OP_IEEENumber123(LotusContext& rContext, SvStream& r, sal_uInt16 /*n*/)
+{
+ sal_uInt16 nTmpRow(0);
+ sal_uInt8 nTmpCol(0), nTmpTab(0);
+ double dValue(0.0);
+ r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol).ReadDouble(dValue);
+ SCTAB nTab(static_cast<SCTAB>(nTmpTab));
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ ScAddress aAddr(nCol, nRow, nTab);
+ if (rContext.rDoc.ValidAddress(aAddr) && nTab <= rContext.rDoc.GetMaxTableNumber())
+ {
+ rContext.rDoc.EnsureTable(nTab);
+ // coverity[tainted_data : FALSE] - ValidAddress has sanitized aAddr
+ rContext.rDoc.SetValue(aAddr, dValue);
+ }
+}
+
+void OP_Note123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
+{
+ sal_uInt16 nTmpRow(0);
+ sal_uInt8 nTmpTab(0), nTmpCol(0);
+ r.ReadUInt16(nTmpRow).ReadUChar(nTmpTab).ReadUChar(nTmpCol);
+ SCTAB nTab(static_cast<SCTAB>(nTmpTab));
+ SCCOL nCol(static_cast<SCCOL>(nTmpCol));
+ SCROW nRow(static_cast<SCROW>(nTmpRow));
+
+ n -= std::min<sal_uInt16>(n, 4);
+
+ std::unique_ptr<char[]> pText(new char[n + 1]);
+ r.ReadBytes(pText.get(), n);
+ pText[ n ] = 0;
+
+ OUString aNoteText(pText.get(), strlen(pText.get()), rContext.eCharset);
+ pText.reset();
+
+ ScAddress aPos(nCol, nRow, nTab);
+ ScNoteUtil::CreateNoteFromString( rContext.rDoc, aPos, aNoteText, false, false );
+}
+
+void OP_HorAlign123(LotusContext& /*rContext*/, sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet)
+{
+// pre: Pattern is stored in the last 3 bites of the 21st byte
+// post: Appropriate Horizontal Alignment is set in rPattern according to the bit pattern.
+//
+// LEFT:001, RIGHT:010, CENTER:011, JUSTIFY:110,
+// LEFT-Text/RIGHT-NUMBER:100, DEFAULT:000
+
+ nAlignPattern = ( nAlignPattern & 0x07);
+
+ switch (nAlignPattern)
+ {
+ case 1:
+ rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Left, ATTR_HOR_JUSTIFY ) );
+ break;
+ case 2:
+ rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Right, ATTR_HOR_JUSTIFY ) );
+ break;
+ case 3:
+ rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY) );
+ break;
+ case 4:
+ rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard, ATTR_HOR_JUSTIFY ) );
+ break;
+ case 6:
+ rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Block, ATTR_HOR_JUSTIFY ) );
+ break;
+ default:
+ rPatternItemSet.Put( SvxHorJustifyItem( SvxCellHorJustify::Standard, ATTR_HOR_JUSTIFY ) );
+ break;
+ }
+}
+
+void OP_VerAlign123(LotusContext& /*rContext*/, sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet)
+{
+// pre: Pattern is stored in the last 3 bites of the 22nd byte
+// post: Appropriate Vertical Alignment is set in rPattern according to the bit pattern.
+//
+// TOP:001, MIDDLE:010, DOWN:100, DEFAULT:000
+
+ nAlignPattern = ( nAlignPattern & 0x07);
+
+ switch (nAlignPattern)
+ {
+ case 0:
+ rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard, ATTR_VER_JUSTIFY) );
+ break;
+ case 1:
+ rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Top, ATTR_VER_JUSTIFY) );
+ break;
+ case 2:
+ rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Center, ATTR_VER_JUSTIFY) );
+ break;
+ case 4:
+ rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Bottom, ATTR_VER_JUSTIFY) );
+ break;
+ default:
+ rPatternItemSet.Put( SvxVerJustifyItem(SvxCellVerJustify::Standard, ATTR_VER_JUSTIFY) );
+ break;
+ }
+}
+
+void OP_CreatePattern123(LotusContext& rContext, SvStream& r, sal_uInt16 n)
+{
+ sal_uInt16 nCode;
+
+ ScPatternAttr aPattern(rContext.rDoc.GetPool());
+ SfxItemSet& rItemSet = aPattern.GetItemSet();
+
+ r.ReadUInt16( nCode );
+ n -= std::min<sal_uInt16>(n, 2);
+
+ if ( nCode == 0x0fd2 )
+ {
+ sal_uInt16 nPatternId;
+ r.ReadUInt16( nPatternId );
+
+ sal_uInt8 Hor_Align, Ver_Align, temp;
+ bool bIsBold,bIsUnderLine,bIsItalics;
+
+ r.SeekRel(12);
+
+ // Read 17th Byte
+ r.ReadUChar( temp );
+
+ bIsBold = (temp & 0x01);
+ bIsItalics = (temp & 0x02);
+ bIsUnderLine = (temp & 0x04);
+
+ if ( bIsBold )
+ rItemSet.Put( SvxWeightItem(WEIGHT_BOLD,ATTR_FONT_WEIGHT) );
+ if ( bIsItalics )
+ rItemSet.Put( SvxPostureItem(ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
+ if ( bIsUnderLine )
+ rItemSet.Put( SvxUnderlineItem( LINESTYLE_SINGLE, ATTR_FONT_UNDERLINE ) );
+
+ r.SeekRel(3);
+
+ // Read 21st Byte
+ r.ReadUChar( Hor_Align );
+ OP_HorAlign123(rContext, Hor_Align, rItemSet );
+
+ r.ReadUChar( Ver_Align );
+ OP_VerAlign123(rContext, Ver_Align, rItemSet );
+
+ rContext.aLotusPatternPool.emplace( nPatternId, aPattern );
+ n -= std::min<sal_uInt16>(n, 20);
+ }
+ r.SeekRel(n);
+}
+
+void OP_SheetName123(LotusContext& rContext, SvStream& rStream, sal_uInt16 nLength)
+{
+ if (nLength <= 4)
+ {
+ rStream.SeekRel(nLength);
+ return;
+ }
+
+ // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)]
+ rStream.SeekRel(2); // ignore the first 2 bytes (B0 36).
+ sal_uInt16 nSheetNum(0);
+ rStream.ReadUInt16(nSheetNum);
+
+ const size_t nStrLen = nLength - 4;
+ std::vector<char> sSheetName(nStrLen + 1);
+ sSheetName[rStream.ReadBytes(sSheetName.data(), nStrLen)] = 0;
+
+ if (!ValidTab(nSheetNum))
+ return;
+ // coverity[tainted_data : FALSE] - ValidTab has sanitized nSheetNum
+ rContext.rDoc.MakeTable(nSheetNum);
+ if (!sSheetName.empty())
+ {
+ OUString aName(sSheetName.data(), strlen(sSheetName.data()), rContext.eCharset);
+ rContext.rDoc.RenameTab(nSheetNum, aName);
+ }
+}
+
+void OP_ApplyPatternArea123(LotusContext& rContext, SvStream& rStream)
+{
+ sal_uInt16 nOpcode, nLength;
+ sal_uInt16 nCol = 0, nColCount = 0, nRow = 0, nRowCount = 0, nTab = 0, nData, nTabCount = 0, nLevel = 0;
+
+ do
+ {
+ rStream.ReadUInt16( nOpcode ).ReadUInt16( nLength );
+ switch ( nOpcode )
+ {
+ case ROW_FORMAT_MARKER:
+ nLevel++;
+ break;
+ case COL_FORMAT_MARKER:
+ nLevel--;
+ if( nLevel == 1 )
+ {
+ nTab = nTab + nTabCount;
+ nCol = 0; nColCount = 0;
+ nRow = 0; nRowCount = 0;
+ }
+ break;
+ case LOTUS_FORMAT_INDEX:
+ if( nLength >= 2 )
+ {
+ rStream.ReadUInt16( nData );
+ rStream.SeekRel( nLength - 2 );
+ if( nLevel == 1 )
+ nTabCount = SanitizeTab(nData);
+ else if( nLevel == 2 )
+ {
+ nCol = nCol + nColCount;
+ nColCount = nData;
+ if ( nCol > 0xff ) // 256 is the max col size supported by 123
+ nCol = 0;
+ }
+ else if( nLevel == 3 )
+ {
+ nRow = nRow + nRowCount;
+ nRowCount = nData;
+ if ( nRow > 0x1fff ) // 8192 is the max row size supported by 123
+ nRow = 0;
+ }
+ }
+ else
+ rStream.SeekRel( nLength );
+ break;
+ case LOTUS_FORMAT_INFO:
+ if( nLength >= 2 )
+ {
+ rStream.ReadUInt16( nData );
+ rStream.SeekRel( nLength - 2 );
+ std::map<sal_uInt16, ScPatternAttr>::iterator loc = rContext.aLotusPatternPool.find( nData );
+ // #126338# apparently, files with invalid index occur in the wild -> don't crash then
+ if ( loc != rContext.aLotusPatternPool.end() )
+ for( int i = 0; i < nTabCount; i++)
+ {
+ rContext.rDoc.ApplyPatternAreaTab( nCol, nRow, nCol + nColCount - 1, nRow + nRowCount - 1, static_cast< SCTAB >( nTab + i ), loc->second );
+ }
+ }
+ else
+ rStream.SeekRel( nLength );
+ break;
+ default:
+ rStream.SeekRel( nLength );
+ break;
+ }
+ }
+ while( nLevel && rStream.good() );
+
+ rContext.aLotusPatternPool.clear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */