| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# ktraderparsetree.cpp

    00001 /* This file is part of the KDE project
    00002    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
    00003
    00004    This library is free software; you can redistribute it and/or
    00005    modify it under the terms of the GNU Library General Public
    00006    License as published by the Free Software Foundation; either
    00007    version 2 of the License, or (at your option) any later version.
    00008
    00009    This library is distributed in the hope that it will be useful,
    00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012    Library General Public License for more details.
    00013
    00014    You should have received a copy of the GNU Library General Public License
    00015    along with this library; see the file COPYING.LIB.  If not, write to
    00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00017    Boston, MA 02111-1307, USA.
    00018 */
    00019
    00020 #include "ktraderparsetree.h"
    00021
    00022 namespace KIO {
    00023
    00024 bool ParseTreeOR::eval( ParseContext *_context ) const
    00025 {
    00026   ParseContext c1( _context );
    00027   ParseContext c2( _context );
    00028
    00029 // don't evaluate both expressions but return immediately
    00030 // if the first one of them succeeds. Otherwise queries like
    00031 // ((not exist Blah) or (Blah == 'Foo')) do not work, because
    00032 // the evaluation of the second term ends up in a fatal error
    00033 // (Simon)
    00034
    00035   if ( !m_pLeft->eval( &c1 ) )
    00036     return false;
    00037
    00038   if ( c1.type != ParseContext::T_BOOL )
    00039     return false;
    00040
    00041   _context->b = c1.b;
    00042   _context->type = ParseContext::T_BOOL;
    00043   if ( c1.b )
    00044     return true;
    00045
    00046   if ( !m_pRight->eval( &c2 ) )
    00047     return false;
    00048
    00049   if ( c2.type != ParseContext::T_BOOL )
    00050     return false;
    00051
    00052   _context->b = ( c1.b || c2.b );
    00053   _context->type = ParseContext::T_BOOL;
    00054
    00055   return true;
    00056 }
    00057
    00058 bool ParseTreeAND::eval( ParseContext *_context ) const
    00059 {
    00060   _context->type = ParseContext::T_BOOL;
    00061
    00062   ParseContext c1( _context );
    00063   ParseContext c2( _context );
    00064   if ( !m_pLeft->eval( &c1 ) )
    00065     return false;
    00066   if ( c1.type != ParseContext::T_BOOL )
    00067     return false;
    00068   if ( !c1.b )
    00069   {
    00070     _context->b = false;
    00071     return true;
    00072   }
    00073
    00074   if ( !m_pRight->eval( &c2 ) )
    00075     return false;
    00076   if ( c2.type != ParseContext::T_BOOL )
    00077     return false;
    00078
    00079   _context->b = ( c1.b && c2.b );
    00080
    00081   return true;
    00082 }
    00083
    00084 bool ParseTreeCALC::eval( ParseContext *_context ) const
    00085 {
    00086   ParseContext c1( _context );
    00087   ParseContext c2( _context );
    00088   if ( !m_pLeft->eval( &c1 ) )
    00089     return false;
    00090   if ( !m_pRight->eval( &c2 ) )
    00091     return false;
    00092
    00093   // Bool extension
    00094   if ( c1.type != ParseContext::T_NUM && c1.type != ParseContext::T_DOUBLE && c1.type != ParseContext::T_BOOL )
    00095     return false;
    00096   // Bool extension
    00097   if ( c2.type != ParseContext::T_NUM && c2.type != ParseContext::T_DOUBLE && c2.type != ParseContext::T_BOOL )
    00098     return false;
    00099   // Bool extension
    00100   if ( c1.type == ParseContext::T_BOOL && c2.type == ParseContext::T_BOOL )
    00101     return false;
    00102
    00106   if ( c1.type == ParseContext::T_NUM && c2.type == ParseContext::T_DOUBLE )
    00107   {
    00108     c1.type = ParseContext::T_DOUBLE;
    00109     c1.f = (double)c1.i;
    00110   }
    00111   else if ( c1.type == ParseContext::T_DOUBLE && c2.type == ParseContext::T_NUM )
    00112   {
    00113     c2.type = ParseContext::T_DOUBLE;
    00114     c2.f = (double)c2.i;
    00115   }
    00116   // Bool extension
    00117   else if ( c1.type == ParseContext::T_BOOL && c2.type == ParseContext::T_NUM )
    00118   {
    00119     c1.type = ParseContext::T_NUM;
    00120     if ( c1.b )
    00121       c1.i = 1;
    00122     else
    00123       c1.i = -1;
    00124   }
    00125   // Bool extension
    00126   else if ( c1.type == ParseContext::T_BOOL && c2.type == ParseContext::T_DOUBLE )
    00127   {
    00128     c1.type = ParseContext::T_DOUBLE;
    00129     if ( c1.b )
    00130       c1.f = 1.0;
    00131     else
    00132       c1.f = -1.0;
    00133   }
    00134   // Bool extension
    00135   else if ( c1.type == ParseContext::T_NUM && c2.type == ParseContext::T_BOOL )
    00136   {
    00137     c2.type = ParseContext::T_NUM;
    00138     if ( c2.b )
    00139       c2.i = 1;
    00140     else
    00141       c2.i = -1;
    00142   }
    00143   // Bool extension
    00144   else if ( c1.type == ParseContext::T_DOUBLE && c2.type == ParseContext::T_BOOL )
    00145   {
    00146     c2.type = ParseContext::T_DOUBLE;
    00147     if ( c2.b )
    00148       c2.f = 1.0;
    00149     else
    00150       c2.f = -1.0;
    00151   }
    00152
    00153   _context->type = c1.type;
    00154
    00158   switch( m_cmd )
    00159   {
    00160   case 1: /* Add */
    00161     if ( c1.type == ParseContext::T_DOUBLE )
    00162     {
    00163       _context->f = ( c1.f + c2.f );
    00164       return true;
    00165     }
    00166     if ( c1.type == ParseContext::T_NUM )
    00167     {
    00168       _context->i = ( c1.i + c2.i );
    00169       return true;
    00170     }
    00171     break;
    00172   case 2: /* Sub */
    00173     if ( c1.type == ParseContext::T_DOUBLE )
    00174     {
    00175       _context->f = ( c1.f - c2.f );
    00176       return true;
    00177     }
    00178     if ( c1.type == ParseContext::T_NUM )
    00179     {
    00180       _context->i = ( c1.i - c2.i );
    00181       return true;
    00182     }
    00183     break;
    00184   case 3: /* Mul */
    00185     if ( c1.type == ParseContext::T_DOUBLE )
    00186     {
    00187       //cout << "Double Mult" << endl;
    00188       _context->f = ( c1.f * c2.f );
    00189       return true;
    00190     }
    00191     if ( c1.type == ParseContext::T_NUM )
    00192     {
    00193       _context->i = ( c1.i * c2.i );
    00194       return true;
    00195     }
    00196     break;
    00197   case 4: /* Div */
    00198     if ( c1.type == ParseContext::T_DOUBLE )
    00199     {
    00200       _context->f = ( c1.f / c2.f );
    00201       return true;
    00202     }
    00203     if ( c1.type == ParseContext::T_NUM )
    00204     {
    00205       _context->i = ( c1.i / c2.i );
    00206       return true;
    00207     }
    00208     break;
    00209   }
    00210
    00211   return false;
    00212 }
    00213
    00214 bool ParseTreeCMP::eval( ParseContext *_context ) const
    00215 {
    00216   //cout << "CMP 1 cmd=" << m_cmd << endl;
    00217   ParseContext c1( _context );
    00218   ParseContext c2( _context );
    00219   if ( !m_pLeft->eval( &c1 ) )
    00220     return false;
    00221
    00222   if ( !m_pRight->eval( &c2 ) )
    00223     return false;
    00224
    00228   if ( c1.type == ParseContext::T_NUM && c2.type == ParseContext::T_DOUBLE )
    00229   {
    00230     c1.type = ParseContext::T_DOUBLE;
    00231     c1.f = (double)c1.i;
    00232   }
    00233   else if ( c1.type == ParseContext::T_DOUBLE && c2.type == ParseContext::T_NUM )
    00234   {
    00235     c2.type = ParseContext::T_DOUBLE;
    00236     c2.f = (double)c2.i;
    00237   }
    00238
    00242   _context->type = ParseContext::T_BOOL;
    00243
    00244   switch( m_cmd )
    00245   {
    00246   case 1: /* EQ */
    00247     if ( c1.type != c2.type )
    00248     {
    00249       _context->b = false;
    00250       return true;
    00251     }
    00252     if ( c1.type == ParseContext::T_STRING )
    00253     {
    00254       _context->b = ( c1.str == c2.str );
    00255       return true;
    00256     }
    00257     if ( c1.type == ParseContext::T_BOOL )
    00258     {
    00259       _context->b = ( c1.b == c2.b );
    00260       return true;
    00261     }
    00262     if ( c1.type == ParseContext::T_DOUBLE )
    00263     {
    00264       _context->b = ( c1.f == c2.f );
    00265       return true;
    00266     }
    00267     if ( c1.type == ParseContext::T_NUM )
    00268     {
    00269       _context->b = ( c1.i == c2.i );
    00270       return true;
    00271     }
    00272     break;
    00273   case 2: /* NEQ */
    00274     if ( c1.type != c2.type )
    00275     {
    00276       _context->b = true;
    00277       return true;
    00278     }
    00279     if ( c1.type == ParseContext::T_STRING )
    00280     {
    00281       _context->b = ( c1.str != c2.str );
    00282       return true;
    00283     }
    00284     if ( c1.type == ParseContext::T_BOOL )
    00285     {
    00286       _context->b = ( c1.b != c2.b );
    00287       return true;
    00288     }
    00289     if ( c1.type == ParseContext::T_DOUBLE )
    00290     {
    00291       _context->b = ( c1.f != c2.f );
    00292       return true;
    00293     }
    00294     if ( c1.type == ParseContext::T_NUM )
    00295     {
    00296       _context->b = ( c1.i != c2.i );
    00297       return true;
    00298     }
    00299     break;
    00300   case 3: /* GEQ */
    00301     if ( c1.type != c2.type )
    00302     {
    00303       _context->b = false;
    00304       return true;
    00305     }
    00306     if ( c1.type == ParseContext::T_DOUBLE )
    00307     {
    00308       _context->b = ( c1.f >= c2.f );
    00309       return true;
    00310     }
    00311     if ( c1.type == ParseContext::T_NUM )
    00312     {
    00313       _context->b = ( c1.i >= c2.i );
    00314       return true;
    00315     }
    00316     _context->b = false;
    00317     return true;
    00318
    00319   case 4: /* LEQ */
    00320     if ( c1.type != c2.type )
    00321     {
    00322       _context->b = false;
    00323       return true;
    00324     }
    00325     if ( c1.type == ParseContext::T_DOUBLE )
    00326     {
    00327       _context->b = ( c1.f <= c2.f );
    00328       return true;
    00329     }
    00330     if ( c1.type == ParseContext::T_NUM )
    00331     {
    00332       _context->b = ( c1.i <= c2.i );
    00333       return true;
    00334     }
    00335     _context->b = false;
    00336     return true;
    00337
    00338   case 5: /* < */
    00339     if ( c1.type != c2.type )
    00340     {
    00341       _context->b = false;
    00342       return true;
    00343     }
    00344     if ( c1.type == ParseContext::T_DOUBLE )
    00345     {
    00346       _context->b = ( c1.f < c2.f );
    00347       return true;
    00348     }
    00349     if ( c1.type == ParseContext::T_NUM )
    00350     {
    00351       _context->b = ( c1.i < c2.i );
    00352       return true;
    00353     }
    00354     _context->b = false;
    00355     return true;
    00356
    00357   case 6: /* > */
    00358     if ( c1.type != c2.type )
    00359     {
    00360       _context->b = false;
    00361       return true;
    00362     }
    00363     if ( c1.type == ParseContext::T_DOUBLE )
    00364     {
    00365       _context->b = ( c1.f > c2.f );
    00366       return true;
    00367     }
    00368     if ( c1.type == ParseContext::T_NUM )
    00369     {
    00370       _context->b = ( c1.i > c2.i );
    00371       return true;
    00372     }
    00373     _context->b = false;
    00374     return true;
    00375
    00376   }
    00377
    00378   return false;
    00379 }
    00380
    00381 bool ParseTreeNOT::eval( ParseContext *_context ) const
    00382 {
    00383   ParseContext c1( _context );
    00384   if ( !m_pLeft->eval( &c1 ) )
    00385     return false;
    00386   if ( c1.type != ParseContext::T_BOOL )
    00387     return false;
    00388
    00389   _context->b = !c1.b;
    00390   _context->type = ParseContext::T_BOOL;
    00391
    00392   return true;
    00393 }
    00394
    00395 bool ParseTreeEXIST::eval( ParseContext *_context ) const
    00396 {
    00397   _context->type = ParseContext::T_BOOL;
    00398
    00399   QVariant prop = _context->service->property( m_id );
    00400   _context->b = prop.isValid();
    00401
    00402   return true;
    00403 }
    00404
    00405 bool ParseTreeMATCH::eval( ParseContext *_context ) const
    00406 {
    00407   _context->type = ParseContext::T_BOOL;
    00408
    00409   ParseContext c1( _context );
    00410   ParseContext c2( _context );
    00411   if ( !m_pLeft->eval( &c1 ) )
    00412     return false;
    00413   if ( !m_pRight->eval( &c2 ) )
    00414     return false;
    00415   if ( c1.type != ParseContext::T_STRING || c2.type != ParseContext::T_STRING )
    00416     return false;
    00417
    00418   _context->b = ( c2.str.find( c1.str ) != -1 );
    00419
    00420   return true;
    00421 }
    00422
    00423 bool ParseTreeIN::eval( ParseContext *_context ) const
    00424 {
    00425   _context->type = ParseContext::T_BOOL;
    00426
    00427   ParseContext c1( _context );
    00428   ParseContext c2( _context );
    00429   if ( !m_pLeft->eval( &c1 ) )
    00430     return false;
    00431   if ( !m_pRight->eval( &c2 ) )
    00432     return false;
    00433
    00434   if ( (c1.type == ParseContext::T_NUM) &&
    00435        (c2.type == ParseContext::T_SEQ) &&
    00436        ((*(c2.seq.begin())).type() == QVariant::Int)) {
    00437
    00438       QValueList<QVariant>::ConstIterator it = c2.seq.begin();
    00439       QValueList<QVariant>::ConstIterator end = c2.seq.end();
    00440       _context->b = false;
    00441       for (; it != end; it++)
    00442           if ((*it).type() == QVariant::Int &&
    00443               (*it).toInt() == c1.i) {
    00444               _context->b = true;
    00445               break;
    00446           }
    00447       return true;
    00448   }
    00449
    00450   if ( c1.type == ParseContext::T_DOUBLE &&
    00451        c2.type == ParseContext::T_SEQ &&
    00452        (*(c2.seq.begin())).type() == QVariant::Double) {
    00453
    00454       QValueList<QVariant>::ConstIterator it = c2.seq.begin();
    00455       QValueList<QVariant>::ConstIterator end = c2.seq.end();
    00456       _context->b = false;
    00457       for (; it != end; it++)
    00458           if ((*it).type() == QVariant::Double &&
    00459               (*it).toDouble() == c1.i) {
    00460               _context->b = true;
    00461               break;
    00462           }
    00463       return true;
    00464   }
    00465
    00466   if ( c1.type == ParseContext::T_STRING && c2.type == ParseContext::T_STR_SEQ )
    00467   {
    00468     _context->b = ( c2.strSeq.find( c1.str ) != c2.strSeq.end() );
    00469     return true;
    00470   }
    00471
    00472   return false;
    00473 }
    00474
    00475 bool ParseTreeID::eval( ParseContext *_context ) const
    00476 {
    00477   QVariant prop = _context->service->property( m_str );
    00478   if ( !prop.isValid() )
    00479     return false;
    00480
    00481   if ( prop.type() == QVariant::String )
    00482   {
    00483     _context->str = prop.toString();
    00484     _context->type = ParseContext::T_STRING;
    00485     return true;
    00486   }
    00487
    00488   if ( prop.type() == QVariant::Int )
    00489   {
    00490     _context->i = prop.toInt();
    00491     _context->type = ParseContext::T_NUM;
    00492     return true;
    00493   }
    00494
    00495   if ( prop.type() == QVariant::Bool )
    00496   {
    00497     _context->b = prop.toBool();
    00498     _context->type = ParseContext::T_BOOL;
    00499     return true;
    00500   }
    00501
    00502   if ( prop.type() == QVariant::Double )
    00503   {
    00504     _context->f = prop.toDouble();
    00505     _context->type = ParseContext::T_DOUBLE;
    00506     return true;
    00507   }
    00508
    00509   if ( prop.type() == QVariant::List )
    00510   {
    00511     _context->seq = prop.toList();
    00512     _context->type = ParseContext::T_SEQ;
    00513     return true;
    00514   }
    00515
    00516   if ( prop.type() == QVariant::StringList )
    00517   {
    00518     _context->strSeq = prop.toStringList();
    00519     _context->type = ParseContext::T_STR_SEQ;
    00520     return true;
    00521   }
    00522
    00523   // Value has unknown type
    00524   return false;
    00525 }
    00526
    00527 bool ParseTreeMIN2::eval( ParseContext *_context ) const
    00528 {
    00529   _context->type = ParseContext::T_DOUBLE;
    00530
    00531   QVariant prop = _context->service->property( m_strId );
    00532   if ( !prop.isValid() )
    00533     return false;
    00534
    00535   if ( !_context->initMaxima( m_strId ) )
    00536     return false;
    00537
    00538   QMap<QString,PreferencesMaxima>::Iterator it = _context->maxima.find( m_strId );
    00539   if ( it == _context->maxima.end() )
    00540     return false;
    00541
    00542   if ( prop.type() == QVariant::Int && it.data().type == PreferencesMaxima::PM_INT )
    00543   {
    00544     _context->f = (double)( prop.toInt() - it.data().iMin ) /
    00545                   (double)(it.data().iMax - it.data().iMin ) * (-2.0) + 1.0;
    00546     return true;
    00547   }
    00548   else if ( prop.type() == QVariant::Double && it.data().type == PreferencesMaxima::PM_DOUBLE )
    00549   {
    00550     _context->f = ( prop.toDouble() - it.data().fMin ) / (it.data().fMax - it.data().fMin )
    00551                   * (-2.0) + 1.0;
    00552     return true;
    00553   }
    00554
    00555   return false;
    00556 }
    00557
    00558 bool ParseTreeMAX2::eval( ParseContext *_context ) const
    00559 {
    00560   _context->type = ParseContext::T_DOUBLE;
    00561
    00562   QVariant prop = _context->service->property( m_strId );
    00563   if ( !prop.isValid() )
    00564     return false;
    00565
    00566   // Create extrema
    00567   if ( !_context->initMaxima( m_strId ) )
    00568     return false;
    00569
    00570   // Find extrema
    00571   QMap<QString,PreferencesMaxima>::Iterator it = _context->maxima.find( m_strId );
    00572   if ( it == _context->maxima.end() )
    00573     return false;
    00574
    00575   if ( prop.type() == QVariant::Int && it.data().type == PreferencesMaxima::PM_INT )
    00576   {
    00577     _context->f = (double)( prop.toInt() - it.data().iMin ) /
    00578                   (double)(it.data().iMax - it.data().iMin ) * 2.0 - 1.0;
    00579     return true;
    00580   }
    00581   else if ( prop.type() == QVariant::Double && it.data().type == PreferencesMaxima::PM_DOUBLE )
    00582   {
    00583     _context->f = ( prop.toDouble() - it.data().fMin ) /
    00584                   (it.data().fMax - it.data().fMin ) * 2.0 - 1.0;
    00585     return true;
    00586   }
    00587
    00588   return false;
    00589 }
    00590
    00591 int matchConstraint( const ParseTreeBase *_tree, const KService::Ptr &_service,
    00592                      const KServiceTypeProfile::OfferList& _list )
    00593 {
    00594   // Empty tree matches always
    00595   if ( !_tree )
    00596     return 1;
    00597
    00598   QMap<QString,PreferencesMaxima> maxima;
    00599   ParseContext c( _service, _list, maxima );
    00600
    00601   // Error during evaluation ?
    00602   if ( !_tree->eval( &c ) )
    00603     return -1;
    00604
    00605   // Did we get a bool ?
    00606   if ( c.type != ParseContext::T_BOOL )
    00607     return -1;
    00608
    00609   return ( c.b ? 1 : 0 );
    00610 }
    00611
    00612 PreferencesReturn matchPreferences( const ParseTreeBase *_tree, const KService::Ptr &_service,
    00613                                     const KServiceTypeProfile::OfferList& _list )
    00614 {
    00615   // By default: error
    00616   PreferencesReturn ret;
    00617
    00618   if ( !_tree )
    00619     return ret;
    00620
    00621   QMap<QString,PreferencesMaxima> maxima;
    00622   ParseContext c( _service, _list, maxima );
    00623
    00624   if ( !_tree->eval( &c ) )
    00625     return ret;
    00626
    00627   // Did we get a numeric return value ?
    00628   if ( c.type == ParseContext::T_NUM )
    00629   {
    00630     ret.type = PreferencesReturn::PRT_DOUBLE;
    00631     ret.f = (double)c.i;
    00632   }
    00633   else if ( c.type == ParseContext::T_DOUBLE )
    00634   {
    00635     ret.type = PreferencesReturn::PRT_DOUBLE;
    00636     ret.f = c.f;
    00637   }
    00638
    00639   return ret;
    00640 }
    00641
    00642 bool ParseContext::initMaxima( const QString& _prop )
    00643 {
    00644   // Is the property known ?
    00645   QVariant prop = service->property( _prop );
    00646   if ( !prop.isValid() )
    00647     return false;
    00648
    00649   // Numeric ?
    00650   if ( prop.type() != QVariant::Int && prop.type() != QVariant::Double )
    00651     return false;
    00652
    00653   // Did we cache the result ?
    00654   QMap<QString,PreferencesMaxima>::Iterator it = maxima.find( _prop );
    00655   if ( it != maxima.end() )
    00656     return ( it.data().type == PreferencesMaxima::PM_DOUBLE ||
    00657              it.data().type == PreferencesMaxima::PM_INT );
    00658
    00659   // Double or Int ?
    00660   PreferencesMaxima extrema;
    00661   if ( prop.type() == QVariant::Int )
    00662     extrema.type = PreferencesMaxima::PM_INVALID_INT;
    00663   else
    00664     extrema.type = PreferencesMaxima::PM_INVALID_DOUBLE;
    00665
    00666   // Iterate over all offers
    00667   KServiceTypeProfile::OfferList::ConstIterator oit = offers.begin();
    00668   for( ; oit != offers.end(); ++oit )
    00669   {
    00670     QVariant p = (*oit).service()->property( _prop );
    00671     if ( p.isValid() )
    00672     {
    00673       // Determine new maximum/minimum
    00674       if ( extrema.type == PreferencesMaxima::PM_INVALID_INT )
    00675       {
    00676         extrema.type = PreferencesMaxima::PM_INT;
    00677         extrema.iMin = p.toInt();
    00678         extrema.iMax = p.toInt();
    00679       }
    00680       // Correct existing extrema
    00681       else if ( extrema.type == PreferencesMaxima::PM_INT )
    00682       {
    00683         if ( p.toInt() < extrema.iMin )
    00684           extrema.iMin = p.toInt();
    00685         if ( p.toInt() > extrema.iMax )
    00686           extrema.iMax = p.toInt();
    00687       }
    00688       // Determine new maximum/minimum
    00689       else if ( extrema.type == PreferencesMaxima::PM_INVALID_DOUBLE )
    00690       {
    00691         extrema.type = PreferencesMaxima::PM_DOUBLE;
    00692         extrema.fMin = p.toDouble();
    00693         extrema.fMax = p.toDouble();
    00694       }
    00695       // Correct existing extrema
    00696       else if ( extrema.type == PreferencesMaxima::PM_DOUBLE )
    00697       {
    00698         if ( p.toDouble() < it.data().fMin )
    00699           extrema.fMin = p.toDouble();
    00700         if ( p.toDouble() > it.data().fMax )
    00701           extrema.fMax = p.toDouble();
    00702       }
    00703     }
    00704   }
    00705
    00706   // Cache the result
    00707   maxima.insert( _prop, extrema );
    00708
    00709   // Did we succeed ?
    00710   return ( extrema.type == PreferencesMaxima::PM_DOUBLE ||
    00711            extrema.type == PreferencesMaxima::PM_INT );
    00712 }
    00713
    00714 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:14:30 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001