kdeui Library API Documentation

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   proc->ackRead();
01098 
01099 
01100   if ( tempe == -1 ) { //we were called, but no data seems to be ready...
01101     recursive = false;
01102     return;
01103   }
01104 
01105   //If there is more to check, then send another line to ISpell.
01106   if ( (unsigned int)lastline < origbuffer.length() )
01107   {
01108     int i;
01109     QString qs;
01110 
01111     //kdDebug(750) << "[EOL](" << tempe << ")[" << temp << "]" << endl;
01112 
01113     lastpos = (lastlastline=lastline) + offset; //do we really want this?
01114     i = origbuffer.find('\n', lastline) + 1;
01115     qs = origbuffer.mid( lastline, i-lastline );
01116     cleanFputs( qs, false );
01117     lastline = i;
01118     recursive = false;
01119     return;
01120   }
01121   else
01122     //This is the end of it all
01123   {
01124     ksdlg->hide();
01125     //      kdDebug(750) << "check2() done" << endl;
01126     newbuffer.truncate( newbuffer.length()-2 );
01127     emitProgress();
01128     emit done( newbuffer );
01129   }
01130   recursive = false;
01131 }
01132 
01133 void KSpell::check3 ()
01134   // evaluates the return value of the dialog
01135 {
01136   disconnect (this, SIGNAL (dialog3()), this, SLOT (check3()));
01137   kdDebug(750) << "check3 [" << cwword << "] [" << replacement() << "] " << dlgresult << endl;
01138 
01139   //others should have been processed by dialog() already
01140   switch (dlgresult)
01141   {
01142   case KS_REPLACE:
01143   case KS_REPLACEALL:
01144     offset+=replacement().length()-cwword.length();
01145     newbuffer.replace (lastpos, cwword.length(),
01146                        replacement());
01147     emit corrected (dlgorigword, replacement(), lastpos);
01148     break;
01149   case KS_CANCEL:
01150     //      kdDebug(750) << "canceled\n" << endl;
01151     ksdlg->hide();
01152     emit done( origbuffer );
01153     return;
01154   case KS_CONFIG:
01155     ksdlg->hide();
01156     emit done( origbuffer );
01157     KMessageBox::information( 0, i18n("You have to restart the dialog for changes to take effect") );
01158     //check( origbuffer.mid( lastpos ), true );
01159     return;
01160   case KS_STOP:
01161     ksdlg->hide();
01162     //buffer=newbuffer);
01163     emitProgress();
01164     emit done (newbuffer);
01165     return;
01166   };
01167 
01168   proc->ackRead();
01169 }
01170 
01171 void
01172 KSpell::slotStopCancel (int result)
01173 {
01174   if (dialogwillprocess)
01175     return;
01176 
01177   kdDebug(750) << "KSpell::slotStopCancel [" << result << "]" << endl;
01178 
01179   if (result==KS_STOP || result==KS_CANCEL)
01180     if (!dialog3slot.isEmpty())
01181     {
01182       dlgresult=result;
01183       connect (this, SIGNAL (dialog3()), this, dialog3slot.ascii());
01184       emit dialog3();
01185     }
01186 }
01187 
01188 
01189 void KSpell::dialog( const QString & word, QStringList & sugg, const char *_slot )
01190 {
01191   dlgorigword = word;
01192 
01193   dialog3slot = _slot;
01194   dialogwillprocess = true;
01195   connect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
01196   QString tmpBuf = newbuffer;
01197   kdDebug(750)<<" position = "<<lastpos<<endl;
01198 
01199   // extract a context string, replace all characters which might confuse
01200   // the RichText display and highlight the possibly wrong word
01201   QString marker( "_MARKER_" );
01202   tmpBuf.replace( lastpos, word.length(), marker );
01203   QString context = tmpBuf.mid(QMAX(lastpos-18,0), 2*18+marker.length());
01204   context.replace( '\n',QString::fromLatin1(" "));
01205   context.replace( '<', QString::fromLatin1("&lt;") );
01206   context.replace( '>', QString::fromLatin1("&gt;") );
01207   context.replace( marker, QString::fromLatin1("<b>%1</b>").arg( word ) );
01208   context = "<qt>" + context + "</qt>";
01209 
01210   ksdlg->init( word, &sugg, context );
01211   d->m_bNoMisspellingsEncountered = false;
01212   emit misspelling( word, sugg, lastpos );
01213 
01214   emitProgress();
01215   ksdlg->show();
01216 }
01217 
01218 void KSpell::dialog2( int result )
01219 {
01220   QString qs;
01221 
01222   disconnect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
01223   dialogwillprocess = false;
01224   dlgresult = result;
01225   ksdlg->standby();
01226 
01227   dlgreplacement = ksdlg->replacement();
01228 
01229   //process result here
01230   switch ( dlgresult )
01231   {
01232   case KS_IGNORE:
01233     emit ignoreword( dlgorigword );
01234     break;
01235   case KS_IGNOREALL:
01236     // would be better to lower case only words with beginning cap
01237     ignorelist.prepend( dlgorigword.lower() );
01238     emit ignoreall( dlgorigword );
01239     break;
01240   case KS_ADD:
01241     addPersonal( dlgorigword );
01242     personaldict = true;
01243     emit addword( dlgorigword );
01244     // adding to pesonal dict takes effect at the next line, not the current
01245     ignorelist.prepend( dlgorigword.lower() );
01246     break;
01247   case KS_REPLACEALL:
01248   {
01249     replacelist.append( dlgorigword );
01250     QString _replacement = replacement();
01251     replacelist.append( _replacement );
01252     emit replaceall( dlgorigword ,  _replacement );
01253   }
01254     break;
01255   case KS_SUGGEST:
01256     checkWord( ksdlg->replacement(), false, true );
01257     return;
01258     break;
01259   }
01260 
01261   connect( this, SIGNAL(dialog3()), this, dialog3slot.ascii() );
01262   emit dialog3();
01263 }
01264 
01265 
01266 KSpell::~KSpell()
01267 {
01268   delete proc;
01269   delete ksconfig;
01270   delete ksdlg;
01271   delete d->checkNextTimer;
01272   delete d;
01273 }
01274 
01275 
01276 KSpellConfig KSpell::ksConfig() const
01277 {
01278   ksconfig->setIgnoreList(ignorelist);
01279   ksconfig->setReplaceAllList(replacelist);
01280   return *ksconfig;
01281 }
01282 
01283 void KSpell::cleanUp()
01284 {
01285   if ( m_status == Cleaning )
01286     return; // Ignore
01287 
01288   if ( m_status == Running )
01289   {
01290     if ( personaldict )
01291       writePersonalDictionary();
01292     m_status = Cleaning;
01293   }
01294   proc->closeStdin();
01295 }
01296 
01297 void KSpell::ispellExit( KProcess* )
01298 {
01299   kdDebug() << "KSpell::ispellExit() " << m_status << endl;
01300 
01301   if ( (m_status == Starting) && (trystart < maxtrystart) )
01302   {
01303     trystart++;
01304     startIspell();
01305     return;
01306   }
01307 
01308   if ( m_status == Starting )
01309      m_status = Error;
01310   else if (m_status == Cleaning)
01311      m_status = d->m_bNoMisspellingsEncountered ? FinishedNoMisspellingsEncountered : Finished;
01312   else if ( m_status == Running )
01313      m_status = Crashed;
01314   else // Error, Finished, Crashed
01315      return; // Dead already
01316 
01317   kdDebug(750) << "Death" << endl;
01318   QTimer::singleShot( 0, this, SLOT(emitDeath()) );
01319 }
01320 
01321 // This is always called from the event loop to make
01322 // sure that the receiver can safely delete the
01323 // KSpell object.
01324 void KSpell::emitDeath()
01325 {
01326   bool deleteMe = autoDelete; // Can't access object after next call!
01327   emit death();
01328   if ( deleteMe )
01329     deleteLater();
01330 }
01331 
01332 void KSpell::setProgressResolution (unsigned int res)
01333 {
01334   progres=res;
01335 }
01336 
01337 void KSpell::emitProgress ()
01338 {
01339   uint nextprog = (uint) (100.*lastpos/(double)totalpos);
01340 
01341   if ( nextprog >= curprog )
01342   {
01343     curprog = nextprog;
01344     emit progress( curprog );
01345   }
01346 }
01347 
01348 void KSpell::moveDlg( int x, int y )
01349 {
01350   QPoint pt( x,y ), pt2;
01351   pt2 = parent->mapToGlobal( pt );
01352   ksdlg->move( pt2.x(),pt2.y() );
01353 }
01354 
01355 void KSpell::setIgnoreUpperWords(bool _ignore)
01356 {
01357   d->m_bIgnoreUpperWords=_ignore;
01358 }
01359 
01360 void KSpell::setIgnoreTitleCase(bool _ignore)
01361 {
01362   d->m_bIgnoreTitleCase=_ignore;
01363 }
01364 // --------------------------------------------------
01365 // Stuff for modal (blocking) spell checking
01366 //
01367 // Written by Torben Weis <weis@kde.org>. So please
01368 // send bug reports regarding the modal stuff to me.
01369 // --------------------------------------------------
01370 
01371 int
01372 KSpell::modalCheck( QString& text )
01373 {
01374   return modalCheck( text,0 );
01375 }
01376 
01377 int
01378 KSpell::modalCheck( QString& text, KSpellConfig* _kcs )
01379 {
01380   modalreturn = 0;
01381   modaltext = text;
01382 
01383   KSpell* spell = new KSpell( 0L, i18n("Spell Checker"), 0 ,
01384                               0, _kcs, true, true );
01385 
01386   while (spell->status()!=Finished)
01387     kapp->processEvents();
01388 
01389   text = modaltext;
01390 
01391   delete spell;
01392   return modalreturn;
01393 }
01394 
01395 void KSpell::slotSpellCheckerCorrected( const QString & oldText, const QString & newText, unsigned int pos )
01396 {
01397   modaltext=modaltext.replace(pos,oldText.length(),newText);
01398 }
01399 
01400 
01401 void KSpell::slotModalReady()
01402 {
01403   //kdDebug() << qApp->loopLevel() << endl;
01404   //kdDebug(750) << "MODAL READY------------------" << endl;
01405 
01406   Q_ASSERT( m_status == Running );
01407   connect( this, SIGNAL( done( const QString & ) ),
01408            this, SLOT( slotModalDone( const QString & ) ) );
01409   QObject::connect( this, SIGNAL( corrected( const QString&, const QString&, unsigned int ) ),
01410                     this, SLOT( slotSpellCheckerCorrected( const QString&, const QString &, unsigned int ) ) );
01411   QObject::connect( this, SIGNAL( death() ),
01412                     this, SLOT( slotModalSpellCheckerFinished( ) ) );
01413   check( modaltext );
01414 }
01415 
01416 void KSpell::slotModalDone( const QString &/*_buffer*/ )
01417 {
01418   //kdDebug(750) << "MODAL DONE " << _buffer << endl;
01419   //modaltext = _buffer;
01420   cleanUp();
01421 
01422   //kdDebug() << "ABOUT TO EXIT LOOP" << endl;
01423   //qApp->exit_loop();
01424 
01425   //modalWidgetHack->close(true);
01426   slotModalSpellCheckerFinished();
01427 }
01428 
01429 void KSpell::slotModalSpellCheckerFinished( )
01430 {
01431   modalreturn=(int)this->status();
01432 }
01433 
01434 void KSpell::initialize( QWidget *_parent, const QString &_caption,
01435                          QObject *obj, const char *slot, KSpellConfig *_ksc,
01436                          bool _progressbar, bool _modal, SpellerType type )
01437 {
01438   d = new KSpellPrivate;
01439 
01440   d->m_bIgnoreUpperWords =false;
01441   d->m_bIgnoreTitleCase =false;
01442   d->m_bNoMisspellingsEncountered = true;
01443   d->type = type;
01444   d->checking = false;
01445   d->aspellV6 = false;
01446   d->checkNextTimer = new QTimer( this );
01447   connect( d->checkNextTimer, SIGNAL( timeout() ),
01448        this, SLOT( checkNext() ));
01449   autoDelete = false;
01450   modaldlg = _modal;
01451   progressbar = _progressbar;
01452 
01453   proc     = 0;
01454   ksconfig = 0;
01455   ksdlg    = 0;
01456   lastpos  = 0;
01457 
01458   //won't be using the dialog in ksconfig, just the option values
01459   if ( _ksc )
01460     ksconfig = new KSpellConfig( *_ksc );
01461   else
01462     ksconfig = new KSpellConfig;
01463 
01464   codec = 0;
01465   switch ( ksconfig->encoding() )
01466   {
01467   case KS_E_LATIN1:
01468      codec = QTextCodec::codecForName("ISO 8859-1");
01469      break;
01470   case KS_E_LATIN2:
01471      codec = QTextCodec::codecForName("ISO 8859-2");
01472      break;
01473   case KS_E_LATIN3:
01474       codec = QTextCodec::codecForName("ISO 8859-3");
01475       break;
01476   case KS_E_LATIN4:
01477       codec = QTextCodec::codecForName("ISO 8859-4");
01478       break;
01479   case KS_E_LATIN5:
01480       codec = QTextCodec::codecForName("ISO 8859-5");
01481       break;
01482   case KS_E_LATIN7:
01483       codec = QTextCodec::codecForName("ISO 8859-7");
01484       break;
01485   case KS_E_LATIN8:
01486       codec = QTextCodec::codecForName("ISO 8859-8-i");
01487       break;
01488   case KS_E_LATIN9:
01489       codec = QTextCodec::codecForName("ISO 8859-9");
01490       break;
01491   case KS_E_LATIN13:
01492       codec = QTextCodec::codecForName("ISO 8859-13");
01493       break;
01494   case KS_E_LATIN15:
01495       codec = QTextCodec::codecForName("ISO 8859-15");
01496       break;
01497   case KS_E_UTF8:
01498       codec = QTextCodec::codecForName("UTF-8");
01499       break;
01500   case KS_E_KOI8R:
01501       codec = QTextCodec::codecForName("KOI8-R");
01502       break;
01503   case KS_E_KOI8U:
01504       codec = QTextCodec::codecForName("KOI8-U");
01505       break;
01506   case KS_E_CP1251:
01507       codec = QTextCodec::codecForName("CP1251");
01508       break;
01509   case KS_E_CP1255:
01510       codec = QTextCodec::codecForName("CP1255");
01511       break;
01512   default:
01513      break;
01514   }
01515 
01516   kdDebug(750) << __FILE__ << ":" << __LINE__ << " Codec = " << (codec ? codec->name() : "<default>") << endl;
01517 
01518   // copy ignore list from ksconfig
01519   ignorelist += ksconfig->ignoreList();
01520 
01521   replacelist += ksconfig->replaceAllList();
01522   texmode=dlgon=false;
01523   m_status = Starting;
01524   dialogsetup = false;
01525   progres=10;
01526   curprog=0;
01527 
01528   dialogwillprocess = false;
01529   dialog3slot = QString::null;
01530 
01531   personaldict = false;
01532   dlgresult = -1;
01533 
01534   caption = _caption;
01535 
01536   parent = _parent;
01537 
01538   trystart = 0;
01539   maxtrystart = 2;
01540 
01541   if ( obj && slot )
01542       // caller wants to know when kspell is ready
01543       connect( this, SIGNAL(ready(KSpell *)), obj, slot);
01544   else
01545       // Hack for modal spell checking
01546       connect( this, SIGNAL(ready(KSpell *)), this, SLOT(slotModalReady()) );
01547 
01548   proc = new KProcIO( codec );
01549 
01550   startIspell();
01551 }
01552 
01553 QString KSpell::modaltext;
01554 int KSpell::modalreturn = 0;
01555 QWidget* KSpell::modalWidgetHack = 0;
01556 
01557 #include "kspell.moc"
01558 
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 Fri Jul 21 13:14:04 2006 by doxygen 1.4.0 written by Dimitri van Heesch, © 1997-2003