kspread Library API Documentation

kspread_functions_text.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998-2002 The KSpread Team
00003                            www.koffice.org/kspread
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 
00022 // built-in text functions
00023 // please keep it in alphabetical order
00024 
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include <float.h>
00028 
00029 #include <qregexp.h>
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 
00033 #include <koscript_parser.h>
00034 #include <koscript_util.h>
00035 #include <koscript_func.h>
00036 #include <koscript_synext.h>
00037 
00038 #include "kspread_functions.h"
00039 #include "kspread_util.h"
00040 #include "kspread_value.h"
00041 #include "valueparser.h"
00042 #include "valueconverter.h"
00043 
00044 // prototypes
00045 bool kspreadfunc_char( KSContext& context );
00046 bool kspreadfunc_clean( KSContext& context );
00047 bool kspreadfunc_code( KSContext& context );
00048 bool kspreadfunc_compare( KSContext& context );
00049 bool kspreadfunc_concatenate( KSContext& context );
00050 bool kspreadfunc_dollar( KSContext& context );
00051 bool kspreadfunc_exact( KSContext& context );
00052 bool kspreadfunc_find( KSContext& context );
00053 bool kspreadfunc_fixed( KSContext& context );
00054 bool kspreadfunc_join( KSContext& context );
00055 bool kspreadfunc_left( KSContext& context );
00056 bool kspreadfunc_len( KSContext& context );
00057 bool kspreadfunc_lower( KSContext& context );
00058 bool kspreadfunc_mid( KSContext& context );
00059 bool kspreadfunc_proper(KSContext & context);
00060 bool kspreadfunc_regexp(KSContext & context);
00061 bool kspreadfunc_regexpre(KSContext & context);
00062 bool kspreadfunc_replace( KSContext& context );
00063 bool kspreadfunc_rept( KSContext& context );
00064 bool kspreadfunc_rot( KSContext& context );
00065 bool kspreadfunc_right( KSContext& context );
00066 bool kspreadfunc_search( KSContext& context );
00067 bool kspreadfunc_sleek( KSContext& context );
00068 bool kspreadfunc_substitute( KSContext& context );
00069 bool kspreadfunc_t( KSContext& context );
00070 bool kspreadfunc_text( KSContext& context );
00071 bool kspreadfunc_toggle( KSContext& context );
00072 bool kspreadfunc_trim(KSContext& context );
00073 bool kspreadfunc_upper( KSContext& context );
00074 bool kspreadfunc_value( KSContext& context );
00075 
00076 // registers all text functions
00077 void KSpreadRegisterTextFunctions()
00078 {
00079   KSpreadFunctionRepository* repo = KSpreadFunctionRepository::self();
00080 
00081   repo->registerFunction( "CHAR",        kspreadfunc_char );
00082   repo->registerFunction( "CLEAN",       kspreadfunc_clean );
00083   repo->registerFunction( "CODE",        kspreadfunc_code );
00084   repo->registerFunction( "COMPARE",     kspreadfunc_compare ); // KSpread-specific
00085   repo->registerFunction( "CONCATENATE", kspreadfunc_concatenate );
00086   repo->registerFunction( "DOLLAR",      kspreadfunc_dollar );
00087   repo->registerFunction( "EXACT",       kspreadfunc_exact );
00088   repo->registerFunction( "FIND",        kspreadfunc_find );
00089   repo->registerFunction( "FIXED",       kspreadfunc_fixed );
00090   repo->registerFunction( "LEFT",        kspreadfunc_left );
00091   repo->registerFunction( "LEN",         kspreadfunc_len );
00092   repo->registerFunction( "LOWER",       kspreadfunc_lower );
00093   repo->registerFunction( "MID",         kspreadfunc_mid );
00094   repo->registerFunction( "PROPER",      kspreadfunc_proper );
00095   repo->registerFunction( "REGEXP",      kspreadfunc_regexp );
00096   repo->registerFunction( "REGEXPRE",    kspreadfunc_regexpre );
00097   repo->registerFunction( "REPLACE",     kspreadfunc_replace );
00098   repo->registerFunction( "REPT",        kspreadfunc_rept );
00099   repo->registerFunction( "ROT",         kspreadfunc_rot ); // KSpread-specific, like OpenOffice's ROT13
00100   repo->registerFunction( "RIGHT",       kspreadfunc_right );
00101   repo->registerFunction( "SEARCH",      kspreadfunc_search );
00102   repo->registerFunction( "SLEEK",       kspreadfunc_sleek );  // KSpread-specific
00103   repo->registerFunction( "SUBSTITUTE",  kspreadfunc_substitute );
00104   repo->registerFunction( "T",           kspreadfunc_t );
00105   repo->registerFunction( "TEXT",        kspreadfunc_text );
00106   repo->registerFunction( "TOGGLE",      kspreadfunc_toggle ); // KSpread-specific
00107   repo->registerFunction( "TRIM",        kspreadfunc_trim );
00108   repo->registerFunction( "UPPER",       kspreadfunc_upper );
00109   repo->registerFunction( "VALUE",       kspreadfunc_value );
00110 }
00111 
00112 
00113 // Function: CHAR
00114 bool kspreadfunc_char( KSContext& context )
00115 {
00116   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00117 
00118   if ( !KSUtil::checkArgumentsCount( context, 1, "CHAR", true ) )
00119     return false;
00120 
00121   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) &&
00122        !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00123         return false;
00124 
00125   args[0]->cast( KSValue::IntType );
00126   int val = args[0]->intValue();
00127   QString str = QChar( val );
00128 
00129   context.setValue( new KSValue( str ) );
00130   return true;
00131 }
00132 
00133 // Function: CLEAN
00134 bool kspreadfunc_clean( KSContext& context )
00135 {
00136     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00137 
00138     if ( !KSUtil::checkArgumentsCount( context, 1, "CLEAN", true ) )
00139       return false;
00140 
00141     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00142       return false;
00143 
00144     QString str(args[0]->stringValue());
00145     QString result;
00146     QChar   c;
00147     int     i;
00148     int     l = str.length();
00149 
00150     for (i = 0; i < l; ++i)
00151     {
00152       c = str[i];
00153       if (c.isPrint())
00154         result += c;
00155     }
00156 
00157     context.setValue(new KSValue(result));
00158 
00159     return true;
00160 }
00161 
00162 // Function: CODE
00163 bool kspreadfunc_code( KSContext& context )
00164 {
00165   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00166 
00167   if ( !KSUtil::checkArgumentsCount( context, 1, "CODE", true ) )
00168     return false;
00169 
00170   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00171     return false;
00172 
00173   QString str = args[0]->stringValue();
00174   if( str.length() <= 0 )
00175      return false;
00176 
00177   context.setValue( new KSValue( str[0].unicode() ) );
00178   return true;
00179 }
00180 
00181 // Function: COMPARE
00182 bool kspreadfunc_compare( KSContext& context )
00183 {
00184   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00185 
00186   if ( !KSUtil::checkArgumentsCount( context, 3, "COMPARE", true ) )
00187     return false;
00188 
00189   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00190     return false;
00191 
00192   if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00193     return false;
00194 
00195   if ( !KSUtil::checkType( context, args[2], KSValue::BoolType, true ) )
00196     return false;
00197 
00198   int  result = 0;
00199   bool exact = args[2]->boolValue();
00200 
00201   QString s1 = args[0]->stringValue();
00202   QString s2 = args[1]->stringValue();
00203 
00204   if (!exact)
00205     result = s1.lower().localeAwareCompare(s2.lower());
00206   else
00207     result = s1.localeAwareCompare(s2);
00208 
00209   if (result < 0)
00210     result = -1;
00211   else if (result > 0)
00212     result = 1;
00213 
00214   context.setValue( new KSValue(result) );
00215   return true;
00216 }
00217 
00218 static bool kspreadfunc_concatenate_helper( KSContext& context, QValueList<KSValue::Ptr>& args, QString& tmp )
00219 {
00220   QValueList<KSValue::Ptr>::Iterator it = args.begin();
00221   QValueList<KSValue::Ptr>::Iterator end = args.end();
00222   QString tmp2;
00223   for( ; it != end; ++it )
00224   {
00225     if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00226     {
00227       if ( !kspreadfunc_concatenate_helper( context, (*it)->listValue(), tmp ) )
00228         return false;
00229     }
00230     else if ( KSUtil::checkType( context, *it, KSValue::StringType, true ) )
00231       tmp+= (*it)->stringValue();
00232     else if( KSUtil::checkType( context, *it, KSValue::DoubleType, true ) )
00233       tmp+= KGlobal::locale()->formatNumber((*it)->doubleValue());
00234     else
00235       return false;
00236   }
00237   return true;
00238 }
00239 
00240 // Function: CONCATENATE
00241 bool kspreadfunc_concatenate( KSContext& context )
00242 {
00243   QString tmp;
00244   bool b = kspreadfunc_concatenate_helper( context, context.value()->listValue(), tmp );
00245 
00246   if ( b )
00247     context.setValue( new KSValue( tmp ) );
00248 
00249   return b;
00250 }
00251 
00252 // Function: DOLLAR
00253 bool kspreadfunc_dollar( KSContext& context )
00254 {
00255   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00256 
00257   if ( !KSUtil::checkArgumentsCount( context, 1, "DOLLAR", true ) &&
00258        !KSUtil::checkArgumentsCount( context, 2, "DOLLAR", true ) )
00259          return false;
00260 
00261   if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00262     return false;
00263 
00264   double value = args[0]->doubleValue();
00265   int decimals = 2;
00266 
00267   if( KSUtil::checkArgumentsCount( context, 2, "DOLLAR", false ) )
00268     if ( KSUtil::checkType( context, args[0], KSValue::IntType, false ) )
00269       decimals = args[1]->intValue();
00270 
00271   // if decimals < 0, number is rounded
00272   if( decimals < 0 )
00273   {
00274     decimals = -decimals;
00275     value = floor( value/pow(10.0,decimals)+0.5 ) * pow(10.0,decimals);
00276     decimals = 0;
00277   }
00278 
00279   // do round, because formatMoney doesn't
00280   value = floor( value * pow(10.0,decimals)+0.5) / pow(10.0,decimals) ;
00281 
00282   // -30 should be displayed as (30)
00283   QString result = KGlobal::locale()->formatMoney( fabs( value ),
00284     QString::null, decimals );
00285   if( value < 0 )
00286     result = "(" + result + ")";
00287 
00288   context.setValue( new KSValue( result ) );
00289   return true;
00290 }
00291 
00292 // Function: EXACT
00293 bool kspreadfunc_exact( KSContext& context )
00294 {
00295   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00296 
00297   if ( !KSUtil::checkArgumentsCount( context, 2, "EXACT", true ) )
00298     return false;
00299 
00300   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00301     return false;
00302   if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00303     return false;
00304   bool exact = args[1]->stringValue() == args[0]->stringValue();
00305   context.setValue( new KSValue(exact) );
00306   return true;
00307 }
00308 
00309 // Function: FIND
00310 bool kspreadfunc_find( KSContext& context )
00311 {
00312     QString find_text, within_text;
00313     int start_num = 1;
00314 
00315     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00316 
00317     if ( !KSUtil::checkArgumentsCount( context, 2, "FIND", true ) &&
00318          !KSUtil::checkArgumentsCount( context, 3, "FIND", true ) )
00319            return false;
00320 
00321     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00322       return false;
00323 
00324     if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00325       return false;
00326 
00327     if ( KSUtil::checkArgumentsCount( context, 3, "FIND", false ) )
00328       if ( KSUtil::checkType( context, args[2], KSValue::IntType, false ) )
00329          start_num = args[2]->intValue();
00330 
00331     find_text = args[0]->stringValue();
00332     within_text = args[1]->stringValue();
00333 
00334     // conforms to Excel behaviour
00335     if( start_num <= 0 ) return false;
00336     if( start_num > (int)within_text.length() ) return false;
00337 
00338     int pos = within_text.find( find_text, start_num-1 );
00339     if( pos < 0 ) return false;
00340 
00341     context.setValue( new KSValue( pos + 1 ) );
00342     return true;
00343 }
00344 
00345 // Function: FIXED
00346 bool kspreadfunc_fixed( KSContext& context )
00347 {
00348   int decimals = 2;
00349   bool no_commas = FALSE;
00350 
00351   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00352 
00353   if ( !KSUtil::checkArgumentsCount( context, 1, "FIXED", true ) &&
00354        !KSUtil::checkArgumentsCount( context, 2, "FIXED", true ) &&
00355        !KSUtil::checkArgumentsCount( context, 3, "FIXED", true ) )
00356          return false;
00357 
00358   if ( !KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00359     return false;
00360 
00361   if ( KSUtil::checkArgumentsCount( context, 2, "FIXED", false ) ||
00362        KSUtil::checkArgumentsCount( context, 3, "FIXED", false ) )
00363     if ( KSUtil::checkType( context, args[1], KSValue::IntType, false ) )
00364       decimals = args[1]->intValue();
00365 
00366   if ( KSUtil::checkArgumentsCount( context, 3, "FIXED", false ) )
00367     if ( KSUtil::checkType( context, args[2], KSValue::BoolType, false ) )
00368        no_commas = args[2]->boolValue();
00369 
00370   double number = args[0]->doubleValue();
00371 
00372   QString result;
00373 
00374   // unfortunately, we can't just use KLocale::formatNumber because
00375   // * if decimals < 0, number is rounded
00376   // * if no_commas is TRUE, thousand separators shouldn't show up
00377 
00378   if( decimals < 0 )
00379   {
00380     decimals = -decimals;
00381     number = floor( number/pow(10.0,decimals)+0.5 ) * pow(10.0,decimals);
00382     decimals = 0;
00383   }
00384 
00385   bool neg = number < 0;
00386   result = QString::number( neg ? -number:number, 'f', decimals );
00387 
00388   int pos = result.find('.');
00389   if (pos == -1) pos = result.length();
00390     else result.replace(pos, 1, KGlobal::locale()->decimalSymbol());
00391   if( !no_commas )
00392     while (0 < (pos -= 3))
00393       result.insert(pos, KGlobal::locale()->thousandsSeparator());
00394 
00395   result.prepend( neg ? KGlobal::locale()->negativeSign():
00396     KGlobal::locale()->positiveSign() );
00397 
00398   context.setValue( new KSValue( result ) );
00399   return true;
00400 }
00401 
00402 // Function: LEFT
00403 bool kspreadfunc_left( KSContext& context )
00404 {
00405     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00406 
00407     bool hasNoSecondParam = KSUtil::checkArgumentsCount( context, 1, "left", false );
00408 
00409     if ( !KSUtil::checkArgumentsCount( context, 2, "left", false ) &&
00410          !hasNoSecondParam)
00411       return false;
00412 
00413     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00414       return false;
00415 
00416     int nb;
00417 
00418     if(hasNoSecondParam)
00419         nb = 1;
00420     else
00421     {
00422         if( KSUtil::checkType( context, args[1], KSValue::DoubleType, false ) )
00423           nb = (int) args[1]->doubleValue();
00424         else if( KSUtil::checkType( context, args[1], KSValue::IntType, false ) )
00425           nb = args[1]->intValue();
00426         else
00427           return false;
00428     }
00429 
00430     QString tmp = args[0]->stringValue().left(nb);
00431     context.setValue( new KSValue( tmp ) );
00432     return true;
00433 }
00434 
00435 // Function: LEN
00436 bool kspreadfunc_len( KSContext& context )
00437 {
00438   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00439 
00440   if ( !KSUtil::checkArgumentsCount( context, 1, "len", true ) )
00441     return false;
00442 
00443   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00444     return false;
00445 
00446   int nb=args[0]->stringValue().length();
00447   context.setValue( new KSValue(nb));
00448   return true;
00449 }
00450 
00451 // Function: LOWER
00452 bool kspreadfunc_lower( KSContext& context )
00453 {
00454     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00455 
00456     if ( !KSUtil::checkArgumentsCount( context, 1, "lower", true ) )
00457       return false;
00458 
00459     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00460       return false;
00461 
00462     QString tmp = args[0]->stringValue().lower();
00463     context.setValue( new KSValue( tmp ) );
00464     return true;
00465 }
00466 
00467 // Function: MID
00468 bool kspreadfunc_mid( KSContext& context )
00469 {
00470     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00471 
00472     uint len = 0xffffffff;
00473     if ( KSUtil::checkArgumentsCount( context, 3, "mid", false ) )
00474     {
00475       if( KSUtil::checkType( context, args[2], KSValue::DoubleType, false ) )
00476         len = (uint) args[2]->doubleValue();
00477       else if( KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00478         len = (uint) args[2]->intValue();
00479       else
00480         return false;
00481     }
00482     else if ( !KSUtil::checkArgumentsCount( context, 2, "mid", true ) )
00483       return false;
00484 
00485     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00486       return false;
00487     int pos;
00488     if( KSUtil::checkType( context, args[1], KSValue::DoubleType, false ) )
00489       pos = (int) args[1]->doubleValue();
00490     else if( KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00491       pos = args[1]->intValue();
00492     else
00493       return false;
00494 
00495     // Excel compatible
00496     pos--;
00497 
00498     QString tmp = args[0]->stringValue().mid( pos, len );
00499     context.setValue( new KSValue(tmp));
00500     return true;
00501 }
00502 
00503 // Function: PROPER
00504 bool kspreadfunc_proper(KSContext & context)
00505 {
00506   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00507 
00508   if (args.count() != 1)
00509     return false;
00510 
00511   QString str;
00512 
00513   if (KSUtil::checkType(context, args[0],
00514                         KSValue::StringType, true))
00515   {
00516     unsigned int i;
00517     str = args[0]->stringValue().lower();
00518     QChar f;
00519     bool  first = true;
00520 
00521     for (i = 0; i < str.length(); ++i)
00522     {
00523       if (first)
00524       {
00525         f = str[i];
00526         if (f.isNumber())
00527           continue;
00528 
00529         f = f.upper();
00530 
00531         str[i] = f;
00532         first = false;
00533 
00534         continue;
00535       }
00536 
00537       if (str[i] == ' ' || str[i] == '-')
00538         first = true;
00539     }
00540   }
00541 
00542   context.setValue(new KSValue(str));
00543 
00544   return true;
00545 }
00546 
00547 // Function: REGEXP
00548 bool kspreadfunc_regexp(KSContext & context)
00549 {
00550   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00551 
00552   int ac = args.count ();
00553   if ((ac < 2) || (ac > 4))
00554     return false;
00555 
00556   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00557     return false;
00558   if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00559     return false;
00560   if ( (ac >= 3) && ( !KSUtil::checkType( context, args[2], KSValue::StringType, true ) ))
00561     return false;
00562   if ( (ac == 4) && (!KSUtil::checkType( context, args[3], KSValue::IntType, true ) ) )
00563     return false;
00564 
00565   QRegExp exp( args[1]->stringValue() );
00566   if ( !exp.isValid() )
00567     return false;
00568 
00569   QString s( args[0]->stringValue() );
00570   QString defText( (ac >= 3) ? args[2]->stringValue() : QString::null );
00571 
00572   int bkref = (ac == 4) ? args[3]->intValue() : 0;
00573   if (bkref < 0)
00574     return false;  //strange back-reference
00575   
00576   QString returnValue;
00577   
00578   int pos = exp.search( s );
00579   if (pos == -1)
00580     returnValue = defText;
00581   else
00582     returnValue = exp.cap (bkref);
00583 
00584   context.setValue( new KSValue( returnValue ) );
00585   return true;
00586 }
00587 
00588 // Function: REGEXPRE
00589 bool kspreadfunc_regexpre(KSContext & context)
00590 {
00591   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00592 
00593   if (args.count() != 3)
00594     return false;
00595 
00596   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00597     return false;
00598   if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00599     return false;
00600   if ( !KSUtil::checkType( context, args[2], KSValue::StringType, true ) )
00601     return false;
00602 
00603   kdDebug() << "Got parameter" << endl;
00604 
00605   QRegExp exp( args[1]->stringValue() );
00606   //  exp.setWildcard( true );
00607   if ( !exp.isValid() )
00608     return false;
00609 
00610   QString s( args[0]->stringValue() );
00611   QString str( args[2]->stringValue() );
00612 
00613   kdDebug() << "Search: " << args[1]->stringValue() << " in " << s
00614             << ", Result: " << exp.search( s ) << endl;
00615 
00616   int pos = 0;
00617   while ( ( pos = exp.search( s, pos ) ) != -1 )
00618   {
00619     int i = exp.matchedLength();
00620     s = s.replace( pos, i, str );
00621     pos += str.length();
00622   }
00623 
00624   context.setValue( new KSValue( s ) );
00625   return true;
00626 }
00627 
00628 // Function: REPLACE
00629 bool kspreadfunc_replace( KSContext& context )
00630 {
00631   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00632 
00633   if ( !KSUtil::checkArgumentsCount( context, 4, "REPLACE", true ) )
00634     return false;
00635 
00636   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00637     return false;
00638 
00639   if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00640     return false;
00641 
00642   if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00643     return false;
00644 
00645   if ( !KSUtil::checkType( context, args[3], KSValue::StringType, true ) )
00646     return false;
00647 
00648   QString text = args[0]->stringValue();
00649   int pos = args[1]->intValue();
00650   int len = args[2]->intValue();
00651   QString new_text = args[3]->stringValue();
00652 
00653   if( pos < 0 ) pos = 0;
00654 
00655   QString result = text.replace( pos-1, len, new_text );
00656   context.setValue( new KSValue( result ) );
00657 
00658   return true;
00659 }
00660 
00661 // Function: REPT
00662 bool kspreadfunc_rept( KSContext& context )
00663 {
00664   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00665 
00666   if ( !KSUtil::checkArgumentsCount( context, 2, "REPT", true ) )
00667     return false;
00668 
00669   if( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
00670     return false;
00671 
00672   QString s;
00673 
00674   // this is code duplication, can be rewritten once we have KSpreadFormat
00675   if( KSUtil::checkType( context, args[0], KSValue::StringType, false ) )
00676     s = args[0]->stringValue();
00677 
00678   else if( KSUtil::checkType( context, args[0], KSValue::BoolType, false ) )
00679     s = args[0]->boolValue() ? i18n("True") : i18n("False");
00680 
00681   else if( KSUtil::checkType( context, args[0], KSValue::DoubleType, false ) )
00682     s = KGlobal::locale()->formatNumber( args[0]->doubleValue() );
00683 
00684   else if( KSUtil::checkType( context, args[0], KSValue::TimeType, false ) )
00685     s = KGlobal::locale()->formatTime( args[0]->timeValue() );
00686 
00687   else if( KSUtil::checkType( context, args[0], KSValue::DateType, false ) )
00688     s = KGlobal::locale()->formatDate( args[0]->dateValue() );
00689 
00690   else if( KSUtil::checkType( context, args[0], KSValue::IntType, false ) )
00691     s = KGlobal::locale()->formatNumber( args[0]->intValue() );
00692 
00693   else return false;
00694 
00695   int nb=(int) args[1]->doubleValue();
00696   QString result;
00697   for (int i=0 ;i<nb;i++) result += s;
00698   context.setValue( new KSValue( result ) );
00699   return true;
00700 }
00701 
00702 // Function: RIGHT
00703 bool kspreadfunc_right( KSContext& context )
00704 {
00705     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00706 
00707     bool hasNoSecondParam = KSUtil::checkArgumentsCount( context, 1, "right", false );
00708 
00709     if ( !KSUtil::checkArgumentsCount( context, 2, "right", false ) &&
00710          !hasNoSecondParam)
00711       return false;
00712 
00713     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00714       return false;
00715 
00716     int nb;
00717 
00718     if(hasNoSecondParam)
00719         nb = 1;
00720     else
00721     {
00722         if( KSUtil::checkType( context, args[1], KSValue::DoubleType, false ) )
00723           nb = (int) args[1]->doubleValue();
00724         else if( KSUtil::checkType( context, args[1], KSValue::IntType, false ) )
00725           nb = args[1]->intValue();
00726         else
00727           return false;
00728     }
00729 
00730     QString tmp = args[0]->stringValue().right(nb);
00731     context.setValue( new KSValue(tmp));
00732     return true;
00733 }
00734 
00735 // Function: ROT
00736 bool kspreadfunc_rot( KSContext& context )
00737 {
00738   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00739 
00740   if ( !KSUtil::checkArgumentsCount( context, 1, "ROT", true ) )
00741     return false;
00742 
00743   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00744     return false;
00745 
00746   QString text = args[0]->stringValue();
00747 
00748   for( unsigned i=0; i<text.length(); i++ )
00749   {
00750     unsigned c = text[i].upper().unicode();
00751     if( ( c >= 'A' ) && ( c <= 'M' ) )
00752       text[i] = QChar( text[i].unicode() + 13);
00753     if( ( c >= 'N' ) && ( c <= 'Z' ) )
00754       text[i] = QChar( text[i].unicode() - 13);
00755   }
00756 
00757   context.setValue( new KSValue( text ) );
00758   return true;
00759 }
00760 
00761 // Function: SEARCH
00762 bool kspreadfunc_search( KSContext& context )
00763 {
00764     QString find_text, within_text;
00765     int start_num = 1;
00766 
00767     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00768 
00769     if ( KSUtil::checkArgumentsCount( context, 3, "SEARCH", false ) )
00770     {
00771       if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00772         return false;
00773       start_num = args[2]->intValue();
00774     }
00775     else if ( !KSUtil::checkArgumentsCount( context, 2, "SEARCH", true ) )
00776       return false;
00777 
00778     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00779       return false;
00780 
00781     if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00782       return false;
00783 
00784     find_text = args[0]->stringValue();
00785     within_text = args[1]->stringValue();
00786 
00787     // conforms to Excel behaviour
00788     if( start_num <= 0 ) return false;
00789     if( start_num > (int)within_text.length() ) return false;
00790 
00791     // use globbing feature of QRegExp
00792     QRegExp regex( find_text, false, true );
00793     int pos = within_text.find( regex, start_num-1 );
00794     if( pos < 0 ) return false;
00795 
00796     context.setValue( new KSValue( pos + 1 ) );
00797     return true;
00798 }
00799 
00800 // Function: SLEEK
00801 bool kspreadfunc_sleek( KSContext& context )
00802 {
00803     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00804 
00805     if ( !KSUtil::checkArgumentsCount( context, 1, "SLEEK", true ) )
00806       return false;
00807 
00808     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00809       return false;
00810 
00811     QString str(args[0]->stringValue());
00812     QString result;
00813     QChar   c;
00814     int     i;
00815     int     l = str.length();
00816 
00817     for (i = 0; i < l; ++i)
00818     {
00819       c = str[i];
00820       if (!c.isSpace())
00821         result += c;
00822     }
00823 
00824     context.setValue(new KSValue(result));
00825 
00826     return true;
00827 }
00828 
00829 // Function: SUBSTITUTE
00830 bool kspreadfunc_substitute( KSContext& context )
00831 {
00832   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00833 
00834   int num = 1;
00835   bool all = true;
00836 
00837   if ( KSUtil::checkArgumentsCount( context, 4, "SUBSTITUTE", false ) )
00838   {
00839     if ( !KSUtil::checkType( context, args[3], KSValue::IntType, true ) )
00840       return false;
00841     num = args[3]->intValue();
00842     all = false;
00843   }
00844   else
00845   if ( !KSUtil::checkArgumentsCount( context, 3, "SUBSTITUTE", true ) )
00846     return false;
00847 
00848   if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00849       return false;
00850 
00851   if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00852       return false;
00853 
00854   if ( !KSUtil::checkType( context, args[2], KSValue::StringType, true ) )
00855       return false;
00856 
00857   QString text = args[0]->stringValue();
00858   QString old_text = args[1]->stringValue();
00859   QString new_text = args[2]->stringValue();
00860 
00861   if( num <= 0 ) return false;
00862 
00863   QString result = text;
00864 
00865   int p = result.find( old_text );
00866   while ( ( p != -1 ) && ( num > 0 ) )
00867   {
00868     result.replace( p, old_text.length(), new_text );
00869     p = result.find( old_text );
00870     if( !all ) num--;
00871   }
00872 
00873   context.setValue( new KSValue( result ) );
00874 
00875   return true;
00876 
00877 
00878   context.setValue( new KSValue( result ));
00879   return true;
00880 }
00881 
00882 // Function: T
00883 bool kspreadfunc_t( KSContext& context )
00884 {
00885   // almost identical with the TEXT funcion
00886   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00887 
00888   if ( !KSUtil::checkArgumentsCount( context, 1, "T", true ) )
00889     return false;
00890 
00891   KSpreadValue val;
00892   
00893   if( KSUtil::checkType( context, args[0], KSValue::StringType, false ) )
00894     val.setValue (args[0]->stringValue());
00895   
00896   else if( KSUtil::checkType( context, args[0], KSValue::TimeType, false ) )
00897     val.setValue (args[0]->timeValue());
00898   
00899   else if( KSUtil::checkType( context, args[0], KSValue::DateType, false ) )
00900     val.setValue (args[0]->dateValue());
00901   
00902   else if( KSUtil::checkType( context, args[0], KSValue::DoubleType, false ) )
00903     val.setValue (args[0]->doubleValue());
00904   
00905   else if( KSUtil::checkType( context, args[0], KSValue::IntType, false ) )
00906     val.setValue (args[0]->intValue());
00907   
00908   else if( KSUtil::checkType( context, args[0], KSValue::BoolType, false ) )
00909     val.setValue (args[0]->boolValue());
00910   
00911   // temporary hack for value conversion  
00912   KSpread::ValueParser *parser = new KSpread::ValueParser( KGlobal::locale() );
00913   KSpread::ValueConverter *converter = new KSpread::ValueConverter( parser );
00914   val = converter->asString (val);
00915   delete converter;
00916   delete parser;
00917 
00918   context.setValue( new KSValue( val.asString() ));
00919   return true;
00920 }
00921 
00922 // Function: TEXT
00923 bool kspreadfunc_text( KSContext& context )
00924 {
00925   //currently the same as the T function. Well, almost...
00926   
00927   QString format_text;
00928 
00929   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00930 
00931   if ( KSUtil::checkArgumentsCount( context, 2, "TEXT", false ) )
00932   {
00933     if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00934       return false;
00935     format_text = args[1]->stringValue();
00936   }
00937   else if ( !KSUtil::checkArgumentsCount( context, 1, "TEXT", true ) )
00938     return false;
00939 
00940   // not yet Excel-compatible because format_text is omitted
00941 
00942   // currently the same as T
00943   
00944   KSpreadValue val;
00945   
00946   if( KSUtil::checkType( context, args[0], KSValue::StringType, false ) )
00947     val.setValue (args[0]->stringValue());
00948   
00949   else if( KSUtil::checkType( context, args[0], KSValue::DoubleType, false ) )
00950     val.setValue (args[0]->doubleValue());
00951   
00952   else if( KSUtil::checkType( context, args[0], KSValue::TimeType, false ) )
00953     val.setValue (args[0]->timeValue());
00954   
00955   else if( KSUtil::checkType( context, args[0], KSValue::DateType, false ) )
00956     val.setValue (args[0]->dateValue());
00957   
00958   else if( KSUtil::checkType( context, args[0], KSValue::IntType, false ) )
00959     val.setValue (args[0]->intValue());
00960   
00961   else if( KSUtil::checkType( context, args[0], KSValue::BoolType, false ) )
00962     val.setValue (args[0]->boolValue());
00963     
00964   // temporary hack for value conversion  
00965   KSpread::ValueParser *parser = new KSpread::ValueParser( KGlobal::locale() );
00966   KSpread::ValueConverter *converter = new KSpread::ValueConverter( parser );
00967   val = converter->asString (val);
00968   delete converter;
00969   delete parser;
00970 
00971   context.setValue( new KSValue( val.asString() ));
00972   return true;
00973 }
00974 
00975 // Function: TOGGLE
00976 bool kspreadfunc_toggle( KSContext& context )
00977 {
00978     QValueList<KSValue::Ptr>& args = context.value()->listValue();
00979 
00980     if ( !KSUtil::checkArgumentsCount( context, 1, "TOGGLE", true ) )
00981       return false;
00982 
00983     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00984       return false;
00985 
00986     QString str(args[0]->stringValue());
00987     int i;
00988     int l = str.length();
00989 
00990     for (i = 0; i < l; ++i)
00991     {
00992       QChar c = str[i];
00993       QChar lc = c.lower();
00994       QChar uc = c.upper();
00995 
00996       if (c == lc) // it is in lowercase
00997         str[i] = c.upper();
00998       else if (c == uc) // it is in uppercase
00999         str[i] = c.lower();
01000     }
01001 
01002     context.setValue( new KSValue( str ) );
01003 
01004     return true;
01005 }
01006 
01007 // Function: TRIM
01008 bool kspreadfunc_trim(KSContext& context )
01009 {
01010     QValueList<KSValue::Ptr>& args = context.value()->listValue();
01011 
01012     if ( !KSUtil::checkArgumentsCount( context, 1, "trim", true ) )
01013         return false;
01014 
01015     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
01016         return false;
01017     QString text=args[0]->stringValue().simplifyWhiteSpace();
01018     context.setValue( new KSValue(text));
01019     return true;
01020 }
01021 
01022 // Function: UPPER
01023 bool kspreadfunc_upper( KSContext& context )
01024 {
01025     QValueList<KSValue::Ptr>& args = context.value()->listValue();
01026 
01027     if ( !KSUtil::checkArgumentsCount( context, 1, "upper", true ) )
01028       return false;
01029 
01030     if ( !KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
01031       return false;
01032 
01033     QString tmp = args[0]->stringValue().upper();
01034     context.setValue( new KSValue( tmp ) );
01035     return true;
01036 }
01037 
01038 // Function: VALUE
01039 bool kspreadfunc_value( KSContext& context )
01040 {
01041   //currently the same as the N function
01042   
01043   QValueList<KSValue::Ptr>& args = context.value()->listValue();
01044 
01045   if ( !KSUtil::checkArgumentsCount( context, 1, "VALUE", true ) )
01046     return false;
01047 
01048   KSpreadValue val;
01049   
01050   if( KSUtil::checkType( context, args[0], KSValue::StringType, false ) )
01051     val.setValue (args[0]->stringValue());
01052   
01053   else if( KSUtil::checkType( context, args[0], KSValue::DoubleType, false ) )
01054     val.setValue (args[0]->doubleValue());
01055   
01056   else if( KSUtil::checkType( context, args[0], KSValue::TimeType, false ) )
01057     val.setValue (args[0]->timeValue());
01058   
01059   else if( KSUtil::checkType( context, args[0], KSValue::DateType, false ) )
01060     val.setValue (args[0]->dateValue());
01061   
01062   else if( KSUtil::checkType( context, args[0], KSValue::IntType, false ) )
01063     val.setValue (args[0]->intValue());
01064   
01065   else if( KSUtil::checkType( context, args[0], KSValue::BoolType, false ) )
01066     val.setValue (args[0]->boolValue());
01067     
01068   // temporary hack for value conversion  
01069   KSpread::ValueParser *parser = new KSpread::ValueParser( KGlobal::locale() );
01070   KSpread::ValueConverter *converter = new KSpread::ValueConverter( parser );
01071   val = converter->asString (val);
01072   delete converter;
01073   delete parser;
01074 
01075   context.setValue( new KSValue( val.asFloat() ));
01076   
01077   return true;
01078 }
KDE Logo
This file is part of the documentation for kspread Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:43:12 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003