[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    kdelibs/kdeui
From:       Don Sanders <don () sanders ! org>
Date:       2004-11-25 6:28:56
Message-ID: 20041125062856.339A51CF56 () office ! kde ! org
[Download RAW message or body]

CVS commit by sanders: 

Make as-you-type spell checking work with aspell.

Also replace some QTimer::singleShot calls with a standard QTimer, this
probably won't change the semantics of the code but I'm paranoid about
a race condition causing the slot associated with the timer to be called
multiple times (erroneously).

I checked to make sure that I didn't break normal spell checking.

Basically the problem is that aspell has a habit of emitting spurious
white space to stdout. This breaks the inter process
communication (IPC) between kspell.cpp and the spell process.

The IPC between kspell.cpp and the spell process is fragile. kspell.cpp
uses a pair of macros OUTPUT and NOOUTPUT to hook and unhook the
readReady signal from the spell process to a slot in kspell.cpp. This is
fragile because if the spell process emits data to stdout when the
readReady signal is not hooked up to any slot (which happens due to
the spurious emissions by aspell) then the KProcIO instance
managing the spell process will emit a readyRead signal and then not
emit a further readyRead signal until the data that is ready for reading
is read by kspell.cpp. Unfortunately due to the fragile logic of kspell.cpp
this will never happen (because the emission occurred outside of a
OUTPUT/NOOUTPUT connect/disconnect pair).

Thus before kspell.cpp pipes a word into the stdin of the spell process for
checking it must flush any data that has been written to stdout by the
spell process and buffered by KProcIO.


  M +18 -5     kspell.cpp   1.130


--- kdelibs/kdeui/kspell.cpp  #1.129:1.130
@@ -76,4 +76,5 @@ public:
   bool checking;
   QValueList<BufferedWord> unchecked;
+  QTimer *checkNextTimer;
 };
 
@@ -435,5 +436,5 @@ bool KSpell::checkWord( const QString & 
 
   if ( qs.find (' ') != -1 || qs.isEmpty() ) {   // make sure it's a _word_
-    QTimer::singleShot( 0, this, SLOT(checkNext()) );
+    d->checkNextTimer->start( 0, true );
     return false;
   }
@@ -450,4 +451,7 @@ bool KSpell::checkWord( const QString & 
     ksdlg->hide();
 
+  QString blank_line;
+  while (proc->readln( blank_line, true ) != -1); // eat spurious blanks
+
   OUTPUT(checkWord2);
   //  connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
@@ -474,5 +478,5 @@ bool KSpell::checkWord( const QString & 
 
   if ( qs.find (' ') != -1 || qs.isEmpty() ) {   // make sure it's a _word_
-    QTimer::singleShot( 0, this, SLOT(checkNext()) );
+    d->checkNextTimer->start( 0, true );
     return false;
   }
@@ -490,4 +494,8 @@ bool KSpell::checkWord( const QString & 
       ksdlg->hide();
   }
+  
+  QString blank_line;
+  while (proc->readln( blank_line, true ) != -1); // eat spurious blanks
+
   OUTPUT(checkWord2);
   //  connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
@@ -523,5 +531,5 @@ void KSpell::checkWord2( KProcIO* )
     cwword = word;
     dialog( word, sugg, SLOT(checkWord3()) );
-    QTimer::singleShot( 0, this, SLOT(checkNext()) );
+    d->checkNextTimer->start( 0, true );
     return;
   }
@@ -534,5 +542,5 @@ void KSpell::checkWord2( KProcIO* )
   //so that the calling program knows when the check is complete
   emit corrected( word, word, 0L );
-  QTimer::singleShot( 0, this, SLOT(checkNext()) );
+  d->checkNextTimer->start( 0, true );
 }
 
@@ -544,4 +552,5 @@ void KSpell::checkNext()
     BufferedWord buf = d->unchecked.front();
     d->unchecked.pop_front();
+    
     if (buf.method == Method1)
       checkWord( buf.word, buf.useDialog );
@@ -1226,4 +1235,5 @@ KSpell::~KSpell()
   delete ksconfig;
   delete ksdlg;
+  delete d->checkNextTimer;
   delete d;
 }
@@ -1399,4 +1409,7 @@ void KSpell::initialize( QWidget *_paren
   d->type = type;
   d->checking = false;
+  d->checkNextTimer = new QTimer( this );
+  connect( d->checkNextTimer, SIGNAL( timeout() ),
+           this, SLOT( checkNext() ));
   autoDelete = false;
   modaldlg = _modal;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic