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