kdeui Library API Documentation

ksyntaxhighlighter.cpp

00001 /*
00002  ksyntaxhighlighter.cpp
00003 
00004  Copyright (c) 2003 Trolltech AS
00005  Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
00006 
00007  This file is part of the KDE libraries
00008 
00009  This library is free software; you can redistribute it and/or
00010  modify it under the terms of the GNU Library General Public
00011  License version 2 as published by the Free Software Foundation.
00012 
00013  This library is distributed in the hope that it will be useful,
00014  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  Library General Public License for more details.
00017 
00018  You should have received a copy of the GNU Library General Public License
00019  along with this library; see the file COPYING.LIB.  If not, write to
00020  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00021  Boston, MA 02111-1307, USA.
00022 */
00023 
00024 #include <qcolor.h>
00025 #include <qregexp.h>
00026 #include <qsyntaxhighlighter.h>
00027 #include <qtimer.h>
00028 
00029 #include <klocale.h>
00030 #include <kconfig.h>
00031 #include <kdebug.h>
00032 #include <kglobal.h>
00033 #include <kspell.h>
00034 #include <kapplication.h>
00035 
00036 #include "ksyntaxhighlighter.h"
00037 
00038 static int dummy, dummy2, dummy3, dummy4;
00039 static int *Okay = &dummy;
00040 static int *NotOkay = &dummy2;
00041 static int *Ignore = &dummy3;
00042 static int *Unknown = &dummy4;
00043 static const int tenSeconds = 10*1000;
00044 
00045 class KSyntaxHighlighter::KSyntaxHighlighterPrivate
00046 {
00047 public:
00048     QColor col1, col2, col3, col4, col5;
00049     SyntaxMode mode;
00050     bool enabled;
00051 };
00052 
00053 class KSpellingHighlighter::KSpellingHighlighterPrivate
00054 {
00055 public:
00056 
00057     KSpellingHighlighterPrivate() :
00058     alwaysEndsWithSpace( true ),
00059     intraWordEditing( false ) {}
00060 
00061     QString currentWord;
00062     int currentPos;
00063     bool alwaysEndsWithSpace;
00064     QColor color;
00065     bool intraWordEditing;
00066 };
00067 
00068 class KDictSpellingHighlighter::KDictSpellingHighlighterPrivate
00069 {
00070 public:
00071     KDictSpellingHighlighterPrivate() :
00072         mDict( 0 ),
00073     spell( 0 ),
00074         mSpellConfig( 0 ),
00075         rehighlightRequest( 0 ),
00076     wordCount( 0 ),
00077     errorCount( 0 ),
00078     autoReady( false ),
00079         globalConfig( true ),
00080     spellReady( false ) {}
00081 
00082     ~KDictSpellingHighlighterPrivate() {
00083     delete rehighlightRequest;
00084     delete spell;
00085     }
00086 
00087     static QDict<int>* sDict()
00088     {
00089     if (!statDict)
00090         statDict = new QDict<int>(50021);
00091     return statDict;
00092     }
00093 
00094     QDict<int>* mDict;
00095     QDict<int> autoDict;
00096     QDict<int> autoIgnoreDict;
00097     static QObject *sDictionaryMonitor;
00098     KSpell *spell;
00099     KSpellConfig *mSpellConfig;
00100     QTimer *rehighlightRequest, *spellTimeout;
00101     QString spellKey;
00102     int wordCount, errorCount;
00103     int checksRequested, checksDone;
00104     int disablePercentage;
00105     bool completeRehighlightRequired;
00106     bool active, automatic, autoReady;
00107     bool globalConfig, spellReady;
00108 private:
00109     static QDict<int>* statDict;
00110 
00111 };
00112 
00113 QDict<int>* KDictSpellingHighlighter::KDictSpellingHighlighterPrivate::statDict = 0;
00114 
00115 
00116 KSyntaxHighlighter::KSyntaxHighlighter( QTextEdit *textEdit,
00117                       bool colorQuoting,
00118                       const QColor& depth0,
00119                       const QColor& depth1,
00120                       const QColor& depth2,
00121                       const QColor& depth3,
00122                       SyntaxMode mode )
00123     : QSyntaxHighlighter( textEdit )
00124 {
00125     d = new KSyntaxHighlighterPrivate();
00126 
00127     d->enabled = colorQuoting;
00128     d->col1 = depth0;
00129     d->col2 = depth1;
00130     d->col3 = depth2;
00131     d->col4 = depth3;
00132     d->col5 = depth0;
00133 
00134     d->mode = mode;
00135 }
00136 
00137 KSyntaxHighlighter::~KSyntaxHighlighter()
00138 {
00139     delete d;
00140 }
00141 
00142 int KSyntaxHighlighter::highlightParagraph( const QString &text, int )
00143 {
00144     if (!d->enabled) {
00145     setFormat( 0, text.length(), textEdit()->viewport()->paletteForegroundColor() );
00146     return 0;
00147     }
00148 
00149     QString simplified = text;
00150     simplified = simplified.replace( QRegExp( "\\s" ), QString::null ).replace( '|', QString::fromLatin1(">") );
00151     while ( simplified.startsWith( QString::fromLatin1(">>>>") ) )
00152     simplified = simplified.mid(3);
00153     if  ( simplified.startsWith( QString::fromLatin1(">>>") ) || simplified.startsWith( QString::fromLatin1("> >    >") ) )
00154     setFormat( 0, text.length(), d->col2 );
00155     else if ( simplified.startsWith( QString::fromLatin1(">>") ) || simplified.startsWith( QString::fromLatin1("> >") ) )
00156     setFormat( 0, text.length(), d->col3 );
00157     else if ( simplified.startsWith( QString::fromLatin1(">") ) )
00158     setFormat( 0, text.length(), d->col4 );
00159     else
00160     setFormat( 0, text.length(), d->col5 );
00161     return 0;
00162 }
00163 
00164 KSpellingHighlighter::KSpellingHighlighter( QTextEdit *textEdit,
00165                         const QColor& spellColor,
00166                         bool colorQuoting,
00167                         const QColor& depth0,
00168                         const QColor& depth1,
00169                         const QColor& depth2,
00170                         const QColor& depth3 )
00171     : KSyntaxHighlighter( textEdit, colorQuoting, depth0, depth1, depth2, depth3 )
00172 {
00173     d = new KSpellingHighlighterPrivate();
00174 
00175     d->color = spellColor;
00176 }
00177 
00178 KSpellingHighlighter::~KSpellingHighlighter()
00179 {
00180     delete d;
00181 }
00182 
00183 int KSpellingHighlighter::highlightParagraph( const QString &text,
00184                           int paraNo )
00185 {
00186     if ( paraNo == -2 )
00187     paraNo = 0;
00188     // leave #includes, diffs, and quoted replies alone
00189     QString diffAndCo( ">|" );
00190 
00191     bool isCode = diffAndCo.find(text[0]) != -1;
00192 
00193     if ( !text.endsWith(" ") )
00194     d->alwaysEndsWithSpace = false;
00195 
00196     KSyntaxHighlighter::highlightParagraph( text, -2 );
00197 
00198     if ( !isCode ) {
00199         int para, index;
00200     textEdit()->getCursorPosition( &para, &index );
00201     int len = text.length();
00202     if ( d->alwaysEndsWithSpace )
00203         len--;
00204 
00205     d->currentPos = 0;
00206     d->currentWord = "";
00207     for ( int i = 0; i < len; i++ ) {
00208         if ( !text[i].isLetter() && (!(text[i] == '\'')) ) {
00209         if ( ( para != paraNo ) ||
00210             !intraWordEditing() ||
00211             ( i - d->currentWord.length() > (uint)index ) ||
00212             ( i < index ) ) {
00213             flushCurrentWord();
00214         } else {
00215             d->currentWord = "";
00216         }
00217         d->currentPos = i + 1;
00218         } else {
00219         d->currentWord += text[i];
00220         }
00221     }
00222     if ( !text[len - 1].isLetter() ||
00223          (uint)( index + 1 ) != text.length() ||
00224          para != paraNo )
00225         flushCurrentWord();
00226     }
00227     return ++paraNo;
00228 }
00229 
00230 QStringList KSpellingHighlighter::personalWords()
00231 {
00232     QStringList l;
00233     l.append( "KMail" );
00234     l.append( "KOrganizer" );
00235     l.append( "KAddressBook" );
00236     l.append( "KHTML" );
00237     l.append( "KIO" );
00238     l.append( "KJS" );
00239     l.append( "Konqueror" );
00240     l.append( "KSpell" );
00241     l.append( "Kontact" );
00242     l.append( "Qt" );
00243     return l;
00244 }
00245 
00246 void KSpellingHighlighter::flushCurrentWord()
00247 {
00248     while ( d->currentWord[0].isPunct() ) {
00249     d->currentWord = d->currentWord.mid( 1 );
00250     d->currentPos++;
00251     }
00252 
00253     QChar ch;
00254     while ( ( ch = d->currentWord[(int) d->currentWord.length() - 1] ).isPunct() &&
00255          ch != '(' && ch != '@' )
00256     d->currentWord.truncate( d->currentWord.length() - 1 );
00257 
00258     if ( !d->currentWord.isEmpty() ) {
00259     if ( isMisspelled( d->currentWord ) ) {
00260         setFormat( d->currentPos, d->currentWord.length(), d->color );
00261 //      setMisspelled( d->currentPos, d->currentWord.length(), true );
00262     }
00263     }
00264     d->currentWord = "";
00265 }
00266 
00267 QObject *KDictSpellingHighlighter::KDictSpellingHighlighterPrivate::sDictionaryMonitor = 0;
00268 
00269 KDictSpellingHighlighter::KDictSpellingHighlighter( QTextEdit *textEdit,
00270                             bool spellCheckingActive ,
00271                             bool autoEnable,
00272                             const QColor& spellColor,
00273                             bool colorQuoting,
00274                             const QColor& depth0,
00275                             const QColor& depth1,
00276                             const QColor& depth2,
00277                             const QColor& depth3,
00278                                                     KSpellConfig *spellConfig )
00279     : KSpellingHighlighter( textEdit, spellColor,
00280                 colorQuoting, depth0, depth1, depth2, depth3 )
00281 {
00282     d = new KDictSpellingHighlighterPrivate();
00283 
00284     d->mSpellConfig = spellConfig;
00285     d->globalConfig = ( !spellConfig );
00286     d->automatic = autoEnable;
00287     d->active = spellCheckingActive;
00288     d->checksRequested = 0;
00289     d->checksDone = 0;
00290     d->completeRehighlightRequired = false;
00291 
00292     KConfig *config = KGlobal::config();
00293     KConfigGroupSaver cs( config, "KSpell" );
00294     config->reparseConfiguration();
00295     d->disablePercentage = config->readNumEntry( "KSpell_AsYouTypeDisablePercentage", 42 );
00296     d->disablePercentage = QMIN( d->disablePercentage, 101 );
00297 
00298     textEdit->installEventFilter( this );
00299     textEdit->viewport()->installEventFilter( this );
00300 
00301     d->rehighlightRequest = new QTimer(this);
00302     connect( d->rehighlightRequest, SIGNAL( timeout() ),
00303          this, SLOT( slotRehighlight() ));
00304     d->spellTimeout = new QTimer(this);
00305     connect( d->spellTimeout, SIGNAL( timeout() ),
00306          this, SLOT( slotKSpellNotResponding() ));
00307 
00308     if ( d->globalConfig ) {
00309         d->spellKey = spellKey();
00310 
00311         if ( !d->sDictionaryMonitor )
00312             d->sDictionaryMonitor = new QObject();
00313     }
00314     else {
00315         d->mDict = new QDict<int>(4001);
00316         connect( d->mSpellConfig, SIGNAL( configChanged() ),
00317                  this, SLOT( slotLocalSpellConfigChanged() ) );
00318     }
00319 
00320     slotDictionaryChanged();
00321     startTimer( 2 * 1000 );
00322 }
00323 
00324 KDictSpellingHighlighter::~KDictSpellingHighlighter()
00325 {
00326     delete d->spell;
00327     d->spell = 0;
00328     delete d->mDict;
00329     d->mDict = 0;
00330     delete d;
00331 }
00332 
00333 void KDictSpellingHighlighter::slotSpellReady( KSpell *spell )
00334 {
00335     kdDebug(0) << "KDictSpellingHighlighter::slotSpellReady( " << spell << " )" << endl;
00336     if ( d->globalConfig ) {
00337         connect( d->sDictionaryMonitor, SIGNAL( destroyed()),
00338                  this, SLOT( slotDictionaryChanged() ));
00339     }
00340     if ( spell != d->spell )
00341     {
00342         delete d->spell;
00343         d->spell = spell;
00344     }
00345     d->spellReady = true;
00346     const QStringList l = KSpellingHighlighter::personalWords();
00347     for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) {
00348         d->spell->addPersonal( *it );
00349     }
00350     connect( spell, SIGNAL( misspelling( const QString &, const QStringList &, unsigned int )),
00351          this, SLOT( slotMisspelling( const QString &, const QStringList &, unsigned int )));
00352     connect( spell, SIGNAL( corrected( const QString &, const QString &, unsigned int )),
00353          this, SLOT( slotCorrected( const QString &, const QString &, unsigned int )));
00354     d->checksRequested = 0;
00355     d->checksDone = 0;
00356     d->completeRehighlightRequired = true;
00357     d->rehighlightRequest->start( 0, true );
00358 }
00359 
00360 bool KDictSpellingHighlighter::isMisspelled( const QString &word )
00361 {
00362     if (!d->spellReady)
00363     return false;
00364 
00365     // This debug is expensive, only enable it locally
00366     //kdDebug(0) << "KDictSpellingHighlighter::isMisspelled( \"" << word << "\" )" << endl;
00367     // Normally isMisspelled would look up a dictionary and return
00368     // true or false, but kspell is asynchronous and slow so things
00369     // get tricky...
00370     // For auto detection ignore signature and reply prefix
00371     if ( !d->autoReady )
00372     d->autoIgnoreDict.replace( word, Ignore );
00373 
00374     // "dict" is used as a cache to store the results of KSpell
00375     QDict<int>* dict = ( d->globalConfig ? d->sDict() : d->mDict );
00376     if ( !dict->isEmpty() && (*dict)[word] == NotOkay ) {
00377     if ( d->autoReady && ( d->autoDict[word] != NotOkay )) {
00378         if ( !d->autoIgnoreDict[word] )
00379         ++d->errorCount;
00380         d->autoDict.replace( word, NotOkay );
00381     }
00382 
00383     return d->active;
00384     }
00385     if ( !dict->isEmpty() && (*dict)[word] == Okay ) {
00386     if ( d->autoReady && !d->autoDict[word] ) {
00387         d->autoDict.replace( word, Okay );
00388     }
00389     return false;
00390     }
00391 
00392     if ((dict->isEmpty() || !((*dict)[word])) && d->spell ) {
00393     int para, index;
00394     textEdit()->getCursorPosition( &para, &index );
00395     ++d->wordCount;
00396     dict->replace( word, Unknown );
00397     ++d->checksRequested;
00398     if (currentParagraph() != para)
00399         d->completeRehighlightRequired = true;
00400     d->spellTimeout->start( tenSeconds, true );
00401     d->spell->checkWord( word, false );
00402     }
00403     return false;
00404 }
00405 
00406 bool KSpellingHighlighter::intraWordEditing() const
00407 {
00408     return d->intraWordEditing;
00409 }
00410 
00411 void KSpellingHighlighter::setIntraWordEditing( bool editing )
00412 {
00413     d->intraWordEditing = editing;
00414 }
00415 
00416 void KDictSpellingHighlighter::slotMisspelling (const QString &originalWord, const QStringList &suggestions,
00417                                                 unsigned int pos)
00418 {
00419     Q_UNUSED( suggestions );
00420     // kdDebug() << suggestions.join( " " ).latin1() << endl;
00421     if ( d->globalConfig )
00422         d->sDict()->replace( originalWord, NotOkay );
00423     else
00424         d->mDict->replace( originalWord, NotOkay );
00425 
00426     //Emit this baby so that apps that want to have suggestions in a popup over
00427     //the misspelled word can catch them.
00428     emit newSuggestions( originalWord, suggestions, pos );
00429 }
00430 
00431 void KDictSpellingHighlighter::slotCorrected(const QString &word,
00432                          const QString &,
00433                          unsigned int)
00434 
00435 {
00436     QDict<int>* dict = ( d->globalConfig ? d->sDict() : d->mDict );
00437     if ( !dict->isEmpty() && (*dict)[word] == Unknown ) {
00438         dict->replace( word, Okay );
00439     }
00440     ++d->checksDone;
00441     if (d->checksDone == d->checksRequested) {
00442     d->spellTimeout->stop();
00443       slotRehighlight();
00444     } else {
00445     d->spellTimeout->start( tenSeconds, true );
00446     }
00447 }
00448 
00449 void KDictSpellingHighlighter::dictionaryChanged()
00450 {
00451     QObject *oldMonitor = KDictSpellingHighlighterPrivate::sDictionaryMonitor;
00452     KDictSpellingHighlighterPrivate::sDictionaryMonitor = new QObject();
00453     KDictSpellingHighlighterPrivate::sDict()->clear();
00454     delete oldMonitor;
00455 }
00456 
00457 void KDictSpellingHighlighter::restartBackgroundSpellCheck()
00458 {
00459     kdDebug(0) << "KDictSpellingHighlighter::restartBackgroundSpellCheck()" << endl;
00460     slotDictionaryChanged();
00461 }
00462 
00463 void KDictSpellingHighlighter::setActive( bool active )
00464 {
00465     if ( active == d->active )
00466         return;
00467 
00468     d->active = active;
00469     rehighlight();
00470     if ( d->active )
00471         emit activeChanged( i18n("As-you-type spell checking enabled.") );
00472     else
00473         emit activeChanged( i18n("As-you-type spell checking disabled.") );
00474 }
00475 
00476 bool KDictSpellingHighlighter::isActive() const
00477 {
00478     return d->active;
00479 }
00480 
00481 void KDictSpellingHighlighter::setAutomatic( bool automatic )
00482 {
00483     if ( automatic == d->automatic )
00484         return;
00485 
00486     d->automatic = automatic;
00487     if ( d->automatic )
00488         slotAutoDetection();
00489 }
00490 
00491 bool KDictSpellingHighlighter::automatic() const
00492 {
00493     return d->automatic;
00494 }
00495 
00496 void KDictSpellingHighlighter::slotRehighlight()
00497 {
00498     kdDebug(0) << "KDictSpellingHighlighter::slotRehighlight()" << endl;
00499     if (d->completeRehighlightRequired) {
00500     rehighlight();
00501     } else {
00502     int para, index;
00503     textEdit()->getCursorPosition( &para, &index );
00504     //rehighlight the current para only (undo/redo safe)
00505     textEdit()->insertAt( "", para, index );
00506     }
00507     if (d->checksDone == d->checksRequested)
00508     d->completeRehighlightRequired = false;
00509     QTimer::singleShot( 0, this, SLOT( slotAutoDetection() ));
00510 }
00511 
00512 void KDictSpellingHighlighter::slotDictionaryChanged()
00513 {
00514     delete d->spell;
00515     d->spellReady = false;
00516     d->wordCount = 0;
00517     d->errorCount = 0;
00518     d->autoDict.clear();
00519 
00520     d->spell = new KSpell( 0, i18n( "Incremental Spellcheck" ), this,
00521         SLOT( slotSpellReady( KSpell * ) ), d->mSpellConfig );
00522 }
00523 
00524 void KDictSpellingHighlighter::slotLocalSpellConfigChanged()
00525 {
00526     kdDebug(0) << "KDictSpellingHighlighter::slotSpellConfigChanged()" << endl;
00527     // the spell config has been changed, so we have to restart from scratch
00528     d->mDict->clear();
00529     slotDictionaryChanged();
00530 }
00531 
00532 QString KDictSpellingHighlighter::spellKey()
00533 {
00534     KConfig *config = KGlobal::config();
00535     KConfigGroupSaver cs( config, "KSpell" );
00536     config->reparseConfiguration();
00537     QString key;
00538     key += QString::number( config->readNumEntry( "KSpell_NoRootAffix", 0 ));
00539     key += '/';
00540     key += QString::number( config->readNumEntry( "KSpell_RunTogether", 0 ));
00541     key += '/';
00542     key += config->readEntry( "KSpell_Dictionary", "" );
00543     key += '/';
00544     key += QString::number( config->readNumEntry( "KSpell_DictFromList", false ));
00545     key += '/';
00546     key += QString::number( config->readNumEntry( "KSpell_Encoding", KS_E_ASCII ));
00547     key += '/';
00548     key += QString::number( config->readNumEntry( "KSpell_Client", KS_CLIENT_ISPELL ));
00549     return key;
00550 }
00551 
00552 
00553 // Automatic spell checking support
00554 // In auto spell checking mode disable as-you-type spell checking
00555 // iff more than one third of words are spelt incorrectly.
00556 //
00557 // Words in the signature and reply prefix are ignored.
00558 // Only unique words are counted.
00559 
00560 void KDictSpellingHighlighter::slotAutoDetection()
00561 {
00562     if ( !d->autoReady )
00563     return;
00564 
00565     bool savedActive = d->active;
00566 
00567     if ( d->automatic ) {
00568     // tme = Too many errors
00569     bool tme = d->errorCount * 100 >= d->disablePercentage * d->wordCount;
00570     if ( d->active && tme )
00571         d->active = false;
00572     else if ( !d->active && !tme )
00573         d->active = true;
00574     }
00575     if ( d->active != savedActive ) {
00576     if ( d->wordCount > 1 )
00577         if ( d->active )
00578         emit activeChanged( i18n("As-you-type spell checking enabled.") );
00579         else
00580         emit activeChanged( i18n( "Too many misspelled words. "
00581                       "As-you-type spell checking disabled." ) );
00582     d->completeRehighlightRequired = true;
00583     d->rehighlightRequest->start( 100, true );
00584     }
00585 }
00586 
00587 void KDictSpellingHighlighter::slotKSpellNotResponding()
00588 {
00589     static int retries = 0;
00590     if (retries < 10) {
00591         if ( d->globalConfig )
00592         KDictSpellingHighlighter::dictionaryChanged();
00593     else
00594         slotLocalSpellConfigChanged();
00595     } else {
00596     setAutomatic( false );
00597     setActive( false );
00598     }
00599     ++retries;
00600 }
00601 
00602 bool KDictSpellingHighlighter::eventFilter( QObject *o, QEvent *e)
00603 {
00604     if (o == textEdit() && (e->type() == QEvent::FocusIn)) {
00605         if ( d->globalConfig ) {
00606             QString skey = spellKey();
00607             if ( d->spell && d->spellKey != skey ) {
00608                 d->spellKey = skey;
00609                 KDictSpellingHighlighter::dictionaryChanged();
00610             }
00611         }
00612     }
00613 
00614     if (o == textEdit() && (e->type() == QEvent::KeyPress)) {
00615     QKeyEvent *k = static_cast<QKeyEvent *>(e);
00616     d->autoReady = true;
00617     if (d->rehighlightRequest->isActive()) // try to stay out of the users way
00618         d->rehighlightRequest->changeInterval( 500 );
00619     if ( k->key() == Key_Enter ||
00620          k->key() == Key_Return ||
00621          k->key() == Key_Up ||
00622          k->key() == Key_Down ||
00623          k->key() == Key_Left ||
00624          k->key() == Key_Right ||
00625          k->key() == Key_PageUp ||
00626          k->key() == Key_PageDown ||
00627          k->key() == Key_Home ||
00628          k->key() == Key_End ||
00629          (( k->state() & ControlButton ) &&
00630           ((k->key() == Key_A) ||
00631            (k->key() == Key_B) ||
00632            (k->key() == Key_E) ||
00633            (k->key() == Key_N) ||
00634            (k->key() == Key_P))) ) {
00635         if ( intraWordEditing() ) {
00636         setIntraWordEditing( false );
00637         d->completeRehighlightRequired = true;
00638         d->rehighlightRequest->start( 500, true );
00639         }
00640         if (d->checksDone != d->checksRequested) {
00641         // Handle possible change of paragraph while
00642         // words are pending spell checking
00643         d->completeRehighlightRequired = true;
00644         d->rehighlightRequest->start( 500, true );
00645         }
00646     } else {
00647         setIntraWordEditing( true );
00648     }
00649     if ( k->key() == Key_Space ||
00650          k->key() == Key_Enter ||
00651          k->key() == Key_Return ) {
00652         QTimer::singleShot( 0, this, SLOT( slotAutoDetection() ));
00653     }
00654     }
00655 
00656     else if ( o == textEdit()->viewport() &&
00657      ( e->type() == QEvent::MouseButtonPress )) {
00658     d->autoReady = true;
00659     if ( intraWordEditing() ) {
00660         setIntraWordEditing( false );
00661         d->completeRehighlightRequired = true;
00662         d->rehighlightRequest->start( 0, true );
00663     }
00664     }
00665 
00666     return false;
00667 }
00668 
00669 #include "ksyntaxhighlighter.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 28 01:34:49 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003