00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 #include <config.h>
00021 #endif
00022
00023 #include <stdio.h>
00024 #include <sys/time.h>
00025 #include <sys/types.h>
00026 #include <unistd.h>
00027 #include <ctype.h>
00028 #include <stdlib.h>
00029
00030 #ifdef HAVE_STRINGS_H
00031 #include <strings.h>
00032 #endif
00033
00034 #include <qtextcodec.h>
00035 #include <qtimer.h>
00036 #include <kapplication.h>
00037 #include <kdebug.h>
00038 #include <klocale.h>
00039
00040 #include "koSpell.h"
00041 #include "koSpelldlg.h"
00042 #include "koispell.moc"
00043 #include "koispell.h"
00044 #include "koSconfig.h"
00045
00046 #include <kwin.h>
00047 #include <kprocio.h>
00048
00049 #define MAXLINELENGTH 10000
00050
00051 enum {
00052 GOOD= 0,
00053 IGNORE= 1,
00054 REPLACE= 2,
00055 MISTAKE= 3
00056 };
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #define OUTPUT(x) (connect (proc, SIGNAL (readReady(KProcIO *)), this, SLOT (x(KProcIO *))))
00074
00075
00076 #define NOOUTPUT(x) (disconnect (proc, SIGNAL (readReady(KProcIO *)), this, SLOT (x(KProcIO *))))
00077
00078
00079
00080
00081
00082 KOISpell::KOISpell( QWidget *_parent, const QString &_caption,
00083 QObject *obj, const char *slot, KOSpellConfig *_ksc,
00084 bool _progressbar, bool _modal, KOSpellerType _type )
00085 :KOSpell(_parent,_caption,_ksc,_modal,false, _type)
00086 {
00087 initialize( _parent, _caption, obj, slot, _ksc,
00088 _progressbar, _modal );
00089 }
00090
00091 void KOISpell::startIspell()
00092
00093 {
00094
00095 kdDebug(30006) << "Try #" << trystart << endl;
00096 if (trystart>0)
00097 proc->resetAll();
00098
00099 switch (ksconfig->client())
00100 {
00101 case KOS_CLIENT_ISPELL:
00102 *proc << "ispell";
00103 kdDebug(30006) << "Using ispell" << endl;
00104 break;
00105 case KOS_CLIENT_ASPELL:
00106
00107 *proc << "aspell";
00108 kdDebug(30006) << "Using aspell" << endl;
00109 break;
00110 case KOS_CLIENT_HSPELL:
00111 *proc << "hspell";
00112 kdDebug(30006) << "Using hspell" << endl;
00113 break;
00114 default:
00115 kdError(30006) << "Spelling configuration error, client=" << ksconfig->client() <<endl;
00116 }
00117
00118 if (ksconfig->client() == KOS_CLIENT_ISPELL || ksconfig->client() == KOS_CLIENT_ASPELL)
00119 {
00120
00121
00122 *proc << "-a" << "-S";
00123 switch ( type )
00124 {
00125 case HTML:
00126
00127
00128
00129
00130 *proc << "-H";
00131 break;
00132 case TeX:
00133
00134 *proc << "-t";
00135 break;
00136 case Nroff:
00137
00138 if ( ksconfig->client() == KOS_CLIENT_ISPELL )
00139 *proc << "-n";
00140 break;
00141 case Text:
00142 default:
00143
00144 break;
00145 }
00146
00147 if (ksconfig->noRootAffix())
00148 {
00149 *proc<<"-m";
00150 }
00151 if (ksconfig->runTogether())
00152 {
00153 *proc << "-B";
00154 }
00155 else
00156 {
00157 *proc << "-C";
00158 }
00159
00160 if (trystart<2)
00161 {
00162 if (! ksconfig->dictionary().isEmpty())
00163 {
00164 kdDebug(30006) << "using dictionary [" << ksconfig->dictionary() << "]" << endl;
00165 *proc << "-d";
00166 *proc << ksconfig->dictionary();
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 if (trystart<1)
00185 switch (ksconfig->encoding())
00186 {
00187 case KOS_E_LATIN1:
00188 *proc << "-Tlatin1";
00189 break;
00190 case KOS_E_LATIN2:
00191 *proc << "-Tlatin2";
00192 break;
00193 case KOS_E_LATIN3:
00194 *proc << "-Tlatin3";
00195 break;
00196 case KOS_E_LATIN15:
00197
00198
00199
00200
00201
00202 *proc << "-Tlatin1";
00203 break;
00204
00205
00206 case KOS_E_LATIN4:
00207 case KOS_E_LATIN5:
00208 case KOS_E_LATIN7:
00209 case KOS_E_LATIN8:
00210 case KOS_E_LATIN9:
00211 case KOS_E_LATIN13:
00212
00213
00214 kdError(30006) << "charsets iso-8859-4 .. iso-8859-13 not supported yet" << endl;
00215 break;
00216
00217 case KOS_E_UTF8:
00218 *proc << "-Tutf8";
00219 break;
00220
00221 case KOS_E_KOI8U:
00222 *proc << "-w'";
00223 break;
00224
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 }
00236 else
00237 *proc << "-a";
00238
00239 if (trystart==0)
00240 {
00241 connect (proc, SIGNAL ( receivedStderr (KProcess *, char *, int)),
00242 this, SLOT (ispellErrors (KProcess *, char *, int)));
00243
00244
00245 connect(proc, SIGNAL(processExited(KProcess *)),
00246 this, SLOT (ispellExit (KProcess *)));
00247
00248 OUTPUT(KSpell2);
00249 }
00250
00251 if ( proc->start() == false )
00252 {
00253 m_status = Error;
00254 QTimer::singleShot( 0, this, SLOT(emitDeath()));
00255 }
00256 }
00257
00258 QStringList KOISpell::resultCheckWord( const QString &_word )
00259 {
00260 disconnect();
00261 checkWord (_word, false, true);
00262 QStringList sug = suggestions();
00263 return sug;
00264 }
00265
00266
00267 void KOISpell::ispellErrors (KProcess *, char *buffer, int buflen)
00268 {
00269 buffer [buflen-1] = '\0';
00270
00271 }
00272
00273 void KOISpell::KSpell2 (KProcIO *)
00274
00275 {
00276 kdDebug(30006) << "KSpell::KSpell2" << endl;
00277 trystart=maxtrystart;
00278
00279 QString line;
00280
00281 if (proc->fgets (line, true)==-1)
00282 {
00283 QTimer::singleShot( 0, this, SLOT(emitDeath()));
00284 return;
00285 }
00286
00287
00288 if (line[0]!='@')
00289 {
00290 QTimer::singleShot( 0, this, SLOT(emitDeath()));
00291 return;
00292 }
00293
00294
00295 if (ignore ("kde")==false)
00296 {
00297 kdDebug(30006) << "@KDE was false" << endl;
00298 QTimer::singleShot( 0, this, SLOT(emitDeath()));
00299 return;
00300 }
00301
00302
00303 if (ignore ("linux")==false)
00304 {
00305 kdDebug(30006) << "@Linux was false" << endl;
00306 QTimer::singleShot( 0, this, SLOT(emitDeath()));
00307 return;
00308 }
00309
00310 NOOUTPUT (KSpell2);
00311
00312 m_status = Running;
00313 m_ready = true;
00314 emit ready(this);
00315 }
00316
00317 void
00318 KOISpell::setUpDialog (bool reallyuseprogressbar)
00319 {
00320 if (dialogsetup)
00321 return;
00322
00323
00324 ksdlg=new KOSpellDlg (parent, ksconfig, "dialog",
00325 progressbar && reallyuseprogressbar, modaldlg );
00326 ksdlg->setCaption (caption);
00327 connect (ksdlg, SIGNAL (command (int)), this,
00328 SLOT (slotStopCancel (int)) );
00331 #ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded
00332 KWin::setIcons (ksdlg->winId(), kapp->icon(), kapp->miniIcon());
00333 #endif
00334 if ( modaldlg )
00335 ksdlg->setFocus();
00336 dialogsetup = true;
00337 }
00338
00339 bool KOISpell::addPersonal (const QString & word)
00340 {
00341 QString qs = word.simplifyWhiteSpace();
00342
00343
00344 if (qs.find (' ')!=-1 || qs.isEmpty())
00345 return false;
00346
00347 qs.prepend ("*");
00348 personaldict=true;
00349
00350 return proc->fputs(qs);
00351 }
00352
00353 bool KOISpell::writePersonalDictionary ()
00354 {
00355 return proc->fputs ("#");
00356 }
00357
00358 bool KOISpell::ignore (const QString & word)
00359 {
00360 QString qs = word.simplifyWhiteSpace();
00361
00362
00363 if (qs.find (' ')!=-1 || qs.isEmpty())
00364 return false;
00365
00366 qs.prepend ("@");
00367
00368 return proc->fputs(qs);
00369 }
00370
00371 bool
00372 KOISpell::cleanFputsWord (const QString & s, bool appendCR)
00373 {
00374 QString qs(s);
00375
00376 bool empty = true;
00377
00378 for (unsigned int i=0; i<qs.length(); i++)
00379 {
00380
00381 if (qs[i] != '\'' && qs[i] != '\"' && qs[i] != '-'
00382 && qs[i].isPunct() || qs[i].isSpace())
00383 {
00384 qs.remove(i,1);
00385 i--;
00386 } else {
00387 if (qs[i].isLetter()) empty=false;
00388 }
00389 }
00390
00391
00392 if (empty) return false;
00393
00394 return proc->fputs("^"+qs, appendCR);
00395 }
00396
00397 bool
00398 KOISpell::cleanFputs (const QString & s, bool appendCR)
00399 {
00400 QString qs(s);
00401 unsigned l = qs.length();
00402
00403
00404 for(unsigned int i = 0; i < l; ++i)
00405 {
00406 if(qs[i] == '$')
00407 qs[i] = ' ';
00408 }
00409
00410 if (l<MAXLINELENGTH)
00411 {
00412 if (qs.isEmpty())
00413 qs="";
00414
00415 return proc->fputs ("^"+qs, appendCR);
00416 }
00417 else
00418 return proc->fputs ("^\n",appendCR);
00419 }
00420
00421 bool KOISpell::checkWord (const QString & buffer, bool _usedialog)
00422 {
00423 QString qs = buffer.simplifyWhiteSpace();
00424 if (qs.find (' ')!=-1 || qs.isEmpty())
00425 return false;
00426
00428 dialog3slot = SLOT(checkWord3());
00429
00430 usedialog=_usedialog;
00431 setUpDialog(false);
00432 if (_usedialog)
00433 {
00434 emitProgress();
00435 ksdlg->show();
00436 }
00437 else
00438 ksdlg->hide();
00439
00440 OUTPUT (checkWord2);
00441
00442
00443 proc->fputs ("%");
00444 cleanFputsWord( qs );
00445
00446 return true;
00447 }
00448
00449
00450 bool KOISpell::checkWord (const QString & buffer, bool _usedialog, bool synchronous )
00451 {
00452 QString qs = buffer.simplifyWhiteSpace();
00453 if (qs.find (' ')!=-1 || qs.isEmpty())
00454 return false;
00455
00457 dialog3slot = SLOT(checkWord3());
00458
00459 usedialog=_usedialog;
00460 setUpDialog(false);
00461
00462 ksdlg->hide();
00463 if ( synchronous ) {
00464
00465 if ( !m_ready ) {
00466 connect( this, SIGNAL(ready(KOSpell*)),
00467 this, SLOT(slotSynchronousReady()) );
00468 connect( this, SIGNAL(death()),
00469 this, SLOT(slotSynchronousReady()) );
00470
00471 enter_loop();
00472 disconnect( this, SIGNAL(ready(KOSpell*)),
00473 this, SLOT(slotSynchronousReady()) );
00474 disconnect( this, SIGNAL(death()),
00475 this, SLOT(slotSynchronousReady()) );
00476 }
00477 if ( m_status == Error )
00478 return false;
00479 OUTPUT (checkWord2Synchronous);
00480 }
00481 else
00482 OUTPUT (checkWord2);
00483
00484 proc->fputs ("%");
00485
00486 if (cleanFputsWord( qs ))
00487 enter_loop();
00488
00489 return true;
00490 }
00491
00492 void KOISpell::checkWord2 (KProcIO *)
00493 {
00494 QString word;
00495
00496 QString line;
00497 proc->fgets (line, true);
00498
00499
00500
00501
00502 QString blank_line;
00503 proc->fgets(blank_line, true);
00504
00505 NOOUTPUT(checkWord2);
00506
00507 bool mistake = (parseOneResponse(line, word, sugg) == MISTAKE);
00508 if ( mistake && usedialog )
00509 {
00510 cwword=word;
00511 dialog (word, sugg, SLOT (checkWord3()));
00512 return;
00513 }
00514 else if( mistake )
00515 {
00516 misspellingWord (word, sugg, lastpos);
00517 }
00518
00519
00520
00521 emit corrected (word, word, 0L);
00522 }
00523
00524
00525
00526
00527 void KOISpell::checkWord2Synchronous (KProcIO *)
00528 {
00529 QString word;
00530
00531 QString line;
00532 proc->fgets (line, true);
00533
00534
00535
00536
00537 QString blank_line;
00538 proc->fgets(blank_line, true);
00539
00540 NOOUTPUT(checkWord2);
00541
00542 bool mistake = (parseOneResponse(line, word, sugg) == MISTAKE);
00543 if( mistake )
00544 {
00545 misspellingWord (word, sugg, lastpos);
00546 }
00547
00548
00549 emit corrected (word, word, 0L);
00550 qApp->exit_loop();
00551 }
00552
00553 void KOISpell::checkWord3 ()
00554 {
00555 disconnect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
00556
00557 emit corrected (cwword, replacement(), 0L);
00558 }
00559
00560 QString KOISpell::funnyWord (const QString & word)
00561
00562
00563 {
00564 QString qs;
00565 unsigned int i=0;
00566
00567 for (i=0; word [i]!='\0';i++)
00568 {
00569 if (word [i]=='+')
00570 continue;
00571 if (word [i]=='-')
00572 {
00573 QString shorty;
00574 unsigned int j;
00575 int k;
00576
00577 for (j=i+1;word [j]!='\0' && word [j]!='+' &&
00578 word [j]!='-';j++)
00579 shorty+=word [j];
00580 i=j-1;
00581
00582 if ((k=qs.findRev (shorty))==0 || k!=-1)
00583 qs.remove (k,shorty.length());
00584 else
00585 {
00586 qs+='-';
00587 qs+=shorty;
00588 }
00589 }
00590 else
00591 qs+=word [i];
00592 }
00593 return qs;
00594 }
00595
00596
00597 int KOISpell::parseOneResponse (const QString &buffer, QString &word, QStringList & sugg)
00598
00599
00600
00601
00602
00603
00604 {
00605 word = "";
00606 posinline=0;
00607
00608 sugg.clear();
00609
00610 if (buffer [0]=='*' || buffer[0] == '+' || buffer[0] == '-')
00611 {
00612 return GOOD;
00613 }
00614
00615 if (buffer [0]=='&' || buffer [0]=='?' || buffer [0]=='#')
00616 {
00617 int i,j;
00618
00619
00620 word = buffer.mid (2,buffer.find (' ',3)-2);
00621
00622 orig=word;
00623
00624 if(m_bIgnoreTitleCase && word==word.upper())
00625 return IGNORE;
00626
00627 if(m_bIgnoreUpperWords && word[0]==word[0].upper())
00628 {
00629 QString text=word[0]+word.right(word.length()-1).lower();
00630 if(text==word)
00631 return IGNORE;
00632 }
00633
00635
00636
00637
00638 if (ignorelist.findIndex(word.lower())!=-1)
00639 return IGNORE;
00640
00642 QString qs2;
00643
00644 if (buffer.find(':')!=-1)
00645 qs2=buffer.left (buffer.find (':'));
00646 else
00647 qs2=buffer;
00648
00649 posinline = qs2.right( qs2.length()-qs2.findRev(' ') ).toInt()-1;
00650
00652 QStringList::Iterator it = replacelist.begin();
00653 for(;it != replacelist.end(); ++it, ++it)
00654 {
00655 if (word == *it)
00656 {
00657 ++it;
00658 word = *it;
00659 return REPLACE;
00660 }
00661 }
00662
00664 if (buffer [0] != '#')
00665 {
00666 QString qs = buffer.mid(buffer.find(':')+2, buffer.length());
00667 qs+=',';
00668 sugg.clear();
00669 i=j=0;
00670 while ((unsigned int)i<qs.length())
00671 {
00672 QString temp = qs.mid (i,(j=qs.find (',',i))-i);
00673 sugg.append (funnyWord (temp));
00674
00675 i=j+2;
00676 }
00677 }
00678
00679 if ((sugg.count()==1) && (sugg.first() == word))
00680 return GOOD;
00681
00682 return MISTAKE;
00683 }
00684
00685
00686 kdError(750) << "HERE?: [" << buffer << "]" << endl;
00687 kdError(750) << "Please report this to dsweet@kde.org" << endl;
00688 kdError(750) << "Thank you!" << endl;
00689 emit done(false);
00690 emit done (KOISpell::origbuffer);
00691 return MISTAKE;
00692 }
00693
00694 bool KOISpell::checkList (QStringList *_wordlist, bool _usedialog)
00695
00696 {
00697 wordlist=_wordlist;
00698 if ((totalpos=wordlist->count())==0)
00699 return false;
00700 wlIt = wordlist->begin();
00701 usedialog=_usedialog;
00702
00703
00704 setUpDialog();
00705
00706
00707 dialog3slot = SLOT (checkList4 ());
00708
00709 proc->fputs ("%");
00710
00711
00712 lastpos = -1;
00713 checkList2();
00714
00715
00716 OUTPUT(checkList3a);
00717
00718 return true;
00719 }
00720
00721 void KOISpell::checkList2 ()
00722
00723
00724 {
00725
00726 if (wlIt != wordlist->end())
00727 {
00728 kdDebug(30006) << "KS::cklist2 " << lastpos << ": " << *wlIt << endl;
00729
00730 endOfResponse = false;
00731 bool put;
00732 lastpos++; offset=0;
00733 put = cleanFputsWord (*wlIt);
00734 ++wlIt;
00735
00736
00737
00738
00739 if (!put) {
00740 checkList2();
00741 }
00742 }
00743 else
00744
00745 {
00746 NOOUTPUT(checkList3a);
00747 ksdlg->hide();
00748 emit done(true);
00749 }
00750 }
00751
00752 void KOISpell::checkList3a (KProcIO *)
00753
00754 {
00755
00756
00757
00758
00759 if (dlgon) {
00760
00761 return;
00762 }
00763
00764 int e, tempe;
00765
00766 QString word;
00767 QString line;
00768
00769 do
00770 {
00771 tempe=proc->fgets (line, true);
00772
00773
00774
00775
00776 if (tempe == 0) {
00777 endOfResponse = true;
00778
00779 } else if (tempe>0) {
00780 if ((e=parseOneResponse (line, word, sugg))==MISTAKE ||
00781 e==REPLACE)
00782 {
00783 dlgresult=-1;
00784
00785 if (e==REPLACE)
00786 {
00787 QString old = *(--wlIt); ++wlIt;
00788 dlgreplacement=word;
00789 checkListReplaceCurrent();
00790
00791 emit corrected (old, *(--wlIt), lastpos); ++wlIt;
00792 }
00793 else if( usedialog )
00794 {
00795 cwword=word;
00796 dlgon=true;
00797
00798 dialog (word, sugg, SLOT (checkList4()));
00799 return;
00800 }
00801 else
00802 {
00803 misspellingWord (word, sugg, lastpos);
00804 }
00805 }
00806
00807 }
00808 emitProgress ();
00809
00810
00811 } while (tempe > 0);
00812
00813
00814
00815
00816
00817 if (endOfResponse && !dlgon) {
00818
00819 checkList2();
00820 }
00821 }
00822
00823 void KOISpell::checkListReplaceCurrent () {
00824
00825
00826 wlIt--;
00827
00828 QString s = *wlIt;
00829 s.replace(posinline+offset,orig.length(),replacement());
00830 offset += replacement().length()-orig.length();
00831 wordlist->insert (wlIt, s);
00832 wlIt = wordlist->remove (wlIt);
00833
00834
00835 }
00836
00837 void KOISpell::checkList4 ()
00838
00839 {
00840 dlgon=false;
00841 QString old;
00842
00843 disconnect (this, SIGNAL (dialog3()), this, SLOT (checkList4()));
00844
00845
00846 switch (dlgresult)
00847 {
00848 case KOS_REPLACE:
00849 case KOS_REPLACEALL:
00850 kdDebug(30006) << "KS: cklist4: lastpos: " << lastpos << endl;
00851 old = *(--wlIt); ++wlIt;
00852
00853 checkListReplaceCurrent();
00854 emit corrected (old, *(--wlIt), lastpos); ++wlIt;
00855 break;
00856 case KOS_CANCEL:
00857 ksdlg->hide();
00858 emit done (false);
00859 return;
00860 case KOS_STOP:
00861 ksdlg->hide();
00862 emit done (true);
00863 break;
00864 };
00865
00866
00867 if (!endOfResponse) {
00868
00869 checkList3a(NULL);
00870 }
00871 }
00872
00873 bool KOISpell::check( const QString &_buffer, bool _usedialog )
00874 {
00875 QString qs;
00876
00877 usedialog=_usedialog;
00878 setUpDialog ();
00879
00880 dialog3slot = SLOT (check3 ());
00881
00882 kdDebug(30006) << "KS: check" << endl;
00883 origbuffer = _buffer;
00884 if ( ( totalpos = origbuffer.length() ) == 0 )
00885 {
00886 emit done(origbuffer);
00887 return false;
00888 }
00889
00890
00891
00892
00893 if ( origbuffer.right(2) != "\n\n" )
00894 {
00895 if (origbuffer.at(origbuffer.length()-1)!='\n')
00896 {
00897 origbuffer+='\n';
00898 origbuffer+='\n';
00899 }
00900 else
00901 origbuffer+='\n';
00902 }
00903
00904 newbuffer=origbuffer;
00905
00906
00907 OUTPUT(check2);
00908 proc->fputs ("!");
00909
00910
00911 offset=lastlastline=lastpos=lastline=0;
00912
00913 emitProgress ();
00914
00915
00916 int i = origbuffer.find('\n', 0)+1;
00917 qs=origbuffer.mid (0,i);
00918 cleanFputs (qs,false);
00919
00920 lastline=i;
00921
00922 if (usedialog)
00923 {
00924 emitProgress();
00925 ksdlg->show();
00926 }
00927 else
00928 ksdlg->hide();
00929
00930 return true;
00931 }
00932
00933 void KOISpell::check2 (KProcIO *)
00934
00935 {
00936 int e, tempe;
00937 QString word;
00938 QString line;
00939 static bool recursive = false;
00940 if (recursive &&
00941 (!ksdlg || ksdlg->isHidden()))
00942 {
00943 return;
00944 }
00945 recursive = true;
00946
00947 do
00948 {
00949 tempe=proc->fgets (line);
00950 kdDebug(30006) << "KSpell::check2 (" << tempe << "b)" << endl;
00951
00952 if (tempe>0)
00953 {
00954 if ((e=parseOneResponse (line, word, sugg))==MISTAKE ||
00955 e==REPLACE)
00956 {
00957 dlgresult=-1;
00958
00959
00960 if (ksconfig->encoding() == KOS_E_UTF8) {
00961
00962
00963
00964
00965
00966
00967 posinline = (QString::fromUtf8(
00968 origbuffer.mid(lastlastline,lastline-lastlastline).utf8(),
00969 posinline)).length();
00970
00971 }
00972
00973 lastpos=posinline+lastlastline+offset;
00974
00975
00976
00977 if (e==REPLACE)
00978 {
00979 dlgreplacement=word;
00980 emit corrected (orig, replacement(), lastpos);
00981 offset+=replacement().length()-orig.length();
00982 newbuffer.replace (lastpos, orig.length(), word);
00983 }
00984 else
00985 {
00986 cwword=word;
00987
00988 if ( usedialog ) {
00989
00990 dialog (word, sugg, SLOT (check3()));
00991 } else {
00992
00993 misspellingWord (word, sugg, lastpos);
00994 dlgresult = KOS_IGNORE;
00995 check3();
00996 }
00997 recursive = false;
00998 return;
00999 }
01000 }
01001
01002 }
01003
01004 emitProgress ();
01005
01006 } while (tempe>0);
01007
01008 proc->ackRead();
01009
01010 if (tempe==-1) {
01011 recursive = false;
01012 return;
01013 }
01014
01015 proc->ackRead();
01016
01017 if ((unsigned int)lastline<origbuffer.length())
01018 {
01019 int i;
01020 QString qs;
01021
01022
01023
01024 lastpos=(lastlastline=lastline)+offset;
01025 i=origbuffer.find('\n', lastline)+1;
01026 qs=origbuffer.mid (lastline, i-lastline);
01027 cleanFputs (qs,false);
01028 lastline=i;
01029 recursive = false;
01030 return;
01031 }
01032 else
01033
01034 {
01035 ksdlg->hide();
01036
01037 newbuffer.truncate (newbuffer.length()-2);
01038 emitProgress();
01039 NOOUTPUT( check2 );
01040 emit done (newbuffer);
01041 }
01042 recursive = false;
01043 }
01044
01045 void KOISpell::check3 ()
01046
01047 {
01048 disconnect (this, SIGNAL (dialog3()), this, SLOT (check3()));
01049
01050 kdDebug(30006) << "check3 [" << cwword << "] [" << replacement() << "] " << dlgresult << endl;
01051
01052
01053 switch (dlgresult)
01054 {
01055 case KOS_REPLACE:
01056 case KOS_REPLACEALL:
01057 offset+=replacement().length()-cwword.length();
01058 newbuffer.replace (lastpos, cwword.length(),
01059 replacement());
01060 emit corrected (dlgorigword, replacement(), lastpos);
01061 break;
01062 case KOS_CANCEL:
01063
01064 ksdlg->hide();
01065 emit done (origbuffer);
01066 return;
01067 case KOS_STOP:
01068 ksdlg->hide();
01069
01070 emitProgress();
01071 emit done (newbuffer);
01072 return;
01073 };
01074
01075 proc->ackRead();
01076 }
01077
01078 void
01079 KOISpell::slotStopCancel (int result)
01080 {
01081 if (dialogwillprocess)
01082 return;
01083
01084 kdDebug(30006) << "KSpell::slotStopCancel [" << result << "]" << endl;
01085
01086 if (result==KOS_STOP || result==KOS_CANCEL)
01087 if (!dialog3slot.isEmpty())
01088 {
01089 dlgresult=result;
01090 connect (this, SIGNAL (dialog3()), this, dialog3slot.ascii());
01091 emit dialog3();
01092 }
01093 }
01094
01095
01096 void KOISpell::dialog(const QString & word, QStringList & sugg, const char *_slot)
01097 {
01098 dlgorigword=word;
01099
01100 dialog3slot=_slot;
01101 dialogwillprocess=true;
01102 connect (ksdlg, SIGNAL (command (int)), this, SLOT (dialog2(int)));
01103 ksdlg->init (word, &sugg);
01104 misspellingWord (word, sugg, lastpos);
01105
01106 emitProgress();
01107 ksdlg->show();
01108 }
01109
01110 void KOISpell::dialog2 (int result)
01111 {
01112 QString qs;
01113
01114 disconnect (ksdlg, SIGNAL (command (int)), this, SLOT (dialog2(int)));
01115 dialogwillprocess=false;
01116 dlgresult=result;
01117 ksdlg->standby();
01118
01119 dlgreplacement=ksdlg->replacement();
01120
01121
01122 switch (dlgresult)
01123 {
01124
01125 case KOS_IGNORE:
01126 emit ignoreword(dlgorigword);
01127 break;
01128 case KOS_IGNOREALL:
01129
01130 ignorelist.prepend(dlgorigword.lower());
01131 emit ignoreall (dlgorigword);
01132 break;
01133 case KOS_ADD:
01134 addPersonal (dlgorigword);
01135 personaldict=true;
01136 emit addword (dlgorigword);
01137
01138 ignorelist.prepend(dlgorigword.lower());
01139 break;
01140 case KOS_REPLACEALL:
01141 {
01142 replacelist.append (dlgorigword);
01143 QString _replacement = replacement();
01144 replacelist.append (_replacement);
01145 emit replaceall( dlgorigword , _replacement );
01146 }
01147 break;
01148 case KOS_ADDAUTOCORRECT:
01149 {
01150
01151 QString _replacement = replacement();
01152 emit addAutoCorrect (dlgorigword , _replacement);
01153 break;
01154 }
01155 }
01156
01157 connect (this, SIGNAL (dialog3()), this, dialog3slot.ascii());
01158 emit dialog3();
01159 }
01160
01161
01162 KOISpell:: ~KOISpell ()
01163 {
01164 delete proc;
01165 }
01166
01167
01168 void KOISpell::cleanUp ()
01169 {
01170 if (m_status == Cleaning) return;
01171 if (m_status == Running)
01172 {
01173 if (personaldict)
01174 writePersonalDictionary();
01175 m_status = Cleaning;
01176 }
01177 proc->closeStdin();
01178 }
01179
01180 void KOISpell::ispellExit (KProcess *)
01181 {
01182 kdDebug(30006) << "KSpell::ispellExit() " << m_status << endl;
01183
01184 if ((m_status == Starting) && (trystart<maxtrystart))
01185 {
01186 trystart++;
01187 startIspell();
01188 return;
01189 }
01190
01191 if (m_status == Starting)
01192 m_status = Error;
01193 else if (m_status == Cleaning)
01194 m_status = m_bNoMisspellingsEncountered ? FinishedNoMisspellingsEncountered : Finished;
01195 else if (m_status == Running)
01196 m_status = Crashed;
01197 else
01198 return;
01199
01200 kdDebug(30006) << "Death" << endl;
01201 QTimer::singleShot( 0, this, SLOT(emitDeath()));
01202 }
01203
01204
01205
01206
01207 void KOISpell::emitDeath()
01208 {
01209 bool deleteMe = autoDelete;
01210 emit death();
01211 if (deleteMe)
01212 deleteLater();
01213 }
01214
01215 void KOISpell::setProgressResolution (unsigned int res)
01216 {
01217 progres=res;
01218 }
01219
01220 void KOISpell::emitProgress ()
01221 {
01222 uint nextprog = (uint) (100.*lastpos/(double)totalpos);
01223
01224 if (nextprog>=curprog)
01225 {
01226 curprog=nextprog;
01227 emit progress (curprog);
01228 }
01229 }
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239 int
01240 KOISpell::modalCheck( QString& text, KOSpellConfig* _kcs )
01241 {
01242 modalreturn = 0;
01243 modaltext = text;
01244
01245
01246
01247 KOISpell* spell = new KOISpell( 0L, i18n("Spell Checker"), 0 ,
01248 0, _kcs, true, true );
01249
01250
01251 while ((spell->status()==Starting) || (spell->status()==Running) || (spell->status()==Cleaning))
01252 kapp->processEvents();
01253
01254 text = modaltext;
01255
01256 delete spell;
01257 return modalreturn;
01258 }
01259
01260 void KOISpell::slotSpellCheckerCorrected( const QString & oldText, const QString & newText, unsigned int pos )
01261 {
01262 modaltext=modaltext.replace(pos,oldText.length(),newText);
01263 }
01264
01265
01266 void KOISpell::slotModalReady()
01267 {
01268
01269
01270
01271 Q_ASSERT( m_status == Running );
01272 connect( this, SIGNAL( done( const QString & ) ),
01273 this, SLOT( slotModalDone( const QString & ) ) );
01274 QObject::connect( this, SIGNAL( corrected( const QString&, const QString&, unsigned int ) ),
01275 this, SLOT( slotSpellCheckerCorrected( const QString&, const QString &, unsigned int ) ) );
01276 QObject::connect( this, SIGNAL( death() ),
01277 this, SLOT( slotModalSpellCheckerFinished( ) ) );
01278 check( modaltext );
01279 }
01280
01281 void KOISpell::slotModalDone( const QString & )
01282 {
01283
01284
01285 cleanUp();
01286
01287
01288
01289
01290 slotModalSpellCheckerFinished();
01291 }
01292
01293 void KOISpell::slotModalSpellCheckerFinished( )
01294 {
01295 modalreturn=(int)this->status();
01296 }
01297
01298
01299 void KOISpell::initialize( QWidget *_parent, const QString &_caption,
01300 QObject *obj, const char *slot, KOSpellConfig *_ksc,
01301 bool _progressbar, bool _modal )
01302 {
01303 m_ready = false;
01304 m_bIgnoreUpperWords=false;
01305 m_bIgnoreTitleCase=false;
01306
01307 autoDelete = false;
01308 modaldlg = _modal;
01309 progressbar = _progressbar;
01310
01311 proc=0;
01312 ksdlg=0;
01313
01314 texmode=dlgon=false;
01315
01316 dialogsetup = false;
01317 progres=10;
01318 curprog=0;
01319
01320 dialogwillprocess=false;
01321 dialog3slot="";
01322
01323 personaldict=false;
01324 dlgresult=-1;
01325
01326 caption=_caption;
01327
01328 parent=_parent;
01329
01330 trystart=0;
01331 maxtrystart=2;
01332
01333 if ( obj && slot )
01334
01335 connect (this, SIGNAL (ready(KOSpell *)), obj, slot);
01336 else
01337
01338 connect (this, SIGNAL (ready(KOSpell *)), this, SLOT( slotModalReady() ) );
01339 proc=new KProcIO(codec);
01340
01341 startIspell();
01342 }
01343
01344
01345
01346 void qt_enter_modal( QWidget *widget );
01347 void qt_leave_modal( QWidget *widget );
01348 void KOISpell::enter_loop()
01349 {
01350 QWidget dummy(0,0,WType_Dialog | WShowModal);
01351 dummy.setFocusPolicy( QWidget::NoFocus );
01352 qt_enter_modal(&dummy);
01353 qApp->enter_loop();
01354 qt_leave_modal(&dummy);
01355 }
01356
01357 void KOISpell::slotSynchronousReady()
01358 {
01359 qApp->exit_loop();
01360 }