Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

sheet.cpp

Go to the documentation of this file.
00001 /*
00002                =.            This file is part of the Opie Project
00003              .=l.            Copyright (C) 2004 Opie Developer Team <opie-devel@handhelds.org>
00004            .>+-=
00005  _;:,     .>    :=|.         This program is free software; you can
00006 .> <`_,   >  .   <=          redistribute it and/or  modify it under
00007 :`=1 )Y*s>-.--   :           the terms of the GNU General Public
00008 .="- .-=="i,     .._         License as published by the Free Software
00009  - .   .-<_>     .<>         Foundation; either version 2 of the License,
00010      ._= =}       :          or (at your option) any later version.
00011     .%`+i>       _;_.
00012     .i_,=:_.      -<s.       This program is distributed in the hope that
00013      +  .  -:.       =       it will be useful,  but WITHOUT ANY WARRANTY;
00014     : ..    .:,     . . .    without even the implied warranty of
00015     =_        +     =;=|`    MERCHANTABILITY or FITNESS FOR A
00016   _.=:.       :    :=>`:     PARTICULAR PURPOSE. See the GNU
00017 ..}^=.=       =       ;      Library General Public License for more
00018 ++=   -.     .`     .:       details.
00019  :     =  ...= . :.=-
00020  -.   .:....=;==+<;          You should have received a copy of the GNU
00021   -_. . .   )=.  =           Library General Public License along with
00022     --        :-=`           this library; see the file COPYING.LIB.
00023                              If not, write to the Free Software Foundation,
00024                              Inc., 59 Temple Place - Suite 330,
00025                              Boston, MA 02111-1307, USA.
00026 
00027 */
00028 
00029 /*
00030  * Opie Sheet (formerly Sheet/Qt)
00031  * by Serdar Ozler <sozler@sitebest.com>
00032  */
00033 
00034 #include "sheet.h"
00035 
00036 /* QT */
00037 #include <qmessagebox.h>
00038 
00039 /* STD */
00040 #include <math.h>
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <time.h>
00044 
00045 #define DEFAULT_COL_WIDTH 50
00046 
00047 Sheet::Sheet(int numRows, int numCols, QWidget *parent)
00048         :QTable(numRows, numCols, parent)
00049 {
00050     defaultBorders.right=defaultBorders.bottom=QPen(Qt::gray, 1, Qt::SolidLine);
00051     defaultCellData.data="";
00052     defaultCellData.background=QBrush(Qt::white, Qt::SolidPattern);
00053     defaultCellData.alignment=(Qt::AlignmentFlags)(Qt::AlignLeft | Qt::AlignTop);
00054     defaultCellData.fontColor=Qt::black;
00055     defaultCellData.font=font();
00056     defaultCellData.borders=defaultBorders;
00057 
00058     clicksLocked=FALSE;
00059     selectionNo=-1;
00060     setSelectionMode(QTable::Single);
00061 
00062     sheetData.setAutoDelete(TRUE);
00063     clipboardData.setAutoDelete(TRUE);
00064     for (int i=0; i<numCols; ++i)
00065         horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH);
00066 
00067 
00068     connect(this, SIGNAL(currentChanged(int,int)), this, SLOT(slotCellSelected(int,int)));
00069     connect(this, SIGNAL(valueChanged(int,int)), this, SLOT(slotCellChanged(int,int)));
00070 }
00071 
00072 Sheet::~Sheet()
00073 {}
00074 
00075 typeCellData *Sheet::findCellData(int row, int col)
00076 {
00077     typeCellData *tempCellData;
00078     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
00079     {
00080         if (tempCellData->row==row && tempCellData->col==col) return tempCellData;
00081     }
00082     return NULL;
00083 }
00084 
00085 void Sheet::slotCellSelected(int row, int col)
00086 {
00087     typeCellData *cellData=findCellData(row, col);
00088     if (cellData)
00089     {
00090         emit currentDataChanged(cellData->data);
00091     }
00092     else
00093         emit currentDataChanged("");
00094 }
00095 
00096 typeCellData *Sheet::createCellData(int row, int col)
00097 {
00098     if (row<0 || col<0) return NULL;
00099     typeCellData *cellData=new typeCellData;
00100     cellData->row=row;
00101     cellData->col=col;
00102     cellData->data=defaultCellData.data;
00103     cellData->borders=defaultCellData.borders;
00104     cellData->alignment=defaultCellData.alignment;
00105     cellData->font=defaultCellData.font;
00106     cellData->fontColor=defaultCellData.fontColor;
00107     cellData->background=defaultCellData.background;
00108     sheetData.append(cellData);
00109     return cellData;
00110 }
00111 
00112 void Sheet::slotCellChanged(int row, int col)
00113 {
00114     typeCellData *cellData=findCellData(row, col);
00115     if (!cellData) cellData=createCellData(row, col);
00116     if (cellData) cellData->data=text(row, col);
00117     for (cellData=sheetData.first(); cellData; cellData=sheetData.next())
00118     {
00119         // modified by Toussis Manolis koppermind@panafonet.gr
00120         // the parser was crashing if there were no closed parenthesis.
00121         int w1,ii=0;
00122         for(w1=0;w1<=(int)text(row, col).length();w1++)
00123         {
00124             if(text(row,col)[w1]=='(') ii++;
00125             if(text(row,col)[w1]==')') ii--;
00126         };
00127         if(ii==0) setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data));
00128         //end of modification
00129         // old was plain:
00130         //setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data));
00131     };
00132     emit sheetModified();
00133 }
00134 
00135 
00136 void Sheet::ReCalc(void)
00137 {
00138     typeCellData* cellData;
00139     for (cellData=sheetData.first(); cellData; cellData=sheetData.next())
00140     {
00141         //printf("cellchanged:%d, %d\r\n",cellData->row,cellData->col);
00142 
00143         slotCellChanged(cellData->row,cellData->col);
00144     };
00145 };
00146 
00147 
00148 
00149 
00150 void Sheet::swapCells(int row1, int col1, int row2, int col2)
00151 {
00152     typeCellData *cellData1=findCellData(row1, col1), *cellData2=findCellData(row2, col2);
00153     if (!cellData1) cellData1=createCellData(row1, col1);
00154     if (!cellData2) cellData2=createCellData(row2, col2);
00155     if (cellData1 && cellData2)
00156     {
00157         QString tempData(cellData1->data);
00158         cellData1->data=cellData2->data;
00159         cellData2->data=tempData;
00160         setText(cellData1->row, cellData1->col, dataParser(findCellName(cellData1->row, cellData1->col), cellData1->data));
00161         setText(cellData2->row, cellData2->col, dataParser(findCellName(cellData2->row, cellData2->col), cellData2->data));
00162         emit sheetModified();
00163     }
00164 }
00165 
00166 QString Sheet::getParameter(const QString &parameters, int paramNo, bool giveError, const QString funcName)
00167 {
00168     QString params(parameters);
00169     int position;
00170     for (int i=0; i<paramNo; ++i)
00171     {
00172         position=params.find(',');
00173         if (position<0)
00174         {
00175             if (giveError) QMessageBox::critical(this, tr("Error"), tr("Too few arguments to function '"+funcName+'\''));
00176             //printf("params:%s\r\n",parameters.ascii());
00177             return QString(NULL);
00178         }
00179         params=params.mid(position+1);
00180     }
00181     position=params.find(',');
00182     if (position<0) return params;
00183     return params.left(position);
00184 }
00185 
00186 bool Sheet::findRange(const QString &variable1, const QString &variable2, int *row1, int *col1, int *row2, int *col2)
00187 {
00188     int row, col;
00189     if (!findRowColumn(variable1, row1, col1, FALSE) || !findRowColumn(variable2, row2, col2, FALSE)) return FALSE;
00190     if (*row1>*row2)
00191     {
00192         row=*row1;
00193         *row1=*row2;
00194         *row2=row;
00195     }
00196     if (*col1>*col2)
00197     {
00198         col=*col1;
00199         *col1=*col2;
00200         *col2=col;
00201     }
00202     return TRUE;
00203 }
00204 
00205 bool Sheet::findRowColumn(const QString &variable, int *row, int *col, bool giveError)
00206 {
00207     int position=variable.find(QRegExp("\\d"));
00208     if (position<1)
00209     {
00210         if (giveError) QMessageBox::critical(this, tr("Error"), tr("Invalid variable: '"+variable+'\''));
00211         return FALSE;
00212     }
00213     *row=variable.mid(position).toInt()-1;
00214     *col=getHeaderColumn(variable.left(position))-1;
00215     return TRUE;
00216 }
00217 
00218 QString Sheet::calculateVariable(const QString &variable)
00219 {
00220     bool ok;
00221     printf("calculateVariable=%s,len=%d\r\n",variable.ascii(),variable.length());
00222     if(variable.left(1)=="\"") return QString(variable.mid(1,variable.length()-2));
00223     double tempResult=variable.toDouble(&ok);
00224     if (ok)
00225     {
00226         if(tempResult!=0.0)
00227         {
00228             return QString::number(tempResult);
00229         }
00230         else
00231         {
00232             if(variable!="0" || variable!="0.0") return QString(variable); // hereis a string variable
00233             return QString::number(tempResult);
00234         };
00235     };
00236 
00237     int row, col;
00238     if(findRowColumn(variable, &row, &col, FALSE)) return dataParser(variable, text(row,col));
00239     //return (findRowColumn(variable, &row, &col, TRUE) ? dataParser(variable, text(row, col)) : 0);
00240     return QString(variable);
00241 }
00242 
00243 double Sheet::BesselI0(double x)
00244 {
00245     //Returns the modi ed Bessel function I0(x) for any real x.
00246     double ax,ans;
00247     double y;
00248     if ((ax=fabs(x)) < 3.75)
00249     {
00250         y=x/3.75;
00251         y*=y;
00252         ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492 +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
00253     }
00254     else
00255     {
00256         y=3.75/ax;
00257         ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1 +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 +y*0.392377e-2))))))));
00258     }
00259     return ans;
00260 };
00261 
00262 double Sheet::BesselI1(double x)
00263 {
00264     double ax,ans;
00265     double y;
00266     if ((ax=fabs(x)) < 3.75)
00267     {
00268         y=x/3.75;
00269         y*=y;
00270         ans=ax*(0.5+y*(0.87890594+y*(0.51498869+y*(0.15084934 +y*(0.2658733e-1+y*(0.301532e-2+y*0.32411e-3))))));
00271     }
00272     else
00273     {
00274         y=3.75/ax;
00275         ans=0.2282967e-1+y*(-0.2895312e-1+y*(0.1787654e-1 -y*0.420059e-2)); ans=0.39894228+y*(-0.3988024e-1+y*(-0.362018e-2 +y*(0.163801e-2+y*(-0.1031555e-1+y*ans))));
00276         ans *= (exp(ax)/sqrt(ax));
00277     }
00278     return x < 0.0 ? -ans : ans;
00279 };
00280 
00281 double Sheet::BesselI(int n, double x)
00282 {
00283     double ACC=40.0;
00284     double BIGNO=1.0e10;
00285     double BIGNI=1.0e-10;
00286     int j;
00287     double bi,bim,bip,tox,ans;
00288     if (n < 2) return 0.0;
00289     if (x == 0.0) return 0.0; else
00290     {
00291         tox=2.0/fabs(x);
00292         bip=ans=0.0;
00293         bi=1.0;
00294         for (j=2*(n+(int) sqrt(ACC*n));j>0;j--)
00295         {
00296             bim=bip+j*tox*bi;
00297             bip=bi;
00298             bi=bim;
00299             if (fabs(bi) > BIGNO)
00300             {
00301                 ans *= BIGNI;
00302                 bi *= BIGNI;
00303                 bip *= BIGNI;
00304             }
00305             if (j == n) ans=bip;
00306         }
00307         ans *= BesselI0(x)/bi;
00308         return x < 0.0 && (n & 1) ? -ans : ans;
00309     }
00310 };
00311 
00312 double Sheet::BesselK0(double x)
00313 {
00314     double y,ans;
00315     if (x <= 2.0)
00316     {
00317         y=x*x/4.0;
00318         ans=(-log(x/2.0)*BesselI0(x))+(-0.57721566+y*(0.42278420 +y*(0.23069756+y*(0.3488590e-1+y*(0.262698e-2 +y*(0.10750e-3+y*0.74e-5))))));
00319     }
00320     else
00321     {
00322         y=2.0/x;
00323         ans=(exp(-x)/sqrt(x))*(1.25331414+y*(-0.7832358e-1 +y*(0.2189568e-1+y*(-0.1062446e-1+y*(0.587872e-2 +y*(-0.251540e-2+y*0.53208e-3))))));
00324     }
00325     return ans;
00326 };
00327 
00328 double Sheet::BesselK1(double x)
00329 {
00330     double y,ans;
00331     if (x <= 2.0)
00332     {
00333         y=x*x/4.0;
00334         ans=(log(x/2.0)*BesselI1(x))+(1.0/x)*(1.0+y*(0.15443144 +y*(-0.67278579+y*(-0.18156897+y*(-0.1919402e-1 +y*(-0.110404e-2+y*(-0.4686e-4)))))));
00335     }
00336     else
00337     {
00338         y=2.0/x;
00339         ans=(exp(-x)/sqrt(x))*(1.25331414+y*(0.23498619 +y*(-0.3655620e-1+y*(0.1504268e-1+y*(-0.780353e-2 +y*(0.325614e-2+y*(-0.68245e-3)))))));
00340     }
00341     return ans;
00342 };
00343 
00344 double Sheet::BesselK(int n, double x)
00345 {
00346     int j;
00347     double bk,bkm,bkp,tox;
00348     if (n < 2) return 0.0;
00349     tox=2.0/x;
00350     bkm=BesselK0(x);
00351     bk=BesselK1(x);
00352     for (j=1;j<n;j++)
00353     {
00354         bkp=bkm+j*tox*bk;
00355         bkm=bk;
00356         bk=bkp;
00357     }
00358     return bk;
00359 };
00360 
00361 double Sheet::BesselJ0(double x)
00362 {
00363     double ax,z;
00364     double xx,y,ans,ans1,ans2;
00365     if ((ax=fabs(x)) < 8.0)
00366     {
00367         y=x*x;
00368         ans1=57568490574.0+y*(-13362590354.0+y*(651619640.7 +y*(-11214424.18+y*(77392.33017+y*(-184.9052456)))));
00369         ans2=57568490411.0+y*(1029532985.0+y*(9494680.718 +y*(59272.64853+y*(267.8532712+y*1.0))));
00370         ans=ans1/ans2;
00371     }
00372     else
00373     {
00374         z=8.0/ax;
00375         y=z*z;
00376         xx=ax-0.785398164;
00377         ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4 +y*(-0.2073370639e-5+y*0.2093887211e-6)));
00378         ans2 = -0.1562499995e-1+y*(0.1430488765e-3 +y*(-0.6911147651e-5+y*(0.7621095161e-6 -y*0.934935152e-7)));
00379         ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2);
00380     }
00381     return ans;
00382 };
00383 
00384 double Sheet::BesselY0(double x)
00385 {
00386     double z;
00387     double xx,y,ans,ans1,ans2;
00388     if (x < 8.0)
00389     {
00390         y=x*x;
00391         ans1 = -2957821389.0+y*(7062834065.0+y*(-512359803.6 +y*(10879881.29+y*(-86327.92757+y*228.4622733))));
00392         ans2=40076544269.0+y*(745249964.8+y*(7189466.438 +y*(47447.26470+y*(226.1030244+y*1.0))));
00393         ans=(ans1/ans2)+0.636619772*BesselJ0(x)*log(x);
00394     }
00395     else
00396     {
00397         z=8.0/x;
00398         y=z*z;
00399         xx=x-0.785398164;
00400         ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4 +y*(-0.2073370639e-5+y*0.2093887211e-6)));
00401         ans2 = -0.1562499995e-1+y*(0.1430488765e-3 +y*(-0.6911147651e-5+y*(0.7621095161e-6 +y*(-0.934945152e-7))));
00402         ans=sqrt(0.636619772/x)*(sin(xx)*ans1+z*cos(xx)*ans2);
00403     }
00404     return ans;
00405 };
00406 
00407 double Sheet::BesselJ1(double x)
00408 {
00409     double ax,z;
00410     double xx,y,ans,ans1,ans2;
00411     if ((ax=fabs(x)) < 8.0)
00412     {
00413         y=x*x;
00414         ans1=x*(72362614232.0+y*(-7895059235.0+y*(242396853.1 +y*(-2972611.439+y*(15704.48260+y*(-30.16036606))))));
00415         ans2=144725228442.0+y*(2300535178.0+y*(18583304.74 +y*(99447.43394+y*(376.9991397+y*1.0))));
00416         ans=ans1/ans2;
00417     }
00418     else
00419     {
00420         z=8.0/ax; y=z*z; xx=ax-2.356194491;
00421         ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4 +y*(0.2457520174e-5+y*(-0.240337019e-6))));
00422         ans2=0.04687499995+y*(-0.2002690873e-3 +y*(0.8449199096e-5+y*(-0.88228987e-6 +y*0.105787412e-6)));
00423         ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2);
00424         if (x < 0.0) ans = -ans;
00425     }
00426     return ans;
00427 };
00428 
00429 double Sheet::BesselY1(double x)
00430 {
00431     double z;
00432     double xx,y,ans,ans1,ans2;
00433     if (x < 8.0)
00434     {
00435         y=x*x;
00436         ans1=x*(-0.4900604943e13+y*(0.1275274390e13 +y*(-0.5153438139e11+y*(0.7349264551e9 +y*(-0.4237922726e7+y*0.8511937935e4)))));
00437         ans2=0.2499580570e14+y*(0.4244419664e12 +y*(0.3733650367e10+y*(0.2245904002e8 +y*(0.1020426050e6+y*(0.3549632885e3+y)))));
00438         ans=(ans1/ans2)+0.636619772*(BesselJ1(x)*log(x)-1.0/x);
00439     }
00440     else
00441     {
00442         z=8.0/x;
00443         y=z*z;
00444         xx=x-2.356194491;
00445         ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4 +y*(0.2457520174e-5+y*(-0.240337019e-6))));
00446         ans2=0.04687499995+y*(-0.2002690873e-3 +y*(0.8449199096e-5+y*(-0.88228987e-6 +y*0.105787412e-6)));
00447         ans=sqrt(0.636619772/x)*(sin(xx)*ans1+z*cos(xx)*ans2);
00448     }
00449     return ans;
00450 };
00451 
00452 double Sheet::BesselY(int n, double x)
00453 {
00454     int j;
00455     double by,bym,byp,tox;
00456     if (n < 2) return 0.0;
00457     tox=2.0/x;
00458     by=BesselY1(x);
00459     bym=BesselY0(x);
00460     for (j=1;j<n;j++)
00461     {
00462         byp=j*tox*by-bym;
00463         bym=by;
00464         by=byp;
00465     }
00466     return by;
00467 };
00468 
00469 double Sheet::BesselJ(int n, double x)
00470 {
00471     double ACC=40.0;
00472     double BIGNO=1.0e10;
00473     double BIGNI=1.0e-10;
00474     int j,jsum,m;
00475     double ax,bj,bjm,bjp,sum,tox,ans;
00476     if (n < 2) return 0.0;
00477     ax=fabs(x);
00478     if (ax == 0.0) return 0.0;
00479     else if (ax > (double) n)
00480     {
00481         tox=2.0/ax;
00482         bjm=BesselJ0(ax);
00483         bj=BesselJ1(ax);
00484         for (j=1;j<n;j++)
00485         {
00486             bjp=j*tox*bj-bjm;
00487             bjm=bj;
00488             bj=bjp;
00489         }
00490         ans=bj;
00491     }
00492     else
00493     {
00494         tox=2.0/ax;
00495         m=2*((n+(int) sqrt(ACC*n))/2);
00496         jsum=0;
00497         bjp=ans=sum=0.0;
00498         bj=1.0;
00499         for (j=m;j>0;j--)
00500         {
00501             bjm=j*tox*bj-bjp;
00502             bjp=bj;
00503             bj=bjm;
00504             if (fabs(bj) > BIGNO)
00505             {
00506                 bj *= BIGNI;
00507                 bjp *= BIGNI;
00508                 ans *= BIGNI;
00509                 sum *= BIGNI;
00510             }
00511             if (jsum) sum += bj;
00512             jsum=!jsum;
00513             if (j == n) ans=bjp;
00514         }
00515         sum=2.0*sum-bj;
00516         ans /= sum;
00517     }
00518     return x < 0.0 && (n & 1) ? -ans : ans;
00519 };
00520 
00521 double Sheet::GammaLn(double xx)
00522 {
00523     double x,y,tmp,ser;
00524     static double cof[6]={76.18009172947146,-86.50532032941677, 24.01409824083091,-1.231739572450155, 0.1208650973866179e-2,-0.5395239384953e-5};
00525     int j;
00526     y=x=xx;
00527     tmp=x+5.5;
00528     tmp -= (x+0.5)*log(tmp);
00529     ser=1.000000000190015;
00530     for (j=0;j<=5;j++) ser += cof[j]/++y;
00531     return -tmp+log(2.5066282746310005*ser/x);
00532 };
00533 
00534 double Sheet::Factorial(double n)
00535 {
00536     if (n < 0) return 0.0;
00537     if (n > 100) return 0.0;
00538     return exp(GammaLn(n+1.0));
00539 };
00540 
00541 double Sheet::GammaP(double a, double x)
00542 {
00543     // returns GammaP(a,x)
00544     //void gcf(float *gammcf, float a, float x, float *gln);
00545     //void gser(float *gamser, float a, float x, float *gln);
00546     double gamser,gammcf,gln;
00547     if (x < 0.0 || a <= 0.0) return 0.0;//error
00548     if (x < (a+1.0))
00549     {
00550         GammaSeries(&gamser,a,x,&gln);
00551         return gamser;
00552     }
00553     else
00554     {
00555         GammaContinuedFraction(&gammcf,a,x,&gln);
00556         return 1.0-gammcf;
00557     }
00558 };
00559 
00560 double Sheet::GammaQ(double a,double x)
00561 {
00562     //returns GammaQ(a,x)=1.0 - GammaP(a,x);
00563     return (1.0-GammaP(a,x));
00564 };
00565 
00566 
00567 void Sheet::GammaSeries(double *gamser, double a, double x, double *gln)
00568 {
00569     double EPS=3.0e-7;
00570     int ITMAX=100;
00571     int n;
00572     double sum,del,ap;
00573     *gln=GammaLn(a);
00574     if (x <= 0.0)
00575     {
00576         if (x < 0.0) return;//error
00577         *gamser=0.0;
00578         return;
00579     }
00580     else
00581     {
00582         ap=a;
00583         del=sum=1.0/a;
00584         for (n=1;n<=ITMAX;n++)
00585         {
00586             ++ap;
00587             del *= x/ap;
00588             sum += del;
00589             if (fabs(del) < fabs(sum)*EPS)
00590             {
00591                 *gamser=sum*exp(-x+a*log(x)-(*gln));
00592                 return;
00593             }
00594         }
00595         return;
00596         return;
00597     }
00598 };
00599 
00600 
00601 void Sheet::GammaContinuedFraction(double *gammcf, double a, double x, double *gln)
00602 {
00603     double EPS=3.0e-7;
00604     double FPMIN=1.0e-30;
00605     int ITMAX=100;
00606     int i;
00607     double an,b,c,d,del,h;
00608     *gln=GammaLn(a);
00609     b=x+1.0-a;
00610     c=1.0/FPMIN;
00611     d=1.0/b; h=d;
00612     for (i=1;i<=ITMAX;i++)
00613     {
00614         an = -i*(i-a);
00615         b += 2.0; d=an*d+b;
00616         if (fabs(d) < FPMIN) d=FPMIN;
00617         c=b+an/c;
00618         if (fabs(c) < FPMIN) c=FPMIN;
00619         d=1.0/d; del=d*c; h *= del;
00620         if (fabs(del-1.0) < EPS) break;
00621     }
00622     if (i > ITMAX) return;
00623     *gammcf=exp(-x+a*log(x)-(*gln))*h;
00624 };
00625 
00626 double Sheet::ErrorFunction(double x)
00627 {
00628     return x < 0.0 ? -GammaP(0.5,x*x) : GammaP(0.5,x*x);
00629 };
00630 
00631 double Sheet::ErrorFunctionComplementary(double x)
00632 {
00633     return x < 0.0 ? 1.0+GammaP(0.5,x*x) : GammaQ(0.5,x*x);
00634 };
00635 
00636 double Sheet::Beta(double z, double w)
00637 {
00638     return exp(GammaLn(z)+GammaLn(w)-GammaLn(z+w));
00639 };
00640 
00641 
00642 double Sheet::BetaContinuedFraction(double a, double b, double x)
00643 {
00644     int MAXIT=100;
00645     double EPS=3.0e-7;
00646     double FPMIN=1.0e-30;
00647     int m,m2;
00648     double aa,c,d,del,h,qab,qam,qap;
00649     qab=a+b;
00650     qap=a+1.0; qam=a-1.0; c=1.0;
00651     d=1.0-qab*x/qap;
00652     if (fabs(d) < FPMIN) d=FPMIN;
00653     d=1.0/d; h=d;
00654     for (m=1;m<=MAXIT;m++)
00655     {
00656         m2=2*m; aa=m*(b-m)*x/((qam+m2)*(a+m2));
00657         d=1.0+aa*d;
00658         if (fabs(d) < FPMIN) d=FPMIN;
00659         c=1.0+aa/c;
00660         if (fabs(c) < FPMIN) c=FPMIN;
00661         d=1.0/d; h *= d*c;
00662         aa = -(a+m)*(qab+m)*x/((a+m2)*(qap+m2)); d=1.0+aa*d;
00663         if (fabs(d) < FPMIN) d=FPMIN;
00664         c=1.0+aa/c;
00665         if (fabs(c) < FPMIN) c=FPMIN; d=1.0/d;
00666         del=d*c; h *= del;
00667         if (fabs(del-1.0) < EPS) break;
00668     }
00669     if (m > MAXIT) return 0.0;
00670     return h;
00671 };
00672 
00673 double Sheet::BetaIncomplete(double a, double b, double x)
00674 {
00675     double bt;
00676     if (x < 0.0 || x > 1.0) return 0.0;
00677     if (x == 0.0 || x == 1.0) bt=0.0; else
00678         bt=exp(GammaLn(a+b)-GammaLn(a)-GammaLn(b)+a*log(x)+b*log(1.0-x));
00679     if (x < (a+1.0)/(a+b+2.0)) return bt*BetaContinuedFraction(a,b,x)/a; else
00680         return 1.0-bt*BetaContinuedFraction(b,a,1.0-x)/b;
00681 };
00682 
00683 
00684 
00685 double Sheet::functionSum(const QString &param1, const QString &param2)
00686 {
00687     int row1, col1, row2, col2, row, col;
00688     double result=0, tempResult;
00689     bool ok;
00690     if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00691     {
00692         for (row=row1; row<=row2; ++row)
00693             for (col=col1; col<=col2; ++col)
00694             {
00695                 tempResult=text(row, col).toDouble(&ok);
00696                 if (ok) result+=tempResult;
00697             }
00698         return result;
00699     }
00700     else
00701     {
00702         double d1=0,d2=0;
00703         d1=calculateVariable(param1).toDouble(&ok);
00704         d2=calculateVariable(param2).toDouble(&ok);
00705         return(d1+d2);
00706     };
00707     return 0;
00708 }
00709 
00710 QString Sheet::functionIndex(const QString &param1, const QString &param2, int indx)
00711 {
00712     int row1, col1, row2, col2, row, col;
00713     if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00714     int ii=1;
00715     for (col=col1; col<=col2; ++col)
00716         for (row=row1; row<=row2; ++row)
00717         {
00718             if(ii==indx) return text(row,col);
00719             ii++;
00720         }
00721     return QString("");
00722 }
00723 
00724 
00725 
00726 double Sheet::functionVariancePopulation(const QString &param1, const QString &param2)
00727 {
00728     int row1, col1, row2, col2, row, col;
00729     if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00730     double avg1=functionAvg(param1,param2);
00731     double result=0, tempResult;
00732     int count1=0;
00733     bool ok;
00734     for (row=row1; row<=row2; ++row)
00735         for (col=col1; col<=col2; ++col)
00736         {
00737             tempResult=text(row, col).toDouble(&ok);
00738             if (ok) { result=result + (tempResult - avg1)*(tempResult - avg1); count1++;};
00739         }
00740     if(count1>0) result=result/double(count1); else result=0.0;
00741     return result;
00742 };
00743 
00744 double Sheet::functionVariance(const QString &param1, const QString &param2)
00745 {
00746     int row1, col1, row2, col2, row, col;
00747     if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00748     double avg1=functionAvg(param1,param2);
00749     double result=0, tempResult;
00750     int count1=0;
00751     bool ok;
00752     for (row=row1; row<=row2; ++row)
00753         for (col=col1; col<=col2; ++col)
00754         {
00755             tempResult=text(row, col).toDouble(&ok);
00756             if (ok) { result=result + (tempResult - avg1)*(tempResult - avg1); count1++;};
00757         }
00758     if(count1>1) result=result/double(count1-1); else result=0.0;
00759     return result;
00760 };
00761 
00762 double Sheet::functionSkew(const QString &param1, const QString &param2)
00763 {
00764     int row1, col1, row2, col2, row, col;
00765     if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00766     double avg1=functionAvg(param1,param2);
00767     double var1=sqrt(functionVariancePopulation(param1,param2));
00768     if(var1==0.0) return 0.0;
00769     double result=0, tempResult;
00770     int count1=0;
00771     bool ok;
00772     for (row=row1; row<=row2; ++row)
00773         for (col=col1; col<=col2; ++col)
00774         {
00775             tempResult=text(row, col).toDouble(&ok);
00776             if (ok)
00777             {
00778                 result=result + (tempResult - avg1)*(tempResult - avg1)*(tempResult - avg1)/(var1*var1*var1);
00779                 count1++;
00780             };
00781         }
00782     if(count1>0) result=result/double(count1); else result=0.0;
00783     return result;
00784 };
00785 
00786 double Sheet::functionKurt(const QString &param1, const QString &param2)
00787 {
00788     int row1, col1, row2, col2, row, col;
00789     if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00790     double avg1=functionAvg(param1,param2);
00791     double var1=sqrt(functionVariancePopulation(param1,param2));
00792     if(var1==0.0) return 0.0;
00793     double result=0, tempResult;
00794     int count1=0;
00795     bool ok;
00796     for (row=row1; row<=row2; ++row)
00797         for (col=col1; col<=col2; ++col)
00798         {
00799             tempResult=text(row, col).toDouble(&ok);
00800             if (ok)
00801             {
00802                 result=result + (tempResult - avg1)*(tempResult - avg1)*
00803                        (tempResult - avg1)*(tempResult - avg1)/(var1*var1*var1*var1);
00804                 count1++;
00805             };
00806         }
00807     if(count1>0) result=result/double(count1)-3.0; else result=0.0;
00808     return result;
00809 };
00810 
00811 
00812 
00813 double Sheet::functionSumSQ(const QString &param1, const QString &param2)
00814 {
00815     int row1, col1, row2, col2, row, col;
00816     double result=0, tempResult;
00817     bool ok;
00818     if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00819     {
00820         for (row=row1; row<=row2; ++row)
00821             for (col=col1; col<=col2; ++col)
00822             {
00823                 tempResult=text(row, col).toDouble(&ok);
00824                 if (ok) result+=tempResult*tempResult;
00825             }
00826         return result;
00827     }
00828     else
00829     {
00830         double d1=0,d2=0;
00831         d1=calculateVariable(param1).toDouble(&ok);
00832         d2=calculateVariable(param2).toDouble(&ok);
00833         return(d1*d1+d2*d2);
00834     };
00835     return 0;
00836 }
00837 
00838 
00839 
00840 double Sheet::functionMin(const QString &param1, const QString &param2)
00841 {
00842     int row1, col1, row2, col2, row, col;
00843     double min=0, tempMin;
00844     bool ok, init=FALSE;
00845     if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00846     {
00847         for (row=row1; row<=row2; ++row)
00848             for (col=col1; col<=col2; ++col)
00849             {
00850                 tempMin=text(row, col).toDouble(&ok);
00851                 if (ok && (!init || tempMin<min))
00852                 {
00853                     min=tempMin;
00854                     init=TRUE;
00855                 }
00856             }
00857         return min;
00858     }
00859     else
00860     {
00861         double d1=0,d2=0;
00862         d1=calculateVariable(param1).toDouble(&ok);
00863         d2=calculateVariable(param2).toDouble(&ok);
00864         if(d1<d2) return(d1); else return(d2);
00865     };
00866     return 0;
00867 }
00868 
00869 double Sheet::functionMax(const QString &param1, const QString &param2)
00870 {
00871     int row1, col1, row2, col2, row, col;
00872     double max=0, tempMax;
00873     bool ok, init=FALSE;
00874     if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00875     {
00876         for (row=row1; row<=row2; ++row)
00877             for (col=col1; col<=col2; ++col)
00878             {
00879                 tempMax=text(row, col).toDouble(&ok);
00880                 if (ok && (!init || tempMax>max))
00881                 {
00882                     max=tempMax;
00883                     init=TRUE;
00884                 }
00885             };
00886         return max;
00887     }
00888     else
00889     {
00890         double d1=0,d2=0;
00891         d1=calculateVariable(param1).toDouble(&ok);
00892         d2=calculateVariable(param2).toDouble(&ok);
00893         if(d1>d2) return(d1); else return(d2);
00894     };
00895     return 0;
00896 }
00897 
00898 double Sheet::functionAvg(const QString &param1, const QString &param2)
00899 {
00900     double resultSum=functionSum(param1, param2), resultCount=functionCount(param1, param2);
00901     return (resultCount>0 ? resultSum/resultCount : 0);
00902 }
00903 
00904 double Sheet::functionCount(const QString &param1, const QString &param2)
00905 {
00906     int row1, col1, row2, col2, row, col;
00907     int divider=0;
00908     bool ok;
00909     if (findRange(param1, param2, &row1, &col1, &row2, &col2))
00910     {
00911         for (row=row1; row<=row2; ++row)
00912             for (col=col1; col<=col2; ++col)
00913             {
00914                 text(row, col).toDouble(&ok);
00915                 if (ok) ++divider;
00916             };
00917         return divider;
00918     }
00919     else
00920     {
00921         double d1=0,d2=0;int ii=0;
00922         d1=calculateVariable(param1).toDouble(&ok);
00923         if (ok) ii++;
00924         d2=calculateVariable(param2).toDouble(&ok);
00925         if (ok) ii++;
00926         return(ii);
00927     };
00928     return 0;
00929 }
00930 
00931 double Sheet::functionCountIf(const QString &param1, const QString &param2, const QString &param3)
00932 {
00933     int row1, col1, row2, col2, row, col;
00934     if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
00935     //same as count except check if each field is equal to param3
00936     int divider=0;
00937     QString s2;
00938     bool ok;
00939     s2=calculateVariable(param3);
00940     for (row=row1; row<=row2; ++row)
00941         for (col=col1; col<=col2; ++col)
00942         {
00943             text(row, col).toDouble(&ok);
00944             if (ok && (s2==text(row,col)) ) ++divider;
00945         }
00946     return divider;
00947 }
00948 
00949 
00950 QString Sheet::calculateFunction(const QString &func, const QString &parameters, int NumOfParams)
00951 {
00952     bool ok;
00953     double val1=0.0,val2=0.0,val3=0.0;
00954     long int vali=0;
00955     int w1,w2;
00956     int row,col;
00957     QString s1,s2;
00958     //basic functions
00959     QString function;
00960     function=func.upper();
00961     if (function=="+")
00962     {
00963         s1=calculateVariable(getParameter(parameters, 0));
00964         s2=calculateVariable(getParameter(parameters, 1));
00965         val1=s1.toDouble(&ok)+s2.toDouble(&ok);
00966         return QString::number(val1);
00967 
00968     };
00969     if (function=="-")
00970     {
00971         s1=calculateVariable(getParameter(parameters, 0));
00972         s2=calculateVariable(getParameter(parameters, 1));
00973         val1=s1.toDouble(&ok)-s2.toDouble(&ok);
00974         return QString::number(val1);
00975     };
00976     if (function=="*")
00977     {
00978         val1=calculateVariable(
00979                  getParameter(parameters, 0)).toDouble(&ok)
00980              *calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
00981         return QString::number(val1);
00982     };
00983     if (function=="/")
00984     {
00985         val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
00986         val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
00987         if(val2==0.0) return QString("Err101");
00988         val1=val1/val2;
00989         return QString::number(val1);
00990     };
00991     if (function==">")
00992     {
00993         val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
00994         val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
00995         if(val1>val2) return QString::number(1); else return QString::number(0);
00996     };
00997     if (function=="<")
00998     {
00999         val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01000         val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01001         if(val1<val2) return QString::number(1); else return QString::number(0);
01002     };
01003     if (function==">=")
01004     {
01005         val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01006         val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01007         if(val1>=val2) return QString::number(1); else return QString::number(0);
01008     };
01009     if (function=="<=")
01010     {
01011         val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01012         val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01013         if(val1<=val2) return QString::number(1); else return QString::number(0);
01014     };
01015     if (function=="!=")
01016     {
01017         val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01018         val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01019         if(val1!=val2) return QString::number(1); else return QString::number(0);
01020     };
01021     if (function=="=="||function=="=")
01022     {
01023         val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
01024         val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
01025         if(val1==val2) return QString::number(1); else return QString::number(0);
01026     };
01027 
01028     //LOGICAL / INFO
01029     if (function=="ISBLANK")
01030     {
01031         if(findRowColumn(getParameter(parameters, 0), &row, &col, FALSE))
01032         {
01033             if(text(row,col).length()==0) val1=1; else val1=0;
01034         }
01035         else
01036         {
01037             if(findRowColumn(calculateVariable(getParameter(parameters, 0)), &row,&col, FALSE))
01038             {
01039                 if(text(row,col).length()==0) val1=1; else val1=0;
01040             }
01041             else
01042             {
01043                 val1=0;
01044             };
01045         };
01046         return QString::number(val1);
01047     };
01048 
01049 
01050     if (function=="ISNUMBER")
01051     {
01052         if(findRowColumn(getParameter(parameters, 0, TRUE, function), &row, &col, FALSE))
01053         {
01054             val1=text(row,col).toDouble(&ok);
01055             if(ok) val1=1; else val1=0;
01056         }
01057         else
01058         {
01059             if(findRowColumn(calculateVariable(getParameter(parameters, 0, TRUE, function)), &row,&col, FALSE))
01060             {
01061                 val1=text(row,col).toDouble(&ok);
01062                 if(ok) val1=1; else val1=0;
01063             }
01064             else
01065             {
01066                 val1=0;
01067             };
01068         };
01069         return QString::number(val1);
01070     };
01071     if (function=="AND")
01072     {
01073         vali=calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok)
01074              & calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01075         return QString::number(vali);
01076     };
01077     if (function=="OR")
01078     {
01079         vali=calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok)
01080              | calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01081         return QString::number(vali);
01082     };
01083     if (function=="NOT")
01084     {
01085         vali=!calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok);
01086         return QString::number(vali);
01087     };
01088 
01089     // MATHEMATICAL FUNCTIONS
01090     if (function=="ABS")
01091     {
01092         val1=fabs(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01093         return QString::number(val1);
01094     };
01095     if (function=="ACOS")
01096     {
01097         val1=acos(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01098         return QString::number(val1);
01099     };
01100     if (function=="ACOSH")
01101     {
01102         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01103         if(val1<1.0) return QString::number(0);
01104         val1=acosh(val1);
01105         return QString::number(val1);
01106     };
01107     if (function=="ASIN")
01108     {
01109         val1=asin(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01110         return QString::number(val1);
01111     };
01112     if (function=="ASINH")
01113     {
01114         val1=asinh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01115         return QString::number(val1);
01116     };
01117     if (function=="ATAN")
01118     {
01119         val1=atan(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01120         return QString::number(val1);
01121     };
01122     if (function=="ATAN2")
01123     {
01124         val1=atan2(calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok),
01125                    calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01126         return QString::number(val1);
01127     };
01128     if (function=="ATANH")
01129     {
01130         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01131         if(val1<=-1.0 || val1>=1.0) return QString("Err101");
01132         val1=atanh(val1);
01133         return QString::number(val1);
01134     };
01135     if (function=="CEILING")
01136     {
01137         // rounds up param1 to specified accuracy param2
01138         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01139         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01140         if(val2==0.0) return QString::number(val1);
01141         val1=ceil(val1/val2)*val2;
01142         return QString::number(val1);
01143     };
01144     if (function=="COS")
01145     {
01146         val1=cos(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01147         return QString::number(val1);
01148     };
01149     if (function=="COSH")
01150     {
01151         val1=cosh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01152         return QString::number(val1);
01153     };
01154     if (function=="DEGREES")
01155     {
01156         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok)*180.0/M_PI;
01157         return QString::number(val1);
01158     };
01159     if (function=="EXP")
01160     {
01161         val1=exp(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01162         return QString::number(val1);
01163     };
01164     if (function=="FACT")
01165     {
01166         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01167         val2=Factorial(val1);
01168         return QString::number(val2);
01169     };
01170     if (function=="FLOOR")
01171     {
01172         // rounds down param1 to specified accuracy param2
01173         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01174         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01175         if(val2==0.0) return QString::number(val1);
01176         val1=floor(val1/val2)*val2;
01177         return QString::number(val1);
01178     };
01179     if (function=="INT")
01180     {
01181         // rounds down param1
01182         val1=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01183         return QString::number(val1);
01184     };
01185     if (function=="EVEN")
01186     {
01187         //converts param1 to even
01188         vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01189         if(vali % 2 !=0) val1=vali+1; else val1=vali;
01190         return QString::number(val1);
01191     };
01192     if (function=="ODD")
01193     {
01194         //converts param1 to odd
01195         vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01196         if(vali % 2 !=0) val1=vali; else val1=vali+1;
01197         return QString::number(val1);
01198     };
01199     if (function=="ISEVEN")
01200     {
01201         //Is Even param1?
01202         vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01203         if(vali % 2 == 0) val1=1; else val1=0;
01204         return QString::number(val1);
01205     };
01206     if (function=="ISODD")
01207     {
01208         //Is odd param1?
01209         vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01210         if(vali % 2 == 0) val1=0; else val1=1;
01211         return QString::number(val1);
01212     };
01213     if (function=="LN")
01214     {
01215         // returns the natural logarithm of param1
01216         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01217         if(val1<=0.0) return QString("Err101");
01218         val1=log(val1);
01219         return QString::number(val1);
01220     };
01221     if (function=="LOG10")
01222     {
01223         // returns the base-10 logarithm of param1
01224         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01225         if(val1<=0.0) return QString("Err101");
01226         val1=log10(val1);
01227         return QString::number(val1);
01228     };
01229     if (function=="LOG")
01230     {
01231         // return the base-param2 logarithm of param1
01232         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01233         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01234         if(val1<=0.0 || val2<=0.0 ) return QString("Err101");
01235         val1=log(val1)/log(val2);
01236         return QString::number(val1);
01237     };
01238     if (function=="MOD")
01239     {
01240         // return the modulus of param1/param2
01241         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01242         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01243         if(val2==0.0) return QString("Err101");
01244         val1=(int(val1) % int(val2));
01245         return QString::number(val1);
01246     };
01247     if (function=="POWER")
01248     {
01249         // return the param1^param2
01250         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01251         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01252         if(val1<0.0 && (floor(val2)!=val2)) return QString("Err101");
01253         val1=pow(val1,val2);
01254         return QString::number(val1);
01255     };
01256     if (function=="PI")
01257     {
01258         return QString::number(M_PI);
01259     };
01260     if (function=="RADIANS")
01261     {
01262         // param1 deg->rad
01263         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok)*M_PI/180.0;
01264         return QString::number(val1);
01265     };
01266     if (function=="RAND")
01267     {
01268         // retuns random number 0>x>1
01269         srand((unsigned int)time((time_t *)NULL));
01270         val1=double(rand())/double(RAND_MAX);
01271         return QString::number(val1);
01272     };
01273     if (function=="RANDBETWEEN")
01274     {
01275         // returns random number between param1>x>param2
01276         //TOFIX: this is not ok because I think results is always int related.
01277         srand((unsigned int)time((time_t *)NULL));
01278         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01279         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01280         val1=fmod(double(rand()),(val2-val1))+val1;
01281         return QString::number(val1);
01282     };
01283     if (function=="ROUND")
01284     {
01285         // rounds down param1 to specified digits param2 (positive decimal digits)
01286         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01287         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01288         val2=pow(10.0,-val2);
01289         val1=floor(val1/val2)*val2;
01290         return QString::number(val1);
01291     };
01292     if (function=="SIGN")
01293     {
01294         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01295         if(val1>=0.0) return QString::number(1.0); else return QString::number(-1.0);
01296     };
01297     if (function=="CHGSGN")//changes sign (for unary operator)
01298     {
01299         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01300         return QString::number((-1.0)*val1);
01301     };
01302     if (function=="SIN")
01303     {
01304         val1=sin(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01305         return QString::number(val1);
01306     };
01307     if (function=="SINH")
01308     {
01309         val1=sinh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01310         return QString::number(val1);
01311     };
01312     if (function=="TAN")
01313     {
01314         val1=tan(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01315         return QString::number(val1);
01316     };
01317     if (function=="TANH")
01318     {
01319         val1=tanh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01320         return QString::number(val1);
01321     };
01322     if (function=="SQRT")
01323     {
01324         val1=sqrt(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
01325         return QString::number(val1);
01326     };
01327 
01328 
01329     // STRING FUNCTIONS
01330     if (function=="CONCATENATE")
01331     {
01332         // concatenates strings together
01333         w1=0;
01334         s1="";
01335         while(getParameter(parameters, w1, FALSE, function)!="") //parse all params;
01336         {
01337             s1=s1+calculateVariable(getParameter(parameters, w1));
01338             w1++;
01339         };
01340         return QString(s1);
01341     };
01342     if (function=="EXACT")
01343     {
01344         // compare two string if they are exactly the same
01345         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01346         s2=calculateVariable(getParameter(parameters, 1, TRUE, function));
01347         if(s1==s2) return QString::number(1); else return QString::number(0);
01348     };
01349     if (function=="FIND")
01350     {
01351         // finds param1 in param2 from pos param3 and after
01352         // returns -1 if not found
01353         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01354         s2=calculateVariable(getParameter(parameters, 1, TRUE, function));
01355         vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01356         val1=s2.find(s1,vali);
01357         return QString::number(val1);
01358     };
01359     if (function=="LEFT")
01360     {
01361         // returns the param2 left chars from param1 string
01362         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01363         vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01364         s2=s1.left(vali);
01365         return QString(s2);
01366     };
01367     if (function=="LEN")
01368     {
01369         // return the length of a string(param1)
01370         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01371         return QString::number(s1.length());
01372     };
01373     if (function=="MID")
01374     {
01375         // returns the mid word of string param1 with start param2 and len param3
01376         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01377         w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01378         w2=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01379         s2=s1.mid(w1,w2);
01380         return QString(s2);
01381     };
01382     if (function=="REPLACE")
01383     {
01384         //replace in param1 text in pos param2 and length param3 to newtext param4
01385         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01386         w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01387         w2=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01388         s2=calculateVariable(getParameter(parameters, 3, TRUE, function));
01389         if(w1<0 || w2<0) return QString(s1);
01390         s1=s1.left(w2-1)+s2+s1.right(s1.length()-w1-w2);
01391         return QString(s1);
01392     };
01393     if (function=="REPT")
01394     {
01395         //repeats param1 string param2 times
01396         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01397         w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01398         for(w2=1;w2<=w1;w2++)
01399         {
01400             s2=s2.append(s1);
01401         };
01402         return QString(s2);
01403     };
01404     if (function=="RIGHT")
01405     {
01406         // returns the param2 right chars from param1 string
01407         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01408         vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01409         s2=s1.right(vali);
01410         return QString(s2);
01411     };
01412     if (function=="UPPER")
01413     {
01414         // returns the upper param1 string
01415         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01416         s1=s1.upper();
01417         return QString(s1);
01418     };
01419     if (function=="LOWER")
01420     {
01421         // returns the lower param1 string
01422         s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
01423         s1=s1.lower();
01424         return QString(s1);
01425     };
01426     if (function=="IF")
01427     {
01428         //usage: IF(param1,param2,param3)
01429         //returns param4 if true(param1)/   param5 if false(param1)
01430         val1=getParameter(parameters, 0, TRUE, function).toDouble(&ok);
01431         if(val1==1.0)
01432         {
01433             s1=calculateVariable(getParameter(parameters, 1, TRUE, function));
01434             return QString(s1);
01435         }
01436         else
01437         {
01438             s1=calculateVariable(getParameter(parameters, 2, TRUE, function));
01439             return QString(s1);
01440         };
01441     };
01442     if (function=="SUM")
01443     {
01444         //NumOfParams
01445         val2=0.0;
01446         for(w1=1;w1<=(NumOfParams/2);w1++)
01447         {
01448             val1=functionSum(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01449             val2=val2+val1;
01450         };
01451         if(NumOfParams%2==1)
01452         {
01453             val2=val2+calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01454         };
01455         return QString::number(val2);
01456     };
01457     if (function=="INDEX")
01458     {
01459         s1=functionIndex(getParameter(parameters,0,TRUE,function), getParameter(parameters, 1, TRUE, function), getParameter(parameters,2,TRUE,function).toInt(&ok));
01460         return QString(s1);
01461     };
01462     if (function=="SUMSQ")
01463     {
01464         //NumOfParams
01465         val2=0.0;
01466         for(w1=1;w1<=(NumOfParams/2);w1++)
01467         {
01468             val1=functionSumSQ(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01469             val2=val2+val1;
01470         };
01471         if(NumOfParams%2==1)
01472         {
01473             val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01474             val2=val2+val1*val1;
01475         };
01476         return QString::number(val2);
01477     };
01478     if (function=="COUNT")
01479     {
01480         //NumOfParams
01481         val2=0.0;
01482         for(w1=1;w1<=(NumOfParams/2);w1++)
01483         {
01484             val1=functionCount(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01485             val2=val2+val1;
01486         };
01487         if(NumOfParams%2==1)
01488         {
01489             val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01490             if(ok) val2=val2+1;
01491         };
01492         return QString::number(val2);
01493     };
01494     if (function=="COUNTIF")
01495     {
01496         //NumOfParams
01497         val1=functionCountIf(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function), getParameter(parameters, 2, TRUE, function));
01498         return QString::number(val1);
01499     };
01500     if (function=="MIN")
01501     {
01502         //NumOfParams
01503         val2=0.0;
01504         for(w1=1;w1<=(NumOfParams/2);w1++)
01505         {
01506             val1=functionMin(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01507             val2=val1;
01508         };
01509         if(NumOfParams%2==1)
01510         {
01511             val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01512             if(val1<val2) val2=val1;
01513         };
01514         return QString::number(val2);
01515     };
01516     if (function=="MAX")
01517     {
01518         //NumOfParams
01519         val2=0.0;
01520         for(w1=1;w1<=(NumOfParams/2);w1++)
01521         {
01522             val1=functionMax(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
01523             val2=val1;
01524         };
01525         if(NumOfParams%2==1)
01526         {
01527             val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
01528             if(val1>val2) val2=val1;
01529         };
01530         return QString::number(val2);
01531     };
01532     if (function=="AVERAGE")
01533     {
01534         val1=functionAvg(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01535         return QString::number(val1);
01536     };
01537 
01538     if(function=="BESSELI")
01539     {
01540         // BesselI (x,n)
01541         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01542         vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01543         val2=BesselI(vali,val1);
01544         return QString::number(val2);
01545     };
01546     if(function=="BESSELJ")
01547     {
01548         // BesselJ (x,n)
01549         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01550         vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01551         val2=BesselJ(vali,val1);
01552         return QString::number(val2);
01553     };
01554     if(function=="BESSELK")
01555     {
01556         // BesselK (x,n)
01557         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01558         vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01559         val2=BesselK(vali,val1);
01560         return QString::number(val2);
01561     };
01562     if(function=="BESSELY")
01563     {
01564         // BesselY (x,n)
01565         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01566         vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01567         val2=BesselY(vali,val1);
01568         return QString::number(val2);
01569     };
01570     if(function=="GAMMALN")
01571     {
01572         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01573         val2=GammaLn(val1);
01574         return QString::number(val2);
01575     };
01576     if(function=="ERF")
01577     {
01578         // ERF (a,b)
01579         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01580         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01581         return QString::number(ErrorFunction(val2)-ErrorFunction(val1));
01582     };
01583     if(function=="ERFC")
01584     {
01585         // ERFC (a,b)
01586         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01587         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01588         return QString::number(ErrorFunctionComplementary(val2)-ErrorFunctionComplementary(val1));
01589     };
01590     if(function=="POISSON")
01591     {
01592         // POISSON DISTR(x,n,distr/desnt)
01593         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01594         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01595         vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01596         if(vali==1)
01597         {
01598             return QString::number(GammaQ(floor(val1)+1, val2));
01599         }
01600         else
01601         {
01602             return QString::number(exp(-val2)*pow(val2,val1)/exp(GammaLn(val1+1.0)));
01603         };
01604     };
01605     if(function=="CHIDIST")
01606     {
01607         // POISSON CHIDIST(x,n,distr/density)
01608         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01609         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01610         vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01611         if(vali==1)
01612         {
01613             return QString::number(GammaP(val2/2.0,val1*val1/2.0));
01614         }
01615         else
01616         {
01617             return QString::number(
01618                        pow(val1,val2-1.0)*exp(-val1*val1/2)/ ( pow(2,val2/2.0-1.0)*exp(GammaLn(val2/2.0)))
01619                    );
01620         };
01621     };
01622     if(function=="CHI2DIST")
01623     {
01624         // POISSON CHISQUAREDIST(x,n,distr/density)
01625         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01626         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01627         vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
01628         if(vali==1)
01629         {
01630             return QString::number(GammaP(val2/2.0,val1/2.0));
01631         }
01632         else
01633         {
01634             return QString::number(
01635                        pow(val1,val2/2.0-1.0)/(exp(val1/2.0)*pow(sqrt(2.0),val2)*exp(GammaLn(val2/2.0)))
01636                    );
01637         };
01638     };
01639     if(function=="BETAI")
01640     {
01641         // BETA INCOMPLETE BETA(x,a,b)
01642         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01643         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01644         val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01645         return QString::number(BetaIncomplete(val2,val3,val1));
01646     };
01647     if(function=="GAMMAP")
01648     {
01649         // GammaP (x,a)
01650         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01651         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01652         return QString::number(GammaP(val2,val1));
01653     };
01654     if(function=="GAMMAQ")
01655     {
01656         // GammaQ (x,a)
01657         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01658         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01659         return QString::number(GammaQ(val2,val1));
01660     };
01661     if (function=="VAR")
01662     {
01663         val1=functionVariance(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01664         return QString::number(val1);
01665     };
01666     if (function=="VARP")
01667     {
01668         val1=functionVariancePopulation(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01669         return QString::number(val1);
01670     };
01671     if (function=="STDEV")
01672     {
01673         val1=functionVariance(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01674         if(val1<=0.0) return QString::number(0.0);
01675         return QString::number(sqrt(val1));
01676     };
01677     if (function=="STDEVP")
01678     {
01679         val1=functionVariancePopulation(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01680         if(val1<=0.0) return QString::number(0.0);
01681         return QString::number(sqrt(val1));
01682     };
01683     if (function=="SKEW")
01684     {
01685         val1=functionSkew(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01686         return QString::number(val1);
01687     };
01688     if (function=="KURT")
01689     {
01690         val1=functionKurt(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
01691         return QString::number(val1);
01692     };
01693     if(function=="GAMMADIST")
01694     {
01695         // GAMMADIST (x,alpha,beta,distribution?density1:0)
01696         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01697         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01698         val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01699         vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01700         if(vali==1)//distribution
01701         {
01702             if(val3==0.0) return QString::number(0.0);
01703             else
01704                 return QString::number(GammaP(val2,val1/val3));
01705         }else //density
01706         {
01707             return QString::number(
01708                        pow(val1,val2-1.0)*exp(-val1/val3) / (pow(val3,val2)*exp(GammaLn(val2)))
01709                    );
01710         };
01711     };
01712     if(function=="BETADIST")
01713     {
01714         // BETADIST (z,alpha,beta,distribution?density1:0)
01715         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01716         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01717         val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01718         vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01719         if(vali==1)//distribution
01720         {
01721             return QString::number(BetaIncomplete(val2,val3,val1));
01722         }else //density
01723         {
01724             return QString::number(
01725                        pow(val1,val2-1.0)*pow(1.0-val1,val3-1.0) / Beta(val2,val3)
01726                    );
01727         };
01728     };
01729     if(function=="FDIST")
01730     {
01731         // FDIST (z,d1,d2,distribution?density1:0)
01732         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01733         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01734         val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01735         vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01736         if(vali==1)//distribution
01737         {
01738             return QString::number(
01739                        -BetaIncomplete(val3/2,val2/2,val3/(val3+val2*val1))
01740                        +BetaIncomplete(val3/2,val2/2,1)
01741                    );
01742         }else //density
01743         {
01744             return QString::number(
01745                        pow(val2,val2/2)*pow(val3,val3/2)*pow(val1,val2/2-1)/
01746                        (pow(val3+val2*val1,(val2+val3)/2)*Beta(val2/2,val3/2))
01747                    );
01748         };
01749     };
01750     if(function=="NORMALDIST")
01751     {
01752         // NORMALDIST (x,m,s,distribution?density1:0)
01753         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01754         val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
01755         val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
01756         vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
01757         if(vali==1)//distribution
01758         {
01759             return QString::number(
01760                        (ErrorFunction((val1-val2)/(sqrt(2)*val3))+1)/2.0
01761                    );
01762         }else //density
01763         {
01764             return QString::number(
01765                        exp(-pow(((val1-val2)/val3),2)/2)/(val3*sqrt(2*M_PI))
01766                    );
01767         };
01768     };
01769     if(function=="PHI")
01770     {
01771         // NORMALDIST (x,distribution?density1:0) with mean=0 s=1.0
01772         val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
01773         vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
01774         if(vali==1)//distribution
01775         {
01776             return QString::number(
01777                        (ErrorFunction(val1/(sqrt(2)))+1)/2.0
01778                    );
01779         }else //density
01780         {
01781             return QString::number(
01782                        exp(-pow(val1,2)/2)/(sqrt(2*M_PI))
01783                    );
01784         };
01785     };
01786     /*
01787     StudentTDistribution/: PDF[StudentTDistribution[n_], x_] :=
01788         1/(Sqrt[n] Beta[n/2, 1/2]) Sqrt[n/(n+x^2)]^(n+1) /;
01789                     ParameterQ[StudentTDistribution[n]]
01790 
01791     StudentTDistribution/: CDF[StudentTDistribution[n_], x_] :=
01792         (1 + Sign[x] BetaRegularized[n/(n+x^2), 1, n/2, 1/2])/2 /;
01793                     ParameterQ[StudentTDistribution[n]]
01794     */
01795 
01796 
01797 
01798     return 0;
01799 };
01800 
01801 
01802 
01803 
01804 QString Sheet::dataParserHelper(const QString &data)
01805 {
01806     if(data.left(1)=="""" && data.right(1)=="""") return QString(data);
01807     Expression exp1(data);
01808     exp1.Parse();
01809     QStack<QString> stack1;
01810     stack1.setAutoDelete(TRUE);
01811     int i=0;
01812     QString* s1;
01813     QString* s2=NULL;
01814     int* i1;
01815     int args,tokentype;
01816     QString tempval;
01817     s1=exp1.CompiledBody.first();i1=exp1.CompiledBodyType.first();
01818     while(i<=(int)exp1.CompiledBody.count()-1)
01819     {
01820         args= ((*i1) & 0xFF00)>>8; tokentype=(*i1) & 0x00FF;
01821         if(tokentype==NUMBER_TOKEN)
01822         {
01823             stack1.push(new QString(*s1));
01824             //printf("Parse:Number=%s\r\n",s1->latin1());
01825         }
01826         else if(tokentype==VARIABLE_TOKEN)
01827         {
01828             stack1.push(new QString(QString(*s1).upper()));
01829             //printf("Parse:Var=%s\r\n",s1->latin1());
01830             //here to put implementation of other types of variables except cell.
01831             //for example names
01832         }
01833         else if(tokentype==STRING_TOKEN)
01834         {
01835             stack1.push(new QString(*s1));
01836             //printf("Parse:String=%s\r\n",s1->ascii());
01837         }
01838         else if(tokentype==FUNCTION_TOKEN)
01839         {
01840             QString params="";
01841             for(int w1=1;w1<=args;w1++)
01842             {
01843                 if((int)stack1.count()!=0) s2=stack1.pop();
01844                 params=*s2+params;//args in reverse order
01845                 params=","+params;
01846             };
01847             params=params.mid(1);
01848             if(params==NULL) params="0";
01849             //printf("Parse:Func=%s, params=%s, stackcount=%d,args=%d\r\n"
01850             //  ,s1->latin1(),params.latin1(),stack1.count(),args);
01851             tempval=calculateFunction(*s1,params,args);
01852             tempval=tempval;
01853             stack1.push(new QString(tempval));
01854         };
01855 
01856         //loops to next token
01857         if(exp1.CompiledBody.next()!=NULL) s1=exp1.CompiledBody.current(); else break;
01858         if(exp1.CompiledBodyType.next()!=NULL) i1=exp1.CompiledBodyType.current(); else break;
01859         i++;
01860     };
01861     if((int)stack1.count()!=0)s2=stack1.pop(); else s2=new QString("!ERROR");
01862     tempval=*s2;
01863     return(tempval);
01864 };
01865 
01866 
01867 
01868 QString Sheet::dataParser(const QString &cell, const QString &data)
01869 {
01870     QString strippedData(data);
01871     strippedData.replace(QRegExp("\\s"), "");
01872     if (strippedData.isEmpty() || strippedData[0]!='=') return data;
01873     if (listDataParser.find(cell)!=listDataParser.end()) return "0";
01874     listDataParser.append(cell);
01875     // printf("DATAPARSER: data=%s, cell=%s\r\n",data.ascii(),cell.ascii());
01876     strippedData=dataParserHelper(strippedData.remove(0, 1).replace(QRegExp(":"), ","));
01877 
01878     int i=0;
01879     QString tempParameter(getParameter(strippedData, i)), result="";
01880     do
01881     {
01882         result+=","+calculateVariable(tempParameter);
01883         tempParameter=getParameter(strippedData, ++i);
01884     }
01885     while (!tempParameter.isNull());
01886     listDataParser.remove(cell);
01887     return result.mid(1);
01888 }
01889 
01890 
01891 void Sheet::setData(const QString &data)
01892 {
01893     setText(currentRow(), currentColumn(), data);
01894     slotCellChanged(currentRow(), currentColumn());
01895     activateNextCell();
01896 }
01897 
01898 QString Sheet::getData()
01899 {
01900     typeCellData *cellData=findCellData(currentRow(), currentColumn());
01901     if (cellData)
01902         return cellData->data;
01903     return "";
01904 }
01905 
01906 void Sheet::lockClicks(bool lock)
01907 {
01908     clicksLocked=lock;
01909 }
01910 
01911 void Sheet::paintCell(QPainter *p, int row, int col, const QRect & cr, bool selected)
01912 {
01913     if (selected && row==currentRow() && col==currentColumn()) selected=FALSE;
01914 
01915     int sheetDataCurrent=sheetData.at();
01916     typeCellData *cellData=findCellData(row, col);
01917     if (sheetDataCurrent>=0) sheetData.at(sheetDataCurrent);
01918     if (!cellData) cellData=&defaultCellData;
01919     if (selected)
01920         p->fillRect(0, 0, cr.width(), cr.height(), colorGroup().highlight());
01921     else
01922     {
01923         p->fillRect(0, 0, cr.width(), cr.height(), colorGroup().base());
01924         p->fillRect(0, 0, cr.width(), cr.height(), cellData->background);
01925     }
01926 
01927     QTableItem *cellItem=item(row, col);
01928     if (cellItem)
01929     {
01930         p->setPen(selected ? colorGroup().highlightedText() : cellData->fontColor);
01931         p->setFont(cellData->font);
01932         QString str=cellItem->text();
01933         p->drawText(2, 2, cr.width()-4, cr.height()-4, cellData->alignment, cellItem->text());
01934     }
01935 
01936     int rx=cr.width()-1, ry=cr.height()-1;
01937     QPen pen(p->pen());
01938     p->setPen(cellData->borders.right);
01939     p->drawLine(rx, 0, rx, ry);
01940     p->setPen(cellData->borders.bottom);
01941     p->drawLine(0, ry, rx, ry);
01942     p->setPen(pen);
01943 }
01944 
01945 void Sheet::viewportMousePressEvent(QMouseEvent *e)
01946 {
01947     QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
01948     if (clicksLocked)
01949     {
01950         if (selectionNo<0)
01951         {
01952             clearSelection();
01953             QTableSelection newSelection;
01954             newSelection.init(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
01955             newSelection.expandTo(newSelection.anchorRow(), newSelection.anchorCol());
01956             selectionNo=addSelection(newSelection);
01957         }
01958     }
01959     else
01960         QTable::contentsMousePressEvent(&ce);
01961 }
01962 
01963 void Sheet::viewportMouseMoveEvent(QMouseEvent *e)
01964 {
01965     QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
01966     if (clicksLocked)
01967     {
01968         if (selectionNo>=0)
01969         {
01970             QTableSelection oldSelection(selection(selectionNo));
01971             oldSelection.expandTo(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
01972             if (!(oldSelection==selection(selectionNo)))
01973             {
01974                 removeSelection(selectionNo);
01975                 selectionNo=addSelection(oldSelection);
01976             }
01977         }
01978     }
01979     else
01980         QTable::contentsMouseMoveEvent(&ce);
01981 }
01982 
01983 void Sheet::viewportMouseReleaseEvent(QMouseEvent *e)
01984 {
01985     QMouseEvent ce(e->type(), viewportToContents(e->pos()), e->globalPos(), e->button(), e->state());
01986     if (clicksLocked && selectionNo>=0)
01987     {
01988         QTableSelection oldSelection(selection(selectionNo));
01989         oldSelection.expandTo(rowAt(ce.pos().y()), columnAt(ce.pos().x()));
01990         removeSelection(selectionNo);
01991         selectionNo=-1;
01992         if (oldSelection.topRow()==oldSelection.bottomRow() && oldSelection.leftCol()==oldSelection.rightCol())
01993             emit cellClicked(findCellName(oldSelection.topRow(), oldSelection.leftCol()));
01994         else
01995             emit cellClicked(findCellName(oldSelection.topRow(), oldSelection.leftCol())+','+findCellName(oldSelection.bottomRow(), oldSelection.rightCol()));
01996     }
01997     else
01998         QTable::contentsMouseReleaseEvent(&ce);
01999 }
02000 
02001 QString Sheet::findCellName(int row, int col)
02002 {
02003     return (getHeaderString(col+1)+QString::number(row+1));
02004 }
02005 
02006 void Sheet::copySheetData(QList<typeCellData> *destSheetData)
02007 {
02008     typeCellData *tempCellData, *newCellData;
02009     destSheetData->clear();
02010 
02011     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02012     {
02013         newCellData=new typeCellData;
02014         *newCellData=*tempCellData;
02015         destSheetData->append(newCellData);
02016     }
02017 }
02018 
02019 void Sheet::setSheetData(QList<typeCellData> *srcSheetData)
02020 {
02021     typeCellData *tempCellData, *newCellData;
02022 
02023     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02024     {
02025         clearCell(tempCellData->row, tempCellData->col);
02026         updateCell(tempCellData->row, tempCellData->col);
02027     }
02028     sheetData.clear();
02029 
02030     for (tempCellData=srcSheetData->first(); tempCellData; tempCellData=srcSheetData->next())
02031     {
02032         newCellData=new typeCellData;
02033         *newCellData=*tempCellData;
02034         sheetData.append(newCellData);
02035         setText(newCellData->row, newCellData->col, dataParser(findCellName(newCellData->row, newCellData->col), newCellData->data));
02036     }
02037     emit sheetModified();
02038 }
02039 
02040 void Sheet::setName(const QString &name)
02041 {
02042     sheetName=name;
02043     emit sheetModified();
02044 }
02045 
02046 QString Sheet::getName()
02047 {
02048     return sheetName;
02049 }
02050 
02051 void Sheet::setBrush(int row, int col, const QBrush &brush)
02052 {
02053     typeCellData *cellData=findCellData(row, col);
02054     if (!cellData) cellData=createCellData(row, col);
02055     if (cellData)
02056     {
02057         cellData->background=brush;
02058         emit sheetModified();
02059     }
02060 }
02061 
02062 QBrush Sheet::getBrush(int row, int col)
02063 {
02064     typeCellData *cellData=findCellData(row, col);
02065     if (!cellData) cellData=&defaultCellData;
02066     return cellData->background;
02067 }
02068 
02069 void Sheet::setTextAlign(int row, int col, Qt::AlignmentFlags flags)
02070 {
02071     typeCellData *cellData=findCellData(row, col);
02072     if (!cellData) cellData=createCellData(row, col);
02073     if (cellData)
02074     {
02075         cellData->alignment=flags;
02076         emit sheetModified();
02077     }
02078 }
02079 
02080 Qt::AlignmentFlags Sheet::getAlignment(int row, int col)
02081 {
02082     typeCellData *cellData=findCellData(row, col);
02083     if (!cellData) cellData=&defaultCellData;
02084     return cellData->alignment;
02085 }
02086 
02087 void Sheet::setTextFont(int row, int col, const QFont &font, const QColor &color)
02088 {
02089     typeCellData *cellData=findCellData(row, col);
02090     if (!cellData) cellData=createCellData(row, col);
02091     if (cellData)
02092     {
02093         cellData->font=font;
02094         cellData->fontColor=color;
02095         emit sheetModified();
02096     }
02097 }
02098 
02099 QFont Sheet::getFont(int row, int col)
02100 {
02101     typeCellData *cellData=findCellData(row, col);
02102     if (!cellData) cellData=&defaultCellData;
02103     return cellData->font;
02104 }
02105 
02106 QColor Sheet::getFontColor(int row, int col)
02107 {
02108     typeCellData *cellData=findCellData(row, col);
02109     if (!cellData) cellData=&defaultCellData;
02110     return cellData->fontColor;
02111 }
02112 
02113 void Sheet::setPen(int row, int col, int vertical, const QPen &pen)
02114 {
02115     typeCellData *cellData=findCellData(row, col);
02116     if (!cellData) cellData=createCellData(row, col);
02117     if (cellData)
02118     {
02119         if (vertical)
02120             cellData->borders.right=pen;
02121         else
02122             cellData->borders.bottom=pen;
02123         emit sheetModified();
02124     }
02125 }
02126 
02127 QPen Sheet::getPen(int row, int col, int vertical)
02128 {
02129     typeCellData *cellData=findCellData(row, col);
02130     if (!cellData) cellData=&defaultCellData;
02131     return (vertical ? cellData->borders.right : cellData->borders.bottom);
02132 }
02133 
02134 void Sheet::getSelection(int *row1, int *col1, int *row2, int *col2)
02135 {
02136     int selectionNo=currentSelection();
02137     if (selectionNo>=0)
02138     {
02139         QTableSelection select(selection(selectionNo));
02140         *row1=select.topRow();
02141         *row2=select.bottomRow();
02142         *col1=select.leftCol();
02143         *col2=select.rightCol();
02144     }
02145     else
02146     {
02147         *row1=*row2=currentRow();
02148         *col1=*col2=currentColumn();
02149     }
02150 }
02151 
02152 void Sheet::editClear()
02153 {
02154     int row1, row2, col1, col2;
02155     getSelection(&row1, &col1, &row2, &col2);
02156 
02157     int row, col;
02158     for (row=row1; row<=row2; ++row)
02159         for (col=col1; col<=col2; ++col)
02160         {
02161             setText(row, col, "");
02162             slotCellChanged(row, col);
02163         }
02164 }
02165 
02166 void Sheet::editCopy()
02167 {
02168     clipboardData.clear();
02169 
02170     int row1, row2, col1, col2;
02171     getSelection(&row1, &col1, &row2, &col2);
02172 
02173     typeCellData *cellData, *newCellData;
02174     int row, col;
02175     for (row=row1; row<=row2; ++row)
02176         for (col=col1; col<=col2; ++col)
02177         {
02178             cellData=findCellData(row, col);
02179             if (cellData)
02180             {
02181                 newCellData=new typeCellData;
02182                 *newCellData=*cellData;
02183                 newCellData->row-=row1;
02184                 newCellData->col-=col1;
02185                 clipboardData.append(newCellData);
02186             }
02187         }
02188 }
02189 
02190 void Sheet::editCut()
02191 {
02192     editCopy();
02193     editClear();
02194 }
02195 
02196 void Sheet::editPaste(bool onlyContents)
02197 {
02198     int row1=currentRow(), col1=currentColumn();
02199     typeCellData *cellData, *tempCellData;
02200 
02201     for (tempCellData=clipboardData.first(); tempCellData; tempCellData=clipboardData.next())
02202     {
02203         cellData=findCellData(tempCellData->row+row1, tempCellData->col+col1);
02204         if (!cellData) cellData=createCellData(tempCellData->row+row1, tempCellData->col+col1);
02205         if (cellData)
02206         {
02207             if (onlyContents)
02208                 cellData->data=tempCellData->data;
02209             else
02210             {
02211                 *cellData=*tempCellData;
02212                 cellData->row+=row1;
02213                 cellData->col+=col1;
02214             }
02215             setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data));
02216             emit sheetModified();
02217         }
02218     }
02219 }
02220 
02221 void Sheet::insertRows(int no, bool allColumns)
02222 {
02223     setNumRows(numRows()+no);
02224 
02225     typeCellData *tempCellData;
02226     int row=currentRow(), col=currentColumn();
02227 
02228     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02229         if (tempCellData->row>=row && (allColumns || tempCellData->col==col))
02230         {
02231             clearCell(tempCellData->row, tempCellData->col);
02232             tempCellData->row+=no;
02233         }
02234     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02235         if (tempCellData->row>=row && (allColumns || tempCellData->col==col))
02236         {
02237             updateCell(tempCellData->row-no, tempCellData->col);
02238             setText(tempCellData->row, tempCellData->col, dataParser(findCellName(tempCellData->row, tempCellData->col), tempCellData->data));
02239         }
02240     emit sheetModified();
02241 }
02242 
02243 void Sheet::insertColumns(int no, bool allRows)
02244 {
02245     int noCols=numCols();
02246     int newCols=noCols+no;
02247     setNumCols(newCols);
02248     for (int i=noCols; i<newCols; ++i)
02249         horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH);
02250 
02251     typeCellData *tempCellData;
02252     int col=currentColumn(), row=currentRow();
02253 
02254     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02255         if (tempCellData->col>=col && (allRows || tempCellData->row==row))
02256         {
02257             clearCell(tempCellData->row, tempCellData->col);
02258             tempCellData->col+=no;
02259         }
02260     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02261         if (tempCellData->col>=col && (allRows || tempCellData->row==row))
02262         {
02263             updateCell(tempCellData->row, tempCellData->col-no);
02264             setText(tempCellData->row, tempCellData->col, dataParser(findCellName(tempCellData->row, tempCellData->col), tempCellData->data));
02265         }
02266     emit sheetModified();
02267 }
02268 
02269 void Sheet::dataFindReplace(const QString &findStr, const QString &replaceStr, bool matchCase, bool allCells, bool entireCell, bool replace, bool replaceAll)
02270 {
02271     typeCellData *tempCellData;
02272     int row1, col1, row2, col2;
02273     getSelection(&row1, &col1, &row2, &col2);
02274     bool found=FALSE;
02275 
02276     for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
02277         if (allCells || (tempCellData->row>=row1 && tempCellData->row<=row2 && tempCellData->col>=col1 && tempCellData->col<=col2))
02278         {
02279             QTableItem *cellItem=item(tempCellData->row, tempCellData->col);
02280             if (cellItem && (entireCell ? (matchCase ? cellItem->text()==findStr : cellItem->text().upper()==findStr.upper()) : cellItem->text().find(findStr, 0, matchCase)>=0))
02281             {
02282                 if (!found)
02283                 {
02284                     found=TRUE;
02285                     clearSelection();
02286                 }
02287                 setCurrentCell(tempCellData->row, tempCellData->col);
02288                 if (replace)
02289                 {
02290                     tempCellData->data=cellItem->text().replace(QRegExp(findStr, matchCase), replaceStr);
02291                     setText(tempCellData->row, tempCellData->col, dataParser(findCellName(tempCellData->row, tempCellData->col), tempCellData->data));
02292                 }
02293                 if (!replace || !replaceAll) break;
02294             }
02295         }
02296 
02297     if (found)
02298     {
02299         if (replace)
02300             slotCellChanged(currentRow(), currentColumn());
02301     }
02302     else
02303         QMessageBox::warning(this, tr("Error"), tr("Search key not found!"));
02304 }
02305 
02306 //
02307 // Static functions
02308 //
02309 
02310 QString Sheet::getHeaderString(int section)
02311 {
02312     if (section<1) return "";
02313     return getHeaderString((section-1)/26)+QChar('A'+(section-1)%26);
02314 }
02315 
02316 int Sheet::getHeaderColumn(const QString &section)
02317 {
02318     if (section.isEmpty()) return 0;
02319     return (section[section.length()-1]-'A'+1)+getHeaderColumn(section.left(section.length()-1))*26;
02320 }
02321 
02322 
02323 //Expression Parser Class Definition
02324 
02325 
02326 QChar Expression::chunk0(void)
02327 {
02328     if(chunk.length()>0) return(chunk[0]); else return('\0');
02329 };
02330 
02331 Expression::Expression(QString expr1)// constructor
02332 {
02333     Body=expr1;
02334     SYMBOL="+-*/%^=()<>&|!,";
02335     MATHSYMBOL="+-*/%^=<>&|!,";
02336     //      lnlim=1.0e-36;      // Smallest number allowed
02337     //      loglim=1.0e-10 ;    // Smallest number allowed in call to log10() *
02338     ErrorFound=TRUE;
02339     n=0;chunk="";SymbGroup=NONE_TOKEN;InExpr=Body;
02340     ArgsOfFunc=0;
02341     CompiledBody.setAutoDelete(TRUE);
02342     CompiledBodyType.setAutoDelete(TRUE);
02343     //CompiledBody=QStringList(0);
02344 };
02345 
02346 bool Expression::isSymbol(QChar ch)
02347 {
02348     int j = 0;
02349     while (j<=((int)SYMBOL.length()-1) && ch!=SYMBOL[j]) j++;
02350     if(j<((int)SYMBOL.length())) return true; else return false;
02351 };
02352 
02353 bool Expression::isMathSymbol(QChar ch)
02354 {
02355     int j = 0;
02356     while (j<=((int)MATHSYMBOL.length()-1) && ch!=MATHSYMBOL[j]) j++;
02357     if(j<((int)MATHSYMBOL.length())) return true; else return false;
02358 };
02359 
02360 void Expression::GetNext()
02361 {
02362     chunk="";
02363     if(n>=(int)InExpr.length()) return;
02364     while (InExpr[n]==' ') n++;
02365     if(InExpr[n]=='\"')
02366     {
02367         while ( (n<(int)InExpr.length()) && (InExpr[n+1]!='\"') )
02368         {
02369             printf("chunk=%s\r\n",chunk.latin1());
02370             chunk+=InExpr[n];
02371             n++;
02372         };
02373         chunk+=InExpr[n];
02374         printf("2\r\n");
02375         SymbGroup=STRING_TOKEN;
02376     }
02377     else if (isSymbol(InExpr[n]))
02378     {
02379         SymbGroup=SYMBOL_TOKEN;
02380         chunk+=InExpr[n];
02381         n++;
02382         if( (n<(int)InExpr.length()) &&
02383                 isMathSymbol(InExpr[n-1])  &&
02384                 isMathSymbol(InExpr[n])      )
02385         {
02386             SymbGroup=SYMBOL_TOKEN;
02387             chunk+=InExpr[n];
02388             n++;
02389         };
02390     }
02391     else if ((InExpr[n].isLetter())||(InExpr[n]=='#'))
02392     {
02393         while ( (n<(int)InExpr.length()) && !isSymbol(InExpr[n]) )
02394         {
02395             if (!(InExpr[n]==' ')) chunk+=InExpr[n];
02396             n++;
02397         };
02398         if (InExpr[n]=='(') SymbGroup=FUNCTION_TOKEN; // function TOKEN
02399         else SymbGroup=VARIABLE_TOKEN;
02400     }
02401     else if((n<(int)InExpr.length()) &&
02402             ((InExpr[n].isDigit()) || (InExpr[n]=='.')))
02403     {
02404         while( n<(int)InExpr.length() )
02405         {
02406             if((InExpr[n].isDigit()) || InExpr[n]=='.')
02407             {
02408                 chunk+=InExpr[n];
02409                 SymbGroup=NUMBER_TOKEN;
02410                 n++;
02411             }
02412             else if(InExpr[n]=='e')
02413             {
02414                 if((n+1)<(int)InExpr.length())
02415                 {
02416                     if(InExpr[n+1]=='-' || InExpr[n+1]=='+' ||  InExpr[n+1].isDigit())
02417                     {
02418                         chunk+=InExpr[n];
02419                         chunk+=InExpr[n+1];
02420                         SymbGroup=NUMBER_TOKEN;
02421                         n+=2;
02422                     }
02423                 }
02424                 else
02425                 {
02426                     break;
02427                 }
02428             }
02429             else
02430             {
02431                 break;
02432             }
02433         }//while
02434     }//else if
02435 }
02436 ;//end function
02437 
02438 
02439 void Expression::First()
02440 {
02441     GetNext();
02442     if (!(chunk=="") && !ErrorFound) Third();
02443     else ErrorFound = true;
02444 };
02445 
02446 void Expression::Third()
02447 {
02448     QChar sign, secS='\0';
02449     Fourth();
02450     sign = chunk0();
02451     if((int)chunk.length()>1) secS=chunk[1];
02452     while( sign == '+' || sign == '-'||
02453             sign == '<' || sign == '>'|| sign == '%'||
02454             sign == '&' || sign == '|' || sign == '!' || sign == '='
02455          )
02456     {
02457         GetNext();
02458         Fourth();
02459         QString name;
02460         if( sign == '+' ) name= "+" ;
02461         else if(sign=='-') name= "-" ;
02462         else if(sign=='>' && secS=='\0') name= ">" ;
02463         else if(sign=='<' && secS=='\0') name= "<" ;
02464         else if(sign=='=' && secS=='=') name= "==" ;
02465         else if(sign=='!' && secS=='=') name= "!=" ;
02466         else if(sign=='>' && secS=='=') name= ">=" ;
02467         else if(sign=='<' && secS=='=') name= "<=" ;
02468         else if(sign=='&' && secS=='&') name= "AND" ;
02469         else if(sign=='|' && secS=='|') name= "OR" ;
02470         else if(sign=='%') name= "MOD" ;
02471         CompiledBody.append(new QString(name)); // not sure if pushed in the back.
02472         CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8)); //2 argument functions
02473         sign = chunk0();
02474     }
02475 };
02476 
02477 void Expression::Fourth()
02478 {
02479     QChar sign;
02480     Fifth();
02481     sign = chunk0();
02482     while( sign == '*' || sign == '/' )
02483     {
02484         GetNext();
02485         Fifth();
02486         QString name;
02487         if( sign == '*' ) name= "*" ;
02488         else name= "/" ;
02489         CompiledBody.append(new QString(name));
02490         CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8)); //2 arguments functions
02491         sign = chunk0();
02492     }
02493 };
02494 
02495 void Expression::Fifth()
02496 {
02497     Sixth();
02498     //if(chunk.Length==0) return;
02499     if( chunk0() == '^' )
02500     {
02501         GetNext();
02502         Fifth();
02503         CompiledBody.append(new QString("POWER"));
02504         CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8)); // 2 argument functions
02505     }
02506 };
02507 
02508 void Expression::Sixth()
02509 {
02510     char sign;
02511     sign = ' ';
02512     if(SymbGroup== SYMBOL_TOKEN &&
02513             chunk0() == '+' || chunk0() == '-'  | chunk0() == '!')
02514     {
02515         sign = chunk0();
02516         GetNext();
02517     }
02518     Seventh();
02519     if( sign == '-' )
02520     {
02521         CompiledBody.append(new QString("CHGSGN")); // unary minus
02522         CompiledBodyType.append(new int(FUNCTION_TOKEN | 1<<8)); //1 argument
02523     }
02524     if( sign == '!' )
02525     {
02526         CompiledBody.append(new QString("NOT")); // unary minus
02527         CompiledBodyType.append(new int(FUNCTION_TOKEN | 1<<8)); //1 argument
02528     }
02529 };
02530 
02531 
02532 void Expression::Seventh()
02533 {
02534     if( chunk0() == '(' && SymbGroup==SYMBOL_TOKEN)
02535     {
02536         GetNext();
02537         Third(); //parse the insides until we get a ')'
02538         if (chunk0() != ')') ErrorFound = true;
02539         GetNext();
02540     }
02541     else Eighth();
02542 };
02543 
02544 void Expression::Eighth()
02545 {
02546     if ( SymbGroup== NUMBER_TOKEN )
02547     {
02548         CompiledBody.append(new QString(chunk));
02549         CompiledBodyType.append(new int(NUMBER_TOKEN));
02550         GetNext();
02551     }
02552     else if ( SymbGroup== VARIABLE_TOKEN  )
02553     {
02554         CompiledBody.append(new QString(chunk));
02555         CompiledBodyType.append(new int(VARIABLE_TOKEN));
02556         GetNext();
02557     }
02558     else if (SymbGroup== STRING_TOKEN )
02559     {
02560         CompiledBody.append(new QString(chunk+QString("\"")));
02561         CompiledBodyType.append(new int(STRING_TOKEN));
02562         GetNext();
02563     }
02564     else Ninth();
02565 };
02566 
02567 void Expression::Ninth()
02568 {
02569     if (  SymbGroup== FUNCTION_TOKEN  )
02570     {
02571         QString TempFunk =  chunk ;
02572         GetNext();
02573         if(chunk0() == '(' )
02574         {
02575             FuncDepth++;
02576             ArgsOfFunc.resize(FuncDepth+1);
02577             ArgsOfFunc[FuncDepth]=1;
02578             //ArgsOfFunc=1;
02579             GetNext();
02580             Third();
02581             while(chunk0()==',')  //function arguments separator
02582             {
02583                 //ArgsOfFunc++;
02584                 ArgsOfFunc[FuncDepth]++;
02585                 GetNext();
02586                 Third();
02587             };
02588             if (chunk0() != ')') ErrorFound = true;
02589 
02590             CompiledBody.append(new QString(TempFunk));
02591             if (TempFunk=="PI") ArgsOfFunc[FuncDepth]=0;
02592             // couldn't find a better way to parse function PI() with 0 args. :)
02593             CompiledBodyType.append(new int(FUNCTION_TOKEN | (ArgsOfFunc[FuncDepth]<<8) ));
02594             //the mask &FF00 gives the arguments of the functions passed.
02595             FuncDepth--;
02596             ArgsOfFunc.resize(FuncDepth+1);
02597             GetNext();
02598         }
02599     }
02600     else
02601         ErrorFound = true;
02602 };
02603 
02604 bool Expression::Parse()
02605 {
02606     CompiledBody.clear();
02607     ErrorFound = false;
02608     n = 0;ArgsOfFunc.resize(0);FuncDepth=0;
02609     InExpr=Body;
02610     First();
02611     return(!ErrorFound);
02612 };
02613 
02614 

Generated on Sat Nov 5 16:17:01 2005 for OPIE by  doxygen 1.4.2