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