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