blob: af43a6335568b2d1587589a99cc71b30a350396a [file] [log] [blame]
/**************************************************************
*
* 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_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;
}