• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdeui

kspell.cpp

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

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal