/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_scfilt.hxx" //------------------------------------------------------------------------ #include #include #include #include #include #include #include #include "scitems.hxx" #include "patattr.hxx" #include "docpool.hxx" #include #include #include #include #include "cell.hxx" #include "rangenam.hxx" #include "document.hxx" #include "postit.hxx" #include "op.h" #include "optab.h" #include "tool.h" #include "decl.h" #include "lotform.hxx" #include "lotrange.hxx" #include "root.hxx" #include "ftools.hxx" #include #include extern WKTYP eTyp; // -> filter.cxx, aktueller Dateityp extern sal_Bool bEOF; // -> filter.cxx, zeigt Dateiende an extern sal_uInt8 nDefaultFormat; // -> tool.cxx, Default-Zellenformat extern ScDocument* pDoc; // -> filter.cxx, Aufhaenger zum Dokumentzugriff extern CharSet eCharVon; // -> filter.cxx, character set specified static sal_uInt16 nDefWidth = ( sal_uInt16 ) ( TWIPS_PER_CHAR * 10 ); extern std::map aLotusPatternPool; void NI( SvStream& r, sal_uInt16 n ) { r.SeekRel( n ); } void OP_BOF( SvStream& r, sal_uInt16 /*n*/ ) { r.SeekRel( 2 ); // Versionsnummer ueberlesen } void OP_EOF( SvStream& /*r*/, sal_uInt16 /*n*/ ) { bEOF = sal_True; } void OP_Integer( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt8 nFormat; sal_uInt16 nCol, nRow; SCTAB nTab = 0; sal_Int16 nValue; r >> nFormat >> nCol >> nRow >> nValue; if (ValidColRow( static_cast(nCol), nRow)) { ScValueCell* pZelle = new ScValueCell( ( double ) nValue ); pDoc->PutCell( static_cast (nCol), static_cast (nRow), nTab, pZelle, ( sal_Bool ) sal_True ); // 0 Stellen nach'm Komma! SetFormat( static_cast (nCol), static_cast (nRow), nTab, nFormat, 0 ); } } void OP_Number( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt8 nFormat; sal_uInt16 nCol, nRow; SCTAB nTab = 0; double fValue; r >> nFormat >> nCol >> nRow >> fValue; if (ValidColRow( static_cast(nCol), nRow)) { fValue = ::rtl::math::round( fValue, 15 ); ScValueCell* pZelle = new ScValueCell( fValue ); pDoc->PutCell( static_cast (nCol), static_cast (nRow), nTab, pZelle, ( sal_Bool ) sal_True ); SetFormat( static_cast (nCol), static_cast (nRow), nTab, nFormat, nDezFloat ); } } void OP_Label( SvStream& r, sal_uInt16 n ) { sal_uInt8 nFormat; sal_uInt16 nCol, nRow; SCTAB nTab = 0; r >> nFormat >> nCol >> nRow; n -= (n > 5) ? 5 : n; sal_Char* pText = new sal_Char[n + 1]; r.Read( pText, n ); pText[n] = 0; if (ValidColRow( static_cast(nCol), nRow)) { nFormat &= 0x80; // Bit 7 belassen nFormat |= 0x75; // protected egal, special-text gesetzt PutFormString( static_cast (nCol), static_cast (nRow), nTab, pText ); SetFormat( static_cast (nCol), static_cast (nRow), nTab, nFormat, nDezStd ); } delete [] pText; } void OP_Formula( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt8 nFormat; sal_uInt16 nCol, nRow, nFormulaSize; SCTAB nTab = 0; r >> nFormat >> nCol >> nRow; r.SeekRel( 8 ); // Ergebnis ueberspringen r >> nFormulaSize; const ScTokenArray* pErg; sal_Int32 nBytesLeft = nFormulaSize; ScAddress aAddress( static_cast (nCol), static_cast (nRow), nTab ); LotusToSc aConv( r, pLotusRoot->eCharsetQ, sal_False ); aConv.Reset( aAddress ); aConv.Convert( pErg, nBytesLeft ); if (ValidColRow( static_cast(nCol), nRow)) { ScFormulaCell* pZelle = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg ); pZelle->AddRecalcMode( RECALCMODE_ONLOAD_ONCE ); pDoc->PutCell( static_cast (nCol), static_cast (nRow), nTab, pZelle, ( sal_Bool ) sal_True ); // nFormat = Standard -> Nachkommastellen wie Float SetFormat( static_cast (nCol), static_cast (nRow), nTab, nFormat, nDezFloat ); } } void OP_ColumnWidth( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt16 nCol, nBreite; sal_uInt8 nWidthSpaces; SCTAB nTab = 0; r >> nCol >> nWidthSpaces; if (ValidCol( static_cast(nCol))) { if( nWidthSpaces ) // Annahme: 10cpi-Zeichensatz nBreite = ( sal_uInt16 ) ( TWIPS_PER_CHAR * nWidthSpaces ); else { pDoc->SetColHidden(static_cast(nCol), static_cast(nCol), 0, true); nBreite = nDefWidth; } pDoc->SetColWidth( static_cast (nCol), nTab, nBreite ); } } void OP_NamedRange( SvStream& r, sal_uInt16 /*n*/ ) { // POST: waren Koordinaten ungueltig, wird nicht gespeichert sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd; sal_Char cPuffer[ 16+1 ]; r.Read( cPuffer, 16 ); cPuffer[ 16 ] = 0; r >> nColSt >> nRowSt >> nColEnd >> nRowEnd; if (ValidColRow( static_cast(nColSt), nRowSt) && ValidColRow( static_cast(nColEnd), nRowEnd)) { LotusRange* pRange; if( nColSt == nColEnd && nRowSt == nRowEnd ) pRange = new LotusRange( static_cast (nColSt), static_cast (nRowSt) ); else pRange = new LotusRange( static_cast (nColSt), static_cast (nRowSt), static_cast (nColEnd), static_cast (nRowEnd) ); sal_Char cBuf[sizeof(cPuffer)+1]; if( isdigit( *cPuffer ) ) { // erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen cBuf[0] = 'A'; strcpy( cBuf + 1, cPuffer ); // #100211# - checked } else strcpy( cBuf, cPuffer ); // #100211# - checked String aTmp( cBuf, pLotusRoot->eCharsetQ ); ScfTools::ConvertToScDefinedName( aTmp ); pLotusRoot->pRangeNames->Append( pRange, aTmp ); } } void OP_SymphNamedRange( SvStream& r, sal_uInt16 /*n*/ ) { // POST: waren Koordinaten ungueltig, wird nicht gespeichert sal_uInt16 nColSt, nRowSt, nColEnd, nRowEnd; sal_uInt8 nType; sal_Char cPuffer[ 16+1 ]; r.Read( cPuffer, 16 ); cPuffer[ 16 ] = 0; r >> nColSt >> nRowSt >> nColEnd >> nRowEnd >> nType; if (ValidColRow( static_cast(nColSt), nRowSt) && ValidColRow( static_cast(nColEnd), nRowEnd)) { LotusRange* pRange; if( nType ) pRange = new LotusRange( static_cast (nColSt), static_cast (nRowSt) ); else pRange = new LotusRange( static_cast (nColSt), static_cast (nRowSt), static_cast (nColEnd), static_cast (nRowEnd) ); sal_Char cBuf[sizeof(cPuffer)+1]; if( isdigit( *cPuffer ) ) { // erstes Zeichen im Namen eine Zahl -> 'A' vor Namen setzen cBuf[0] = 'A'; strcpy( cBuf + 1, cPuffer ); // #100211# - checked } else strcpy( cBuf, cPuffer ); // #100211# - checked String aTmp( cBuf, pLotusRoot->eCharsetQ ); ScfTools::ConvertToScDefinedName( aTmp ); pLotusRoot->pRangeNames->Append( pRange, aTmp ); } } void OP_Footer( SvStream& r, sal_uInt16 n ) { r.SeekRel( n ); } void OP_Header( SvStream& r, sal_uInt16 n ) { r.SeekRel( n ); } void OP_Margins( SvStream& r, sal_uInt16 n ) { r.SeekRel( n ); } void OP_HiddenCols( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt16 nByte, nBit; SCCOL nCount; sal_uInt8 nAkt; nCount = 0; for( nByte = 0 ; nByte < 32 ; nByte++ ) // 32 Bytes mit ... { r >> nAkt; for( nBit = 0 ; nBit < 8 ; nBit++ ) // ...jeweils 8 Bits = 256 Bits { if( nAkt & 0x01 ) // unterstes Bit gesetzt? // -> Hidden Col pDoc->SetColHidden(nCount, nCount, 0, true); nCount++; nAkt = nAkt / 2; // der Naechste bitte... } } } void OP_Window1( SvStream& r, sal_uInt16 n ) { r.SeekRel( 4 ); // Cursor Pos ueberspringen r >> nDefaultFormat; r.SeekRel( 1 ); // 'unused' ueberspringen r >> nDefWidth; r.SeekRel( n - 8 ); // und den Rest ueberspringen nDefWidth = ( sal_uInt16 ) ( TWIPS_PER_CHAR * nDefWidth ); // statt Defaulteinstellung in SC alle Cols zu Fuss setzen for( SCCOL nCol = 0 ; nCol <= MAXCOL ; nCol++ ) pDoc->SetColWidth( nCol, 0, nDefWidth ); } void OP_Blank( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt16 nCol, nRow; sal_uInt8 nFormat; r >> nFormat >> nCol >> nRow; SetFormat( static_cast (nCol), static_cast (nRow), 0, nFormat, nDezFloat ); } void OP_BOF123( SvStream& r, sal_uInt16 /*n*/ ) { r.SeekRel( 26 ); } void OP_EOF123( SvStream& /*r*/, sal_uInt16 /*n*/ ) { bEOF = sal_True; } void OP_Label123( SvStream& r, sal_uInt16 n ) { sal_uInt8 nTab, nCol; sal_uInt16 nRow; r >> nRow >> nTab >> nCol; n -= (n > 4) ? 4 : n; sal_Char* pText = new sal_Char[n + 1]; r.Read( pText, n ); pText[ n ] = 0; PutFormString( static_cast(nCol), static_cast(nRow), static_cast(nTab), pText ); delete []pText; } void OP_Number123( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt8 nCol,nTab; sal_uInt16 nRow; sal_uInt32 nValue; r >> nRow >> nTab >> nCol >> nValue; if (ValidColRow( static_cast(nCol), nRow) && nTab < pDoc->GetMaxTableNumber()) { double fValue = Snum32ToDouble( nValue ); ScValueCell *pCell = new ScValueCell( fValue ); pDoc->PutCell( static_cast(nCol), static_cast(nRow), static_cast(nTab), pCell, (sal_Bool) sal_True ); } } void OP_Formula123( SvStream& r, sal_uInt16 n ) { sal_uInt8 nCol,nTab; sal_uInt16 nRow; r >> nRow >> nTab >> nCol; r.SeekRel( 8 ); // Result- jump over const ScTokenArray* pErg; sal_Int32 nBytesLeft = (n > 12) ? n - 12 : 0; ScAddress aAddress( nCol, nRow, nTab ); LotusToSc aConv( r, pLotusRoot->eCharsetQ, sal_True ); aConv.Reset( aAddress ); aConv.Convert( pErg, nBytesLeft ); if (ValidColRow( static_cast(nCol), nRow) && nTab < pDoc->GetMaxTableNumber()) { ScFormulaCell* pCell = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg ); pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE ); pDoc->PutCell( static_cast(nCol), static_cast(nRow), static_cast(nTab), pCell, (sal_Bool) sal_True ); } } void OP_IEEENumber123( SvStream& r, sal_uInt16 /*n*/ ) { sal_uInt8 nCol,nTab; sal_uInt16 nRow; double dValue; r >> nRow >> nTab >> nCol >> dValue; if (ValidColRow( static_cast(nCol), nRow) && nTab < pDoc->GetMaxTableNumber()) { ScValueCell *pCell = new ScValueCell(dValue); pDoc->PutCell( static_cast(nCol), static_cast(nRow), static_cast(nTab), pCell, (sal_Bool) sal_True ); } } void OP_Note123( SvStream& r, sal_uInt16 n) { sal_uInt8 nTab, nCol; sal_uInt16 nRow; r >> nRow >> nTab >> nCol; n -= (n > 4) ? 4 : n; sal_Char* pText = new sal_Char[n + 1]; r.Read( pText, n ); pText[ n ] = 0; String aNoteText(pText,pLotusRoot->eCharsetQ); delete [] pText; ScAddress aPos( static_cast(nCol), static_cast(nRow), static_cast(nTab) ); ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false, false ); } void OP_HorAlign123( sal_uInt8 nAlignPattern, SfxItemSet& rPatternItemSet ) { // pre: Pattern is stored in the last 3 bites of the 21st byte // post: Appropriate Horizontal Alignement 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( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) ); break; case 2: rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY ) ); break; case 3: rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY) ); break; case 4: rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) ); break; case 6: rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_BLOCK, ATTR_HOR_JUSTIFY ) ); break; default: rPatternItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_STANDARD, ATTR_HOR_JUSTIFY ) ); break; } } void OP_VerAlign123( sal_uInt8 nAlignPattern,SfxItemSet& rPatternItemSet ) { // pre: Pattern is stored in the last 3 bites of the 22nd byte // post: Appropriate Verticle Alignement 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(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) ); break; case 1: rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_TOP, ATTR_VER_JUSTIFY) ); break; case 2: rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_CENTER, ATTR_VER_JUSTIFY) ); break; case 4: rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_BOTTOM, ATTR_VER_JUSTIFY) ); break; default: rPatternItemSet.Put( SvxVerJustifyItem(SVX_VER_JUSTIFY_STANDARD, ATTR_VER_JUSTIFY) ); break; } } void OP_CreatePattern123( SvStream& r, sal_uInt16 n) { sal_uInt16 nCode,nPatternId; ScPatternAttr aPattern(pDoc->GetPool()); SfxItemSet& rItemSet = aPattern.GetItemSet(); r >> nCode; n -= (n > 2) ? 2 : n; if ( nCode == 0x0fd2 ) { r >> nPatternId; sal_uInt8 Hor_Align, Ver_Align, temp; sal_Bool bIsBold,bIsUnderLine,bIsItalics; r.SeekRel(12); // Read 17th Byte r >> 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( UNDERLINE_SINGLE, ATTR_FONT_UNDERLINE ) ); r.SeekRel(3); // Read 21st Byte r >> Hor_Align; OP_HorAlign123( Hor_Align, rItemSet ); r >> Ver_Align; OP_VerAlign123( Ver_Align, rItemSet ); aLotusPatternPool.insert( std::map::value_type( nPatternId, aPattern ) ); n -= (n > 20) ? 20 : n; } r.SeekRel(n); } void OP_SheetName123( SvStream& rStream, sal_uInt16 nLength ) { if (nLength <= 4) { rStream.SeekRel(nLength); return; } // B0 36 [sheet number (2 bytes?)] [sheet name (null terminated char array)] sal_uInt16 nDummy; rStream >> nDummy; // ignore the first 2 bytes (B0 36). rStream >> nDummy; SCTAB nSheetNum = static_cast(nDummy); pDoc->MakeTable(nSheetNum); ::std::vector sSheetName; sSheetName.reserve(nLength-4); for (sal_uInt16 i = 4; i < nLength; ++i) { sal_Char c; rStream >> c; sSheetName.push_back(c); } if (!sSheetName.empty()) { String aName(&sSheetName[0], eCharVon); pDoc->RenameTab(nSheetNum, aName); } } void OP_ApplyPatternArea123( 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 >> nOpcode >> 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 >> nData; rStream.SeekRel( nLength - 2 ); if( nLevel == 1 ) nTabCount = 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 >> nData; rStream.SeekRel( nLength - 2 ); std::map::iterator loc = aLotusPatternPool.find( nData ); // #126338# apparently, files with invalid index occur in the wild -> don't crash then if ( loc != aLotusPatternPool.end() ) for( int i = 0; i < nTabCount; i++) { pDoc->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.IsEof() ); aLotusPatternPool.clear(); }