38#include <QtGui/QApplication>
39#include <QtCore/QTextCodec>
40#include <QtCore/QTimer>
50#define MAXLINELENGTH 10000
70class K3Spell::K3SpellPrivate
74 bool m_bIgnoreUpperWords;
75 bool m_bIgnoreTitleCase;
76 bool m_bNoMisspellingsEncountered;
81 QTimer *checkNextTimer;
84 QString convertQByteArray(
const QByteArray& b )
86 QTextCodec* originalCodec = QTextCodec::codecForCStrings();
87 QTextCodec::setCodecForCStrings( m_codec );
89 QTextCodec::setCodecForCStrings( originalCodec );
92 QByteArray convertQString(
const QString& s )
94 QTextCodec* originalCodec = QTextCodec::codecForCStrings();
95 QTextCodec::setCodecForCStrings( m_codec );
96 QByteArray b = s.toLatin1();
97 QTextCodec::setCodecForCStrings( originalCodec );
118#define OUTPUT(x) (connect (proc, SIGNAL (readyReadStandardOutput()), this, SLOT (x())))
121#define NOOUTPUT(x) (disconnect (proc, SIGNAL (readyReadStandardOutput()), this, SLOT (x())))
127 bool _progressbar,
bool _modal )
129 initialize( _parent, _caption, obj, slot, _ksc,
130 _progressbar, _modal,
Text );
137 initialize( _parent, _caption, obj, slot, _ksc,
138 _progressbar, _modal, type );
170 FILE *fs = popen(
"aspell -v",
"r");
175 QTextStream ts(fs, QIODevice::ReadOnly);
176 result = ts.readAll().trimmed();
181 QRegExp rx(
"Aspell (\\d.\\d)");
182 if (rx.indexIn(result) != -1)
184 float version = rx.cap(1).toFloat();
185 return (version >= 0.6);
208 kDebug(750) <<
"Using ispell";
212 kDebug(750) <<
"Using aspell";
216 kDebug(750) <<
"Using hspell";
220 kDebug(750) <<
"Using zemberek(zpspell)";
224 kDebug(750) <<
"Using hunspell";
231 *
proc <<
"-a" <<
"-S";
291 *
proc <<
"-i" <<
"ISO-8859-1";
294 *
proc <<
"-i" <<
"ISO-8859-2";
297 *
proc <<
"-i" <<
"ISO-8859-3";
300 *
proc <<
"-i" <<
"ISO-8859-4";
303 *
proc <<
"-i" <<
"ISO-8859-5";
306 *
proc <<
"-i" <<
"ISO-8859-7";
309 *
proc <<
"-i" <<
"ISO-8859-8";
312 *
proc <<
"-i" <<
"ISO-8859-9";
315 *
proc <<
"-i" <<
"ISO-8859-13";
318 *
proc <<
"-i" <<
"ISO-8859-15";
321 *
proc <<
"-i" <<
"UTF-8";
324 *
proc <<
"-i" <<
"KOI8-R";
327 *
proc <<
"-i" <<
"KOI8-U";
330 *
proc <<
"-i" <<
"CP1251";
333 *
proc <<
"-i" <<
"CP1255";
359 kError(750) <<
"charsets ISO-8859-4, -5, -7, -8, -9 and -13 not supported yet" << endl;
372 kError(750) <<
"ISO-8859-15 not supported for aspell yet." << endl;
377 *
proc <<
"--encoding=utf-8";
395 connect(
proc, SIGNAL(readyReadStandardError()),
398 connect(
proc, SIGNAL(finished(
int,QProcess::ExitStatus)),
408 if ( !
proc->waitForStarted() )
411 QTimer::singleShot( 0,
this, SLOT(
emitDeath()));
427 kDebug(750) <<
"K3Spell::K3Spell2";
433 qint64 read =
proc->readLine(data.data(),data.count());
436 QTimer::singleShot( 0,
this, SLOT(
emitDeath()) );
439 line = d->convertQByteArray( data );
441 if ( !line.startsWith(
'@') )
443 QTimer::singleShot( 0,
this, SLOT(
emitDeath()) );
450 kDebug(750) <<
"@KDE was false";
451 QTimer::singleShot( 0,
this, SLOT(
emitDeath()) );
458 kDebug(750) <<
"@Linux was false";
459 QTimer::singleShot( 0,
this, SLOT(
emitDeath()) );
479 connect(
ksdlg, SIGNAL(command(
int)),
481 connect(
this, SIGNAL(
progress(uint)),
482 ksdlg, SLOT(slotProgress(uint)) );
491 QString qs = word.simplified();
494 if ( qs.indexOf(
' ') != -1 || qs.isEmpty() )
500 return proc->write( d->convertQString( qs ) );
505 return proc->write( QByteArray(
"#" ) );
510 QString qs = word.simplified();
513 if ( qs.indexOf (
' ') != -1 || qs.isEmpty() )
518 return proc->write( d->convertQString( qs ) );
527 for(
int i = 0; i < qs.length(); i++ )
530 if ( (qs[i] !=
'\'' && qs[i] !=
'\"' && qs[i] !=
'-'
531 && qs[i].isPunct()) || qs[i].isSpace() )
536 if ( qs[i].isLetter() )
545 return proc->write( d->convertQString( QString(
'^'+qs+
'\n') ) );
552 unsigned l = qs.length();
555 for(
unsigned int i = 0; i < l; ++i )
565 return proc->write( d->convertQString(
'^'+qs+
'\n') );
568 return proc->write( d->convertQString(
"^\n" ) );
574 BufferedWord bufferedWord;
576 bufferedWord.word = buffer;
577 bufferedWord.useDialog = _usedialog;
578 d->unchecked.append( bufferedWord );
582 QString qs = buffer.simplified();
584 if ( qs.indexOf (
' ') != -1 || qs.isEmpty() ) {
585 d->checkNextTimer->setInterval(0);
586 d->checkNextTimer->setSingleShot(
true);
587 d->checkNextTimer->start();
603 while (
proc->readLine( data.data(), data.count() ) != -1 )
609 proc->write( d->convertQString( QString(
"%" ) ) );
610 proc->write( d->convertQString( buffer ) );
618 BufferedWord bufferedWord;
620 bufferedWord.word = buffer;
621 bufferedWord.useDialog = _usedialog;
622 bufferedWord.suggest = suggest;
623 d->unchecked.append( bufferedWord );
627 QString qs = buffer.simplified();
629 if ( qs.indexOf (
' ') != -1 || qs.isEmpty() ) {
630 d->checkNextTimer->setInterval(0);
631 d->checkNextTimer->setSingleShot(
true);
632 d->checkNextTimer->start();
650 while (
proc->readLine( data.data(), data.count() ) != -1 ) ;
655 proc->write( d->convertQString( QString(
"%" ) ) );
656 proc->write( d->convertQString( buffer ) );
665 line = d->convertQByteArray(
proc->readLine() );
677 while (
proc->readLine( data.data(), data.count() ) != -1 ) ;
685 d->checkNextTimer->setInterval(0);
686 d->checkNextTimer->setSingleShot(
true);
687 d->checkNextTimer->start();
698 d->checkNextTimer->setInterval(0);
699 d->checkNextTimer->setSingleShot(
true);
700 d->checkNextTimer->start();
707 if (!d->unchecked.empty()) {
708 BufferedWord buf = d->unchecked.front();
709 d->unchecked.pop_front();
714 checkWord( buf.word, buf.useDialog, buf.suggest );
722 line = d->convertQByteArray(
proc->readLine() );
728 while (
proc->readLine( data.data(), data.count() ) != -1 ) ;
753 for(
int i=0; i<word.size(); i++ )
762 for( j = i+1; j < word.size() && word[j] !=
'+' && word[j] !=
'-'; j++ )
767 if ( !( k = qs.lastIndexOf(shorty) ) || k != -1 )
768 qs.remove( k, shorty.length() );
796 if ( buffer[0] ==
'*' || buffer[0] ==
'+' || buffer[0] ==
'-' )
801 if ( buffer[0] ==
'&' || buffer[0] ==
'?' || buffer[0] ==
'#' )
806 word = buffer.mid( 2, buffer.indexOf(
' ', 3 ) -2 );
810 if( d->m_bIgnoreTitleCase && word == word.toUpper() )
813 if( d->m_bIgnoreUpperWords && word[0] == word[0].toUpper() )
815 QString text = word[0] + word.right( word.length()-1 ).toLower();
824 if (
ignorelist.indexOf( word.toLower() ) != -1 )
830 if ( buffer.indexOf(
':' ) != -1 )
831 qs2 = buffer.left( buffer.indexOf(
':') );
835 posinline = qs2.right( qs2.length()-qs2.lastIndexOf(
' ') ).toInt()-1;
850 if ( buffer[0] !=
'#' )
852 QString qs = buffer.mid( buffer.indexOf(
':')+2, buffer.length() );
857 while( i < qs.length() )
859 QString temp = qs.mid( i, (j=qs.indexOf(
',',i)) - i );
866 if ( (sugg.count()==1) && (sugg.first() == word) )
872 if ( buffer.isEmpty() ) {
873 kDebug(750) <<
"Got an empty response: ignoring";
877 kError(750) <<
"HERE?: [" << buffer <<
"]" << endl;
878 kError(750) <<
"Please report this to zack@kde.org" << endl;
879 kError(750) <<
"Thank you!" << endl;
901 proc->write(QByteArray(
'%' ) );
922 d->endOfResponse =
false;
965 tempe =
proc->readLine( data.data(), data.count() );
968 line = d->convertQByteArray( data );
971 d->endOfResponse =
true;
973 }
else if ( tempe>0 ) {
997 d->m_bNoMisspellingsEncountered =
false;
1006 }
while (tempe > 0);
1012 if (d->endOfResponse && !
dlgon) {
1076 if (!d->endOfResponse) {
1091 kDebug(750) <<
"KS: check";
1117 proc->write( QByteArray(
"!" ) );
1154 static bool recursive =
false;
1165 tempe =
proc->readLine( data.data(), data.count() );
1166 line = d->convertQByteArray( data );
1210 d->m_bNoMisspellingsEncountered =
false;
1226 if ( tempe == -1 ) {
1269 disconnect (
this, SIGNAL (
dialog3()),
this, SLOT (
check3()));
1310 kDebug(750) <<
"K3Spell::slotStopCancel [" << result <<
"]";
1328 connect(
ksdlg, SIGNAL(command(
int)),
this, SLOT(
dialog2(
int)) );
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(
"<") );
1339 context.replace(
'>', QLatin1String(
">") );
1340 context.replace( marker, QString::fromLatin1(
"<b>%1</b>").arg( word ) );
1341 context =
"<qt>" + context +
"</qt>";
1344 d->m_bNoMisspellingsEncountered =
false;
1360 disconnect(
ksdlg, SIGNAL(command(
int)),
this, SLOT(
dialog2(
int)) );
1409 delete d->checkNextTimer;
1432 proc->closeWriteChannel();
1461 QTimer::singleShot( 0,
this, SLOT(
emitDeath()) );
1493 QPoint pt( x,y ), pt2;
1494 pt2 =
parent->mapToGlobal( pt );
1495 ksdlg->move( pt2.x(),pt2.y() );
1500 d->m_bIgnoreUpperWords=_ignore;
1505 d->m_bIgnoreTitleCase=_ignore;
1527 0, _kcs,
true,
true );
1530 qApp->processEvents();
1538void K3Spell::slotSpellCheckerCorrected(
const QString & oldText,
const QString & newText,
unsigned int pos )
1540 modaltext=modaltext.replace(pos,oldText.length(),newText);
1544void K3Spell::slotModalReady()
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()) );
1559void K3Spell::slotModalDone(
const QString & )
1569 slotModalSpellCheckerFinished();
1572void K3Spell::slotModalSpellCheckerFinished( )
1579 bool _progressbar,
bool _modal,
SpellerType type )
1581 d =
new K3SpellPrivate;
1583 d->m_bIgnoreUpperWords =
false;
1584 d->m_bIgnoreTitleCase =
false;
1585 d->m_bNoMisspellingsEncountered =
true;
1587 d->checking =
false;
1588 d->aspellV6 =
false;
1589 d->checkNextTimer =
new QTimer(
this );
1590 connect( d->checkNextTimer, SIGNAL(
timeout()),
1611 d->m_codec = QTextCodec::codecForName(
"ISO 8859-1");
1614 d->m_codec = QTextCodec::codecForName(
"ISO 8859-2");
1617 d->m_codec = QTextCodec::codecForName(
"ISO 8859-3");
1620 d->m_codec = QTextCodec::codecForName(
"ISO 8859-4");
1623 d->m_codec = QTextCodec::codecForName(
"ISO 8859-5");
1626 d->m_codec = QTextCodec::codecForName(
"ISO 8859-7");
1629 d->m_codec = QTextCodec::codecForName(
"ISO 8859-8-i");
1632 d->m_codec = QTextCodec::codecForName(
"ISO 8859-9");
1635 d->m_codec = QTextCodec::codecForName(
"ISO 8859-13");
1638 d->m_codec = QTextCodec::codecForName(
"ISO 8859-15");
1641 d->m_codec = QTextCodec::codecForName(
"UTF-8");
1644 d->m_codec = QTextCodec::codecForName(
"KOI8-R");
1647 d->m_codec = QTextCodec::codecForName(
"KOI8-U");
1650 d->m_codec = QTextCodec::codecForName(
"CP1251");
1653 d->m_codec = QTextCodec::codecForName(
"CP1255");
1659 kDebug(750) << __FILE__ <<
":" << __LINE__ <<
" Codec = " << (d->m_codec ? d->m_codec->name() :
"<default>");
1689 connect(
this, SIGNAL(
ready(
K3Spell*)),
this, SLOT(slotModalReady()) );
1700#include "k3spell.moc"
A configuration class/dialog for K3Spell.
QStringList replaceAllList() const
int client() const
Spell checker client,.
void setIgnoreList(const QStringList &_ignorelist)
@sect Options setting routines.
const QString dictionary() const
void setReplaceAllList(const QStringList &_replaceAllList)
The _replaceAllList contains word you like that replace word.
QStringList ignoreList() const
QString replacement() const
void init(const QString &_word, QStringList *_sugg)
Change the misspelled word and suggested replacements and enable the disabled buttons on the dialog b...
virtual bool ignore(const QString &word)
Tells ISpell/ASpell to ignore this word for the life of this K3Spell instance.
void moveDlg(int x, int y)
Moves the dialog.
bool cleanFputs(const QString &s)
K3SpellConfig ksConfig() const
void done(const QString &buffer)
Emitted when check() is done.
void checkListReplaceCurrent()
void dialog(const QString &word, QStringList &sugg, const char *_slot)
QString intermediateBuffer() const
Returns the partially spellchecked buffer.
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...
spellStatus status() const
Returns the status of K3Spell.
virtual void cleanUp()
Cleans up ISpell.
void dialog2(int dlgresult)
QStringList suggestions() const
Returns list of suggested word replacements.
virtual bool checkList(QStringList *_wordlist, bool usedialog=true)
Spellchecks a list of words.
bool cleanFputsWord(const QString &s)
void initialize(QWidget *_parent, const QString &_caption, QObject *obj, const char *slot, K3SpellConfig *_ksc, bool _progressbar, bool _modal, SpellerType type)
K3Spell(QWidget *parent, const QString &caption, QObject *receiver, const char *slot, K3SpellConfig *kcs=0, bool progressbar=true, bool modal=false)
Starts the spellchecker.
void ignoreall(const QString &originalword)
Emitted when the user pressed "Ignore All" in the dialog.
void setIgnoreUpperWords(bool b)
Call setIgnoreUpperWords(true) to tell the spell-checker to ignore words that are completely uppercas...
void setIgnoreTitleCase(bool b)
Call setIgnoreTitleCase(true) to tell the spell-checker to ignore words with a 'title' case,...
int widthDlg() const
Returns the width of the dialog box.
void death()
Emitted on terminal errors and after clean up.
virtual ~K3Spell()
The destructor instructs ISpell/ASpell to write out the personal dictionary and then terminates ISpel...
void replaceall(const QString &origword, const QString &replacement)
Emitted when the user pressed "ReplaceAll" in the dialog.
void hide()
Hides the dialog box.
int dlgResult() const
Gets the result code of the dialog box.
virtual bool addPersonal(const QString &word)
Adds a word to the user's personal dictionary.
static QWidget * modalWidgetHack
bool writePersonalDictionary()
void addword(const QString &originalword)
Emitted when the user pressed "Add" in the dialog.
QString replacement() const
spellStatus
Possible states of the spell checker.
@ FinishedNoMisspellingsEncountered
QString funnyWord(const QString &word)
void misspelling(const QString &originalword, const QStringList &suggestions, unsigned int pos)
Emitted whenever a misspelled word is found by check() or by checkWord().
void progress(unsigned int i)
Emitted during a check().
void ignoreword(const QString &originalword)
Emitted when the user pressed "Ignore" in the dialog.
void setAutoDelete(bool _autoDelete)
Sets the auto-delete flag.
void setUpDialog(bool reallyusedialogbox=true)
void setProgressResolution(unsigned int res)
Sets the resolution (in percent) of the progress() signals.
SpellerType
These are possible types of documents which the spell checker can check.
unsigned int lastlastline
int lastPosition() const
Returns the position (when using check()) or word number (when using checkList()) of the last word ch...
QStringList::Iterator wlIt
bool modaldlg
Used for modalCheck.
int heightDlg() const
Returns the height of the dialog box.
virtual bool check(const QString &_buffer, bool usedialog=true)
Spellchecks a buffer of many words in plain text format.
void ready(K3Spell *)
Emitted after K3Spell has verified that ISpell/ASpell is running and working properly.
int parseOneResponse(const QString &_buffer, QString &word, QStringList &sugg)
virtual bool checkWord(const QString &_buffer, bool usedialog=false)
Spellchecks a single word.
static int modalCheck(QString &text)
virtual void setCaption(const QString &caption)
static void information(QWidget *parent, const QString &text, const QString &caption=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void setNextOpenMode(QIODevice::OpenMode mode)
void setOutputChannelMode(OutputChannelMode mode)
@ KS_E_LATIN7
ISO-8859-6 (Arabic)
@ KS_E_LATIN5
ISO-8859-5 (Cyrillic)
@ KS_E_LATIN8
ISO-8859-7 (Greek)
@ KS_E_LATIN15
ISO-8859-15 (Latin 9)
@ KS_E_LATIN9
ISO-8859-8 (Hebrew)
@ KS_E_LATIN13
ISO-8859-13 (Latin 7)
static bool determineASpellV6()
QString i18n(const char *text)
TransferJob * put(const KUrl &url, int permissions, JobFlags flags=DefaultFlags)