tdespell.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., 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 <tqregexp.h> 00037 #include <tqtextcodec.h> 00038 #include <tqtimer.h> 00039 00040 #include <tdeapplication.h> 00041 #include <tdemessagebox.h> 00042 #include <kdebug.h> 00043 #include <tdelocale.h> 00044 #include "tdespell.h" 00045 #include "tdespelldlg.h" 00046 #include <twin.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 TQString 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 TQValueList<BufferedWord> unchecked; 00080 TQTimer *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, TQT_SIGNAL (readReady(KProcIO *)), this, TQT_SLOT (x(KProcIO *)))) 00101 00102 // Disconnect a slot from... 00103 #define NOOUTPUT(x) (disconnect (proc, TQT_SIGNAL (readReady(KProcIO *)), this, TQT_SLOT (x(KProcIO *)))) 00104 00105 00106 00107 KSpell::KSpell( TQWidget *_parent, const TQString &_caption, 00108 TQObject *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( TQWidget *_parent, const TQString &_caption, 00116 TQObject *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 TQString result; 00132 FILE *fs = popen("aspell -v", "r"); 00133 if (fs) 00134 { 00135 // Close textstream before we close fs 00136 { 00137 TQTextStream ts(fs, IO_ReadOnly); 00138 result = ts.read().stripWhiteSpace(); 00139 } 00140 pclose(fs); 00141 } 00142 00143 TQRegExp 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 tdespell 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, TQT_SIGNAL(receivedStderr(TDEProcess *, char *, int)), 00300 this, TQT_SLOT(ispellErrors(TDEProcess *, char *, int)) ); 00301 00302 connect( proc, TQT_SIGNAL(processExited(TDEProcess *)), 00303 this, TQT_SLOT(ispellExit (TDEProcess *)) ); 00304 00305 OUTPUT(KSpell2); 00306 } 00307 00308 if ( !proc->start() ) 00309 { 00310 m_status = Error; 00311 TQTimer::singleShot( 0, this, TQT_SLOT(emitDeath())); 00312 } 00313 } 00314 00315 void 00316 KSpell::ispellErrors( TDEProcess *, 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 TQString 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 TQTimer::singleShot( 0, this, TQT_SLOT(emitDeath()) ); 00335 return; 00336 } 00337 00338 00339 if ( line[0] != '@' ) //@ indicates that ispell is working fine 00340 { 00341 TQTimer::singleShot( 0, this, TQT_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 TQTimer::singleShot( 0, this, TQT_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 TQTimer::singleShot( 0, this, TQT_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, TQT_SIGNAL(command(int)), 00379 this, TQT_SLOT(slotStopCancel(int)) ); 00380 connect( this, TQT_SIGNAL(progress(unsigned int)), 00381 ksdlg, TQT_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 TQString & word ) 00392 { 00393 TQString 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(TQString("#")); 00408 } 00409 00410 bool KSpell::ignore( const TQString & word ) 00411 { 00412 TQString 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 TQString & s, bool appendCR ) 00425 { 00426 TQString 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 TQString & s, bool appendCR ) 00452 { 00453 TQString 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( TQString::fromAscii( "^\n" ),appendCR ); 00471 } 00472 00473 bool KSpell::checkWord( const TQString & 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 TQString 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 = TQT_SLOT(checkWord3()); 00492 00493 usedialog = _usedialog; 00494 setUpDialog( false ); 00495 if ( _usedialog ) 00496 { 00497 emitProgress(); 00498 } 00499 else 00500 ksdlg->hide(); 00501 00502 TQString blank_line; 00503 while (proc->readln( blank_line, true ) != -1); // eat spurious blanks 00504 00505 OUTPUT(checkWord2); 00506 // connect (this, TQT_SIGNAL (dialog3()), this, TQT_SLOT (checkWord3())); 00507 00508 proc->writeStdin(TQString("%")); // turn off terse mode 00509 proc->writeStdin( buffer ); // send the word to ispell 00510 00511 return true; 00512 } 00513 00514 bool KSpell::checkWord( const TQString & 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 TQString 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 = TQT_SLOT(checkWord3()); 00536 usedialog = _usedialog; 00537 setUpDialog( false ); 00538 if ( _usedialog ) 00539 { 00540 emitProgress(); 00541 } 00542 else 00543 ksdlg->hide(); 00544 } 00545 00546 TQString blank_line; 00547 while (proc->readln( blank_line, true ) != -1); // eat spurious blanks 00548 00549 OUTPUT(checkWord2); 00550 // connect (this, TQT_SIGNAL (dialog3()), this, TQT_SLOT (checkWord3())); 00551 00552 proc->writeStdin(TQString("%")); // 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 TQString word; 00561 TQString 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 TQString 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, TQT_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 tdespell 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 TQString word; 00614 TQString 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 TQString 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, TQT_SLOT(checkWord3()) ); 00630 return; 00631 } 00632 } 00633 00634 void KSpell::checkWord3() 00635 { 00636 disconnect( this, TQT_SIGNAL(dialog3()), this, TQT_SLOT(checkWord3()) ); 00637 00638 emit corrected( cwword, replacement(), 0L ); 00639 } 00640 00641 TQString KSpell::funnyWord( const TQString & word ) 00642 // composes a guess from ispell to a readable word 00643 // e.g. "re+fry-y+ies" -> "refries" 00644 { 00645 TQString 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 TQString 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 TQString &buffer, TQString &word, TQStringList & 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 TQString 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 TQString 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 TQStringList::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 TQString 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 TQString 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 (TQStringList *_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 = TQT_SLOT (checkList4 ()); 00796 00797 proc->writeStdin (TQString("%")); // 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 TQString word; 00855 TQString 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 TQString 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, TQT_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 TQString 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 TQString old; 00932 00933 disconnect (this, TQT_SIGNAL (dialog3()), this, TQT_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 TQString &_buffer, bool _usedialog ) 00977 { 00978 TQString qs; 00979 00980 usedialog = _usedialog; 00981 setUpDialog(); 00982 //set the dialog signal handler 00983 dialog3slot = TQT_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(TQString("!")); 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 TQString word; 01041 TQString 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 = (TQString::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, TQT_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 TQString 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, TQT_SIGNAL (dialog3()), this, TQT_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, TQT_SIGNAL (dialog3()), this, dialog3slot.ascii()); 01203 emit dialog3(); 01204 } 01205 } 01206 01207 01208 void KSpell::dialog( const TQString & word, TQStringList & sugg, const char *_slot ) 01209 { 01210 dlgorigword = word; 01211 01212 dialog3slot = _slot; 01213 dialogwillprocess = true; 01214 connect( ksdlg, TQT_SIGNAL(command(int)), this, TQT_SLOT(dialog2(int)) ); 01215 TQString 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 TQString marker( "_MARKER_" ); 01221 tmpBuf.replace( lastpos, word.length(), marker ); 01222 TQString context = tmpBuf.mid(TQMAX(lastpos-18,0), 2*18+marker.length()); 01223 context.replace( '\n',TQString::fromLatin1(" ")); 01224 context.replace( '<', TQString::fromLatin1("<") ); 01225 context.replace( '>', TQString::fromLatin1(">") ); 01226 context.replace( marker, TQString::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 TQString qs; 01240 01241 disconnect( ksdlg, TQT_SIGNAL(command(int)), this, TQT_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 TQString _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, TQT_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( TDEProcess* ) 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 TQTimer::singleShot( 0, this, TQT_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 TQPoint 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( TQString& text ) 01392 { 01393 return modalCheck( text,0 ); 01394 } 01395 01396 int 01397 KSpell::modalCheck( TQString& 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 TQString & oldText, const TQString & newText, unsigned int pos ) 01415 { 01416 modaltext=modaltext.replace(pos,oldText.length(),newText); 01417 } 01418 01419 01420 void KSpell::slotModalReady() 01421 { 01422 //kdDebug() << tqApp->loopLevel() << endl; 01423 //kdDebug(750) << "MODAL READY------------------" << endl; 01424 01425 Q_ASSERT( m_status == Running ); 01426 connect( this, TQT_SIGNAL( done( const TQString & ) ), 01427 this, TQT_SLOT( slotModalDone( const TQString & ) ) ); 01428 TQObject::connect( this, TQT_SIGNAL( corrected( const TQString&, const TQString&, unsigned int ) ), 01429 this, TQT_SLOT( slotSpellCheckerCorrected( const TQString&, const TQString &, unsigned int ) ) ); 01430 TQObject::connect( this, TQT_SIGNAL( death() ), 01431 this, TQT_SLOT( slotModalSpellCheckerFinished( ) ) ); 01432 check( modaltext ); 01433 } 01434 01435 void KSpell::slotModalDone( const TQString &/*_buffer*/ ) 01436 { 01437 //kdDebug(750) << "MODAL DONE " << _buffer << endl; 01438 //modaltext = _buffer; 01439 cleanUp(); 01440 01441 //kdDebug() << "ABOUT TO EXIT LOOP" << endl; 01442 //tqApp->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( TQWidget *_parent, const TQString &_caption, 01454 TQObject *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 TQTimer( this ); 01466 connect( d->checkNextTimer, TQT_SIGNAL( timeout() ), 01467 this, TQT_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 = TQTextCodec::codecForName("ISO 8859-1"); 01488 break; 01489 case KS_E_LATIN2: 01490 codec = TQTextCodec::codecForName("ISO 8859-2"); 01491 break; 01492 case KS_E_LATIN3: 01493 codec = TQTextCodec::codecForName("ISO 8859-3"); 01494 break; 01495 case KS_E_LATIN4: 01496 codec = TQTextCodec::codecForName("ISO 8859-4"); 01497 break; 01498 case KS_E_LATIN5: 01499 codec = TQTextCodec::codecForName("ISO 8859-5"); 01500 break; 01501 case KS_E_LATIN7: 01502 codec = TQTextCodec::codecForName("ISO 8859-7"); 01503 break; 01504 case KS_E_LATIN8: 01505 codec = TQTextCodec::codecForName("ISO 8859-8-i"); 01506 break; 01507 case KS_E_LATIN9: 01508 codec = TQTextCodec::codecForName("ISO 8859-9"); 01509 break; 01510 case KS_E_LATIN13: 01511 codec = TQTextCodec::codecForName("ISO 8859-13"); 01512 break; 01513 case KS_E_LATIN15: 01514 codec = TQTextCodec::codecForName("ISO 8859-15"); 01515 break; 01516 case KS_E_UTF8: 01517 codec = TQTextCodec::codecForName("UTF-8"); 01518 break; 01519 case KS_E_KOI8R: 01520 codec = TQTextCodec::codecForName("KOI8-R"); 01521 break; 01522 case KS_E_KOI8U: 01523 codec = TQTextCodec::codecForName("KOI8-U"); 01524 break; 01525 case KS_E_CP1251: 01526 codec = TQTextCodec::codecForName("CP1251"); 01527 break; 01528 case KS_E_CP1255: 01529 codec = TQTextCodec::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 = TQString::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 tdespell is ready 01562 connect( this, TQT_SIGNAL(ready(KSpell *)), obj, slot); 01563 else 01564 // Hack for modal spell checking 01565 connect( this, TQT_SIGNAL(ready(KSpell *)), this, TQT_SLOT(slotModalReady()) ); 01566 01567 proc = new KProcIO( codec ); 01568 01569 startIspell(); 01570 } 01571 01572 TQString KSpell::modaltext; 01573 int KSpell::modalreturn = 0; 01574 TQWidget* KSpell::modalWidgetHack = 0; 01575 01576 #include "tdespell.moc" 01577