• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDE3Support

  • kde3support
  • kdeui
k3spell.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 Copyright (C) 1997 David Sweet <dsweet@kde.org>
3 Copyright (C) 2000-2001 Wolfram Diestel <wolfram@steloj.de>
4 Copyright (C) 2003 Zack Rusin <zack@kde.org>
5 Copyright (C) 2007-2008 Kevin Kofler <Kevin@tigcc.ticalc.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License version 2 as published by the Free Software Foundation.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21
22#include "k3spell.h"
23
24#include <config.h>
25
26#include <stdio.h>
27#include <sys/time.h>
28#include <sys/types.h>
29#include <unistd.h>
30#include <ctype.h>
31#include <stdlib.h> // atoi
32
33#ifdef HAVE_STRINGS_H
34#include <strings.h>
35#endif
36
37
38#include <QtGui/QApplication>
39#include <QtCore/QTextCodec>
40#include <QtCore/QTimer>
41
42#include <kmessagebox.h>
43#include <kdebug.h>
44#include <klocale.h>
45#include "k3sconfig.h"
46#include "k3spelldlg.h"
47#include <kprocess.h>
48#include <QTextStream>
49
50#define MAXLINELENGTH 10000
51#undef IGNORE //fix possible conflict
52
53enum {
54 GOOD= 0,
55 IGNORE= 1,
56 REPLACE= 2,
57 MISTAKE= 3
58};
59
60enum checkMethod { Method1 = 0, Method2 };
61
62struct BufferedWord
63{
64 checkMethod method;
65 QString word;
66 bool useDialog;
67 bool suggest;
68};
69
70class K3Spell::K3SpellPrivate
71{
72public:
73 bool endOfResponse;
74 bool m_bIgnoreUpperWords;
75 bool m_bIgnoreTitleCase;
76 bool m_bNoMisspellingsEncountered;
77 SpellerType type;
78 K3Spell* suggestSpell;
79 bool checking;
80 QList<BufferedWord> unchecked;
81 QTimer *checkNextTimer;
82 bool aspellV6;
83 QTextCodec* m_codec;
84 QString convertQByteArray( const QByteArray& b )
85 {
86 QTextCodec* originalCodec = QTextCodec::codecForCStrings();
87 QTextCodec::setCodecForCStrings( m_codec );
88 QString s( b );
89 QTextCodec::setCodecForCStrings( originalCodec );
90 return s;
91 }
92 QByteArray convertQString( const QString& s )
93 {
94 QTextCodec* originalCodec = QTextCodec::codecForCStrings();
95 QTextCodec::setCodecForCStrings( m_codec );
96 QByteArray b = s.toLatin1();
97 QTextCodec::setCodecForCStrings( originalCodec );
98 return b;
99 }
100};
101
102//TODO
103//Parse stderr output
104//e.g. -- invalid dictionary name
105
106/*
107 Things to put in K3SpellConfigDlg:
108 make root/affix combinations that aren't in the dictionary (-m)
109 don't generate any affix/root combinations (-P)
110 Report run-together words with missing blanks as spelling errors. (-B)
111 default dictionary (-d [dictionary])
112 personal dictionary (-p [dictionary])
113 path to ispell -- NO: ispell should be in $PATH
114 */
115
116
117// Connects a slot to KProcess's output signal
118#define OUTPUT(x) (connect (proc, SIGNAL (readyReadStandardOutput()), this, SLOT (x())))
119
120// Disconnect a slot from...
121#define NOOUTPUT(x) (disconnect (proc, SIGNAL (readyReadStandardOutput()), this, SLOT (x())))
122
123
124
125K3Spell::K3Spell( QWidget *_parent, const QString &_caption,
126 QObject *obj, const char *slot, K3SpellConfig *_ksc,
127 bool _progressbar, bool _modal )
128{
129 initialize( _parent, _caption, obj, slot, _ksc,
130 _progressbar, _modal, Text );
131}
132
133K3Spell::K3Spell( QWidget *_parent, const QString &_caption,
134 QObject *obj, const char *slot, K3SpellConfig *_ksc,
135 bool _progressbar, bool _modal, SpellerType type )
136{
137 initialize( _parent, _caption, obj, slot, _ksc,
138 _progressbar, _modal, type );
139}
140
141K3Spell::spellStatus K3Spell::status() const
142{
143 return m_status;
144}
145
146void K3Spell::hide() { ksdlg->hide(); }
147
148QStringList K3Spell::suggestions() const
149{
150 return sugg;
151}
152
153int K3Spell::dlgResult () const
154{
155 return dlgresult;
156}
157
158int K3Spell::heightDlg() const { return ksdlg->height(); }
159int K3Spell::widthDlg() const { return ksdlg->width(); }
160
161QString K3Spell::intermediateBuffer() const
162{
163 return K3Spell::newbuffer;
164}
165
166// Check if aspell is at least version 0.6
167static bool determineASpellV6()
168{
169 QString result;
170 FILE *fs = popen("aspell -v", "r");
171 if (fs)
172 {
173 // Close textstream before we close fs
174 {
175 QTextStream ts(fs, QIODevice::ReadOnly);
176 result = ts.readAll().trimmed();
177 }
178 pclose(fs);
179 }
180
181 QRegExp rx("Aspell (\\d.\\d)");
182 if (rx.indexIn(result) != -1)
183 {
184 float version = rx.cap(1).toFloat();
185 return (version >= 0.6);
186 }
187 return false;
188}
189
190
191void
192K3Spell::startIspell()
193 //trystart = {0,1,2}
194{
195 if ((trystart == 0) && (ksconfig->client() == KS_CLIENT_ASPELL))
196 d->aspellV6 = determineASpellV6();
197
198 kDebug(750) << "Try #" << trystart;
199
200 if ( trystart > 0 ) {
201 proc->reset();
202 }
203
204 switch ( ksconfig->client() )
205 {
206 case KS_CLIENT_ISPELL:
207 *proc << "ispell";
208 kDebug(750) << "Using ispell";
209 break;
210 case KS_CLIENT_ASPELL:
211 *proc << "aspell";
212 kDebug(750) << "Using aspell";
213 break;
214 case KS_CLIENT_HSPELL:
215 *proc << "hspell";
216 kDebug(750) << "Using hspell";
217 break;
218 case KS_CLIENT_ZEMBEREK:
219 *proc << "zpspell";
220 kDebug(750) << "Using zemberek(zpspell)";
221 break;
222 case KS_CLIENT_HUNSPELL:
223 *proc << "hunspell";
224 kDebug(750) << "Using hunspell";
225 break;
226 }
227
228 // Hunspell doesn't need all of these options, but it'll ignore those it doesn't understand.
229 if ( ksconfig->client() == KS_CLIENT_ISPELL || ksconfig->client() == KS_CLIENT_ASPELL || ksconfig->client() == KS_CLIENT_HUNSPELL )
230 {
231 *proc << "-a" << "-S";
232
233 switch ( d->type )
234 {
235 case HTML:
236 //Debian uses an ispell version that has the -h option instead.
237 //Not sure what they did, but the preferred spell checker
238 //on that platform is aspell anyway, so use -H untill I'll come
239 //up with something better.
240 *proc << "-H";
241 break;
242 case TeX:
243 //same for aspell and ispell
244 *proc << "-t";
245 break;
246 case Nroff:
247 //only ispell and hunspell support
248 if ( ksconfig->client() == KS_CLIENT_ISPELL || ksconfig->client() == KS_CLIENT_HUNSPELL )
249 *proc << "-n";
250 break;
251 case Text:
252 default:
253 //nothing
254 break;
255 }
256 if (ksconfig->noRootAffix())
257 {
258 *proc<<"-m";
259 }
260 if (ksconfig->runTogether())
261 {
262 *proc << "-B";
263 }
264 else
265 {
266 *proc << "-C";
267 }
268
269
270 if (trystart<2)
271 {
272 if (! ksconfig->dictionary().isEmpty())
273 {
274 kDebug(750) << "using dictionary [" << ksconfig->dictionary() << "]";
275 *proc << "-d";
276 *proc << ksconfig->dictionary();
277 }
278 }
279
280 //Note to potential debuggers: -Tlatin2 _is_ being added on the
281 // _first_ try. But, some versions of ispell will fail with this
282 // option, so k3spell tries again without it. That's why as 'ps -ax'
283 // shows "ispell -a -S ..." withou the "-Tlatin2" option.
284
285 if ( ksconfig->client() == KS_CLIENT_HUNSPELL && trystart<1 ) {
286 // Note: This sets I/O encoding. Hunspell correctly handles dictionary encoding != I/O encoding.
287 // It will be faster if the I/O encoding matches the dictionary encoding, but using UTF-8 is always safe.
288 switch ( ksconfig->encoding() )
289 {
290 case KS_E_LATIN1:
291 *proc << "-i" << "ISO-8859-1";
292 break;
293 case KS_E_LATIN2:
294 *proc << "-i" << "ISO-8859-2";
295 break;
296 case KS_E_LATIN3:
297 *proc << "-i" << "ISO-8859-3";
298 break;
299 case KS_E_LATIN4:
300 *proc << "-i" << "ISO-8859-4";
301 break;
302 case KS_E_LATIN5:
303 *proc << "-i" << "ISO-8859-5";
304 break;
305 case KS_E_LATIN7:
306 *proc << "-i" << "ISO-8859-7";
307 break;
308 case KS_E_LATIN8:
309 *proc << "-i" << "ISO-8859-8";
310 break;
311 case KS_E_LATIN9:
312 *proc << "-i" << "ISO-8859-9";
313 break;
314 case KS_E_LATIN13:
315 *proc << "-i" << "ISO-8859-13";
316 break;
317 case KS_E_LATIN15:
318 *proc << "-i" << "ISO-8859-15";
319 break;
320 case KS_E_UTF8:
321 *proc << "-i" << "UTF-8";
322 break;
323 case KS_E_KOI8R:
324 *proc << "-i" << "KOI8-R";
325 break;
326 case KS_E_KOI8U:
327 *proc << "-i" << "KOI8-U";
328 break;
329 case KS_E_CP1251:
330 *proc << "-i" << "CP1251";
331 break;
332 case KS_E_CP1255:
333 *proc << "-i" << "CP1255";
334 break;
335 default:
336 break;
337 }
338 } else if ( trystart<1 ) {
339 switch ( ksconfig->encoding() )
340 {
341 case KS_E_LATIN1:
342 *proc << "-Tlatin1";
343 break;
344 case KS_E_LATIN2:
345 *proc << "-Tlatin2";
346 break;
347 case KS_E_LATIN3:
348 *proc << "-Tlatin3";
349 break;
350
351 // add the other charsets here
352 case KS_E_LATIN4:
353 case KS_E_LATIN5:
354 case KS_E_LATIN7:
355 case KS_E_LATIN8:
356 case KS_E_LATIN9:
357 case KS_E_LATIN13:
358 // will work, if this is the default charset in the dictionary
359 kError(750) << "charsets ISO-8859-4, -5, -7, -8, -9 and -13 not supported yet" << endl;
360 break;
361 case KS_E_LATIN15: // ISO-8859-15 (Latin 9)
362 if (ksconfig->client() == KS_CLIENT_ISPELL)
363 {
364 /*
365 * As far as I know, there are no ispell dictionary using ISO-8859-15
366 * but users have the tendency to select this encoding instead of ISO-8859-1
367 * So put ispell in ISO-8859-1 (Latin 1) mode.
368 */
369 *proc << "-Tlatin1";
370 }
371 else
372 kError(750) << "ISO-8859-15 not supported for aspell yet." << endl;
373 break;
374 case KS_E_UTF8:
375 *proc << "-Tutf8";
376 if (ksconfig->client() == KS_CLIENT_ASPELL)
377 *proc << "--encoding=utf-8";
378 break;
379 case KS_E_KOI8U:
380 *proc << "-w'"; // add ' as a word char
381 break;
382 default:
383 break;
384 }
385 }
386
387 // -a : pipe mode
388 // -S : sort suggestions by probable correctness
389 }
390 else // hspell and Zemberek(zpspell) doesn't need all the rest of the options
391 *proc << "-a";
392
393 if (trystart == 0) //don't connect these multiple times
394 {
395 connect( proc, SIGNAL(readyReadStandardError()),
396 this, SLOT(ispellErrors()) );
397
398 connect( proc, SIGNAL(finished(int,QProcess::ExitStatus)),
399 this, SLOT(ispellExit()) );
400
401 proc->setOutputChannelMode( KProcess::SeparateChannels );
402 proc->setNextOpenMode( QIODevice::ReadWrite | QIODevice::Text );
403
404 OUTPUT(K3Spell2);
405 }
406
407 proc->start();
408 if ( !proc->waitForStarted() )
409 {
410 m_status = Error;
411 QTimer::singleShot( 0, this, SLOT(emitDeath()));
412 }
413}
414
415void
416K3Spell::ispellErrors( )
417{
418 // buffer[buflen-1] = '\0';
419 // kDebug(750) << "ispellErrors [" << buffer << "]\n";
420}
421
422void K3Spell::K3Spell2( )
423
424{
425 QString line;
426
427 kDebug(750) << "K3Spell::K3Spell2";
428
429 trystart = maxtrystart; //We've officially started ispell and don't want
430 //to try again if it dies.
431
432 QByteArray data;
433 qint64 read = proc->readLine(data.data(),data.count());
434 if ( read == -1 )
435 {
436 QTimer::singleShot( 0, this, SLOT(emitDeath()) );
437 return;
438 }
439 line = d->convertQByteArray( data );
440
441 if ( !line.startsWith('@') ) //@ indicates that ispell is working fine
442 {
443 QTimer::singleShot( 0, this, SLOT(emitDeath()) );
444 return;
445 }
446
447 //We want to recognize KDE in any text!
448 if ( !ignore("kde") )
449 {
450 kDebug(750) << "@KDE was false";
451 QTimer::singleShot( 0, this, SLOT(emitDeath()) );
452 return;
453 }
454
455 //We want to recognize linux in any text!
456 if ( !ignore("linux") )
457 {
458 kDebug(750) << "@Linux was false";
459 QTimer::singleShot( 0, this, SLOT(emitDeath()) );
460 return;
461 }
462
463 NOOUTPUT( K3Spell2 );
464
465 m_status = Running;
466 emit ready( this );
467}
468
469void
470K3Spell::setUpDialog( bool reallyuseprogressbar )
471{
472 if ( dialogsetup )
473 return;
474
475 //Set up the dialog box
476 ksdlg = new K3SpellDlg( parent, progressbar && reallyuseprogressbar, modaldlg );
477 ksdlg->setCaption( caption );
478
479 connect( ksdlg, SIGNAL(command(int)),
480 this, SLOT(slotStopCancel(int)) );
481 connect( this, SIGNAL(progress(uint)),
482 ksdlg, SLOT(slotProgress(uint)) );
483
484 if ( modaldlg )
485 ksdlg->setFocus();
486 dialogsetup = true;
487}
488
489bool K3Spell::addPersonal( const QString & word )
490{
491 QString qs = word.simplified();
492
493 //we'll let ispell do the work here b/c we can
494 if ( qs.indexOf(' ') != -1 || qs.isEmpty() ) // make sure it's a _word_
495 return false;
496
497 qs.prepend( "*" );
498 personaldict = true;
499
500 return proc->write( d->convertQString( qs ) );
501}
502
503bool K3Spell::writePersonalDictionary()
504{
505 return proc->write( QByteArray( "#" ) );
506}
507
508bool K3Spell::ignore( const QString & word )
509{
510 QString qs = word.simplified();
511
512 //we'll let ispell do the work here b/c we can
513 if ( qs.indexOf (' ') != -1 || qs.isEmpty() ) // make sure it's a _word_
514 return false;
515
516 qs.prepend( "@" );
517
518 return proc->write( d->convertQString( qs ) );
519}
520
521bool
522K3Spell::cleanFputsWord( const QString & s )
523{
524 QString qs(s);
525 bool empty = true;
526
527 for( int i = 0; i < qs.length(); i++ )
528 {
529 //we need some punctuation for ornaments
530 if ( (qs[i] != '\'' && qs[i] != '\"' && qs[i] != '-'
531 && qs[i].isPunct()) || qs[i].isSpace() )
532 {
533 qs.remove(i,1);
534 i--;
535 } else {
536 if ( qs[i].isLetter() )
537 empty=false;
538 }
539 }
540
541 // don't check empty words, otherwise synchronization will lost
542 if (empty)
543 return false;
544
545 return proc->write( d->convertQString( QString('^'+qs+'\n') ) );
546}
547
548bool
549K3Spell::cleanFputs( const QString & s )
550{
551 QString qs(s);
552 unsigned l = qs.length();
553
554 // some uses of '$' (e.g. "$0") cause ispell to skip all following text
555 for( unsigned int i = 0; i < l; ++i )
556 {
557 if( qs[i] == '$' )
558 qs[i] = ' ';
559 }
560
561 if ( l<MAXLINELENGTH )
562 {
563 if ( qs.isEmpty() )
564 qs="";
565 return proc->write( d->convertQString('^'+qs+'\n') );
566 }
567 else
568 return proc->write( d->convertQString( "^\n" ) );
569}
570
571bool K3Spell::checkWord( const QString & buffer, bool _usedialog )
572{
573 if (d->checking) { // don't check multiple words simultaneously
574 BufferedWord bufferedWord;
575 bufferedWord.method = Method1;
576 bufferedWord.word = buffer;
577 bufferedWord.useDialog = _usedialog;
578 d->unchecked.append( bufferedWord );
579 return true;
580 }
581 d->checking = true;
582 QString qs = buffer.simplified();
583
584 if ( qs.indexOf (' ') != -1 || qs.isEmpty() ) { // make sure it's a _word_
585 d->checkNextTimer->setInterval(0);
586 d->checkNextTimer->setSingleShot(true);
587 d->checkNextTimer->start();
588 return false;
589 }
591 dialog3slot = SLOT(checkWord3());
592
593 usedialog = _usedialog;
594 setUpDialog( false );
595 if ( _usedialog )
596 {
597 emitProgress();
598 }
599 else
600 ksdlg->hide();
601
602 QByteArray data;
603 while (proc->readLine( data.data(), data.count() ) != -1 )
604 ; // eat spurious blanks
605
606 OUTPUT(checkWord2);
607 // connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
608
609 proc->write( d->convertQString( QString( "%" ) ) ); // turn off terse mode
610 proc->write( d->convertQString( buffer ) ); // send the word to ispell
611
612 return true;
613}
614
615bool K3Spell::checkWord( const QString & buffer, bool _usedialog, bool suggest )
616{
617 if (d->checking) { // don't check multiple words simultaneously
618 BufferedWord bufferedWord;
619 bufferedWord.method = Method2;
620 bufferedWord.word = buffer;
621 bufferedWord.useDialog = _usedialog;
622 bufferedWord.suggest = suggest;
623 d->unchecked.append( bufferedWord );
624 return true;
625 }
626 d->checking = true;
627 QString qs = buffer.simplified();
628
629 if ( qs.indexOf (' ') != -1 || qs.isEmpty() ) { // make sure it's a _word_
630 d->checkNextTimer->setInterval(0);
631 d->checkNextTimer->setSingleShot(true);
632 d->checkNextTimer->start();
633 return false;
634 }
635
637 if ( !suggest ) {
638 dialog3slot = SLOT(checkWord3());
639 usedialog = _usedialog;
640 setUpDialog( false );
641 if ( _usedialog )
642 {
643 emitProgress();
644 }
645 else
646 ksdlg->hide();
647 }
648
649 QByteArray data;
650 while (proc->readLine( data.data(), data.count() ) != -1 ) ; // eat spurious blanks
651
652 OUTPUT(checkWord2);
653 // connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
654
655 proc->write( d->convertQString( QString( "%" ) ) ); // turn off terse mode
656 proc->write( d->convertQString( buffer ) ); // send the word to ispell
657
658 return true;
659}
660
661void K3Spell::checkWord2( )
662{
663 QString word;
664 QString line;
665 line = d->convertQByteArray( proc->readLine() ); //get ispell's response
666
667/* ispell man page: "Each sentence of text input is terminated with an
668 additional blank line, indicating that ispell has completed processing
669 the input line."
670 <sanders>
671 But there can be multiple lines returned in the case of an error,
672 in this case we should consume all the output given otherwise spell checking
673 can get out of sync.
674 </sanders>
675*/
676 QByteArray data;
677 while (proc->readLine( data.data(), data.count() ) != -1 ) ; // eat spurious blanks
678 NOOUTPUT(checkWord2);
679
680 bool mistake = ( parseOneResponse(line, word, sugg) == MISTAKE );
681 if ( mistake && usedialog )
682 {
683 cwword = word;
684 dialog( word, sugg, SLOT(checkWord3()) );
685 d->checkNextTimer->setInterval(0);
686 d->checkNextTimer->setSingleShot(true);
687 d->checkNextTimer->start();
688 return;
689 }
690 else if( mistake )
691 {
692 emit misspelling( word, sugg, lastpos );
693 }
694
695 //emits a "corrected" signal _even_ if no change was made
696 //so that the calling program knows when the check is complete
697 emit corrected( word, word, 0L );
698 d->checkNextTimer->setInterval(0);
699 d->checkNextTimer->setSingleShot(true);
700 d->checkNextTimer->start();
701}
702
703void K3Spell::checkNext()
704{
705// Queue words to prevent kspell from turning into a fork bomb
706 d->checking = false;
707 if (!d->unchecked.empty()) {
708 BufferedWord buf = d->unchecked.front();
709 d->unchecked.pop_front();
710
711 if (buf.method == Method1)
712 checkWord( buf.word, buf.useDialog );
713 else
714 checkWord( buf.word, buf.useDialog, buf.suggest );
715 }
716}
717
718void K3Spell::suggestWord()
719{
720 QString word;
721 QString line;
722 line = d->convertQByteArray( proc->readLine() ); //get ispell's response
723
724/* ispell man page: "Each sentence of text input is terminated with an
725 additional blank line, indicating that ispell has completed processing
726 the input line." */
727 QByteArray data;
728 while (proc->readLine( data.data(), data.count() ) != -1 ) ; // eat spurious blanks
729
730 NOOUTPUT(checkWord2);
731
732 bool mistake = ( parseOneResponse(line, word, sugg) == MISTAKE );
733 if ( mistake && usedialog )
734 {
735 cwword=word;
736 dialog( word, sugg, SLOT(checkWord3()) );
737 return;
738 }
739}
740
741void K3Spell::checkWord3()
742{
743 disconnect( this, SIGNAL(dialog3()), this, SLOT(checkWord3()) );
744
745 emit corrected( cwword, replacement(), 0L );
746}
747
748QString K3Spell::funnyWord( const QString & word )
749 // composes a guess from ispell to a readable word
750 // e.g. "re+fry-y+ies" -> "refries"
751{
752 QString qs;
753 for( int i=0; i<word.size(); i++ )
754 {
755 if (word [i]=='+')
756 continue;
757 if (word [i]=='-')
758 {
759 QString shorty;
760 int j, k;
761
762 for( j = i+1; j < word.size() && word[j] != '+' && word[j] != '-'; j++ )
763 shorty += word[j];
764
765 i = j-1;
766
767 if ( !( k = qs.lastIndexOf(shorty) ) || k != -1 )
768 qs.remove( k, shorty.length() );
769 else
770 {
771 qs += '-';
772 qs += shorty; //it was a hyphen, not a '-' from ispell
773 }
774 }
775 else
776 qs += word[i];
777 }
778
779 return qs;
780}
781
782
783int K3Spell::parseOneResponse( const QString &buffer, QString &word, QStringList & sugg )
784 // buffer is checked, word and sugg are filled in
785 // returns
786 // GOOD if word is fine
787 // IGNORE if word is in ignorelist
788 // REPLACE if word is in replacelist
789 // MISTAKE if word is misspelled
790{
791 word = "";
792 posinline=0;
793
794 sugg.clear();
795
796 if ( buffer[0] == '*' || buffer[0] == '+' || buffer[0] == '-' )
797 {
798 return GOOD;
799 }
800
801 if ( buffer[0] == '&' || buffer[0] == '?' || buffer[0] == '#' )
802 {
803 int i,j;
804
805
806 word = buffer.mid( 2, buffer.indexOf( ' ', 3 ) -2 );
807 //check() needs this
808 orig=word;
809
810 if( d->m_bIgnoreTitleCase && word == word.toUpper() )
811 return IGNORE;
812
813 if( d->m_bIgnoreUpperWords && word[0] == word[0].toUpper() )
814 {
815 QString text = word[0] + word.right( word.length()-1 ).toLower();
816 if( text == word )
817 return IGNORE;
818 }
819
821 //We don't take advantage of ispell's ignore function because
822 //we can't interrupt ispell's output (when checking a large
823 //buffer) to add a word to _it's_ ignore-list.
824 if ( ignorelist.indexOf( word.toLower() ) != -1 )
825 return IGNORE;
826
828 QString qs2;
829
830 if ( buffer.indexOf( ':' ) != -1 )
831 qs2 = buffer.left( buffer.indexOf(':') );
832 else
833 qs2 = buffer;
834
835 posinline = qs2.right( qs2.length()-qs2.lastIndexOf(' ') ).toInt()-1;
836
838 QStringList::Iterator it = replacelist.begin();
839 for( ;it != replacelist.end(); ++it, ++it ) // Skip two entries at a time.
840 {
841 if ( word == *it ) // Word matches
842 {
843 ++it;
844 word = *it; // Replace it with the next entry
845 return REPLACE;
846 }
847 }
848
850 if ( buffer[0] != '#' )
851 {
852 QString qs = buffer.mid( buffer.indexOf(':')+2, buffer.length() );
853 qs += ',';
854 sugg.clear();
855 i = j = 0;
856
857 while( i < qs.length() )
858 {
859 QString temp = qs.mid( i, (j=qs.indexOf(',',i)) - i );
860 sugg.append( funnyWord(temp) );
861
862 i=j+2;
863 }
864 }
865
866 if ( (sugg.count()==1) && (sugg.first() == word) )
867 return GOOD;
868
869 return MISTAKE;
870 }
871
872 if ( buffer.isEmpty() ) {
873 kDebug(750) << "Got an empty response: ignoring";
874 return GOOD;
875 }
876
877 kError(750) << "HERE?: [" << buffer << "]" << endl;
878 kError(750) << "Please report this to zack@kde.org" << endl;
879 kError(750) << "Thank you!" << endl;
880
881 emit done( false );
882 emit done( K3Spell::origbuffer );
883 return MISTAKE;
884}
885
886bool K3Spell::checkList (QStringList *_wordlist, bool _usedialog)
887 // prepare check of string list
888{
889 wordlist=_wordlist;
890 if ((totalpos=wordlist->count())==0)
891 return false;
892 wlIt = wordlist->begin();
893 usedialog=_usedialog;
894
895 // prepare the dialog
896 setUpDialog();
897
898 //set the dialog signal handler
899 dialog3slot = SLOT (checkList4());
900
901 proc->write(QByteArray( '%' ) ); // turn off terse mode & check one word at a time
902
903 //lastpos now counts which *word number* we are at in checkListReplaceCurrent()
904 lastpos = -1;
905 checkList2();
906
907 // when checked, KProcess calls checkList3a
908 OUTPUT(checkList3a);
909
910 return true;
911}
912
913void K3Spell::checkList2 ()
914 // send one word from the list to KProcess
915 // invoked first time by checkList, later by checkListReplaceCurrent and checkList4
916{
917 // send next word
918 if (wlIt != wordlist->end())
919 {
920 kDebug(750) << "KS::cklist2 " << lastpos << ": " << *wlIt;
921
922 d->endOfResponse = false;
923 bool put;
924 lastpos++; offset=0;
925 put = cleanFputsWord (*wlIt);
926 ++wlIt;
927
928 // when cleanFPutsWord failed (e.g. on empty word)
929 // try next word; may be this is not good for other
930 // problems, because this will make read the list up to the end
931 if (!put) {
932 checkList2();
933 }
934 }
935 else
936 // end of word list
937 {
938 NOOUTPUT(checkList3a);
939 ksdlg->hide();
940 emit done(true);
941 }
942}
943
944void K3Spell::checkList3a ()
945 // invoked by KProcess, when data from ispell are read
946{
947 //kDebug(750) << "start of checkList3a";
948
949 // don't read more data, when dialog is waiting
950 // for user interaction
951 if ( dlgon ) {
952 //kDebug(750) << "dlgon: don't read more data";
953 return;
954 }
955
956 int e;
957 qint64 tempe;
958
959 QString word;
960 QString line;
961
962 do
963 {
964 QByteArray data;
965 tempe = proc->readLine( data.data(), data.count() ); //get ispell's response
966
967 //kDebug(750) << "checkList3a: read bytes [" << tempe << "]";
968 line = d->convertQByteArray( data );
969
970 if ( tempe == 0 ) {
971 d->endOfResponse = true;
972 //kDebug(750) << "checkList3a: end of resp";
973 } else if ( tempe>0 ) {
974 if ( (e=parseOneResponse( line, word, sugg ) ) == MISTAKE ||
975 e==REPLACE )
976 {
977 dlgresult=-1;
978
979 if ( e == REPLACE )
980 {
981 QString old = *(--wlIt); ++wlIt;
982 dlgreplacement = word;
983 checkListReplaceCurrent();
984 // inform application
985 emit corrected( old, *(--wlIt), lastpos ); ++wlIt;
986 }
987 else if( usedialog )
988 {
989 cwword = word;
990 dlgon = true;
991 // show the dialog
992 dialog( word, sugg, SLOT(checkList4()) );
993 return;
994 }
995 else
996 {
997 d->m_bNoMisspellingsEncountered = false;
998 emit misspelling( word, sugg, lastpos );
999 }
1000 }
1001
1002 }
1003 emitProgress (); //maybe
1004
1005 // stop when empty line or no more data
1006 } while (tempe > 0);
1007
1008 //kDebug(750) << "checkList3a: exit loop with [" << tempe << "]";
1009
1010 // if we got an empty line, t.e. end of ispell/aspell response
1011 // and the dialog isn't waiting for user interaction, send next word
1012 if (d->endOfResponse && !dlgon) {
1013 //kDebug(750) << "checkList3a: send next word";
1014 checkList2();
1015 }
1016}
1017
1018void K3Spell::checkListReplaceCurrent()
1019{
1020
1021 // go back to misspelled word
1022 wlIt--;
1023
1024 QString s = *wlIt;
1025 s.replace(posinline+offset,orig.length(),replacement());
1026 offset += replacement().length()-orig.length();
1027 wordlist->insert (wlIt, s);
1028 wlIt = wordlist->erase (wlIt);
1029 // wlIt now points to the word after the repalced one
1030
1031}
1032
1033void K3Spell::checkList4 ()
1034 // evaluate dialog return, when a button was pressed there
1035{
1036 dlgon=false;
1037 QString old;
1038
1039 disconnect (this, SIGNAL (dialog3()), this, SLOT (checkList4()));
1040
1041 //others should have been processed by dialog() already
1042 switch (dlgresult)
1043 {
1044 case KS_REPLACE:
1045 case KS_REPLACEALL:
1046 kDebug(750) << "KS: cklist4: lastpos: " << lastpos;
1047 old = *(--wlIt);
1048 ++wlIt;
1049 // replace word
1050 checkListReplaceCurrent();
1051 emit corrected( old, *(--wlIt), lastpos );
1052 ++wlIt;
1053 break;
1054 case KS_CANCEL:
1055 ksdlg->hide();
1056 emit done( false );
1057 return;
1058 case KS_STOP:
1059 ksdlg->hide();
1060 emit done( true );
1061 return;
1062 case KS_CONFIG:
1063 ksdlg->hide();
1064 emit done( false );
1065 //check( origbuffer.mid( lastpos ), true );
1066 //trystart = 0;
1067 //proc->disconnect();
1068 //proc->kill();
1069 //delete proc;
1070 //proc = new KProcess( codec );
1071 //startIspell();
1072 return;
1073 };
1074
1075 // read more if there is more, otherwise send next word
1076 if (!d->endOfResponse) {
1077 //kDebug(750) << "checkList4: read more from response";
1078 checkList3a();
1079 }
1080}
1081
1082bool K3Spell::check( const QString &_buffer, bool _usedialog )
1083{
1084 QString qs;
1085
1086 usedialog = _usedialog;
1087 setUpDialog();
1088 //set the dialog signal handler
1089 dialog3slot = SLOT(check3());
1090
1091 kDebug(750) << "KS: check";
1092 origbuffer = _buffer;
1093 if ( ( totalpos = origbuffer.length() ) == 0 )
1094 {
1095 emit done( origbuffer );
1096 return false;
1097 }
1098
1099
1100 // Torben: I corrected the \n\n problem directly in the
1101 // origbuffer since I got errors otherwise
1102 if ( !origbuffer.endsWith("\n\n" ) )
1103 {
1104 if (origbuffer.at(origbuffer.length()-1)!='\n')
1105 {
1106 origbuffer+='\n';
1107 origbuffer+='\n'; //shouldn't these be removed at some point?
1108 }
1109 else
1110 origbuffer+='\n';
1111 }
1112
1113 newbuffer = origbuffer;
1114
1115 // KProcess calls check2 when read from ispell
1116 OUTPUT( check2 );
1117 proc->write( QByteArray( "!" ) );
1118
1119 //lastpos is a position in newbuffer (it has offset in it)
1120 offset = lastlastline = lastpos = lastline = 0;
1121
1122 emitProgress();
1123
1124 // send first buffer line
1125 int i = origbuffer.indexOf( '\n', 0 ) + 1;
1126 qs = origbuffer.mid( 0, i );
1127 cleanFputs( qs );
1128
1129 lastline=i; //the character position, not a line number
1130
1131 if ( usedialog )
1132 {
1133 emitProgress();
1134 }
1135 else
1136 ksdlg->hide();
1137
1138 return true;
1139}
1140
1141int K3Spell::lastPosition() const
1142{
1143 return lastpos;
1144}
1145
1146
1147void K3Spell::check2()
1148 // invoked by KProcess when read from ispell
1149{
1150 int e;
1151 qint64 tempe;
1152 QString word;
1153 QString line;
1154 static bool recursive = false;
1155 if (recursive &&
1156 !ksdlg )
1157 {
1158 return;
1159 }
1160 recursive = true;
1161
1162 do
1163 {
1164 QByteArray data;
1165 tempe = proc->readLine( data.data(), data.count() ); //get ispell's response
1166 line = d->convertQByteArray( data );
1167 //kDebug(750) << "K3Spell::check2 (" << tempe << "b)";
1168
1169 if ( tempe>0 )
1170 {
1171 if ( ( e=parseOneResponse (line, word, sugg) )==MISTAKE ||
1172 e==REPLACE)
1173 {
1174 dlgresult=-1;
1175
1176 // for multibyte encoding posinline needs correction
1177 if ((ksconfig->encoding() == KS_E_UTF8) && !d->aspellV6) {
1178 // kDebug(750) << "line: " << origbuffer.mid(lastlastline,
1179 // lastline-lastlastline) << endl;
1180 // kDebug(750) << "posinline uncorr: " << posinline;
1181
1182 // convert line to UTF-8, cut at pos, convert back to UCS-2
1183 // and get string length
1184 posinline = (QString::fromUtf8(
1185 origbuffer.mid(lastlastline,lastline-lastlastline).toUtf8(),
1186 posinline)).length();
1187 // kDebug(750) << "posinline corr: " << posinline;
1188 }
1189
1190 lastpos = posinline+lastlastline+offset;
1191
1192 //orig is set by parseOneResponse()
1193
1194 if (e==REPLACE)
1195 {
1196 dlgreplacement=word;
1197 emit corrected( orig, replacement(), lastpos );
1198 offset += replacement().length()-orig.length();
1199 newbuffer.replace( lastpos, orig.length(), word );
1200 }
1201 else //MISTAKE
1202 {
1203 cwword = word;
1204 //kDebug(750) << "(Before dialog) word=[" << word << "] cwword =[" << cwword << "]\n";
1205 if ( usedialog ) {
1206 // show the word in the dialog
1207 dialog( word, sugg, SLOT(check3()) );
1208 } else {
1209 // No dialog, just emit misspelling and continue
1210 d->m_bNoMisspellingsEncountered = false;
1211 emit misspelling( word, sugg, lastpos );
1212 dlgresult = KS_IGNORE;
1213 check3();
1214 }
1215 recursive = false;
1216 return;
1217 }
1218 }
1219
1220 }
1221
1222 emitProgress(); //maybe
1223
1224 } while( tempe>0 );
1225
1226 if ( tempe == -1 ) { //we were called, but no data seems to be ready...
1227 // Make sure we don't get called directly again and make sure we do get
1228 // called when new data arrives.
1229 NOOUTPUT( check2 );
1230// proc->enableReadSignals(true);
1231 OUTPUT( check2 );
1232 recursive = false;
1233 return;
1234 }
1235
1236// proc->ackRead();
1237
1238 //If there is more to check, then send another line to ISpell.
1239 if ( lastline < origbuffer.length() )
1240 {
1241 int i;
1242 QString qs;
1243
1244 //kDebug(750) << "[EOL](" << tempe << ")[" << temp << "]";
1245
1246 lastpos = (lastlastline=lastline) + offset; //do we really want this?
1247 i = origbuffer.indexOf('\n', lastline) + 1;
1248 qs = origbuffer.mid( lastline, i-lastline );
1249 cleanFputs( qs );
1250 lastline = i;
1251 recursive = false;
1252 return;
1253 }
1254 else
1255 //This is the end of it all
1256 {
1257 ksdlg->hide();
1258 // kDebug(750) << "check2() done";
1259 newbuffer.truncate( newbuffer.length()-2 );
1260 emitProgress();
1261 emit done( newbuffer );
1262 }
1263 recursive = false;
1264}
1265
1266void K3Spell::check3 ()
1267 // evaluates the return value of the dialog
1268{
1269 disconnect (this, SIGNAL (dialog3()), this, SLOT (check3()));
1270 kDebug(750) << "check3 [" << cwword << "] [" << replacement() << "] " << dlgresult;
1271
1272 //others should have been processed by dialog() already
1273 switch (dlgresult)
1274 {
1275 case KS_REPLACE:
1276 case KS_REPLACEALL:
1277 offset+=replacement().length()-cwword.length();
1278 newbuffer.replace (lastpos, cwword.length(),
1279 replacement());
1280 emit corrected (dlgorigword, replacement(), lastpos);
1281 break;
1282 case KS_CANCEL:
1283 // kDebug(750) << "canceled\n";
1284 ksdlg->hide();
1285 emit done( origbuffer );
1286 return;
1287 case KS_CONFIG:
1288 ksdlg->hide();
1289 emit done( origbuffer );
1290 KMessageBox::information( 0, i18n("You have to restart the dialog for changes to take effect") );
1291 //check( origbuffer.mid( lastpos ), true );
1292 return;
1293 case KS_STOP:
1294 ksdlg->hide();
1295 //buffer=newbuffer);
1296 emitProgress();
1297 emit done (newbuffer);
1298 return;
1299 };
1300
1301// proc->ackRead();
1302}
1303
1304void
1305K3Spell::slotStopCancel (int result)
1306{
1307 if (dialogwillprocess)
1308 return;
1309
1310 kDebug(750) << "K3Spell::slotStopCancel [" << result << "]";
1311
1312 if (result==KS_STOP || result==KS_CANCEL)
1313 if (!dialog3slot.isEmpty())
1314 {
1315 dlgresult=result;
1316 connect (this, SIGNAL (dialog3()), this, dialog3slot.toLatin1().constData());
1317 emit dialog3();
1318 }
1319}
1320
1321
1322void K3Spell::dialog( const QString & word, QStringList & sugg, const char *_slot )
1323{
1324 dlgorigword = word;
1325
1326 dialog3slot = _slot;
1327 dialogwillprocess = true;
1328 connect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
1329 QString tmpBuf = newbuffer;
1330 kDebug(750)<<" position = "<<lastpos;
1331
1332 // extract a context string, replace all characters which might confuse
1333 // the RichText display and highlight the possibly wrong word
1334 QString marker( "_MARKER_" );
1335 tmpBuf.replace( lastpos, word.length(), marker );
1336 QString context = tmpBuf.mid(qMax(lastpos-18,0), 2*18+marker.length());
1337 context.replace( '\n',QLatin1Char(' '));
1338 context.replace( '<', QLatin1String("&lt;") );
1339 context.replace( '>', QLatin1String("&gt;") );
1340 context.replace( marker, QString::fromLatin1("<b>%1</b>").arg( word ) );
1341 context = "<qt>" + context + "</qt>";
1342
1343 ksdlg->init( word, &sugg, context );
1344 d->m_bNoMisspellingsEncountered = false;
1345 emit misspelling( word, sugg, lastpos );
1346
1347 emitProgress();
1348 ksdlg->show();
1349}
1350
1351QString K3Spell::replacement () const
1352{
1353 return dlgreplacement;
1354}
1355
1356void K3Spell::dialog2( int result )
1357{
1358 QString qs;
1359
1360 disconnect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
1361 dialogwillprocess = false;
1362 dlgresult = result;
1363 ksdlg->standby();
1364
1365 dlgreplacement = ksdlg->replacement();
1366
1367 //process result here
1368 switch ( dlgresult )
1369 {
1370 case KS_IGNORE:
1371 emit ignoreword( dlgorigword );
1372 break;
1373 case KS_IGNOREALL:
1374 // would be better to lower case only words with beginning cap
1375 ignorelist.prepend( dlgorigword.toLower() );
1376 emit ignoreall( dlgorigword );
1377 break;
1378 case KS_ADD:
1379 addPersonal( dlgorigword );
1380 personaldict = true;
1381 emit addword( dlgorigword );
1382 // adding to pesonal dict takes effect at the next line, not the current
1383 ignorelist.prepend( dlgorigword.toLower() );
1384 break;
1385 case KS_REPLACEALL:
1386 {
1387 replacelist.append( dlgorigword );
1388 QString _replacement = replacement();
1389 replacelist.append( _replacement );
1390 emit replaceall( dlgorigword , _replacement );
1391 }
1392 break;
1393 case KS_SUGGEST:
1394 checkWord( ksdlg->replacement(), false, true );
1395 return;
1396 break;
1397 }
1398
1399 connect( this, SIGNAL(dialog3()), this, dialog3slot.toLatin1().constData() );
1400 emit dialog3();
1401}
1402
1403
1404K3Spell::~K3Spell()
1405{
1406 delete proc;
1407 delete ksconfig;
1408 delete ksdlg;
1409 delete d->checkNextTimer;
1410 delete d;
1411}
1412
1413
1414K3SpellConfig K3Spell::ksConfig() const
1415{
1416 ksconfig->setIgnoreList(ignorelist);
1417 ksconfig->setReplaceAllList(replacelist);
1418 return *ksconfig;
1419}
1420
1421void K3Spell::cleanUp()
1422{
1423 if ( m_status == Cleaning )
1424 return; // Ignore
1425
1426 if ( m_status == Running )
1427 {
1428 if ( personaldict )
1429 writePersonalDictionary();
1430 m_status = Cleaning;
1431 }
1432 proc->closeWriteChannel();
1433}
1434
1435void K3Spell::setAutoDelete(bool _autoDelete)
1436{
1437 autoDelete = _autoDelete;
1438}
1439
1440void K3Spell::ispellExit()
1441{
1442 kDebug() << "K3Spell::ispellExit() " << m_status;
1443
1444 if ( (m_status == Starting) && (trystart < maxtrystart) )
1445 {
1446 trystart++;
1447 startIspell();
1448 return;
1449 }
1450
1451 if ( m_status == Starting )
1452 m_status = Error;
1453 else if (m_status == Cleaning)
1454 m_status = d->m_bNoMisspellingsEncountered ? FinishedNoMisspellingsEncountered : Finished;
1455 else if ( m_status == Running )
1456 m_status = Crashed;
1457 else // Error, Finished, Crashed
1458 return; // Dead already
1459
1460 kDebug(750) << "Death";
1461 QTimer::singleShot( 0, this, SLOT(emitDeath()) );
1462}
1463
1464// This is always called from the event loop to make
1465// sure that the receiver can safely delete the
1466// K3Spell object.
1467void K3Spell::emitDeath()
1468{
1469 bool deleteMe = autoDelete; // Can't access object after next call!
1470 emit death();
1471 if ( deleteMe )
1472 deleteLater();
1473}
1474
1475void K3Spell::setProgressResolution (unsigned int res)
1476{
1477 progres=res;
1478}
1479
1480void K3Spell::emitProgress ()
1481{
1482 uint nextprog = (uint) (100.*lastpos/(double)totalpos);
1483
1484 if ( nextprog >= curprog )
1485 {
1486 curprog = nextprog;
1487 emit progress( curprog );
1488 }
1489}
1490
1491void K3Spell::moveDlg( int x, int y )
1492{
1493 QPoint pt( x,y ), pt2;
1494 pt2 = parent->mapToGlobal( pt );
1495 ksdlg->move( pt2.x(),pt2.y() );
1496}
1497
1498void K3Spell::setIgnoreUpperWords(bool _ignore)
1499{
1500 d->m_bIgnoreUpperWords=_ignore;
1501}
1502
1503void K3Spell::setIgnoreTitleCase(bool _ignore)
1504{
1505 d->m_bIgnoreTitleCase=_ignore;
1506}
1507// --------------------------------------------------
1508// Stuff for modal (blocking) spell checking
1509//
1510// Written by Torben Weis <weis@kde.org>. So please
1511// send bug reports regarding the modal stuff to me.
1512// --------------------------------------------------
1513
1514int
1515K3Spell::modalCheck( QString& text )
1516{
1517 return modalCheck( text,0 );
1518}
1519
1520int
1521K3Spell::modalCheck( QString& text, K3SpellConfig* _kcs )
1522{
1523 modalreturn = 0;
1524 modaltext = text;
1525
1526 K3Spell* spell = new K3Spell( 0L, i18n("Spell Checker"), 0 ,
1527 0, _kcs, true, true );
1528
1529 while (spell->status()!=Finished)
1530 qApp->processEvents();
1531
1532 text = modaltext;
1533
1534 delete spell;
1535 return modalreturn;
1536}
1537
1538void K3Spell::slotSpellCheckerCorrected( const QString & oldText, const QString & newText, unsigned int pos )
1539{
1540 modaltext=modaltext.replace(pos,oldText.length(),newText);
1541}
1542
1543
1544void K3Spell::slotModalReady()
1545{
1546 //kDebug() << qApp->loopLevel();
1547 //kDebug(750) << "MODAL READY------------------";
1548
1549 Q_ASSERT( m_status == Running );
1550 connect( this, SIGNAL(done(QString)),
1551 this, SLOT(slotModalDone(QString)) );
1552 QObject::connect( this, SIGNAL(corrected(QString,QString,uint)),
1553 this, SLOT(slotSpellCheckerCorrected(QString,QString,uint)) );
1554 QObject::connect( this, SIGNAL(death()),
1555 this, SLOT(slotModalSpellCheckerFinished()) );
1556 check( modaltext );
1557}
1558
1559void K3Spell::slotModalDone( const QString &/*_buffer*/ )
1560{
1561 //kDebug(750) << "MODAL DONE " << _buffer;
1562 //modaltext = _buffer;
1563 cleanUp();
1564
1565 //kDebug() << "ABOUT TO EXIT LOOP";
1566 //qApp->exit_loop();
1567
1568 //modalWidgetHack->close(true);
1569 slotModalSpellCheckerFinished();
1570}
1571
1572void K3Spell::slotModalSpellCheckerFinished( )
1573{
1574 modalreturn=(int)this->status();
1575}
1576
1577void K3Spell::initialize( QWidget *_parent, const QString &_caption,
1578 QObject *obj, const char *slot, K3SpellConfig *_ksc,
1579 bool _progressbar, bool _modal, SpellerType type )
1580{
1581 d = new K3SpellPrivate;
1582
1583 d->m_bIgnoreUpperWords =false;
1584 d->m_bIgnoreTitleCase =false;
1585 d->m_bNoMisspellingsEncountered = true;
1586 d->type = type;
1587 d->checking = false;
1588 d->aspellV6 = false;
1589 d->checkNextTimer = new QTimer( this );
1590 connect( d->checkNextTimer, SIGNAL(timeout()),
1591 this, SLOT(checkNext()));
1592 autoDelete = false;
1593 modaldlg = _modal;
1594 progressbar = _progressbar;
1595
1596 proc = 0;
1597 ksconfig = 0;
1598 ksdlg = 0;
1599 lastpos = 0;
1600
1601 //won't be using the dialog in ksconfig, just the option values
1602 if ( _ksc )
1603 ksconfig = new K3SpellConfig( *_ksc );
1604 else
1605 ksconfig = new K3SpellConfig;
1606
1607 d->m_codec = 0;
1608 switch ( ksconfig->encoding() )
1609 {
1610 case KS_E_LATIN1:
1611 d->m_codec = QTextCodec::codecForName("ISO 8859-1");
1612 break;
1613 case KS_E_LATIN2:
1614 d->m_codec = QTextCodec::codecForName("ISO 8859-2");
1615 break;
1616 case KS_E_LATIN3:
1617 d->m_codec = QTextCodec::codecForName("ISO 8859-3");
1618 break;
1619 case KS_E_LATIN4:
1620 d->m_codec = QTextCodec::codecForName("ISO 8859-4");
1621 break;
1622 case KS_E_LATIN5:
1623 d->m_codec = QTextCodec::codecForName("ISO 8859-5");
1624 break;
1625 case KS_E_LATIN7:
1626 d->m_codec = QTextCodec::codecForName("ISO 8859-7");
1627 break;
1628 case KS_E_LATIN8:
1629 d->m_codec = QTextCodec::codecForName("ISO 8859-8-i");
1630 break;
1631 case KS_E_LATIN9:
1632 d->m_codec = QTextCodec::codecForName("ISO 8859-9");
1633 break;
1634 case KS_E_LATIN13:
1635 d->m_codec = QTextCodec::codecForName("ISO 8859-13");
1636 break;
1637 case KS_E_LATIN15:
1638 d->m_codec = QTextCodec::codecForName("ISO 8859-15");
1639 break;
1640 case KS_E_UTF8:
1641 d->m_codec = QTextCodec::codecForName("UTF-8");
1642 break;
1643 case KS_E_KOI8R:
1644 d->m_codec = QTextCodec::codecForName("KOI8-R");
1645 break;
1646 case KS_E_KOI8U:
1647 d->m_codec = QTextCodec::codecForName("KOI8-U");
1648 break;
1649 case KS_E_CP1251:
1650 d->m_codec = QTextCodec::codecForName("CP1251");
1651 break;
1652 case KS_E_CP1255:
1653 d->m_codec = QTextCodec::codecForName("CP1255");
1654 break;
1655 default:
1656 break;
1657 }
1658
1659 kDebug(750) << __FILE__ << ":" << __LINE__ << " Codec = " << (d->m_codec ? d->m_codec->name() : "<default>");
1660
1661 // copy ignore list from ksconfig
1662 ignorelist += ksconfig->ignoreList();
1663
1664 replacelist += ksconfig->replaceAllList();
1665 texmode=dlgon=false;
1666 m_status = Starting;
1667 dialogsetup = false;
1668 progres=10;
1669 curprog=0;
1670
1671 dialogwillprocess = false;
1672 dialog3slot.clear();
1673
1674 personaldict = false;
1675 dlgresult = -1;
1676
1677 caption = _caption;
1678
1679 parent = _parent;
1680
1681 trystart = 0;
1682 maxtrystart = 2;
1683
1684 if ( obj && slot )
1685 // caller wants to know when k3spell is ready
1686 connect( this, SIGNAL(ready(K3Spell*)), obj, slot);
1687 else
1688 // Hack for modal spell checking
1689 connect( this, SIGNAL(ready(K3Spell*)), this, SLOT(slotModalReady()) );
1690
1691 proc = new KProcess();
1692
1693 startIspell();
1694}
1695
1696QString K3Spell::modaltext;
1697int K3Spell::modalreturn = 0;
1698QWidget* K3Spell::modalWidgetHack = 0;
1699
1700#include "k3spell.moc"
1701
K3SpellConfig
A configuration class/dialog for K3Spell.
Definition: k3sconfig.h:89
K3SpellConfig::replaceAllList
QStringList replaceAllList() const
Definition: k3sconfig.cpp:1181
K3SpellConfig::client
int client() const
Spell checker client,.
Definition: k3sconfig.cpp:988
K3SpellConfig::setIgnoreList
void setIgnoreList(const QStringList &_ignorelist)
@sect Options setting routines.
Definition: k3sconfig.cpp:1163
K3SpellConfig::encoding
int encoding() const
Definition: k3sconfig.cpp:1026
K3SpellConfig::dictionary
const QString dictionary() const
Definition: k3sconfig.cpp:1013
K3SpellConfig::setReplaceAllList
void setReplaceAllList(const QStringList &_replaceAllList)
The _replaceAllList contains word you like that replace word.
Definition: k3sconfig.cpp:1175
K3SpellConfig::noRootAffix
bool noRootAffix() const
Definition: k3sconfig.cpp:1001
K3SpellConfig::runTogether
bool runTogether() const
Definition: k3sconfig.cpp:1007
K3SpellConfig::ignoreList
QStringList ignoreList() const
Definition: k3sconfig.cpp:1169
K3SpellDlg
Definition: k3spelldlg.h:51
K3SpellDlg::replacement
QString replacement() const
Definition: k3spelldlg.cpp:114
K3SpellDlg::standby
void standby()
Definition: k3spelldlg.cpp:188
K3SpellDlg::init
void init(const QString &_word, QStringList *_sugg)
Change the misspelled word and suggested replacements and enable the disabled buttons on the dialog b...
Definition: k3spelldlg.cpp:120
K3Spell
KDE Spellchecker
Definition: k3spell.h:47
K3Spell::texmode
bool texmode
Definition: k3spell.h:506
K3Spell::progressbar
bool progressbar
Definition: k3spell.h:510
K3Spell::totalpos
unsigned int totalpos
Definition: k3spell.h:527
K3Spell::ignore
virtual bool ignore(const QString &word)
Tells ISpell/ASpell to ignore this word for the life of this K3Spell instance.
Definition: k3spell.cpp:508
K3Spell::checkWord3
void checkWord3()
Definition: k3spell.cpp:741
K3Spell::moveDlg
void moveDlg(int x, int y)
Moves the dialog.
Definition: k3spell.cpp:1491
K3Spell::K3Spell2
void K3Spell2()
Definition: k3spell.cpp:422
K3Spell::cleanFputs
bool cleanFputs(const QString &s)
Definition: k3spell.cpp:549
K3Spell::curprog
unsigned int curprog
Definition: k3spell.h:533
K3Spell::replacelist
QStringList replacelist
Definition: k3spell.h:500
K3Spell::ispellExit
void ispellExit()
Definition: k3spell.cpp:1440
K3Spell::lastpos
int lastpos
Definition: k3spell.h:526
K3Spell::offset
unsigned int offset
Definition: k3spell.h:531
K3Spell::ksConfig
K3SpellConfig ksConfig() const
Definition: k3spell.cpp:1414
K3Spell::done
void done(const QString &buffer)
Emitted when check() is done.
K3Spell::checkListReplaceCurrent
void checkListReplaceCurrent()
Definition: k3spell.cpp:1018
K3Spell::dialog
void dialog(const QString &word, QStringList &sugg, const char *_slot)
Definition: k3spell.cpp:1322
K3Spell::intermediateBuffer
QString intermediateBuffer() const
Returns the partially spellchecked buffer.
Definition: k3spell.cpp:161
K3Spell::progres
unsigned int progres
Definition: k3spell.h:532
K3Spell::corrected
void corrected(const QString &originalword, const QString &newword, unsigned int pos)
Emitted after the "Replace" or "Replace All" buttons of the dialog was pressed, or if the word was co...
K3Spell::origbuffer
QString origbuffer
Definition: k3spell.h:516
K3Spell::status
spellStatus status() const
Returns the status of K3Spell.
Definition: k3spell.cpp:141
K3Spell::cleanUp
virtual void cleanUp()
Cleans up ISpell.
Definition: k3spell.cpp:1421
K3Spell::m_status
spellStatus m_status
Definition: k3spell.h:503
K3Spell::dialog2
void dialog2(int dlgresult)
Definition: k3spell.cpp:1356
K3Spell::checkNext
void checkNext()
Definition: k3spell.cpp:703
K3Spell::cwword
QString cwword
Definition: k3spell.h:518
K3Spell::suggestions
QStringList suggestions() const
Returns list of suggested word replacements.
Definition: k3spell.cpp:148
K3Spell::dialog3
void dialog3()
K3Spell::checkList
virtual bool checkList(QStringList *_wordlist, bool usedialog=true)
Spellchecks a list of words.
Definition: k3spell.cpp:886
K3Spell::modaltext
static QString modaltext
Definition: k3spell.h:539
K3Spell::trystart
int trystart
Definition: k3spell.h:524
K3Spell::cleanFputsWord
bool cleanFputsWord(const QString &s)
Definition: k3spell.cpp:522
K3Spell::initialize
void initialize(QWidget *_parent, const QString &_caption, QObject *obj, const char *slot, K3SpellConfig *_ksc, bool _progressbar, bool _modal, SpellerType type)
Definition: k3spell.cpp:1577
K3Spell::check2
void check2()
Definition: k3spell.cpp:1147
K3Spell::K3Spell
K3Spell(QWidget *parent, const QString &caption, QObject *receiver, const char *slot, K3SpellConfig *kcs=0, bool progressbar=true, bool modal=false)
Starts the spellchecker.
Definition: k3spell.cpp:125
K3Spell::ignoreall
void ignoreall(const QString &originalword)
Emitted when the user pressed "Ignore All" in the dialog.
K3Spell::setIgnoreUpperWords
void setIgnoreUpperWords(bool b)
Call setIgnoreUpperWords(true) to tell the spell-checker to ignore words that are completely uppercas...
Definition: k3spell.cpp:1498
K3Spell::setIgnoreTitleCase
void setIgnoreTitleCase(bool b)
Call setIgnoreTitleCase(true) to tell the spell-checker to ignore words with a 'title' case,...
Definition: k3spell.cpp:1503
K3Spell::widthDlg
int widthDlg() const
Returns the width of the dialog box.
Definition: k3spell.cpp:159
K3Spell::autoDelete
bool autoDelete
Definition: k3spell.h:512
K3Spell::slotStopCancel
void slotStopCancel(int)
Definition: k3spell.cpp:1305
K3Spell::death
void death()
Emitted on terminal errors and after clean up.
K3Spell::usedialog
bool usedialog
Definition: k3spell.h:505
K3Spell::newbuffer
QString newbuffer
Definition: k3spell.h:517
K3Spell::~K3Spell
virtual ~K3Spell()
The destructor instructs ISpell/ASpell to write out the personal dictionary and then terminates ISpel...
Definition: k3spell.cpp:1404
K3Spell::replaceall
void replaceall(const QString &origword, const QString &replacement)
Emitted when the user pressed "ReplaceAll" in the dialog.
K3Spell::hide
void hide()
Hides the dialog box.
Definition: k3spell.cpp:146
K3Spell::dlgResult
int dlgResult() const
Gets the result code of the dialog box.
Definition: k3spell.cpp:153
K3Spell::addPersonal
virtual bool addPersonal(const QString &word)
Adds a word to the user's personal dictionary.
Definition: k3spell.cpp:489
K3Spell::check3
void check3()
Definition: k3spell.cpp:1266
K3Spell::modalWidgetHack
static QWidget * modalWidgetHack
Definition: k3spell.h:541
K3Spell::personaldict
bool personaldict
Definition: k3spell.h:508
K3Spell::writePersonalDictionary
bool writePersonalDictionary()
Definition: k3spell.cpp:503
K3Spell::caption
QString caption
Definition: k3spell.h:514
K3Spell::checkList3a
void checkList3a()
Definition: k3spell.cpp:944
K3Spell::addword
void addword(const QString &originalword)
Emitted when the user pressed "Add" in the dialog.
K3Spell::ignorelist
QStringList ignorelist
Definition: k3spell.h:499
K3Spell::replacement
QString replacement() const
Definition: k3spell.cpp:1351
K3Spell::spellStatus
spellStatus
Possible states of the spell checker.
Definition: k3spell.h:65
K3Spell::Running
@ Running
Definition: k3spell.h:65
K3Spell::FinishedNoMisspellingsEncountered
@ FinishedNoMisspellingsEncountered
Definition: k3spell.h:65
K3Spell::Starting
@ Starting
Definition: k3spell.h:65
K3Spell::Cleaning
@ Cleaning
Definition: k3spell.h:65
K3Spell::Finished
@ Finished
Definition: k3spell.h:65
K3Spell::Crashed
@ Crashed
Definition: k3spell.h:65
K3Spell::funnyWord
QString funnyWord(const QString &word)
Definition: k3spell.cpp:748
K3Spell::dlgresult
int dlgresult
Definition: k3spell.h:523
K3Spell::dialog3slot
QString dialog3slot
Definition: k3spell.h:521
K3Spell::misspelling
void misspelling(const QString &originalword, const QStringList &suggestions, unsigned int pos)
Emitted whenever a misspelled word is found by check() or by checkWord().
K3Spell::maxtrystart
int maxtrystart
Definition: k3spell.h:525
K3Spell::sugg
QStringList sugg
Definition: k3spell.h:501
K3Spell::wordlist
QStringList * wordlist
Definition: k3spell.h:497
K3Spell::lastline
int lastline
Definition: k3spell.h:528
K3Spell::progress
void progress(unsigned int i)
Emitted during a check().
K3Spell::ignoreword
void ignoreword(const QString &originalword)
Emitted when the user pressed "Ignore" in the dialog.
K3Spell::emitDeath
void emitDeath()
Definition: k3spell.cpp:1467
K3Spell::setAutoDelete
void setAutoDelete(bool _autoDelete)
Sets the auto-delete flag.
Definition: k3spell.cpp:1435
K3Spell::parent
QWidget * parent
Definition: k3spell.h:494
K3Spell::setUpDialog
void setUpDialog(bool reallyusedialogbox=true)
Definition: k3spell.cpp:470
K3Spell::ksdlg
K3SpellDlg * ksdlg
Definition: k3spell.h:496
K3Spell::dlgorigword
QString dlgorigword
Definition: k3spell.h:519
K3Spell::setProgressResolution
void setProgressResolution(unsigned int res)
Sets the resolution (in percent) of the progress() signals.
Definition: k3spell.cpp:1475
K3Spell::startIspell
void startIspell()
Definition: k3spell.cpp:192
K3Spell::dlgreplacement
QString dlgreplacement
Definition: k3spell.h:520
K3Spell::SpellerType
SpellerType
These are possible types of documents which the spell checker can check.
Definition: k3spell.h:80
K3Spell::TeX
@ TeX
Definition: k3spell.h:80
K3Spell::HTML
@ HTML
Definition: k3spell.h:80
K3Spell::Text
@ Text
Definition: k3spell.h:80
K3Spell::Nroff
@ Nroff
Definition: k3spell.h:80
K3Spell::lastlastline
unsigned int lastlastline
Definition: k3spell.h:530
K3Spell::checkWord2
void checkWord2()
Definition: k3spell.cpp:661
K3Spell::lastPosition
int lastPosition() const
Returns the position (when using check()) or word number (when using checkList()) of the last word ch...
Definition: k3spell.cpp:1141
K3Spell::wlIt
QStringList::Iterator wlIt
Definition: k3spell.h:498
K3Spell::modaldlg
bool modaldlg
Used for modalCheck.
Definition: k3spell.h:538
K3Spell::heightDlg
int heightDlg() const
Returns the height of the dialog box.
Definition: k3spell.cpp:158
K3Spell::checkList4
void checkList4()
Definition: k3spell.cpp:1033
K3Spell::check
virtual bool check(const QString &_buffer, bool usedialog=true)
Spellchecks a buffer of many words in plain text format.
Definition: k3spell.cpp:1082
K3Spell::emitProgress
void emitProgress()
Definition: k3spell.cpp:1480
K3Spell::proc
KProcess * proc
Definition: k3spell.h:493
K3Spell::dlgon
bool dlgon
Definition: k3spell.h:507
K3Spell::modalreturn
static int modalreturn
Definition: k3spell.h:540
K3Spell::posinline
unsigned int posinline
Definition: k3spell.h:529
K3Spell::ready
void ready(K3Spell *)
Emitted after K3Spell has verified that ISpell/ASpell is running and working properly.
K3Spell::dialogwillprocess
bool dialogwillprocess
Definition: k3spell.h:509
K3Spell::parseOneResponse
int parseOneResponse(const QString &_buffer, QString &word, QStringList &sugg)
Definition: k3spell.cpp:783
K3Spell::checkList2
void checkList2()
Definition: k3spell.cpp:913
K3Spell::ispellErrors
void ispellErrors()
Definition: k3spell.cpp:416
K3Spell::checkWord
virtual bool checkWord(const QString &_buffer, bool usedialog=false)
Spellchecks a single word.
Definition: k3spell.cpp:571
K3Spell::ksconfig
K3SpellConfig * ksconfig
Definition: k3spell.h:495
K3Spell::orig
QString orig
Definition: k3spell.h:515
K3Spell::dialogsetup
bool dialogsetup
Definition: k3spell.h:511
K3Spell::suggestWord
void suggestWord()
Definition: k3spell.cpp:718
K3Spell::modalCheck
static int modalCheck(QString &text)
Definition: k3spell.cpp:1515
KDialog::setCaption
virtual void setCaption(const QString &caption)
KMessageBox::information
static void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
KProcess
KProcess::start
void start()
KProcess::setNextOpenMode
void setNextOpenMode(QIODevice::OpenMode mode)
KProcess::SeparateChannels
SeparateChannels
KProcess::setOutputChannelMode
void setOutputChannelMode(OutputChannelMode mode)
QList
QObject
QWidget
kDebug
#define kDebug
k3sconfig.h
KS_CLIENT_HUNSPELL
@ KS_CLIENT_HUNSPELL
Definition: k3sconfig.h:65
KS_CLIENT_ISPELL
@ KS_CLIENT_ISPELL
Definition: k3sconfig.h:61
KS_CLIENT_ASPELL
@ KS_CLIENT_ASPELL
Definition: k3sconfig.h:62
KS_CLIENT_HSPELL
@ KS_CLIENT_HSPELL
Definition: k3sconfig.h:63
KS_CLIENT_ZEMBEREK
@ KS_CLIENT_ZEMBEREK
Definition: k3sconfig.h:64
KS_E_LATIN7
@ KS_E_LATIN7
ISO-8859-6 (Arabic)
Definition: k3sconfig.h:48
KS_E_KOI8R
@ KS_E_KOI8R
Definition: k3sconfig.h:54
KS_E_LATIN5
@ KS_E_LATIN5
ISO-8859-5 (Cyrillic)
Definition: k3sconfig.h:47
KS_E_UTF8
@ KS_E_UTF8
Definition: k3sconfig.h:53
KS_E_LATIN2
@ KS_E_LATIN2
Definition: k3sconfig.h:44
KS_E_CP1251
@ KS_E_CP1251
Definition: k3sconfig.h:56
KS_E_LATIN8
@ KS_E_LATIN8
ISO-8859-7 (Greek)
Definition: k3sconfig.h:49
KS_E_KOI8U
@ KS_E_KOI8U
Definition: k3sconfig.h:55
KS_E_LATIN15
@ KS_E_LATIN15
ISO-8859-15 (Latin 9)
Definition: k3sconfig.h:52
KS_E_LATIN9
@ KS_E_LATIN9
ISO-8859-8 (Hebrew)
Definition: k3sconfig.h:50
KS_E_CP1255
@ KS_E_CP1255
Definition: k3sconfig.h:57
KS_E_LATIN3
@ KS_E_LATIN3
Definition: k3sconfig.h:45
KS_E_LATIN4
@ KS_E_LATIN4
Definition: k3sconfig.h:46
KS_E_LATIN1
@ KS_E_LATIN1
Definition: k3sconfig.h:43
KS_E_LATIN13
@ KS_E_LATIN13
ISO-8859-13 (Latin 7)
Definition: k3sconfig.h:51
NOOUTPUT
#define NOOUTPUT(x)
Definition: k3spell.cpp:121
MAXLINELENGTH
#define MAXLINELENGTH
Definition: k3spell.cpp:50
checkMethod
checkMethod
Definition: k3spell.cpp:60
Method2
@ Method2
Definition: k3spell.cpp:60
Method1
@ Method1
Definition: k3spell.cpp:60
MISTAKE
@ MISTAKE
Definition: k3spell.cpp:57
REPLACE
@ REPLACE
Definition: k3spell.cpp:56
GOOD
@ GOOD
Definition: k3spell.cpp:54
IGNORE
@ IGNORE
Definition: k3spell.cpp:55
determineASpellV6
static bool determineASpellV6()
Definition: k3spell.cpp:167
OUTPUT
#define OUTPUT(x)
Definition: k3spell.cpp:118
k3spell.h
k3spelldlg.h
KS_SUGGEST
@ KS_SUGGEST
Definition: k3spelldlg.h:43
KS_CONFIG
@ KS_CONFIG
Definition: k3spelldlg.h:44
KS_STOP
@ KS_STOP
Definition: k3spelldlg.h:42
KS_IGNOREALL
@ KS_IGNOREALL
Definition: k3spelldlg.h:40
KS_REPLACE
@ KS_REPLACE
Definition: k3spelldlg.h:37
KS_REPLACEALL
@ KS_REPLACEALL
Definition: k3spelldlg.h:38
KS_CANCEL
@ KS_CANCEL
Definition: k3spelldlg.h:36
KS_IGNORE
@ KS_IGNORE
Definition: k3spelldlg.h:39
KS_ADD
@ KS_ADD
Definition: k3spelldlg.h:41
kdebug.h
timeout
int timeout
klocale.h
i18n
QString i18n(const char *text)
kmessagebox.h
kprocess.h
put
TransferJob * put(const KUrl &url, int permissions, JobFlags flags=DefaultFlags)
Error
Error
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDE3Support

Skip menu "KDE3Support"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal