kspread

kspread_functions_conversion.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998-2002 The KSpread Team
00003                            www.koffice.org/kspread
00004    Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 // built-in conversion functions
00023 
00024 #include "functions.h"
00025 #include "valuecalc.h"
00026 #include "valueconverter.h"
00027 
00028 using namespace KSpread;
00029 
00030 // prototypes
00031 Value func_arabic (valVector args, ValueCalc *calc, FuncExtra *);
00032 Value func_carx (valVector args, ValueCalc *calc, FuncExtra *);
00033 Value func_cary (valVector args, ValueCalc *calc, FuncExtra *);
00034 Value func_decsex (valVector args, ValueCalc *calc, FuncExtra *);
00035 Value func_polr (valVector args, ValueCalc *calc, FuncExtra *);
00036 Value func_pola (valVector args, ValueCalc *calc, FuncExtra *);
00037 Value func_roman (valVector args, ValueCalc *calc, FuncExtra *);
00038 Value func_sexdec (valVector args, ValueCalc *calc, FuncExtra *);
00039 Value func_AsciiToChar (valVector args, ValueCalc *calc, FuncExtra *);
00040 Value func_CharToAscii (valVector args, ValueCalc *calc, FuncExtra *);
00041 Value func_inttobool (valVector args, ValueCalc *calc, FuncExtra *);
00042 Value func_booltoint (valVector args, ValueCalc *calc, FuncExtra *);
00043 Value func_ToString (valVector args, ValueCalc *calc, FuncExtra *);
00044 
00045 // registers all conversion functions
00046 void RegisterConversionFunctions()
00047 {
00048   FunctionRepository* repo = FunctionRepository::self();
00049   Function *f;
00050   
00051   f = new Function ("ARABIC", func_arabic);
00052   repo->add (f);
00053   f = new Function ("CARX", func_carx);
00054   f->setParamCount (2);
00055   repo->add (f);
00056   f = new Function ("CARY", func_cary);
00057   f->setParamCount (2);
00058   repo->add (f);
00059   f = new Function ("DECSEX", func_decsex);
00060   repo->add (f);
00061   f = new Function ("POLR", func_polr);
00062   f->setParamCount (2);
00063   repo->add (f);
00064   f = new Function ("POLA", func_pola);
00065   f->setParamCount (2);
00066   repo->add (f);
00067   f = new Function ("ROMAN", func_roman);
00068   repo->add (f);
00069   f = new Function ("SEXDEC", func_sexdec);
00070   f->setParamCount (1, 3);
00071   repo->add (f);
00072   f = new Function ("ASCIITOCHAR", func_AsciiToChar);
00073   f->setParamCount (1, -1);
00074   f->setAcceptArray ();
00075   repo->add (f);
00076   f = new Function ("CHARTOASCII", func_CharToAscii);
00077   repo->add (f);
00078   f = new Function ("BOOL2INT", func_booltoint);
00079   repo->add (f);
00080   f = new Function ("INT2BOOL", func_inttobool);
00081   repo->add (f);
00082   f = new Function ("BOOL2STRING", func_ToString);
00083   repo->add (f);
00084   f = new Function ("NUM2STRING", func_ToString);
00085   repo->add (f);
00086   f = new Function ("STRING", func_ToString);
00087   repo->add (f);
00088 }
00089 
00090 // Function: POLR
00091 Value func_polr (valVector args, ValueCalc *calc, FuncExtra *)
00092 {
00093   // sqrt (a^2 + b^2)
00094   Value a = args[0];
00095   Value b = args[1];
00096   Value res = calc->sqrt (calc->add (calc->sqr (a), calc->sqr (b)));
00097   return res;
00098 }
00099 
00100 // Function: POLA
00101 Value func_pola (valVector args, ValueCalc *calc, FuncExtra *)
00102 {
00103   // acos (a / polr(a,b))
00104   Value polr = func_polr (args, calc, 0);
00105   if (calc->isZero (polr))
00106     return Value::errorDIV0();
00107   Value res = calc->acos (calc->div (args[0], polr));
00108   return res;
00109 }
00110 
00111 // Function: CARX
00112 Value func_carx (valVector args, ValueCalc *calc, FuncExtra *)
00113 {
00114   // a * cos(b)
00115   Value res = calc->mul (args[0], calc->cos (args[1]));
00116   return res;
00117 }
00118 
00119 // Function: CARY
00120 Value func_cary (valVector args, ValueCalc *calc, FuncExtra *)
00121 {
00122   // a * sin(b)
00123   Value res = calc->mul (args[0], calc->sin (args[1]));
00124   return res;
00125 }
00126 
00127 // Function: DECSEX
00128 Value func_decsex (valVector args, ValueCalc *calc, FuncExtra *)
00129 {
00130   // original function was very compicated, but I see no reason for that,
00131   // when it can be done as simply as this ...
00132   // maybe it was due to all the infrastructure not being ready back then
00133   return calc->conv()->asTime (calc->div (args[0], 24));
00134 }
00135 
00136 // Function: SEXDEC
00137 Value func_sexdec (valVector args, ValueCalc *calc, FuncExtra *)
00138 {
00139   if (args.count() == 1)
00140   {
00141     // convert given value to number
00142     Value time = calc->conv()->asTime (args[0]);
00143     return calc->mul (calc->conv()->asFloat (time), 24);
00144   }
00145   
00146   // convert h/m/s to number of hours
00147   Value h = args[0];
00148   Value m = args[1];
00149 
00150   Value res = calc->add (h, calc->div (m, 60));
00151   if (args.count() == 3) {
00152     Value s = args[2];
00153     res = calc->add (res, calc->div (s, 3600));
00154   }
00155   return res;
00156 }
00157 
00158 // Function: ROMAN
00159 Value func_roman (valVector args, ValueCalc *calc, FuncExtra *)
00160 {
00161   const QCString RNUnits[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
00162   const QCString RNTens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
00163   const QCString RNHundreds[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
00164   const QCString RNThousands[] = {"", "M", "MM", "MMM"};
00165 
00166   // precision loss is not a problem here, as we only use the 0-3999 range
00167   long value = calc->conv()->asInteger (args[0]).asInteger ();
00168   if ((value < 0) || (value > 3999))
00169     return Value::errorNA();
00170   QString result;
00171   result = QString::fromLatin1 (RNThousands[(value / 1000)] +
00172                                 RNHundreds[(value / 100) % 10] +
00173                                 RNTens[(value / 10 ) % 10] +
00174                                 RNUnits[(value) % 10]);
00175   return Value (result);
00176 }
00177 
00178 // convert single roman character to decimal
00179 // return < 0 if invalid
00180 int func_arabic_helper (QChar c)
00181 {
00182   switch (c.upper().unicode())
00183   {
00184     case 'M': return 1000;
00185     case 'D': return 500;
00186     case 'C': return 100;
00187     case 'L': return 50;
00188     case 'X': return 10;
00189     case 'V': return 5;
00190     case 'I': return 1;
00191   }
00192   return -1;
00193 }
00194 
00195 // Function: ARABIC
00196 Value func_arabic (valVector args, ValueCalc *calc, FuncExtra *)
00197 {
00198   QString roman = calc->conv()->asString (args[0]).asString();
00199   if( roman.isEmpty() ) return Value::errorVALUE();
00200 
00201   int val = 0, lastd = 0, d = 0;
00202 
00203   for (unsigned i = 0; i < roman.length(); i++) {
00204     d = func_arabic_helper( roman[i] );
00205     if( d < 0 ) return Value::errorVALUE();
00206 
00207     if( lastd < d ) val -= lastd;
00208       else val += lastd;
00209     lastd = d;
00210   }
00211   if( lastd < d ) val -= lastd;
00212     else val += lastd;
00213 
00214   return Value (val);
00215 }
00216 
00217 // helper for AsciiToChar
00218 void func_a2c_helper (ValueCalc *calc, QString &s, Value val)
00219 {
00220   if (val.isArray()) {
00221     for (unsigned int row = 0; row < val.rows(); ++row)
00222       for (unsigned int col = 0; col < val.columns(); ++col)
00223         func_a2c_helper (calc, s, val.element (col, row));
00224   } else {
00225     int v = calc->conv()->asInteger (val).asInteger();
00226     if (v == 0) return;
00227     QChar c (v);
00228     s = s + c;
00229   }
00230 }
00231 
00232 // Function: AsciiToChar
00233 Value func_AsciiToChar (valVector args, ValueCalc *calc, FuncExtra *)
00234 {
00235   QString str;
00236   for (unsigned int i = 0; i < args.count(); i++)
00237     func_a2c_helper (calc, str, args[i]);
00238   return Value (str);
00239 }
00240 
00241 // Function: CharToAscii
00242 Value func_CharToAscii (valVector args, ValueCalc *calc, FuncExtra *)
00243 {
00244   QString val = calc->conv()->asString (args[0]).asString ();
00245   if (val.length() == 1)
00246     return Value (QString (val[0]));
00247   return Value::errorVALUE();
00248 }
00249 
00250 // Function: inttobool
00251 Value func_inttobool (valVector args, ValueCalc *calc, FuncExtra *)
00252 {
00253   return calc->conv()->asBoolean (args[0]);
00254 }
00255 
00256 // Function: booltoint
00257 Value func_booltoint (valVector args, ValueCalc *calc, FuncExtra *)
00258 {
00259   return calc->conv()->asInteger (args[0]);
00260 }
00261 
00262 // Function: BoolToString, NumberToString, String
00263 Value func_ToString (valVector args, ValueCalc *calc, FuncExtra *)
00264 {
00265   return calc->conv()->asString (args[0]);
00266 }
KDE Home | KDE Accessibility Home | Description of Access Keys