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