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

# kspell.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 1997 David Sweet <dsweet@kde.org>
    00003    Copyright (C) 2000-2001 Wolfram Diestel <wolfram@steloj.de>
    00004    Copyright (C) 2003 Zack Rusin <zack@kde.org>
    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 version 2 as published by the Free Software Foundation.
    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 #ifdef HAVE_CONFIG_H
    00022 #include <config.h>
    00023 #endif
    00024
    00025 #include <stdio.h>
    00026 #include <sys/time.h>
    00027 #include <sys/types.h>
    00028 #include <unistd.h>
    00029 #include <ctype.h>
    00030 #include <stdlib.h> // atoi
    00031
    00032 #ifdef HAVE_STRINGS_H
    00033 #include <strings.h>
    00034 #endif
    00035
    00036 #include <qregexp.h>
    00037 #include <qtextcodec.h>
    00038 #include <qtimer.h>
    00039
    00040 #include <kapplication.h>
    00041 #include <kmessagebox.h>
    00042 #include <kdebug.h>
    00043 #include <klocale.h>
    00044 #include "kspell.h"
    00045 #include "kspelldlg.h"
    00046 #include <kwin.h>
    00047 #include <kprocio.h>
    00048
    00049 #define MAXLINELENGTH 10000
    00050 #undef IGNORE //fix possible conflict
    00051
    00052 enum {
    00053   GOOD=     0,
    00054   IGNORE=   1,
    00055   REPLACE=  2,
    00056   MISTAKE=  3
    00057 };
    00058
    00059 enum checkMethod { Method1 = 0, Method2 };
    00060
    00061 struct BufferedWord
    00062 {
    00063   checkMethod method;
    00064   QString word;
    00065   bool useDialog;
    00066   bool suggest;
    00067 };
    00068
    00069 class KSpell::KSpellPrivate
    00070 {
    00071 public:
    00072   bool endOfResponse;
    00073   bool m_bIgnoreUpperWords;
    00074   bool m_bIgnoreTitleCase;
    00075   bool m_bNoMisspellingsEncountered;
    00076   SpellerType type;
    00077   KSpell* suggestSpell;
    00078   bool checking;
    00079   QValueList<BufferedWord> unchecked;
    00080   QTimer *checkNextTimer;
    00081   bool aspellV6;
    00082 };
    00083
    00084 //TODO
    00085 //Parse stderr output
    00086 //e.g. -- invalid dictionary name
    00087
    00088 /*
    00089   Things to put in KSpellConfigDlg:
    00090     make root/affix combinations that aren't in the dictionary (-m)
    00091     don't generate any affix/root combinations (-P)
    00092     Report  run-together  words   with   missing blanks as spelling errors.  (-B)
    00093     default dictionary (-d [dictionary])
    00094     personal dictionary (-p [dictionary])
    00095     path to ispell -- NO: ispell should be in $PATH
    00096     */
    00097
    00098
    00099 //  Connects a slot to KProcIO's output signal
    00100 #define OUTPUT(x) (connect (proc, SIGNAL (readReady(KProcIO *)), this, SLOT (x(KProcIO *))))
    00101
    00102 // Disconnect a slot from...
    00103 #define NOOUTPUT(x) (disconnect (proc, SIGNAL (readReady(KProcIO *)), this, SLOT (x(KProcIO *))))
    00104
    00105
    00106
    00107 KSpell::KSpell( QWidget *_parent, const QString &_caption,
    00108         QObject *obj, const char *slot, KSpellConfig *_ksc,
    00109         bool _progressbar, bool _modal )
    00110 {
    00111   initialize( _parent, _caption, obj, slot, _ksc,
    00112               _progressbar, _modal, Text );
    00113 }
    00114
    00115 KSpell::KSpell( QWidget *_parent, const QString &_caption,
    00116         QObject *obj, const char *slot, KSpellConfig *_ksc,
    00117         bool _progressbar, bool _modal, SpellerType type )
    00118 {
    00119   initialize( _parent, _caption, obj, slot, _ksc,
    00120               _progressbar, _modal, type );
    00121 }
    00122
    00123 void KSpell::hide() { ksdlg->hide(); }
    00124
    00125 int KSpell::heightDlg() const { return ksdlg->height(); }
    00126 int KSpell::widthDlg() const { return ksdlg->width(); }
    00127
    00128 // Check if aspell is at least version 0.6
    00129 static bool determineASpellV6()
    00130 {
    00131   QString result;
    00132   FILE *fs = popen("aspell -v", "r");
    00133   if (fs)
    00134   {
    00135     // Close textstream before we close fs
    00136     {
    00137     QTextStream ts(fs, IO_ReadOnly);
    00138     result = ts.read().stripWhiteSpace();
    00139     }
    00140     pclose(fs);
    00141   }
    00142
    00143   QRegExp rx("Aspell (\\d.\\d)");
    00144   if (rx.search(result) != -1)
    00145   {
    00146      float version = rx.cap(1).toFloat();
    00147      return (version >= 0.6);
    00148   }
    00149   return false;
    00150 }
    00151
    00152
    00153 void
    00154 KSpell::startIspell()
    00155   //trystart = {0,1,2}
    00156 {
    00157   if ((trystart == 0) && (ksconfig->client() == KS_CLIENT_ASPELL))
    00158      d->aspellV6 = determineASpellV6();
    00159
    00160   kdDebug(750) << "Try #" << trystart << endl;
    00161
    00162   if ( trystart > 0 ) {
    00163     proc->resetAll();
    00164   }
    00165
    00166   switch ( ksconfig->client() )
    00167   {
    00168   case KS_CLIENT_ISPELL:
    00169     *proc << "ispell";
    00170     kdDebug(750) << "Using ispell" << endl;
    00171     break;
    00172   case KS_CLIENT_ASPELL:
    00173     *proc << "aspell";
    00174     kdDebug(750) << "Using aspell" << endl;
    00175     break;
    00176   case KS_CLIENT_HSPELL:
    00177     *proc << "hspell";
    00178     kdDebug(750) << "Using hspell" << endl;
    00179     break;
    00180   }
    00181
    00182   if ( ksconfig->client() == KS_CLIENT_ISPELL || ksconfig->client() == KS_CLIENT_ASPELL )
    00183   {
    00184     *proc << "-a" << "-S";
    00185
    00186     switch ( d->type )
    00187     {
    00188     case HTML:
    00189       //Debian uses an ispell version that has the -h option instead.
    00190       //Not sure what they did, but the preferred spell checker
    00191       //on that platform is aspell anyway, so use -H untill I'll come
    00192       //up with something better.
    00193       *proc << "-H";
    00194       break;
    00195     case TeX:
    00196       //same for aspell and ispell
    00197       *proc << "-t";
    00198       break;
    00199     case Nroff:
    00200       //only ispell supports
    00201       if ( ksconfig->client() == KS_CLIENT_ISPELL )
    00202         *proc << "-n";
    00203       break;
    00204     case Text:
    00205     default:
    00206       //nothing
    00207       break;
    00208     }
    00209     if (ksconfig->noRootAffix())
    00210     {
    00211       *proc<<"-m";
    00212     }
    00213     if (ksconfig->runTogether())
    00214     {
    00215       *proc << "-B";
    00216     }
    00217     else
    00218     {
    00219       *proc << "-C";
    00220     }
    00221
    00222
    00223     if (trystart<2)
    00224     {
    00225       if (! ksconfig->dictionary().isEmpty())
    00226       {
    00227         kdDebug(750) << "using dictionary [" << ksconfig->dictionary() << "]" << endl;
    00228         *proc << "-d";
    00229         *proc << ksconfig->dictionary();
    00230       }
    00231     }
    00232
    00233   //Note to potential debuggers:  -Tlatin2 _is_ being added on the
    00234   //  _first_ try.  But, some versions of ispell will fail with this
    00235   // option, so kspell tries again without it.  That's why as 'ps -ax'
    00236   // shows "ispell -a -S ..." withou the "-Tlatin2" option.
    00237
    00238     if ( trystart<1 ) {
    00239       switch ( ksconfig->encoding() )
    00240       {
    00241       case KS_E_LATIN1:
    00242     *proc << "-Tlatin1";
    00243     break;
    00244       case KS_E_LATIN2:
    00245     *proc << "-Tlatin2";
    00246     break;
    00247       case KS_E_LATIN3:
    00248         *proc << "-Tlatin3";
    00249         break;
    00250
    00251         // add the other charsets here
    00252       case KS_E_LATIN4:
    00253       case KS_E_LATIN5:
    00254       case KS_E_LATIN7:
    00255       case KS_E_LATIN8:
    00256       case KS_E_LATIN9:
    00257       case KS_E_LATIN13:
    00258       case KS_E_LATIN15:
    00259     // will work, if this is the default charset in the dictionary
    00260     kdError(750) << "charsets iso-8859-4 .. iso-8859-15 not supported yet" << endl;
    00261     break;
    00262       case KS_E_UTF8:
    00263         *proc << "-Tutf8";
    00264         if (ksconfig->client() == KS_CLIENT_ASPELL)
    00265           *proc << "--encoding=utf-8";
    00266         else
    00267           *proc << "-Tutf8";
    00268
    00269         break;
    00270       case KS_E_KOI8U:
    00271     *proc << "-w'"; // add ' as a word char
    00272     break;
    00273       }
    00274     }
    00275
    00276   // -a : pipe mode
    00277   // -S : sort suggestions by probable correctness
    00278   }
    00279   else       // hspell doesn't need all the rest of the options
    00280     *proc << "-a";
    00281
    00282   if (trystart == 0) //don't connect these multiple times
    00283   {
    00284     connect( proc, SIGNAL(receivedStderr(KProcess *, char *, int)),
    00285              this, SLOT(ispellErrors(KProcess *, char *, int)) );
    00286
    00287     connect( proc, SIGNAL(processExited(KProcess *)),
    00288              this, SLOT(ispellExit (KProcess *)) );
    00289
    00290     OUTPUT(KSpell2);
    00291   }
    00292
    00293   if ( !proc->start() )
    00294   {
    00295     m_status = Error;
    00296     QTimer::singleShot( 0, this, SLOT(emitDeath()));
    00297   }
    00298 }
    00299
    00300 void
    00301 KSpell::ispellErrors( KProcess *, char *buffer, int buflen )
    00302 {
    00303   buffer[buflen-1] = '\0';
    00304   //  kdDebug(750) << "ispellErrors [" << buffer << "]\n" << endl;
    00305 }
    00306
    00307 void KSpell::KSpell2( KProcIO * )
    00308
    00309 {
    00310   QString line;
    00311
    00312   kdDebug(750) << "KSpell::KSpell2" << endl;
    00313
    00314   trystart = maxtrystart;  //We've officially started ispell and don't want
    00315                            //to try again if it dies.
    00316
    00317   if ( proc->readln( line, true ) == -1 )
    00318   {
    00319      QTimer::singleShot( 0, this, SLOT(emitDeath()) );
    00320      return;
    00321   }
    00322
    00323
    00324   if ( line[0] != '@' ) //@ indicates that ispell is working fine
    00325   {
    00326      QTimer::singleShot( 0, this, SLOT(emitDeath()) );
    00327      return;
    00328   }
    00329
    00330   //We want to recognize KDE in any text!
    00331   if ( !ignore("kde") )
    00332   {
    00333      kdDebug(750) << "@KDE was false" << endl;
    00334      QTimer::singleShot( 0, this, SLOT(emitDeath()) );
    00335      return;
    00336   }
    00337
    00338   //We want to recognize linux in any text!
    00339   if ( !ignore("linux") )
    00340   {
    00341      kdDebug(750) << "@Linux was false" << endl;
    00342      QTimer::singleShot( 0, this, SLOT(emitDeath()) );
    00343      return;
    00344   }
    00345
    00346   NOOUTPUT( KSpell2 );
    00347
    00348   m_status = Running;
    00349   emit ready( this );
    00350 }
    00351
    00352 void
    00353 KSpell::setUpDialog( bool reallyuseprogressbar )
    00354 {
    00355   if ( dialogsetup )
    00356     return;
    00357
    00358   //Set up the dialog box
    00359   ksdlg = new KSpellDlg( parent, "dialog",
    00360                          progressbar && reallyuseprogressbar, modaldlg );
    00361   ksdlg->setCaption( caption );
    00362
    00363   connect( ksdlg, SIGNAL(command(int)),
    00364            this, SLOT(slotStopCancel(int)) );
    00365   connect( this, SIGNAL(progress(unsigned int)),
    00366        ksdlg, SLOT(slotProgress(unsigned int)) );
    00367
    00368 #ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded
    00369   KWin::setIcons( ksdlg->winId(), kapp->icon(), kapp->miniIcon() );
    00370 #endif
    00371   if ( modaldlg )
    00372     ksdlg->setFocus();
    00373   dialogsetup = true;
    00374 }
    00375
    00376 bool KSpell::addPersonal( const QString & word )
    00377 {
    00378   QString qs = word.simplifyWhiteSpace();
    00379
    00380   //we'll let ispell do the work here b/c we can
    00381   if ( qs.find(' ') != -1 || qs.isEmpty() )    // make sure it's a _word_
    00382     return false;
    00383
    00384   qs.prepend( "*" );
    00385   personaldict = true;
    00386
    00387   return proc->writeStdin( qs );
    00388 }
    00389
    00390 bool KSpell::writePersonalDictionary()
    00391 {
    00392   return proc->writeStdin("#");
    00393 }
    00394
    00395 bool KSpell::ignore( const QString & word )
    00396 {
    00397   QString qs = word.simplifyWhiteSpace();
    00398
    00399   //we'll let ispell do the work here b/c we can
    00400   if ( qs.find (' ') != -1 || qs.isEmpty() )    // make sure it's a _word_
    00401     return false;
    00402
    00403   qs.prepend( "@" );
    00404
    00405   return proc->writeStdin( qs );
    00406 }
    00407
    00408 bool
    00409 KSpell::cleanFputsWord( const QString & s, bool appendCR )
    00410 {
    00411   QString qs(s);
    00412   bool empty = true;
    00413
    00414   for( unsigned int i = 0; i < qs.length(); i++ )
    00415   {
    00416     //we need some punctuation for ornaments
    00417     if ( qs[i] != '\'' && qs[i] != '\"' && qs[i] != '-'
    00418          && qs[i].isPunct() || qs[i].isSpace() )
    00419     {
    00420       qs.remove(i,1);
    00421       i--;
    00422     } else {
    00423       if ( qs[i].isLetter() )
    00424         empty=false;
    00425     }
    00426   }
    00427
    00428   // don't check empty words, otherwise synchronization will lost
    00429   if (empty)
    00430     return false;
    00431
    00432   return proc->writeStdin( "^"+qs, appendCR );
    00433 }
    00434
    00435 bool
    00436 KSpell::cleanFputs( const QString & s, bool appendCR )
    00437 {
    00438   QString qs(s);
    00439   unsigned l = qs.length();
    00440
    00441   // some uses of '$' (e.g. "$0") cause ispell to skip all following text
    00442   for( unsigned int i = 0; i < l; ++i )
    00443   {
    00444     if( qs[i] == '$' )
    00445       qs[i] = ' ';
    00446   }
    00447
    00448   if ( l<MAXLINELENGTH )
    00449   {
    00450     if ( qs.isEmpty() )
    00451       qs="";
    00452     return proc->writeStdin( "^"+qs, appendCR );
    00453   }
    00454   else
    00455     return proc->writeStdin( QString::fromAscii( "^\n" ),appendCR );
    00456 }
    00457
    00458 bool KSpell::checkWord( const QString & buffer, bool _usedialog )
    00459 {
    00460   if (d->checking) { // don't check multiple words simultaneously
    00461     BufferedWord bufferedWord;
    00462     bufferedWord.method = Method1;
    00463     bufferedWord.word = buffer;
    00464     bufferedWord.useDialog = _usedialog;
    00465     d->unchecked.append( bufferedWord );
    00466     return true;
    00467   }
    00468   d->checking = true;
    00469   QString qs = buffer.simplifyWhiteSpace();
    00470
    00471   if ( qs.find (' ') != -1 || qs.isEmpty() ) {   // make sure it's a _word_
    00472     d->checkNextTimer->start( 0, true );
    00473     return false;
    00474   }
    00476   dialog3slot = SLOT(checkWord3());
    00477
    00478   usedialog = _usedialog;
    00479   setUpDialog( false );
    00480   if ( _usedialog )
    00481   {
    00482     emitProgress();
    00483   }
    00484   else
    00485     ksdlg->hide();
    00486
    00487   QString blank_line;
    00488   while (proc->readln( blank_line, true ) != -1); // eat spurious blanks
    00489
    00490   OUTPUT(checkWord2);
    00491   //  connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
    00492
    00493   proc->writeStdin( "%" ); // turn off terse mode
    00494   proc->writeStdin( buffer ); // send the word to ispell
    00495
    00496   return true;
    00497 }
    00498
    00499 bool KSpell::checkWord( const QString & buffer, bool _usedialog, bool suggest )
    00500 {
    00501   if (d->checking) { // don't check multiple words simultaneously
    00502     BufferedWord bufferedWord;
    00503     bufferedWord.method = Method2;
    00504     bufferedWord.word = buffer;
    00505     bufferedWord.useDialog = _usedialog;
    00506     bufferedWord.suggest = suggest;
    00507     d->unchecked.append( bufferedWord );
    00508     return true;
    00509   }
    00510   d->checking = true;
    00511   QString qs = buffer.simplifyWhiteSpace();
    00512
    00513   if ( qs.find (' ') != -1 || qs.isEmpty() ) {   // make sure it's a _word_
    00514     d->checkNextTimer->start( 0, true );
    00515     return false;
    00516   }
    00517
    00519   if ( !suggest ) {
    00520     dialog3slot = SLOT(checkWord3());
    00521     usedialog = _usedialog;
    00522     setUpDialog( false );
    00523     if ( _usedialog )
    00524     {
    00525       emitProgress();
    00526     }
    00527     else
    00528       ksdlg->hide();
    00529   }
    00530
    00531   QString blank_line;
    00532   while (proc->readln( blank_line, true ) != -1); // eat spurious blanks
    00533
    00534   OUTPUT(checkWord2);
    00535   //  connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
    00536
    00537   proc->writeStdin( "%" ); // turn off terse mode
    00538   proc->writeStdin( buffer ); // send the word to ispell
    00539
    00540   return true;
    00541 }
    00542
    00543 void KSpell::checkWord2( KProcIO* )
    00544 {
    00545   QString word;
    00546   QString line;
    00547   proc->readln( line, true ); //get ispell's response
    00548
    00549 /* ispell man page: "Each sentence of text input is terminated with an
    00550    additional blank line,  indicating that ispell has completed processing
    00551    the input line."
    00552    <sanders>
    00553    But there can be multiple lines returned in the case of an error,
    00554    in this case we should consume all the output given otherwise spell checking
    00555    can get out of sync.
    00556    </sanders>
    00557 */
    00558   QString blank_line;
    00559   while (proc->readln( blank_line, true ) != -1); // eat the blank line
    00560   NOOUTPUT(checkWord2);
    00561
    00562   bool mistake = ( parseOneResponse(line, word, sugg) == MISTAKE );
    00563   if ( mistake && usedialog )
    00564   {
    00565     cwword = word;
    00566     dialog( word, sugg, SLOT(checkWord3()) );
    00567     d->checkNextTimer->start( 0, true );
    00568     return;
    00569   }
    00570   else if( mistake )
    00571   {
    00572     emit misspelling( word, sugg, lastpos );
    00573   }
    00574
    00575   //emits a "corrected" signal _even_ if no change was made
    00576   //so that the calling program knows when the check is complete
    00577   emit corrected( word, word, 0L );
    00578   d->checkNextTimer->start( 0, true );
    00579 }
    00580
    00581 void KSpell::checkNext()
    00582 {
    00583 // Queue words to prevent kspell from turning into a fork bomb
    00584   d->checking = false;
    00585   if (!d->unchecked.empty()) {
    00586     BufferedWord buf = d->unchecked.front();
    00587     d->unchecked.pop_front();
    00588
    00589     if (buf.method == Method1)
    00590       checkWord( buf.word, buf.useDialog );
    00591     else
    00592       checkWord( buf.word, buf.useDialog, buf.suggest );
    00593   }
    00594 }
    00595
    00596 void KSpell::suggestWord( KProcIO * )
    00597 {
    00598   QString word;
    00599   QString line;
    00600   proc->readln( line, true ); //get ispell's response
    00601
    00602 /* ispell man page: "Each sentence of text input is terminated with an
    00603    additional blank line,  indicating that ispell has completed processing
    00604    the input line." */
    00605   QString blank_line;
    00606   proc->readln( blank_line, true ); // eat the blank line
    00607
    00608   NOOUTPUT(checkWord2);
    00609
    00610   bool mistake = ( parseOneResponse(line, word, sugg) == MISTAKE );
    00611   if ( mistake && usedialog )
    00612   {
    00613     cwword=word;
    00614     dialog( word, sugg, SLOT(checkWord3()) );
    00615     return;
    00616   }
    00617 }
    00618
    00619 void KSpell::checkWord3()
    00620 {
    00621   disconnect( this, SIGNAL(dialog3()), this, SLOT(checkWord3()) );
    00622
    00623   emit corrected( cwword, replacement(), 0L );
    00624 }
    00625
    00626 QString KSpell::funnyWord( const QString & word )
    00627   // composes a guess from ispell to a readable word
    00628   // e.g. "re+fry-y+ies" -> "refries"
    00629 {
    00630   QString qs;
    00631   unsigned int i=0;
    00632
    00633   for( i=0; word [i]!='\0';i++ )
    00634   {
    00635     if (word [i]=='+')
    00636       continue;
    00637     if (word [i]=='-')
    00638     {
    00639       QString shorty;
    00640       unsigned int j;
    00641       int k;
    00642
    00643       for( j = i+1; word[j] != '\0' && word[j] != '+' && word[j] != '-'; j++ )
    00644         shorty += word[j];
    00645
    00646       i = j-1;
    00647
    00648       if ( !( k = qs.findRev(shorty) ) || k != -1 )
    00649         qs.remove( k, shorty.length() );
    00650       else
    00651       {
    00652         qs += '-';
    00653         qs += shorty;  //it was a hyphen, not a '-' from ispell
    00654       }
    00655     }
    00656     else
    00657       qs += word[i];
    00658   }
    00659
    00660   return qs;
    00661 }
    00662
    00663
    00664 int KSpell::parseOneResponse( const QString &buffer, QString &word, QStringList & sugg )
    00665   // buffer is checked, word and sugg are filled in
    00666   // returns
    00667   //   GOOD    if word is fine
    00668   //   IGNORE  if word is in ignorelist
    00669   //   REPLACE if word is in replacelist
    00670   //   MISTAKE if word is misspelled
    00671 {
    00672   word = "";
    00673   posinline=0;
    00674
    00675   sugg.clear();
    00676
    00677   if ( buffer[0] == '*' || buffer[0] == '+' || buffer[0] == '-' )
    00678   {
    00679     return GOOD;
    00680   }
    00681
    00682   if ( buffer[0] == '&' || buffer[0] == '?' || buffer[0] == '#' )
    00683   {
    00684     int i,j;
    00685
    00686
    00687     word = buffer.mid( 2, buffer.find( ' ', 3 ) -2 );
    00688     //check() needs this
    00689     orig=word;
    00690
    00691     if( d->m_bIgnoreTitleCase && word == word.upper() )
    00692       return IGNORE;
    00693
    00694     if( d->m_bIgnoreUpperWords && word[0] == word[0].upper() )
    00695     {
    00696       QString text = word[0] + word.right( word.length()-1 ).lower();
    00697       if( text == word )
    00698         return IGNORE;
    00699     }
    00700
    00702     //We don't take advantage of ispell's ignore function because
    00703     //we can't interrupt ispell's output (when checking a large
    00704     //buffer) to add a word to _it's_ ignore-list.
    00705     if ( ignorelist.findIndex( word.lower() ) != -1 )
    00706       return IGNORE;
    00707
    00709     QString qs2;
    00710
    00711     if ( buffer.find( ':' ) != -1 )
    00712       qs2 = buffer.left( buffer.find(':') );
    00713     else
    00714       qs2 = buffer;
    00715
    00716     posinline = qs2.right( qs2.length()-qs2.findRev(' ') ).toInt()-1;
    00717
    00719     QStringList::Iterator it = replacelist.begin();
    00720     for( ;it != replacelist.end(); ++it, ++it ) // Skip two entries at a time.
    00721     {
    00722       if ( word == *it ) // Word matches
    00723       {
    00724         ++it;
    00725         word = *it;   // Replace it with the next entry
    00726         return REPLACE;
    00727       }
    00728     }
    00729
    00731     if ( buffer[0] != '#' )
    00732     {
    00733       QString qs = buffer.mid( buffer.find(':')+2, buffer.length() );
    00734       qs += ',';
    00735       sugg.clear();
    00736       i = j = 0;
    00737
    00738       while( (unsigned int)i < qs.length() )
    00739       {
    00740         QString temp = qs.mid( i, (j=qs.find (',',i)) - i );
    00741         sugg.append( funnyWord(temp) );
    00742
    00743         i=j+2;
    00744       }
    00745     }
    00746
    00747     if ( (sugg.count()==1) && (sugg.first() == word) )
    00748       return GOOD;
    00749
    00750     return MISTAKE;
    00751   }
    00752
    00753   if ( buffer.isEmpty() ) {
    00754       kdDebug(750) << "Got an empty response: ignoring"<<endl;
    00755       return GOOD;
    00756   }
    00757
    00758   kdError(750) << "HERE?: [" << buffer << "]" << endl;
    00759   kdError(750) << "Please report this to zack@kde.org" << endl;
    00760   kdError(750) << "Thank you!" << endl;
    00761
    00762   emit done( false );
    00763   emit done( KSpell::origbuffer );
    00764   return MISTAKE;
    00765 }
    00766
    00767 bool KSpell::checkList (QStringList *_wordlist, bool _usedialog)
    00768   // prepare check of string list
    00769 {
    00770   wordlist=_wordlist;
    00771   if ((totalpos=wordlist->count())==0)
    00772     return false;
    00773   wlIt = wordlist->begin();
    00774   usedialog=_usedialog;
    00775
    00776   // prepare the dialog
    00777   setUpDialog();
    00778
    00779   //set the dialog signal handler
    00780   dialog3slot = SLOT (checkList4 ());
    00781
    00782   proc->writeStdin ("%"); // turn off terse mode & check one word at a time
    00783
    00784   //lastpos now counts which *word number* we are at in checkListReplaceCurrent()
    00785   lastpos = -1;
    00786   checkList2();
    00787
    00788   // when checked, KProcIO calls checkList3a
    00789   OUTPUT(checkList3a);
    00790
    00791   return true;
    00792 }
    00793
    00794 void KSpell::checkList2 ()
    00795   // send one word from the list to KProcIO
    00796   // invoked first time by checkList, later by checkListReplaceCurrent and checkList4
    00797 {
    00798   // send next word
    00799   if (wlIt != wordlist->end())
    00800   {
    00801     kdDebug(750) << "KS::cklist2 " << lastpos << ": " << *wlIt << endl;
    00802
    00803     d->endOfResponse = false;
    00804     bool put;
    00805     lastpos++; offset=0;
    00806     put = cleanFputsWord (*wlIt);
    00807     ++wlIt;
    00808
    00809     // when cleanFPutsWord failed (e.g. on empty word)
    00810     // try next word; may be this is not good for other
    00811     // problems, because this will make read the list up to the end
    00812     if (!put) {
    00813       checkList2();
    00814     }
    00815   }
    00816   else
    00817     // end of word list
    00818   {
    00819     NOOUTPUT(checkList3a);
    00820     ksdlg->hide();
    00821     emit done(true);
    00822   }
    00823 }
    00824
    00825 void KSpell::checkList3a (KProcIO *)
    00826   // invoked by KProcIO, when data from ispell are read
    00827 {
    00828   //kdDebug(750) << "start of checkList3a" << endl;
    00829
    00830   // don't read more data, when dialog is waiting
    00831   // for user interaction
    00832   if ( dlgon ) {
    00833     //kdDebug(750) << "dlgon: don't read more data" << endl;
    00834     return;
    00835   }
    00836
    00837   int e, tempe;
    00838
    00839   QString word;
    00840   QString line;
    00841
    00842   do
    00843   {
    00844     tempe=proc->readln( line, true ); //get ispell's response
    00845
    00846     //kdDebug(750) << "checkList3a: read bytes [" << tempe << "]" << endl;
    00847
    00848
    00849     if ( tempe == 0 ) {
    00850       d->endOfResponse = true;
    00851       //kdDebug(750) << "checkList3a: end of resp" << endl;
    00852     } else if ( tempe>0 ) {
    00853       if ( (e=parseOneResponse( line, word, sugg ) ) == MISTAKE ||
    00854            e==REPLACE )
    00855       {
    00856         dlgresult=-1;
    00857
    00858         if ( e == REPLACE )
    00859         {
    00860           QString old = *(--wlIt); ++wlIt;
    00861           dlgreplacement = word;
    00862           checkListReplaceCurrent();
    00863           // inform application
    00864           emit corrected( old, *(--wlIt), lastpos ); ++wlIt;
    00865         }
    00866         else if( usedialog )
    00867         {
    00868           cwword = word;
    00869           dlgon = true;
    00870           // show the dialog
    00871           dialog( word, sugg, SLOT(checkList4()) );
    00872           return;
    00873         }
    00874         else
    00875         {
    00876           d->m_bNoMisspellingsEncountered = false;
    00877           emit misspelling( word, sugg, lastpos );
    00878         }
    00879       }
    00880
    00881     }
    00882     emitProgress (); //maybe
    00883
    00884     // stop when empty line or no more data
    00885   } while (tempe > 0);
    00886
    00887   //kdDebug(750) << "checkList3a: exit loop with [" << tempe << "]" << endl;
    00888
    00889   // if we got an empty line, t.e. end of ispell/aspell response
    00890   // and the dialog isn't waiting for user interaction, send next word
    00891   if (d->endOfResponse && !dlgon) {
    00892     //kdDebug(750) << "checkList3a: send next word" << endl;
    00893     checkList2();
    00894   }
    00895 }
    00896
    00897 void KSpell::checkListReplaceCurrent()
    00898 {
    00899
    00900   // go back to misspelled word
    00901   wlIt--;
    00902
    00903   QString s = *wlIt;
    00904   s.replace(posinline+offset,orig.length(),replacement());
    00905   offset += replacement().length()-orig.length();
    00906   wordlist->insert (wlIt, s);
    00907   wlIt = wordlist->remove (wlIt);
    00908   // wlIt now points to the word after the repalced one
    00909
    00910 }
    00911
    00912 void KSpell::checkList4 ()
    00913   // evaluate dialog return, when a button was pressed there
    00914 {
    00915   dlgon=false;
    00916   QString old;
    00917
    00918   disconnect (this, SIGNAL (dialog3()), this, SLOT (checkList4()));
    00919
    00920   //others should have been processed by dialog() already
    00921   switch (dlgresult)
    00922   {
    00923   case KS_REPLACE:
    00924   case KS_REPLACEALL:
    00925     kdDebug(750) << "KS: cklist4: lastpos: " << lastpos << endl;
    00926     old = *(--wlIt);
    00927     ++wlIt;
    00928     // replace word
    00929     checkListReplaceCurrent();
    00930     emit corrected( old, *(--wlIt), lastpos );
    00931     ++wlIt;
    00932     break;
    00933   case KS_CANCEL:
    00934     ksdlg->hide();
    00935     emit done( false );
    00936     return;
    00937   case KS_STOP:
    00938     ksdlg->hide();
    00939     emit done( true );
    00940     return;
    00941   case KS_CONFIG:
    00942     ksdlg->hide();
    00943     emit done( false );
    00944     //check( origbuffer.mid( lastpos ), true );
    00945     //trystart = 0;
    00946     //proc->disconnect();
    00947     //proc->kill();
    00948     //delete proc;
    00949     //proc = new KProcIO( codec );
    00950     //startIspell();
    00951     return;
    00952   };
    00953
    00954   // read more if there is more, otherwise send next word
    00955   if (!d->endOfResponse) {
    00956     //kdDebug(750) << "checkList4: read more from response" << endl;
    00957     checkList3a(NULL);
    00958   }
    00959 }
    00960
    00961 bool KSpell::check( const QString &_buffer, bool _usedialog )
    00962 {
    00963   QString qs;
    00964
    00965   usedialog = _usedialog;
    00966   setUpDialog();
    00967   //set the dialog signal handler
    00968   dialog3slot = SLOT(check3());
    00969
    00970   kdDebug(750) << "KS: check" << endl;
    00971   origbuffer = _buffer;
    00972   if ( ( totalpos = origbuffer.length() ) == 0 )
    00973   {
    00974     emit done( origbuffer );
    00975     return false;
    00976   }
    00977
    00978
    00979   // Torben: I corrected the \n\n problem directly in the
    00980   //         origbuffer since I got errors otherwise
    00981   if ( !origbuffer.endsWith("\n\n" ) )
    00982   {
    00983     if (origbuffer.at(origbuffer.length()-1)!='\n')
    00984     {
    00985       origbuffer+='\n';
    00986       origbuffer+='\n'; //shouldn't these be removed at some point?
    00987     }
    00988     else
    00989       origbuffer+='\n';
    00990   }
    00991
    00992   newbuffer = origbuffer;
    00993
    00994   // KProcIO calls check2 when read from ispell
    00995   OUTPUT( check2 );
    00996   proc->writeStdin( "!" );
    00997
    00998   //lastpos is a position in newbuffer (it has offset in it)
    00999   offset = lastlastline = lastpos = lastline = 0;
    01000
    01001   emitProgress();
    01002
    01003   // send first buffer line
    01004   int i = origbuffer.find( '\n', 0 ) + 1;
    01005   qs = origbuffer.mid( 0, i );
    01006   cleanFputs( qs, false );
    01007
    01008   lastline=i; //the character position, not a line number
    01009
    01010   if ( usedialog )
    01011   {
    01012     emitProgress();
    01013   }
    01014   else
    01015     ksdlg->hide();
    01016
    01017   return true;
    01018 }
    01019
    01020
    01021 void KSpell::check2( KProcIO * )
    01022   // invoked by KProcIO when read from ispell
    01023 {
    01024   int e, tempe;
    01025   QString word;
    01026   QString line;
    01027   static bool recursive = false;
    01028   if (recursive &&
    01029       !ksdlg )
    01030   {
    01031       return;
    01032   }
    01033   recursive = true;
    01034
    01035   do
    01036   {
    01037     tempe = proc->readln( line, false ); //get ispell's response
    01038     //kdDebug(750) << "KSpell::check2 (" << tempe << "b)" << endl;
    01039
    01040     if ( tempe>0 )
    01041     {
    01042       if ( ( e=parseOneResponse (line, word, sugg) )==MISTAKE ||
    01043            e==REPLACE)
    01044       {
    01045         dlgresult=-1;
    01046
    01047         // for multibyte encoding posinline needs correction
    01048         if ((ksconfig->encoding() == KS_E_UTF8) && !d->aspellV6) {
    01049           // kdDebug(750) << "line: " << origbuffer.mid(lastlastline,
    01050           // lastline-lastlastline) << endl;
    01051           // kdDebug(750) << "posinline uncorr: " << posinline << endl;
    01052
    01053           // convert line to UTF-8, cut at pos, convert back to UCS-2
    01054           // and get string length
    01055           posinline = (QString::fromUtf8(
    01056                          origbuffer.mid(lastlastline,lastline-lastlastline).utf8(),
    01057                          posinline)).length();
    01058           // kdDebug(750) << "posinline corr: " << posinline << endl;
    01059         }
    01060
    01061         lastpos = posinline+lastlastline+offset;
    01062
    01063         //orig is set by parseOneResponse()
    01064
    01065         if (e==REPLACE)
    01066         {
    01067           dlgreplacement=word;
    01068           emit corrected( orig, replacement(), lastpos );
    01069           offset += replacement().length()-orig.length();
    01070           newbuffer.replace( lastpos, orig.length(), word );
    01071         }
    01072         else  //MISTAKE
    01073         {
    01074           cwword = word;
    01075           //kdDebug(750) << "(Before dialog) word=[" << word << "] cwword =[" << cwword << "]\n" << endl;
    01076           if ( usedialog ) {
    01077             // show the word in the dialog
    01078             dialog( word, sugg, SLOT(check3()) );
    01079           } else {
    01080             // No dialog, just emit misspelling and continue
    01081             d->m_bNoMisspellingsEncountered = false;
    01082             emit misspelling( word, sugg, lastpos );
    01083             dlgresult = KS_IGNORE;
    01084             check3();
    01085           }
    01086           recursive = false;
    01087           return;
    01088         }
    01089       }
    01090
    01091     }
    01092
    01093     emitProgress(); //maybe
    01094
    01095   } while( tempe>0 );
    01096
    01097   if ( tempe == -1 ) { //we were called, but no data seems to be ready...
    01098     // Make sure we don't get called directly again and make sure we do get
    01099     // called when new data arrives.
    01100     NOOUTPUT( check2 );
    01101     proc->enableReadSignals(true);
    01102     OUTPUT( check2 );
    01103     recursive = false;
    01104     return;
    01105   }
    01106
    01107   proc->ackRead();
    01108
    01109   //If there is more to check, then send another line to ISpell.
    01110   if ( (unsigned int)lastline < origbuffer.length() )
    01111   {
    01112     int i;
    01113     QString qs;
    01114
    01115     //kdDebug(750) << "[EOL](" << tempe << ")[" << temp << "]" << endl;
    01116
    01117     lastpos = (lastlastline=lastline) + offset; //do we really want this?
    01118     i = origbuffer.find('\n', lastline) + 1;
    01119     qs = origbuffer.mid( lastline, i-lastline );
    01120     cleanFputs( qs, false );
    01121     lastline = i;
    01122     recursive = false;
    01123     return;
    01124   }
    01125   else
    01126     //This is the end of it all
    01127   {
    01128     ksdlg->hide();
    01129     //      kdDebug(750) << "check2() done" << endl;
    01130     newbuffer.truncate( newbuffer.length()-2 );
    01131     emitProgress();
    01132     emit done( newbuffer );
    01133   }
    01134   recursive = false;
    01135 }
    01136
    01137 void KSpell::check3 ()
    01138   // evaluates the return value of the dialog
    01139 {
    01140   disconnect (this, SIGNAL (dialog3()), this, SLOT (check3()));
    01141   kdDebug(750) << "check3 [" << cwword << "] [" << replacement() << "] " << dlgresult << endl;
    01142
    01143   //others should have been processed by dialog() already
    01144   switch (dlgresult)
    01145   {
    01146   case KS_REPLACE:
    01147   case KS_REPLACEALL:
    01148     offset+=replacement().length()-cwword.length();
    01149     newbuffer.replace (lastpos, cwword.length(),
    01150                        replacement());
    01151     emit corrected (dlgorigword, replacement(), lastpos);
    01152     break;
    01153   case KS_CANCEL:
    01154     //      kdDebug(750) << "canceled\n" << endl;
    01155     ksdlg->hide();
    01156     emit done( origbuffer );
    01157     return;
    01158   case KS_CONFIG:
    01159     ksdlg->hide();
    01160     emit done( origbuffer );
    01161     KMessageBox::information( 0, i18n("You have to restart the dialog for changes to take effect") );
    01162     //check( origbuffer.mid( lastpos ), true );
    01163     return;
    01164   case KS_STOP:
    01165     ksdlg->hide();
    01166     //buffer=newbuffer);
    01167     emitProgress();
    01168     emit done (newbuffer);
    01169     return;
    01170   };
    01171
    01172   proc->ackRead();
    01173 }
    01174
    01175 void
    01176 KSpell::slotStopCancel (int result)
    01177 {
    01178   if (dialogwillprocess)
    01179     return;
    01180
    01181   kdDebug(750) << "KSpell::slotStopCancel [" << result << "]" << endl;
    01182
    01183   if (result==KS_STOP || result==KS_CANCEL)
    01184     if (!dialog3slot.isEmpty())
    01185     {
    01186       dlgresult=result;
    01187       connect (this, SIGNAL (dialog3()), this, dialog3slot.ascii());
    01188       emit dialog3();
    01189     }
    01190 }
    01191
    01192
    01193 void KSpell::dialog( const QString & word, QStringList & sugg, const char *_slot )
    01194 {
    01195   dlgorigword = word;
    01196
    01197   dialog3slot = _slot;
    01198   dialogwillprocess = true;
    01199   connect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
    01200   QString tmpBuf = newbuffer;
    01201   kdDebug(750)<<" position = "<<lastpos<<endl;
    01202
    01203   // extract a context string, replace all characters which might confuse
    01204   // the RichText display and highlight the possibly wrong word
    01205   QString marker( "_MARKER_" );
    01206   tmpBuf.replace( lastpos, word.length(), marker );
    01207   QString context = tmpBuf.mid(QMAX(lastpos-18,0), 2*18+marker.length());
    01208   context.replace( '\n',QString::fromLatin1(" "));
    01209   context.replace( '<', QString::fromLatin1("&lt;") );
    01210   context.replace( '>', QString::fromLatin1("&gt;") );
    01211   context.replace( marker, QString::fromLatin1("<b>%1</b>").arg( word ) );
    01212   context = "<qt>" + context + "</qt>";
    01213
    01214   ksdlg->init( word, &sugg, context );
    01215   d->m_bNoMisspellingsEncountered = false;
    01216   emit misspelling( word, sugg, lastpos );
    01217
    01218   emitProgress();
    01219   ksdlg->show();
    01220 }
    01221
    01222 void KSpell::dialog2( int result )
    01223 {
    01224   QString qs;
    01225
    01226   disconnect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
    01227   dialogwillprocess = false;
    01228   dlgresult = result;
    01229   ksdlg->standby();
    01230
    01231   dlgreplacement = ksdlg->replacement();
    01232
    01233   //process result here
    01234   switch ( dlgresult )
    01235   {
    01236   case KS_IGNORE:
    01237     emit ignoreword( dlgorigword );
    01238     break;
    01239   case KS_IGNOREALL:
    01240     // would be better to lower case only words with beginning cap
    01241     ignorelist.prepend( dlgorigword.lower() );
    01242     emit ignoreall( dlgorigword );
    01243     break;
    01244   case KS_ADD:
    01245     addPersonal( dlgorigword );
    01246     personaldict = true;
    01247     emit addword( dlgorigword );
    01248     // adding to pesonal dict takes effect at the next line, not the current
    01249     ignorelist.prepend( dlgorigword.lower() );
    01250     break;
    01251   case KS_REPLACEALL:
    01252   {
    01253     replacelist.append( dlgorigword );
    01254     QString _replacement = replacement();
    01255     replacelist.append( _replacement );
    01256     emit replaceall( dlgorigword ,  _replacement );
    01257   }
    01258     break;
    01259   case KS_SUGGEST:
    01260     checkWord( ksdlg->replacement(), false, true );
    01261     return;
    01262     break;
    01263   }
    01264
    01265   connect( this, SIGNAL(dialog3()), this, dialog3slot.ascii() );
    01266   emit dialog3();
    01267 }
    01268
    01269
    01270 KSpell::~KSpell()
    01271 {
    01272   delete proc;
    01273   delete ksconfig;
    01274   delete ksdlg;
    01275   delete d->checkNextTimer;
    01276   delete d;
    01277 }
    01278
    01279
    01280 KSpellConfig KSpell::ksConfig() const
    01281 {
    01282   ksconfig->setIgnoreList(ignorelist);
    01283   ksconfig->setReplaceAllList(replacelist);
    01284   return *ksconfig;
    01285 }
    01286
    01287 void KSpell::cleanUp()
    01288 {
    01289   if ( m_status == Cleaning )
    01290     return; // Ignore
    01291
    01292   if ( m_status == Running )
    01293   {
    01294     if ( personaldict )
    01295       writePersonalDictionary();
    01296     m_status = Cleaning;
    01297   }
    01298   proc->closeStdin();
    01299 }
    01300
    01301 void KSpell::ispellExit( KProcess* )
    01302 {
    01303   kdDebug() << "KSpell::ispellExit() " << m_status << endl;
    01304
    01305   if ( (m_status == Starting) && (trystart < maxtrystart) )
    01306   {
    01307     trystart++;
    01308     startIspell();
    01309     return;
    01310   }
    01311
    01312   if ( m_status == Starting )
    01313      m_status = Error;
    01314   else if (m_status == Cleaning)
    01315      m_status = d->m_bNoMisspellingsEncountered ? FinishedNoMisspellingsEncountered : Finished;
    01316   else if ( m_status == Running )
    01317      m_status = Crashed;
    01318   else // Error, Finished, Crashed
    01319      return; // Dead already
    01320
    01321   kdDebug(750) << "Death" << endl;
    01322   QTimer::singleShot( 0, this, SLOT(emitDeath()) );
    01323 }
    01324
    01325 // This is always called from the event loop to make
    01326 // sure that the receiver can safely delete the
    01327 // KSpell object.
    01328 void KSpell::emitDeath()
    01329 {
    01330   bool deleteMe = autoDelete; // Can't access object after next call!
    01331   emit death();
    01332   if ( deleteMe )
    01333     deleteLater();
    01334 }
    01335
    01336 void KSpell::setProgressResolution (unsigned int res)
    01337 {
    01338   progres=res;
    01339 }
    01340
    01341 void KSpell::emitProgress ()
    01342 {
    01343   uint nextprog = (uint) (100.*lastpos/(double)totalpos);
    01344
    01345   if ( nextprog >= curprog )
    01346   {
    01347     curprog = nextprog;
    01348     emit progress( curprog );
    01349   }
    01350 }
    01351
    01352 void KSpell::moveDlg( int x, int y )
    01353 {
    01354   QPoint pt( x,y ), pt2;
    01355   pt2 = parent->mapToGlobal( pt );
    01356   ksdlg->move( pt2.x(),pt2.y() );
    01357 }
    01358
    01359 void KSpell::setIgnoreUpperWords(bool _ignore)
    01360 {
    01361   d->m_bIgnoreUpperWords=_ignore;
    01362 }
    01363
    01364 void KSpell::setIgnoreTitleCase(bool _ignore)
    01365 {
    01366   d->m_bIgnoreTitleCase=_ignore;
    01367 }
    01368 // --------------------------------------------------
    01369 // Stuff for modal (blocking) spell checking
    01370 //
    01371 // Written by Torben Weis <weis@kde.org>. So please
    01372 // send bug reports regarding the modal stuff to me.
    01373 // --------------------------------------------------
    01374
    01375 int
    01376 KSpell::modalCheck( QString& text )
    01377 {
    01378   return modalCheck( text,0 );
    01379 }
    01380
    01381 int
    01382 KSpell::modalCheck( QString& text, KSpellConfig* _kcs )
    01383 {
    01384   modalreturn = 0;
    01385   modaltext = text;
    01386
    01387   KSpell* spell = new KSpell( 0L, i18n("Spell Checker"), 0 ,
    01388                               0, _kcs, true, true );
    01389
    01390   while (spell->status()!=Finished)
    01391     kapp->processEvents();
    01392
    01393   text = modaltext;
    01394
    01395   delete spell;
    01396   return modalreturn;
    01397 }
    01398
    01399 void KSpell::slotSpellCheckerCorrected( const QString & oldText, const QString & newText, unsigned int pos )
    01400 {
    01401   modaltext=modaltext.replace(pos,oldText.length(),newText);
    01402 }
    01403
    01404
    01405 void KSpell::slotModalReady()
    01406 {
    01407   //kdDebug() << qApp->loopLevel() << endl;
    01408   //kdDebug(750) << "MODAL READY------------------" << endl;
    01409
    01410   Q_ASSERT( m_status == Running );
    01411   connect( this, SIGNAL( done( const QString & ) ),
    01412            this, SLOT( slotModalDone( const QString & ) ) );
    01413   QObject::connect( this, SIGNAL( corrected( const QString&, const QString&, unsigned int ) ),
    01414                     this, SLOT( slotSpellCheckerCorrected( const QString&, const QString &, unsigned int ) ) );
    01415   QObject::connect( this, SIGNAL( death() ),
    01416                     this, SLOT( slotModalSpellCheckerFinished( ) ) );
    01417   check( modaltext );
    01418 }
    01419
    01420 void KSpell::slotModalDone( const QString &/*_buffer*/ )
    01421 {
    01422   //kdDebug(750) << "MODAL DONE " << _buffer << endl;
    01423   //modaltext = _buffer;
    01424   cleanUp();
    01425
    01426   //kdDebug() << "ABOUT TO EXIT LOOP" << endl;
    01427   //qApp->exit_loop();
    01428
    01429   //modalWidgetHack->close(true);
    01430   slotModalSpellCheckerFinished();
    01431 }
    01432
    01433 void KSpell::slotModalSpellCheckerFinished( )
    01434 {
    01435   modalreturn=(int)this->status();
    01436 }
    01437
    01438 void KSpell::initialize( QWidget *_parent, const QString &_caption,
    01439                          QObject *obj, const char *slot, KSpellConfig *_ksc,
    01440                          bool _progressbar, bool _modal, SpellerType type )
    01441 {
    01442   d = new KSpellPrivate;
    01443
    01444   d->m_bIgnoreUpperWords =false;
    01445   d->m_bIgnoreTitleCase =false;
    01446   d->m_bNoMisspellingsEncountered = true;
    01447   d->type = type;
    01448   d->checking = false;
    01449   d->aspellV6 = false;
    01450   d->checkNextTimer = new QTimer( this );
    01451   connect( d->checkNextTimer, SIGNAL( timeout() ),
    01452        this, SLOT( checkNext() ));
    01453   autoDelete = false;
    01454   modaldlg = _modal;
    01455   progressbar = _progressbar;
    01456
    01457   proc     = 0;
    01458   ksconfig = 0;
    01459   ksdlg    = 0;
    01460   lastpos  = 0;
    01461
    01462   //won't be using the dialog in ksconfig, just the option values
    01463   if ( _ksc )
    01464     ksconfig = new KSpellConfig( *_ksc );
    01465   else
    01466     ksconfig = new KSpellConfig;
    01467
    01468   codec = 0;
    01469   switch ( ksconfig->encoding() )
    01470   {
    01471   case KS_E_LATIN1:
    01472      codec = QTextCodec::codecForName("ISO 8859-1");
    01473      break;
    01474   case KS_E_LATIN2:
    01475      codec = QTextCodec::codecForName("ISO 8859-2");
    01476      break;
    01477   case KS_E_LATIN3:
    01478       codec = QTextCodec::codecForName("ISO 8859-3");
    01479       break;
    01480   case KS_E_LATIN4:
    01481       codec = QTextCodec::codecForName("ISO 8859-4");
    01482       break;
    01483   case KS_E_LATIN5:
    01484       codec = QTextCodec::codecForName("ISO 8859-5");
    01485       break;
    01486   case KS_E_LATIN7:
    01487       codec = QTextCodec::codecForName("ISO 8859-7");
    01488       break;
    01489   case KS_E_LATIN8:
    01490       codec = QTextCodec::codecForName("ISO 8859-8-i");
    01491       break;
    01492   case KS_E_LATIN9:
    01493       codec = QTextCodec::codecForName("ISO 8859-9");
    01494       break;
    01495   case KS_E_LATIN13:
    01496       codec = QTextCodec::codecForName("ISO 8859-13");
    01497       break;
    01498   case KS_E_LATIN15:
    01499       codec = QTextCodec::codecForName("ISO 8859-15");
    01500       break;
    01501   case KS_E_UTF8:
    01502       codec = QTextCodec::codecForName("UTF-8");
    01503       break;
    01504   case KS_E_KOI8R:
    01505       codec = QTextCodec::codecForName("KOI8-R");
    01506       break;
    01507   case KS_E_KOI8U:
    01508       codec = QTextCodec::codecForName("KOI8-U");
    01509       break;
    01510   case KS_E_CP1251:
    01511       codec = QTextCodec::codecForName("CP1251");
    01512       break;
    01513   case KS_E_CP1255:
    01514       codec = QTextCodec::codecForName("CP1255");
    01515       break;
    01516   default:
    01517      break;
    01518   }
    01519
    01520   kdDebug(750) << __FILE__ << ":" << __LINE__ << " Codec = " << (codec ? codec->name() : "<default>") << endl;
    01521
    01522   // copy ignore list from ksconfig
    01523   ignorelist += ksconfig->ignoreList();
    01524
    01525   replacelist += ksconfig->replaceAllList();
    01526   texmode=dlgon=false;
    01527   m_status = Starting;
    01528   dialogsetup = false;
    01529   progres=10;
    01530   curprog=0;
    01531
    01532   dialogwillprocess = false;
    01533   dialog3slot = QString::null;
    01534
    01535   personaldict = false;
    01536   dlgresult = -1;
    01537
    01538   caption = _caption;
    01539
    01540   parent = _parent;
    01541
    01542   trystart = 0;
    01543   maxtrystart = 2;
    01544
    01545   if ( obj && slot )
    01546       // caller wants to know when kspell is ready
    01547       connect( this, SIGNAL(ready(KSpell *)), obj, slot);
    01548   else
    01549       // Hack for modal spell checking
    01550       connect( this, SIGNAL(ready(KSpell *)), this, SLOT(slotModalReady()) );
    01551
    01552   proc = new KProcIO( codec );
    01553
    01554   startIspell();
    01555 }
    01556
    01557 QString KSpell::modaltext;
    01558 int KSpell::modalreturn = 0;
    01559 QWidget* KSpell::modalWidgetHack = 0;
    01560
    01561 #include "kspell.moc"
    01562

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:22 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003