kdeui Library API Documentation

kspell.cpp

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