diff options
Diffstat (limited to 'sc/source/filter/qpro/qproform.cxx')
-rw-r--r-- | sc/source/filter/qpro/qproform.cxx | 745 |
1 files changed, 745 insertions, 0 deletions
diff --git a/sc/source/filter/qpro/qproform.cxx b/sc/source/filter/qpro/qproform.cxx new file mode 100644 index 000000000000..913abb27510e --- /dev/null +++ b/sc/source/filter/qpro/qproform.cxx @@ -0,0 +1,745 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include <sal/config.h> +#include "qpro.hxx" + +#include "qproform.hxx" +#include "formel.hxx" +#include "compiler.hxx" +#include <tokstack.hxx> +#include "ftools.hxx" + +void QProToSc::ReadSRD( ScSingleRefData& rSRD, sal_Int8 nPage, sal_Int8 nCol, sal_uInt16 nRelBit ) +{ + sal_uInt16 nTmp = nRelBit & 0x1fff; + rSRD.InitAddress( ScAddress( nCol, (~nTmp + 1), 0 ) ); + if( nRelBit & 0x4000 ) + { + rSRD.nRelCol = nCol; + rSRD.SetColRel( sal_True ); + } + else + { + rSRD.nCol = nCol; + rSRD.SetColRel( sal_False ); + } + if( nRelBit & 0x2000 ) + { + rSRD.nRelRow = (~nTmp + 1); + rSRD.nRelRow = (sal_Int16)(nTmp << 3); + rSRD.nRelRow /= 8; + rSRD.SetRowRel( sal_True ); + } + else + { + rSRD.nRow = nTmp; + rSRD.SetRowRel( sal_False ); + } + if( nRelBit & 0x8000 ) + { + rSRD.nRelTab = nPage; + rSRD.SetTabRel( sal_True ); + // absolute tab needed in caller for comparison in case of DoubleRef + rSRD.nTab = aEingPos.Tab() + nPage; + } + else + { + rSRD.nTab = nPage; + rSRD.SetTabRel( sal_False ); + } + if (rSRD.nTab != aEingPos.Tab()) + rSRD.SetFlag3D( sal_True); +} + +QProToSc::QProToSc( SvStream& rStream, const ScAddress& rRefPos ) : + ConverterBase( 128 ), + maIn( rStream ) +{ + aEingPos = rRefPos; +} + +void QProToSc::DoFunc( DefTokenId eOc, sal_uInt16 nArgs, const sal_Char* pExtString ) +{ + TokenId eParam[ nBufSize ]; + sal_Int32 nCount; + TokenId nPush, nPush1; + + sal_Bool bAddIn = sal_False; + sal_Bool bNeg = sal_False; + + if( eOc == ocNoName ) + { + bAddIn = sal_True; + if( pExtString ) + { + ByteString s; + s = pExtString; + s.Insert( "QPRO_", 0 ); + nPush = aPool.Store( eOc, String( s, maIn.GetStreamCharSet() ) ); + aPool << nPush; + } + else + aPool << ocNoName; + } + + if( nArgs < nBufSize ) + { + for( nCount = 0; nCount < nArgs ; nCount++ ) + aStack >> eParam[ nCount ]; + } + else + return; + + switch( eOc ) + { + case ocIndex: + nPush = eParam[ 0 ]; + eParam[ 0 ] = eParam[ 1 ]; + eParam[ 1 ] = nPush; + IncToken( eParam[ 0 ] ); + IncToken( eParam[ 1 ] ); + break; + + case ocIRR: + nPush = eParam[ 0 ]; + eParam[ 0 ] = eParam[ 1 ]; + eParam[ 1 ] = nPush; + break; + + case ocGetYear: + nPush = aPool.Store( 1900.0 ); + aPool << ocOpen; + break; + + default: + break; + } + + if( !bAddIn ) + aPool << eOc; + + aPool << ocOpen; + + if( nArgs> 0 ) + { + sal_Int16 nNull = -1; + sal_Int16 nLast = nArgs- 1; + + if( eOc == ocZGZ ) + aPool << eParam[ 2 ] << ocSep << eParam[ 1 ] << ocSep << eParam[ 0 ]; + if( eOc == ocZinsZ ) + aPool << eParam[ 3 ] << ocSep << eParam[ 2 ] << ocSep << eParam[ 1 ] << ocSep << eParam[ 0 ]; + else + { + aPool << eParam[ nLast ]; + for( nCount = nLast - 1 ; nCount >= 0 ; nCount-- ) + { + if( nCount != nNull ) + aPool << ocSep << eParam[ nCount ]; + } + } + } + + if( eOc == ocGetYear ) + aPool << ocClose << ocSub << nPush; + else if( eOc == ocFixed ) + aPool << ocSep << ocTrue << ocOpen << ocClose; + + aPool << ocClose; + aPool >> aStack; + + if( bNeg ) + { + aPool << ocOpen << ocSub << aStack << ocClose; + aPool >> aStack; + } +} + +void QProToSc::IncToken( TokenId &rParam ) +{ + aPool << ocOpen << rParam << mnAddToken; + rParam = aPool.Store(); +} + +#define SAFEDEC_OR_RET(nRef, amt, ret) \ +do { \ + if (nRef < amt)\ + return ret; \ + nRef-=amt; \ +} while(0) + +ConvErr QProToSc::Convert( const ScTokenArray*& pArray, sal_uInt16 /*nLen*/, const FORMULA_TYPE /*eFT*/ ) +{ + sal_uInt8 nFmla[ nBufSize ], i, nArg, nArgArray[ nBufSize ]; + sal_Int8 nCol, nPage; + sal_uInt16 nInt, nIntCount = 0, nStringCount = 0, nFloatCount = 0, nDLLCount = 0, nIntArray[ nBufSize ], nArgCount = 0; + String sStringArray[ nBufSize ]; + sal_uInt16 nDummy, nDLLId, nDLLArray[ nBufSize ]; + sal_uInt16 nNote, nRef, nRelBits; + TokenId nPush; + ScComplexRefData aCRD; + ScSingleRefData aSRD; + FUNC_TYPE eType; + DefTokenId eOc; + double nFloatArray[ nBufSize ], nFloat; + const sal_Char* pExtString = 0; + + aCRD.InitFlags(); + aSRD.InitFlags(); + maIn >> nRef; + + if( nRef < nBufSize ) + { + for( i=0; i < nRef; i++) + { + maIn >> nFmla[i]; + + if( nFmla[ i ] == 0x05 ) + { + maIn >> nInt; + nIntArray[ nIntCount ] = nInt; + SAFEDEC_OR_RET(nRef, 2, ConvErrCount); + nIntCount++; + } + + if( nFmla[ i ] == 0x00 ) + { + maIn >> nFloat; + nFloatArray[ nFloatCount ] = nFloat; + SAFEDEC_OR_RET(nRef, 8, ConvErrCount); + nFloatCount++; + } + + if( nFmla[ i ] == 0x1a ) + { + maIn >> nArg >> nDummy >> nDLLId; + nArgArray[ nArgCount ] = nArg; + nDLLArray[ nDLLCount ] = nDLLId; + SAFEDEC_OR_RET(nRef, 5, ConvErrCount); + nDLLCount++; + nArgCount++; + } + if( nFmla[ i ] == 0x06 ) + { + String aTmp( ScfTools::ReadCString( maIn ), maIn.GetStreamCharSet() ); + sStringArray[ nStringCount ] = aTmp; + nStringCount++; + SAFEDEC_OR_RET(nRef, aTmp.Len() + 1, ConvErrCount); + } + } + } + else + return ConvErrCount; + + i = 0, nIntCount = 0, nFloatCount = 0, nDLLCount = 0, nArgCount = 0, nStringCount =0; + + while( i < nRef && ( nFmla[ i ] != 0x03 ) ) + { + eType = IndexToType( nFmla[ i ] ); + eOc = IndexToToken( nFmla[ i ] ); + if( eOc == ocNoName ) + pExtString = getString( nFmla[ i ] ); + + switch( eType ) + { + case FT_NotImpl: + DoFunc( ocNoName, 0, pExtString ); + break; + + case FT_FuncFix0: + DoFunc( eOc, 0, NULL ); + break; + + case FT_FuncFix1: + DoFunc( eOc, 1, NULL ); + break; + + case FT_FuncFix2: + DoFunc( eOc, 2, NULL ); + break; + + case FT_FuncFix3: + DoFunc( eOc, 3, NULL ); + break; + + case FT_FuncFix4: + DoFunc( eOc, 4, NULL ); + break; + + case FT_FuncFix5: + DoFunc( eOc, 5, NULL ); + break; + + case FT_FuncFix6: + DoFunc( eOc, 6, NULL ); + break; + + case FT_DLL:{ + eOc = IndexToDLLId( nDLLArray[ nDLLCount ] ); + sal_uInt8 nPar = nArgArray[ nArgCount ]; + DoFunc( eOc, nPar, NULL ); + nDLLCount++; + nArgCount++; + } + break; + + case FT_Cref : // Single cell reference + maIn >> nNote >> nCol >> nPage >> nRelBits; + ReadSRD( aSRD, nPage, nCol, nRelBits ); + aStack << aPool.Store( aSRD ); + break; + + case FT_Range: // Block reference + maIn >> nNote >> nCol >> nPage >> nRelBits; + ReadSRD( aCRD.Ref1, nPage, nCol, nRelBits ); + maIn >> nCol >> nPage >> nRelBits; + ReadSRD( aCRD.Ref2, nPage, nCol, nRelBits ); + // Sheet name of second corner is not displayed if identical + if (aCRD.Ref1.IsFlag3D() && aCRD.Ref1.nTab == aCRD.Ref2.nTab && + aCRD.Ref1.IsTabRel() == aCRD.Ref2.IsTabRel()) + aCRD.Ref2.SetFlag3D( sal_False); + aStack << aPool.Store( aCRD ); + break; + + case FT_FuncVar:{ // Sum of a sequence of numbers + sal_uInt8 nArgs; + i++; + nArgs = nFmla[ i ]; + DoFunc( eOc, nArgs, NULL ); + } + break; + + case FT_Op: // operators + aStack >> nPush; + aPool << aStack << eOc << nPush; + aPool >> aStack; + break; + + case FT_Braces: + aPool << ocOpen << aStack << ocClose; + aPool >> aStack; + break; + + case FT_ConstInt:{ + sal_uInt16 nVal; + nVal = nIntArray[ nIntCount ]; + aStack << aPool.Store( ( double ) nVal ); + nIntCount++; + } + break; + + case FT_ConstFloat:{ + double nVal; + nVal = nFloatArray[ nFloatCount ]; + aStack << aPool.Store( nVal ); + nFloatCount++; + } + break; + + case FT_ConstString:{ + String aLabel; + aLabel = sStringArray[ nStringCount ]; + aStack << aPool.Store( aLabel ); + nStringCount++; + } + break; + + case FT_Neg: + aPool << ocNegSub << aStack; + aPool >> aStack; + break; + + case FT_NOP: // indicates invalid opcode. + case FT_Return: // indicates end of formula + break; + } + i++; + } + pArray = aPool[ aStack.Get() ]; + return ConvOK; +} + +static const struct +{ + DefTokenId nToken; + FUNC_TYPE nType; +} aFuncMap[] = { + { ocPush, FT_ConstFloat }, + { ocPush, FT_Cref }, + { ocPush, FT_Range }, + { ocPush, FT_Return }, + { ocPush, FT_Braces }, + { ocPush, FT_ConstInt }, + { ocPush, FT_ConstString }, + { ocPush, FT_NOP }, + { ocNegSub, FT_Neg }, // 0x08 + { ocAdd, FT_Op }, + { ocSub, FT_Op }, + { ocMul, FT_Op }, + { ocDiv, FT_Op }, + { ocPow, FT_Op }, + { ocEqual, FT_Op }, + { ocNotEqual, FT_Op }, + { ocLessEqual, FT_Op }, // 0x10 + { ocGreaterEqual, FT_Op }, + { ocLess, FT_Op }, + { ocGreater, FT_Op }, + { ocAnd, FT_Op }, + { ocOr, FT_Op }, + { ocNot, FT_FuncFix1 }, + { ocPush, FT_NOP }, // Unary plus + { ocAddress, FT_FuncFix4 }, // Address of + { ocNoName, FT_NotImpl }, // Halt function + { ocNoName, FT_DLL }, // DLL function + { ocNoName, FT_NOP }, // Extended operands + { ocNoName, FT_NOP }, // Extended operands + { ocNoName, FT_NOP }, // Reserved + { ocNoName, FT_NOP }, // Reserved + { ocNotAvail, FT_FuncFix0 }, // NA + { ocNoName, FT_FuncFix0 }, // Error // 0x20 + { ocAbs, FT_FuncFix1 }, + { ocInt, FT_FuncFix1 }, + { ocSqrt, FT_FuncFix1 }, + { ocLog10, FT_FuncFix1 }, + { ocLn, FT_FuncFix1 }, + { ocPi, FT_FuncFix0 }, + { ocSin, FT_FuncFix1 }, + { ocCos, FT_FuncFix1 }, + { ocTan, FT_FuncFix1 }, + { ocArcTan2, FT_FuncFix2 }, + { ocArcTan, FT_FuncFix1 }, + { ocArcSin, FT_FuncFix1 }, + { ocArcCos, FT_FuncFix1 }, + { ocExp, FT_FuncFix1 }, + { ocMod, FT_FuncFix2 }, + { ocChose, FT_FuncVar }, // 0x30 + { ocIsNA, FT_FuncFix1 }, + { ocIsError, FT_FuncFix1 }, + { ocFalse, FT_FuncFix0 }, + { ocTrue, FT_FuncFix0 }, + { ocRandom, FT_FuncFix0 }, + { ocGetDate, FT_FuncFix3 }, + { ocGetActTime, FT_FuncFix0 }, + { ocNoName, FT_NotImpl }, // QPro Pmt + { ocNoName, FT_NotImpl }, // QPro Pv + { ocNoName, FT_NotImpl }, // QPro Fv + { ocIf, FT_FuncFix3 }, + { ocGetDay, FT_FuncFix1 }, + { ocGetMonth, FT_FuncFix1 }, + { ocGetYear, FT_FuncFix1 }, + { ocRound, FT_FuncFix2 }, + { ocGetTime, FT_FuncFix3 }, // 0x40 + { ocGetHour, FT_FuncFix1 }, + { ocGetMin, FT_FuncFix1 }, + { ocGetSec, FT_FuncFix1 }, + { ocIsValue, FT_FuncFix1 }, + { ocIsString, FT_FuncFix1 }, + { ocLen, FT_FuncFix1 }, + { ocValue, FT_FuncFix1 }, + { ocFixed, FT_FuncFix2 }, + { ocMid, FT_FuncFix3 }, + { ocChar, FT_FuncFix1 }, + { ocCode, FT_FuncFix1 }, + { ocFind, FT_FuncFix3 }, + { ocGetDateValue, FT_FuncFix1 }, + { ocGetTimeValue, FT_FuncFix1 }, + { ocNoName, FT_NotImpl }, + { ocSum, FT_FuncVar }, // 0x50 + { ocAverage, FT_FuncVar }, + { ocCount, FT_FuncVar }, + { ocMin, FT_FuncVar }, + { ocMax, FT_FuncVar }, + { ocVLookup, FT_FuncFix3 }, + { ocNPV, FT_FuncFix2 }, + { ocVar, FT_FuncVar }, + { ocNormDist, FT_FuncVar }, + { ocIRR, FT_FuncFix2 }, + { ocHLookup, FT_FuncFix3 }, + { ocDBSum, FT_FuncFix3 }, + { ocDBAverage, FT_FuncFix3 }, + { ocDBCount, FT_FuncFix3 }, + { ocDBMin, FT_FuncFix3 }, + { ocDBMax, FT_FuncFix3 }, + { ocDBVar, FT_FuncFix3 }, // 0x60 + { ocDBStdDev, FT_FuncFix3 }, + { ocNoName, FT_NotImpl }, + { ocColumns, FT_FuncFix1 }, + { ocRows, FT_FuncFix1 }, + { ocRept, FT_FuncFix2 }, + { ocUpper, FT_FuncFix1 }, + { ocLower, FT_FuncFix1 }, + { ocLeft, FT_FuncFix2 }, + { ocRight, FT_FuncFix2 }, + { ocReplace, FT_FuncFix4 }, + { ocPropper, FT_FuncFix1 }, + { ocCell, FT_FuncFix2 }, + { ocTrim, FT_FuncFix1 }, + { ocClean, FT_FuncFix1 }, + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NotImpl }, // 0x70 + { ocExact, FT_FuncFix2 }, + { ocNoName, FT_NotImpl }, // Call() + { ocIndirect, FT_FuncFix1 }, + { ocZGZ, FT_FuncFix3 }, // Interest + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NotImpl }, + { ocLIA, FT_FuncFix3 }, + { ocDIA, FT_FuncFix4 }, + { ocGDA, FT_FuncFix4 }, + { ocStDevP, FT_FuncVar }, + { ocVarP, FT_FuncVar }, + { ocDBStdDevP, FT_FuncVar }, + { ocDBVarP, FT_FuncVar }, + { ocBW, FT_FuncFix3 }, // QPro Pval + { ocRMZ, FT_FuncFix5 }, // QPro Paymt + { ocZW, FT_FuncFix3 }, // QPro Fval // 0x80 + { ocZZR, FT_FuncFix5 }, + { ocZins, FT_FuncFix5 }, + { ocZinsZ, FT_FuncFix4 }, + { ocKapz, FT_FuncFix6 }, + { ocSumProduct, FT_FuncFix2 }, + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NotImpl }, + { ocDeg, FT_FuncFix1 }, + { ocRad, FT_FuncFix1 }, + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NotImpl }, + { ocGetActDate, FT_FuncFix0 }, + { ocNPV, FT_FuncFix2 }, + { ocNoName, FT_NotImpl }, // 0x90 + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NOP }, + { ocNoName, FT_NOP }, // 147 + { ocNoName, FT_NOP }, // 148 + { ocNoName, FT_NOP }, // 149 + { ocNoName, FT_NOP }, // 150 + { ocNoName, FT_NOP }, // 151 + { ocNoName, FT_NOP }, // 152 + { ocNoName, FT_NOP }, // 153 + { ocTable, FT_FuncFix1 }, + { ocNoName, FT_NOP }, // 155 - opcodes do not represent any function. + { ocNoName, FT_NOP }, // 156 + { ocIndex, FT_FuncFix4 }, + { ocNoName, FT_NotImpl }, + { ocNoName, FT_NotImpl }, // Gives the property of the particular object + { ocNoName, FT_NotImpl }, // Dynamic Data Exchange Link // 0x100 + { ocNoName, FT_NotImpl } // gives properties of DOS menus +}; + +const int nIndexCount = sizeof( aFuncMap ) / sizeof( aFuncMap[ 0 ] ); + +DefTokenId QProToSc::IndexToToken( sal_uInt16 nIndex ) +{ + if( nIndex < nIndexCount ) + return aFuncMap[ nIndex ].nToken; + return ocNoName; +} + +FUNC_TYPE QProToSc::IndexToType( sal_uInt8 nIndex ) +{ + if( nIndex < nIndexCount ) + return aFuncMap[ nIndex ].nType; + return FT_NotImpl; +} + +DefTokenId QProToSc::IndexToDLLId( sal_uInt16 nIndex ) +{ + DefTokenId eId; + switch( nIndex ) + { + case 0x0001: + eId = ocAveDev; + break; + + case 0x0024: + eId = ocGCD; + break; + + case 0x0025: + eId = ocLCM; + break; + + case 0x0027: + eId = ocCeil; + break; + + case 0x0028: + eId = ocEven; + break; + + case 0x0022: + eId = ocFact; + break; + + case 0x002a: + eId = ocFloor; + break; + + case 0x002d: + eId = ocOdd; + break; + + case 0x0006: + eId = ocBetaDist; + break; + + case 0x0008: + eId = ocBetaInv; + break; + + case 0x0010: + eId = ocCovar; + break; + + case 0x000b: + eId = ocChiInv; + break; + + case 0x003d: + eId = ocLaufz; + break; + + case 0x0019: + eId = ocFInv; + break; + + case 0x001a: + eId = ocFisher; + break; + + case 0x001b: + eId = ocFisherInv; + break; + + case 0x0030: + eId = ocMedian; + break; + + default: + eId = ocNoName; + break; + } + return eId; +} + +const sal_Char* QProToSc::getString( sal_uInt8 nIndex ) +{ + const sal_Char* pExtString = 0; + switch( nIndex ) + { + case 57: + pExtString = "Pv"; + break; + + case 58: + pExtString = "Fv"; + break; + + case 98: + pExtString = "Index2D"; + break; + + case 111: + pExtString = "S"; + break; + + case 112: + pExtString = "N"; + break; + + case 114: + pExtString = "CALL"; + break; + + case 117: + pExtString = "TERM"; + break; + + case 118: + pExtString = "CTERM"; + break; + + case 134: + pExtString = "MEMAVAIL"; + break; + + case 135: + pExtString = "MEMEMSAVAIL"; + break; + + case 136: + pExtString = "FILEEXISTS"; + break; + + case 137: + pExtString = "CURVALUE"; + break; + + case 140: + pExtString = "HEX"; + break; + + case 141: + pExtString = "NUM"; + break; + + case 145: + pExtString = "VERSION"; + break; + + case 157: + pExtString = "INDEX3D"; + break; + + case 158: + pExtString = "CELLINDEX3D"; + break; + + case 159: + pExtString = "PROPERTY"; + break; + + case 160: + pExtString = "DDE"; + break; + + case 161: + pExtString = "COMMAND"; + break; + + default: + pExtString = NULL; + break; + } + return pExtString; +} |