mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-22 05:16:21 +00:00
spell rework. revert fix
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6191 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
a4e4ebc7eb
commit
47c34c3afa
@ -1,3 +1,13 @@
|
||||
2003-02-17 John Levon <levon@movementarian.org>
|
||||
|
||||
* SpellBase.h:
|
||||
* ispell.h:
|
||||
* ispell.C:
|
||||
* pspell.h:
|
||||
* pspell.C: reworking. Especially in ispell, a large
|
||||
number of clean ups and bug fixes.
|
||||
|
||||
* lyxfunc.C: fix revert to behave sensibly
|
||||
|
||||
2003-02-17 André Pönitz <poenitz@gmx.net>
|
||||
|
||||
|
@ -36,15 +36,9 @@ public:
|
||||
/// return true if the spellchecker instance still exists
|
||||
virtual bool alive() = 0;
|
||||
|
||||
/// clean up on messy exit
|
||||
virtual void cleanUp() = 0;
|
||||
|
||||
/// check the given word of the given lang code and return the result
|
||||
virtual enum Result check(WordLangTuple const &) = 0;
|
||||
|
||||
/// finish this spellchecker instance
|
||||
virtual void close() = 0;
|
||||
|
||||
/// insert the given word into the personal dictionary
|
||||
virtual void insert(WordLangTuple const &) = 0;
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2003-02-17 John Levon <levon@movementarian.org>
|
||||
|
||||
* ControlDialog.tmpl: build dialog before calling setParams
|
||||
for the benefit of ControlSpellchecker
|
||||
|
||||
* ControlSpellchecker.h:
|
||||
* ControlSpellchecker.C: rework. Lots of bugs fixed and
|
||||
cleanups.
|
||||
|
||||
2003-02-14 Juergen Spitzmueller <j.spitzmueller@gmx.de>
|
||||
|
||||
* ControlBibtex.[Ch]: new function getBibFiles() (provides list
|
||||
|
@ -32,17 +32,17 @@ void ControlDialog<Base>::show()
|
||||
|
||||
connect();
|
||||
|
||||
if (!dialog_built_) {
|
||||
view().build();
|
||||
dialog_built_ = true;
|
||||
}
|
||||
|
||||
setParams();
|
||||
if (emergency_exit_) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dialog_built_) {
|
||||
view().build();
|
||||
dialog_built_ = true;
|
||||
}
|
||||
|
||||
bc().readOnly(bufferIsReadonly());
|
||||
view().show();
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "language.h"
|
||||
#include "lyxrc.h"
|
||||
#include "lyxtext.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "ispell.h"
|
||||
#ifdef USE_PSPELL
|
||||
@ -29,17 +30,41 @@
|
||||
|
||||
#include "BoostFormat.h"
|
||||
|
||||
using std::endl;
|
||||
|
||||
ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
|
||||
: ControlDialogBD(lv, d),
|
||||
newval_(0.0), oldval_(0), newvalue_(0), count_(0),
|
||||
stop_(false), speller_(0)
|
||||
newval_(0.0), oldval_(0), newvalue_(0), count_(0)
|
||||
{}
|
||||
|
||||
|
||||
ControlSpellchecker::~ControlSpellchecker()
|
||||
{}
|
||||
|
||||
|
||||
void ControlSpellchecker::setParams()
|
||||
{
|
||||
if (speller_)
|
||||
lyxerr[Debug::GUI] << "spell setParams" << endl;
|
||||
startSession();
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::clearParams()
|
||||
{
|
||||
lyxerr[Debug::GUI] << "spell clearParams" << endl;
|
||||
endSession();
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::startSession()
|
||||
{
|
||||
lyxerr[Debug::GUI] << "spell startSession" << endl;
|
||||
|
||||
if (speller_.get()) {
|
||||
lyxerr[Debug::GUI] << "startSession: speller exists" << endl;
|
||||
speller_.reset(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// create spell object
|
||||
string tmp;
|
||||
@ -48,73 +73,164 @@ void ControlSpellchecker::setParams()
|
||||
tmp = (lyxrc.isp_use_alt_lang) ?
|
||||
lyxrc.isp_alt_lang : buffer()->params.language->code();
|
||||
|
||||
speller_ = new PSpell(buffer()->params, tmp);
|
||||
speller_.reset(new PSpell(buffer()->params, tmp));
|
||||
} else {
|
||||
#endif
|
||||
tmp = (lyxrc.isp_use_alt_lang) ?
|
||||
lyxrc.isp_alt_lang : buffer()->params.language->lang();
|
||||
|
||||
speller_ = new ISpell(buffer()->params, tmp);
|
||||
speller_.reset(new ISpell(buffer()->params, tmp));
|
||||
#ifdef USE_PSPELL
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!speller_->error().empty()) {
|
||||
emergency_exit_ = true;
|
||||
Alert::alert("The spellchecker has failed", speller_->error());
|
||||
clearParams();
|
||||
// reset values to initial
|
||||
newval_ = 0.0;
|
||||
oldval_ = 0;
|
||||
newvalue_ = 0;
|
||||
count_ = 0;
|
||||
emergency_exit_ = false;
|
||||
|
||||
// start off the check
|
||||
if (speller_->error().empty()) {
|
||||
check();
|
||||
return;
|
||||
}
|
||||
|
||||
emergency_exit_ = true;
|
||||
string message = speller_->error();
|
||||
if (message.empty())
|
||||
message = _("The spell-checker could not be started.\n"
|
||||
"Maybe it is mis-configured.");
|
||||
|
||||
Alert::alert(_("The spell-checker has failed"), message);
|
||||
speller_.reset(0);
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::endSession()
|
||||
{
|
||||
lyxerr[Debug::GUI] << "spell endSession" << endl;
|
||||
|
||||
bufferview()->endOfSpellCheck();
|
||||
|
||||
emergency_exit_ = true;
|
||||
|
||||
if (!speller_.get()) {
|
||||
lyxerr[Debug::GUI] << "endSession with no speller" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
speller_.reset(0);
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::check()
|
||||
{
|
||||
lyxerr[Debug::GUI] << "spell check a word" << endl;
|
||||
|
||||
SpellBase::Result res = SpellBase::OK;
|
||||
stop_ = false;
|
||||
|
||||
// clear any old selection
|
||||
LyXText * text = bufferview()->getLyXText();
|
||||
bufferview()->toggleSelection(true);
|
||||
bufferview()->update(text, BufferView::SELECT);
|
||||
|
||||
while ((res == SpellBase::OK || res == SpellBase::IGNORE) && !stop_) {
|
||||
while ((res == SpellBase::OK || res == SpellBase::IGNORE)) {
|
||||
word_ = bufferview()->nextWord(newval_);
|
||||
|
||||
if (word_.word().empty()) {
|
||||
clearParams();
|
||||
// end of document
|
||||
if (word_.word().empty())
|
||||
break;
|
||||
}
|
||||
|
||||
++count_;
|
||||
|
||||
// Update slider if and only if value has changed
|
||||
newvalue_ = int(100.0 * newval_);
|
||||
if (newvalue_!= oldval_) {
|
||||
lyxerr[Debug::GUI] << "Updating spell progress." << endl;
|
||||
oldval_ = newvalue_;
|
||||
// set progress bar
|
||||
view().partialUpdate(0);
|
||||
view().partialUpdate(SPELL_PROGRESSED);
|
||||
}
|
||||
|
||||
if (!speller_ || !speller_->alive()) {
|
||||
clearParams();
|
||||
stop();
|
||||
// speller might be dead ...
|
||||
if (!checkAlive())
|
||||
return;
|
||||
}
|
||||
|
||||
res = speller_->check(word_);
|
||||
|
||||
// ... or it might just be reporting an error
|
||||
if (!checkAlive())
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stop_ && !word_.word().empty())
|
||||
lyxerr[Debug::GUI] << "Found word \"" << word_.word() << "\"" << endl;
|
||||
|
||||
if (!word_.word().empty()) {
|
||||
bufferview()->selectLastWord();
|
||||
} else {
|
||||
showSummary();
|
||||
endSession();
|
||||
return;
|
||||
}
|
||||
|
||||
// set suggestions
|
||||
if (res != SpellBase::OK && res != SpellBase::IGNORE) {
|
||||
view().partialUpdate(1);
|
||||
lyxerr[Debug::GUI] << "Found a word needing checking." << endl;
|
||||
view().partialUpdate(SPELL_FOUND_WORD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ControlSpellchecker::checkAlive()
|
||||
{
|
||||
if (speller_->alive() && speller_->error().empty())
|
||||
return true;
|
||||
|
||||
string message = speller_->error();
|
||||
if (message.empty())
|
||||
message = _("The spell-checker has died for some reason.\n"
|
||||
"Maybe it has been killed.");
|
||||
|
||||
view().hide();
|
||||
speller_.reset(0);
|
||||
|
||||
Alert::alert(_("The spell-checker has failed"), message);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::showSummary()
|
||||
{
|
||||
if (!checkAlive() || count_ == 0) {
|
||||
view().hide();
|
||||
return;
|
||||
}
|
||||
|
||||
string message;
|
||||
|
||||
#if USE_BOOST_FORMAT
|
||||
if (count_ != 1) {
|
||||
boost::format fmter("%1$d words checked.");
|
||||
fmter % count_;
|
||||
message += fmter.str();
|
||||
} else {
|
||||
message += _("One word checked.");
|
||||
}
|
||||
#else
|
||||
if (count_ != 1) {
|
||||
message += tostr(count_) + " words checked";
|
||||
} else {
|
||||
message = _("One word checked.");
|
||||
}
|
||||
#endif
|
||||
|
||||
view().hide();
|
||||
Alert::alert(_("Spell-checking is complete"), message);
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::replace(string const & replacement)
|
||||
{
|
||||
bufferview()->replaceWord(replacement);
|
||||
@ -157,64 +273,3 @@ void ControlSpellchecker::ignoreAll()
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::stop()
|
||||
{
|
||||
stop_ = true;
|
||||
bufferview()->endOfSpellCheck();
|
||||
}
|
||||
|
||||
|
||||
void ControlSpellchecker::clearParams()
|
||||
{
|
||||
if (!speller_)
|
||||
return;
|
||||
|
||||
if (speller_->alive()) {
|
||||
speller_->close();
|
||||
|
||||
message_ = string(_("Spellchecking completed!")) + '\n';
|
||||
|
||||
#if USE_BOOST_FORMAT
|
||||
if (count_ != 1) {
|
||||
boost::format fmter("%1$d words checked.");
|
||||
fmter % count_;
|
||||
message_ += fmter.str();
|
||||
} else {
|
||||
message_ += _("One word checked.");
|
||||
}
|
||||
#else
|
||||
if (count_ != 1) {
|
||||
message_ += tostr(count_) + " words checked";
|
||||
} else {
|
||||
message_ = _("One word checked.");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
message_ = speller_->error();
|
||||
speller_->cleanUp();
|
||||
if (message_.empty())
|
||||
message_ = _("The spell checker has died for some reason.\n"
|
||||
"Maybe it has been killed.");
|
||||
|
||||
// make sure that the dialog is not launched
|
||||
emergency_exit_ = true;
|
||||
Alert::alert("The spellchecker has failed", message_);
|
||||
}
|
||||
|
||||
delete speller_;
|
||||
|
||||
bufferview()->endOfSpellCheck();
|
||||
|
||||
// show closing message if any words were checked.
|
||||
if (count_ > 0)
|
||||
view().partialUpdate(2);
|
||||
|
||||
// reset values to initial
|
||||
newval_ = 0.0;
|
||||
oldval_ = 0;
|
||||
newvalue_ = 0;
|
||||
count_ = 0;
|
||||
message_.erase();
|
||||
stop_ = false;
|
||||
speller_ = 0;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#ifndef CONTROLSPELLCHECKER_H
|
||||
#define CONTROLSPELLCHECKER_H
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include "ControlDialog_impl.h"
|
||||
#include "LString.h"
|
||||
@ -23,9 +24,15 @@ class SpellBase;
|
||||
*/
|
||||
class ControlSpellchecker : public ControlDialogBD {
|
||||
public:
|
||||
///
|
||||
enum State {
|
||||
SPELL_PROGRESSED, //< update progress bar
|
||||
SPELL_FOUND_WORD //< found a bad word
|
||||
};
|
||||
|
||||
ControlSpellchecker(LyXView &, Dialogs &);
|
||||
|
||||
~ControlSpellchecker();
|
||||
|
||||
/// replace word with replacement
|
||||
void replace(string const &);
|
||||
|
||||
@ -38,10 +45,8 @@ public:
|
||||
/// ignore all occurances of word
|
||||
void ignoreAll();
|
||||
|
||||
/// stop checking
|
||||
void stop();
|
||||
|
||||
/// check text until next misspelled/unknown word
|
||||
/// returns true when finished
|
||||
void check();
|
||||
|
||||
/// get suggestion
|
||||
@ -53,13 +58,22 @@ public:
|
||||
/// returns progress value
|
||||
int getProgress() const { return oldval_; }
|
||||
|
||||
/// returns exit message
|
||||
string const getMessage() const { return message_; }
|
||||
|
||||
/// returns word count
|
||||
int getCount() const { return count_; }
|
||||
|
||||
private:
|
||||
/// give error message is spellchecker dies
|
||||
bool checkAlive();
|
||||
|
||||
/// start a spell-checking session
|
||||
void startSession();
|
||||
|
||||
/// end a spell-checking session
|
||||
void endSession();
|
||||
|
||||
/// show count of checked words at normal exit
|
||||
void showSummary();
|
||||
|
||||
/// set the params before show or update
|
||||
void setParams();
|
||||
/// clean-up on hide.
|
||||
@ -79,14 +93,8 @@ private:
|
||||
/// word count
|
||||
int count_;
|
||||
|
||||
/// exit message
|
||||
string message_;
|
||||
|
||||
/// set to true to stop checking
|
||||
bool stop_;
|
||||
|
||||
/// The actual spellchecker object
|
||||
SpellBase * speller_;
|
||||
boost::scoped_ptr<SpellBase> speller_;
|
||||
};
|
||||
|
||||
#endif // CONTROLSPELLCHECKER_H
|
||||
|
@ -1,3 +1,13 @@
|
||||
2003-02-17 John Levon <levon@movementarian.org>
|
||||
|
||||
* QSpellchecker.h:
|
||||
* QSpellchecker.C:
|
||||
* ui/QSpellcheckerDialogBase.ui:
|
||||
* QSpellcheckerDialog.h:
|
||||
* QSpellcheckerDialog.C: re-working, remove start etc.
|
||||
|
||||
* README: add comment about checking accelerators
|
||||
|
||||
2003-02-17 John Levon <levon@movementarian.org>
|
||||
|
||||
* ui/QPrefSpellcheckerModule.ui: capitalization fix
|
||||
|
@ -43,22 +43,6 @@ void QSpellchecker::build_dialog()
|
||||
}
|
||||
|
||||
|
||||
void QSpellchecker::update_contents()
|
||||
{
|
||||
dialog_->wordED->setText("");
|
||||
dialog_->replaceCO->clear();
|
||||
dialog_->suggestionsLB->clear();
|
||||
dialog_->spellcheckPR->setProgress(0);
|
||||
dialog_->spellcheckPB->setEnabled(true);
|
||||
dialog_->wordED->setEnabled(false);
|
||||
dialog_->replaceCO->setEnabled(false);
|
||||
dialog_->replacePB->setEnabled(false);
|
||||
dialog_->ignorePB->setEnabled(false);
|
||||
dialog_->replacePB_3->setEnabled(false);
|
||||
dialog_->addPB->setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
void QSpellchecker::accept()
|
||||
{
|
||||
controller().ignoreAll();
|
||||
@ -83,35 +67,18 @@ void QSpellchecker::replace()
|
||||
}
|
||||
|
||||
|
||||
void QSpellchecker::spellcheck()
|
||||
void QSpellchecker::partialUpdate(int s)
|
||||
{
|
||||
dialog_->spellcheckPB->setEnabled(false);
|
||||
dialog_->wordED->setEnabled(true);
|
||||
dialog_->replaceCO->setEnabled(true);
|
||||
dialog_->replacePB->setEnabled(true);
|
||||
dialog_->ignorePB->setEnabled(true);
|
||||
dialog_->replacePB_3->setEnabled(true);
|
||||
dialog_->addPB->setEnabled(true);
|
||||
controller().check();
|
||||
}
|
||||
ControlSpellchecker::State const state =
|
||||
static_cast<ControlSpellchecker::State>(s);
|
||||
|
||||
switch (state) {
|
||||
|
||||
void QSpellchecker::stop()
|
||||
{
|
||||
controller().stop();
|
||||
dialog_->spellcheckPB->setEnabled(true);
|
||||
hide();
|
||||
}
|
||||
|
||||
|
||||
void QSpellchecker::partialUpdate(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case 0:
|
||||
case ControlSpellchecker::SPELL_PROGRESSED:
|
||||
dialog_->spellcheckPR->setProgress(controller().getProgress());
|
||||
break;
|
||||
|
||||
case 1: {
|
||||
case ControlSpellchecker::SPELL_FOUND_WORD: {
|
||||
dialog_->wordED->setText(toqstr(controller().getWord()));
|
||||
dialog_->suggestionsLB->clear();
|
||||
|
||||
@ -128,12 +95,5 @@ void QSpellchecker::partialUpdate(int id)
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
dialog_->spellcheckPB->setEnabled(true);
|
||||
hide();
|
||||
QMessageBox::information(0, qt_("Spellcheck complete"),
|
||||
toqstr(controller().getMessage()),
|
||||
qt_("OK"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -31,17 +31,15 @@ public:
|
||||
/// update from controller
|
||||
void partialUpdate(int id);
|
||||
private:
|
||||
void stop();
|
||||
void accept();
|
||||
void add();
|
||||
void ignore();
|
||||
void replace();
|
||||
void spellcheck();
|
||||
|
||||
/// Apply changes
|
||||
virtual void apply() {}
|
||||
/// update
|
||||
virtual void update_contents();
|
||||
/// not needed
|
||||
virtual void update_contents() {}
|
||||
/// build the dialog
|
||||
virtual void build_dialog();
|
||||
};
|
||||
|
@ -26,13 +26,7 @@ QSpellcheckerDialog::QSpellcheckerDialog(QSpellchecker * form)
|
||||
form_(form)
|
||||
{
|
||||
connect(closePB, SIGNAL(clicked()),
|
||||
this, SLOT(stop()));
|
||||
}
|
||||
|
||||
|
||||
void QSpellcheckerDialog::stop()
|
||||
{
|
||||
form_->stop();
|
||||
form, SLOT(slotClose()));
|
||||
}
|
||||
|
||||
|
||||
@ -42,12 +36,6 @@ void QSpellcheckerDialog::acceptClicked()
|
||||
}
|
||||
|
||||
|
||||
void QSpellcheckerDialog::spellcheckClicked()
|
||||
{
|
||||
form_->spellcheck();
|
||||
}
|
||||
|
||||
|
||||
void QSpellcheckerDialog::addClicked()
|
||||
{
|
||||
form_->add();
|
||||
@ -95,7 +83,6 @@ void QSpellcheckerDialog::replaceChanged(QString const & str)
|
||||
|
||||
void QSpellcheckerDialog::closeEvent(QCloseEvent * e)
|
||||
{
|
||||
form_->stop();
|
||||
form_->slotWMHide();
|
||||
e->accept();
|
||||
}
|
||||
|
@ -25,9 +25,7 @@ public slots:
|
||||
virtual void suggestionChanged(const QString &);
|
||||
|
||||
protected slots:
|
||||
virtual void stop();
|
||||
virtual void acceptClicked();
|
||||
virtual void spellcheckClicked();
|
||||
virtual void addClicked();
|
||||
virtual void replaceClicked();
|
||||
virtual void ignoreClicked();
|
||||
|
@ -22,6 +22,8 @@ Remember to check tab order on a dialog (third icon, with blue bars in designer)
|
||||
|
||||
Remember to check sensible resizing behaviour on a dialog.
|
||||
|
||||
Remember to use Edit->Check Accelerators
|
||||
|
||||
If necessary, you should override Qt2Base::isValid() for determining the validity
|
||||
of the current dialog's contents.
|
||||
|
||||
|
@ -13,8 +13,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>294</width>
|
||||
<height>379</height>
|
||||
<width>323</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property stdset="1">
|
||||
@ -218,7 +218,7 @@
|
||||
</property>
|
||||
<property stdset="1">
|
||||
<name>text</name>
|
||||
<string>Unknown:</string>
|
||||
<string>Unknown word:</string>
|
||||
</property>
|
||||
<property>
|
||||
<name>buddy</name>
|
||||
@ -263,21 +263,6 @@
|
||||
<string>Replace with selected word</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget row="1" column="2" >
|
||||
<class>QPushButton</class>
|
||||
<property stdset="1">
|
||||
<name>name</name>
|
||||
<cstring>spellcheckPB</cstring>
|
||||
</property>
|
||||
<property stdset="1">
|
||||
<name>text</name>
|
||||
<string>&Start...</string>
|
||||
</property>
|
||||
<property>
|
||||
<name>toolTip</name>
|
||||
<string>Start spellcheck</string>
|
||||
</property>
|
||||
</widget>
|
||||
</grid>
|
||||
</widget>
|
||||
<connections>
|
||||
@ -311,12 +296,6 @@
|
||||
<receiver>QSpellcheckerDialogBase</receiver>
|
||||
<slot>addClicked()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>spellcheckPB</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>QSpellcheckerDialogBase</receiver>
|
||||
<slot>spellcheckClicked()</slot>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>suggestionsLB</sender>
|
||||
<signal>doubleClicked(QListBoxItem*)</signal>
|
||||
@ -335,11 +314,9 @@
|
||||
<slot access="public">optionsClicked()</slot>
|
||||
<slot access="public">replaceChanged(const QString &)</slot>
|
||||
<slot access="public">replaceClicked()</slot>
|
||||
<slot access="public">spellcheckClicked()</slot>
|
||||
<slot access="public">suggestionChanged(const QString &)</slot>
|
||||
</connections>
|
||||
<tabstops>
|
||||
<tabstop>spellcheckPB</tabstop>
|
||||
<tabstop>wordED</tabstop>
|
||||
<tabstop>replaceCO</tabstop>
|
||||
<tabstop>suggestionsLB</tabstop>
|
||||
|
@ -1,3 +1,9 @@
|
||||
2003-02-17 John Levon <levon@movementarian.org>
|
||||
|
||||
* FormSpellchecker.h:
|
||||
* FormSpellchecker.C:
|
||||
* ui/form_spellchecker.fd: rework, remove start, etc.
|
||||
|
||||
2003-02-16 Jean-Marc Lasgouttes <lasgouttes@freesurf.fr>
|
||||
|
||||
* FormPreferences.C (apply): make sure that rc.font_norm_type is
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
|
||||
#include "xformsBC.h"
|
||||
#include "ControlSpellchecker.h"
|
||||
#include "FormSpellchecker.h"
|
||||
#include "ControlSpellchecker.h"
|
||||
#include "forms/form_spellchecker.h"
|
||||
|
||||
#include "forms_gettext.h"
|
||||
@ -23,11 +23,12 @@
|
||||
|
||||
#include FORMS_H_LOCATION
|
||||
|
||||
using std::endl;
|
||||
|
||||
typedef FormCB<ControlSpellchecker, FormDB<FD_spellchecker> > base_class;
|
||||
|
||||
|
||||
FormSpellchecker::FormSpellchecker()
|
||||
: base_class(_("Spellchecker")), state_(STOPPED)
|
||||
: base_class(_("Spellchecker"))
|
||||
{}
|
||||
|
||||
|
||||
@ -61,8 +62,6 @@ void FormSpellchecker::build()
|
||||
tooltips().init(dialog_->browser_suggestions, str);
|
||||
// Work-around xforms' bug; enable tooltips for browser widgets.
|
||||
setPrehandler(dialog_->browser_suggestions);
|
||||
str = _("Start the spellingchecker.");
|
||||
tooltips().init(dialog_->button_start, str);
|
||||
str = _("Replace unknown word.");
|
||||
tooltips().init(dialog_->button_replace, str);
|
||||
str = _("Ignore unknown word.");
|
||||
@ -76,16 +75,14 @@ void FormSpellchecker::build()
|
||||
}
|
||||
|
||||
|
||||
void FormSpellchecker::updateState(State state)
|
||||
void FormSpellchecker::partialUpdate(int s)
|
||||
{
|
||||
switch (state) {
|
||||
case READY_TO_START:
|
||||
fl_set_slider_value(dialog_->slider_progress, 0.0);
|
||||
fl_set_object_label(dialog_->slider_progress, "0 %");
|
||||
break;
|
||||
ControlSpellchecker::State const state =
|
||||
static_cast<ControlSpellchecker::State>(s);
|
||||
|
||||
case CHECKING:
|
||||
{
|
||||
switch (state) {
|
||||
|
||||
case ControlSpellchecker::SPELL_FOUND_WORD: {
|
||||
// Set suggestions.
|
||||
string w = controller().getWord();
|
||||
fl_set_input(dialog_->input_replacement, w.c_str());
|
||||
@ -98,8 +95,7 @@ void FormSpellchecker::updateState(State state)
|
||||
// Fall through...
|
||||
}
|
||||
|
||||
case STARTED:
|
||||
{
|
||||
case ControlSpellchecker::SPELL_PROGRESSED: {
|
||||
int const progress = controller().getProgress();
|
||||
if (progress == 0)
|
||||
break;
|
||||
@ -111,68 +107,17 @@ void FormSpellchecker::updateState(State state)
|
||||
fl_set_slider_bounds(dialog_->slider_progress, 0.0, total);
|
||||
fl_set_slider_value(dialog_->slider_progress, wordcount);
|
||||
fl_set_object_label(dialog_->slider_progress, label.c_str());
|
||||
fl_redraw_object(dialog_->slider_progress);
|
||||
break;
|
||||
}
|
||||
|
||||
case STOPPED:
|
||||
{
|
||||
controller().stop();
|
||||
|
||||
double const wordcount = controller().getCount();
|
||||
|
||||
fl_set_slider_bounds(dialog_->slider_progress, 0.0, wordcount);
|
||||
fl_set_slider_value(dialog_->slider_progress, wordcount);
|
||||
fl_set_object_label(dialog_->slider_progress, "100 %");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool const state_change = state_ != state;
|
||||
state_ = state;
|
||||
|
||||
if (!state_change)
|
||||
return;
|
||||
|
||||
bool const running = (state == STARTED || state == CHECKING);
|
||||
string const label = running ? _("Stop|#S") : _("Start|#S");
|
||||
|
||||
fl_set_object_label(dialog_->button_start, idex(label).c_str());
|
||||
fl_set_button_shortcut(dialog_->button_start, scex(label).c_str(), 1);
|
||||
fl_redraw_object(dialog_->button_start);
|
||||
|
||||
string const tip = running ?
|
||||
_("Stop the spellingchecker.") :
|
||||
_("Start the spellingchecker.");
|
||||
tooltips().init(dialog_->button_start, tip);
|
||||
|
||||
setEnabled(dialog_->button_replace, running);
|
||||
setEnabled(dialog_->button_ignore, running);
|
||||
setEnabled(dialog_->button_accept, running);
|
||||
setEnabled(dialog_->button_add, running);
|
||||
setEnabled(dialog_->browser_suggestions, running);
|
||||
setEnabled(dialog_->input_replacement, running);
|
||||
}
|
||||
|
||||
|
||||
void FormSpellchecker::update()
|
||||
{
|
||||
// clear input fields
|
||||
fl_set_input(dialog_->input_replacement, "");
|
||||
fl_set_object_label(dialog_->text_unknown, "");
|
||||
fl_clear_browser(dialog_->browser_suggestions);
|
||||
|
||||
// reset dialog and buttons into start condition
|
||||
updateState(READY_TO_START);
|
||||
}
|
||||
|
||||
|
||||
ButtonPolicy::SMInput FormSpellchecker::input(FL_OBJECT * ob, long ob_value)
|
||||
{
|
||||
if (ob == dialog_->button_start) {
|
||||
updateState(STARTED);
|
||||
controller().check();
|
||||
|
||||
} else if (ob == dialog_->button_replace) {
|
||||
if (ob == dialog_->button_replace) {
|
||||
string const tmp = getString(dialog_->input_replacement);
|
||||
controller().replace(tmp);
|
||||
|
||||
@ -206,18 +151,3 @@ ButtonPolicy::SMInput FormSpellchecker::input(FL_OBJECT * ob, long ob_value)
|
||||
|
||||
return ButtonPolicy::SMI_VALID;
|
||||
}
|
||||
|
||||
|
||||
void FormSpellchecker::partialUpdate(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case 1:
|
||||
// Set suggestions.
|
||||
updateState(CHECKING);
|
||||
break;
|
||||
case 2:
|
||||
// End of spell checking.
|
||||
updateState(STOPPED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -30,26 +30,14 @@ private:
|
||||
virtual void apply() {}
|
||||
/// Build the dialog
|
||||
virtual void build();
|
||||
///
|
||||
virtual void update();
|
||||
/// not needed.
|
||||
virtual void update() {}
|
||||
|
||||
/// set suggestions and exit message
|
||||
virtual void partialUpdate(int);
|
||||
|
||||
/// Filter the inputs
|
||||
virtual ButtonPolicy::SMInput input(FL_OBJECT *, long);
|
||||
|
||||
///
|
||||
enum State {
|
||||
READY_TO_START,
|
||||
STARTED,
|
||||
CHECKING,
|
||||
STOPPED
|
||||
};
|
||||
///
|
||||
void updateState(State state);
|
||||
///
|
||||
State state_;
|
||||
};
|
||||
|
||||
#endif // FORMSPELLCHECKER_H
|
||||
|
@ -11,7 +11,7 @@ SnapGrid: 5
|
||||
Name: form_spellchecker
|
||||
Width: 385
|
||||
Height: 375
|
||||
Number of Objects: 13
|
||||
Number of Objects: 12
|
||||
|
||||
--------------------
|
||||
class: FL_BOX
|
||||
@ -121,24 +121,6 @@ name: browser_suggestions
|
||||
callback: C_FormBaseInputCB
|
||||
argument: 0
|
||||
|
||||
--------------------
|
||||
class: FL_BUTTON
|
||||
type: NORMAL_BUTTON
|
||||
box: 280 25 100 25
|
||||
boxtype: FL_UP_BOX
|
||||
colors: FL_COL1 FL_COL1
|
||||
alignment: FL_ALIGN_CENTER
|
||||
style: FL_NORMAL_STYLE
|
||||
size: FL_NORMAL_SIZE
|
||||
lcol: FL_BLACK
|
||||
label: Start|#S
|
||||
shortcut:
|
||||
resize: FL_RESIZE_NONE
|
||||
gravity: FL_NorthEast FL_NorthEast
|
||||
name: button_start
|
||||
callback: C_FormBaseInputCB
|
||||
argument: 0
|
||||
|
||||
--------------------
|
||||
class: FL_BUTTON
|
||||
type: NORMAL_BUTTON
|
||||
@ -185,7 +167,7 @@ alignment: FL_ALIGN_CENTER
|
||||
style: FL_NORMAL_STYLE
|
||||
size: FL_NORMAL_SIZE
|
||||
lcol: FL_BLACK
|
||||
label: Accept|#A
|
||||
label: Ignore All|#g
|
||||
shortcut:
|
||||
resize: FL_RESIZE_X
|
||||
gravity: FL_NorthEast FL_NorthEast
|
||||
|
285
src/ispell.C
285
src/ispell.C
@ -9,35 +9,6 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <cstdio>
|
||||
|
||||
// FIXME: do we need any of this horrible gook ?
|
||||
#if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <ctime>
|
||||
#else
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <ctime>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# ifdef HAVE_STRINGS_H
|
||||
// <strings.h> is needed at least on AIX because FD_ZERO uses bzero().
|
||||
// BUT we cannot include both string.h and strings.h on Irix 6.5 :(
|
||||
# ifdef _AIX
|
||||
# include <strings.h>
|
||||
# endif
|
||||
# endif
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#include "LString.h"
|
||||
#include "lyxrc.h"
|
||||
#include "language.h"
|
||||
@ -45,10 +16,13 @@
|
||||
#include "encoding.h"
|
||||
#include "ispell.h"
|
||||
#include "WordLangTuple.h"
|
||||
#include "gettext.h"
|
||||
|
||||
#include "support/forkedcall.h"
|
||||
#include "support/lstrings.h"
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
#ifndef CXX_GLOBAL_CSTD
|
||||
using std::strcpy;
|
||||
using std::strlen;
|
||||
@ -57,18 +31,16 @@ using std::strstr;
|
||||
#endif
|
||||
|
||||
using std::endl;
|
||||
using std::max;
|
||||
|
||||
namespace {
|
||||
|
||||
/// pid for the `ispell' process.
|
||||
pid_t isp_pid = -1;
|
||||
|
||||
class LaunchIspell : public ForkedProcess {
|
||||
public:
|
||||
///
|
||||
LaunchIspell(BufferParams const & p, string const & l,
|
||||
int * in, int * out)
|
||||
: params(p), lang(l), pipein(in), pipeout(out) {}
|
||||
int * in, int * out, int * err)
|
||||
: params(p), lang(l), pipein(in), pipeout(out), pipeerr(err) {}
|
||||
///
|
||||
virtual ForkedProcess * clone() const {
|
||||
return new LaunchIspell(*this);
|
||||
@ -84,6 +56,7 @@ private:
|
||||
string const & lang;
|
||||
int * const pipein;
|
||||
int * const pipeout;
|
||||
int * const pipeerr;
|
||||
};
|
||||
|
||||
|
||||
@ -96,7 +69,7 @@ int LaunchIspell::start()
|
||||
|
||||
int LaunchIspell::generateChild()
|
||||
{
|
||||
isp_pid = fork();
|
||||
pid_t isp_pid = fork();
|
||||
|
||||
if (isp_pid != 0) {
|
||||
// failed (-1) or parent process (>0)
|
||||
@ -106,10 +79,13 @@ int LaunchIspell::generateChild()
|
||||
// child process
|
||||
dup2(pipein[0], STDIN_FILENO);
|
||||
dup2(pipeout[1], STDOUT_FILENO);
|
||||
::close(pipein[0]);
|
||||
::close(pipein[1]);
|
||||
::close(pipeout[0]);
|
||||
::close(pipeout[1]);
|
||||
dup2(pipeerr[1], STDERR_FILENO);
|
||||
close(pipein[0]);
|
||||
close(pipein[1]);
|
||||
close(pipeout[0]);
|
||||
close(pipeout[1]);
|
||||
close(pipeerr[0]);
|
||||
close(pipeerr[1]);
|
||||
|
||||
char * argv[14];
|
||||
int argc = 0;
|
||||
@ -200,122 +176,161 @@ int LaunchIspell::generateChild()
|
||||
|
||||
|
||||
ISpell::ISpell(BufferParams const & params, string const & lang)
|
||||
: str(0)
|
||||
: in(0), out(0), inerr(0), str(0)
|
||||
{
|
||||
static char o_buf[BUFSIZ]; // jc: it could be smaller
|
||||
int pipein[2];
|
||||
int pipeout[2];
|
||||
lyxerr[Debug::GUI] << "Created ispell" << endl;
|
||||
|
||||
isp_pid = -1;
|
||||
// static due to the setvbuf. Ugly.
|
||||
static char o_buf[BUFSIZ];
|
||||
|
||||
// We need to throw an exception not do this
|
||||
pipein[0] = pipein[1] = pipeout[0] = pipeout[1]
|
||||
= pipeerr[0] = pipeerr[1] = -1;
|
||||
|
||||
if (pipe(pipein) == -1 || pipe(pipeout) == -1) {
|
||||
lyxerr << "LyX: Can't create pipe for spellchecker!" << endl;
|
||||
setError();
|
||||
// This is what happens when goto gets banned.
|
||||
|
||||
if (pipe(pipein) == -1) {
|
||||
error_ = _("Can't create pipe for spellchecker.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pipe(pipeout) == -1) {
|
||||
close(pipein[0]);
|
||||
close(pipein[1]);
|
||||
error_ = _("Can't create pipe for spellchecker.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pipe(pipeerr) == -1) {
|
||||
close(pipein[0]);
|
||||
close(pipein[1]);
|
||||
close(pipeout[0]);
|
||||
close(pipeout[1]);
|
||||
error_ = _("Can't create pipe for spellchecker.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((out = fdopen(pipein[1], "w")) == 0) {
|
||||
lyxerr << "LyX: Can't create stream for pipe for spellchecker!"
|
||||
<< endl;
|
||||
setError();
|
||||
error_ = _("Can't open pipe for spellchecker.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((in = fdopen(pipeout[0], "r")) == 0) {
|
||||
lyxerr <<"LyX: Can't create stream for pipe for spellchecker!"
|
||||
<< endl;
|
||||
setError();
|
||||
error_ = _("Can't open pipe for spellchecker.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((inerr = fdopen(pipeerr[0], "r")) == 0) {
|
||||
error_ = _("Can't open pipe for spellchecker.");
|
||||
return;
|
||||
}
|
||||
|
||||
setvbuf(out, o_buf, _IOLBF, BUFSIZ);
|
||||
|
||||
isp_fd = pipeout[0];
|
||||
|
||||
LaunchIspell childprocess(params, lang, pipein, pipeout);
|
||||
isp_pid = childprocess.start();
|
||||
if (isp_pid == -1) {
|
||||
lyxerr << "LyX: Can't create child process for spellchecker!"
|
||||
<< endl;
|
||||
setError();
|
||||
LaunchIspell * li = new LaunchIspell(params, lang, pipein, pipeout, pipeerr);
|
||||
child_.reset(li);
|
||||
if (li->start() == -1) {
|
||||
error_ = _("Could not create an ispell process.\nYou may not have "
|
||||
" the right languages installed.");
|
||||
child_.reset(0);
|
||||
return;
|
||||
}
|
||||
|
||||
setError();
|
||||
/* Parent process: Read ispells identification message */
|
||||
// Hmm...what are we using this id msg for? Nothing? (Lgb)
|
||||
// Actually I used it to tell if it's truly Ispell or if it's
|
||||
// aspell -- (kevinatk@home.com)
|
||||
// But no code actually used the results for anything useful
|
||||
// so I removed it again. Perhaps we can remove this code too.
|
||||
// - jbl
|
||||
char buf[2048];
|
||||
fd_set infds;
|
||||
struct timeval tv;
|
||||
int retval = 0;
|
||||
FD_ZERO(&infds);
|
||||
FD_SET(pipeout[0], &infds);
|
||||
tv.tv_sec = 15; // fifteen second timeout. Probably too much,
|
||||
// but it can't really hurt.
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// Configure provides us with macros which are supposed to do
|
||||
// the right typecast.
|
||||
retval = select(SELECT_TYPE_ARG1 (pipeout[0]+1),
|
||||
SELECT_TYPE_ARG234 (&infds),
|
||||
0,
|
||||
0,
|
||||
SELECT_TYPE_ARG5 (&tv));
|
||||
bool err_read;
|
||||
bool error = select(err_read);
|
||||
|
||||
if (retval > 0) {
|
||||
// Ok, do the reading. We don't have to FD_ISSET since
|
||||
// there is only one fd in infds.
|
||||
fgets(buf, 2048, in);
|
||||
if (!error) {
|
||||
if (!err_read) {
|
||||
// Set terse mode (silently accept correct words)
|
||||
fputs("!\n", out);
|
||||
return;
|
||||
}
|
||||
|
||||
fputs("!\n", out); // Set terse mode (silently accept correct words)
|
||||
|
||||
} else if (retval == 0) {
|
||||
// timeout. Give nice message to user.
|
||||
lyxerr << "Ispell read timed out, what now?" << endl;
|
||||
// This probably works but could need some thought
|
||||
isp_pid = -1;
|
||||
::close(pipeout[0]);
|
||||
::close(pipeout[1]);
|
||||
::close(pipein[0]);
|
||||
::close(pipein[1]);
|
||||
isp_fd = -1;
|
||||
/* must have read something from stderr */
|
||||
error_ = buf;
|
||||
} else {
|
||||
// Select returned error
|
||||
lyxerr << "Select on ispell returned error, what now?" << endl;
|
||||
// select returned error
|
||||
error_ = _("The spell process returned an error.\nPerhaps "
|
||||
"it has been configured wrongly ?");
|
||||
}
|
||||
|
||||
close(pipein[0]);
|
||||
close(pipein[1]);
|
||||
close(pipeout[0]);
|
||||
close(pipeout[1]);
|
||||
close(pipeerr[0]);
|
||||
close(pipeerr[1]);
|
||||
child_->kill();
|
||||
child_.reset(0);
|
||||
}
|
||||
|
||||
|
||||
ISpell::~ISpell()
|
||||
{
|
||||
delete[] str;
|
||||
lyxerr[Debug::GUI] << "Killing ispell" << endl;
|
||||
|
||||
if (in)
|
||||
fclose(in);
|
||||
|
||||
if (inerr)
|
||||
fclose(inerr);
|
||||
|
||||
if (out) {
|
||||
fputs("#\n", out); // Save personal dictionary
|
||||
|
||||
fflush(out);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
close(pipein[0]);
|
||||
close(pipein[1]);
|
||||
close(pipeout[0]);
|
||||
close(pipeout[1]);
|
||||
close(pipeerr[0]);
|
||||
close(pipeerr[1]);
|
||||
delete [] str;
|
||||
}
|
||||
|
||||
|
||||
void ISpell::setError()
|
||||
bool ISpell::select(bool & err_read)
|
||||
{
|
||||
if (isp_pid == -1) {
|
||||
error_ =
|
||||
"\n\n"
|
||||
"The spellcheck-process has died for some reason.\n"
|
||||
"*One* possible reason could be that you do not have\n"
|
||||
"a dictionary file for the language of this document\n"
|
||||
"installed.\n"
|
||||
"Check your spellchecker or set another dictionary\n"
|
||||
"in the Spellchecker Options menu.\n\n";
|
||||
} else {
|
||||
error_ = 0;
|
||||
fd_set infds;
|
||||
struct timeval tv;
|
||||
int retval = 0;
|
||||
FD_ZERO(&infds);
|
||||
FD_SET(pipeout[0], &infds);
|
||||
FD_SET(pipeerr[0], &infds);
|
||||
tv.tv_sec = 2;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
retval = ::select(SELECT_TYPE_ARG1 (max(pipeout[0], pipeerr[0]) + 1),
|
||||
SELECT_TYPE_ARG234 (&infds),
|
||||
0,
|
||||
0,
|
||||
SELECT_TYPE_ARG5 (&tv));
|
||||
|
||||
// error
|
||||
if (retval <= 0)
|
||||
return true;
|
||||
|
||||
if (FD_ISSET(pipeerr[0], &infds)) {
|
||||
fgets(buf, BUFSIZ, inerr);
|
||||
err_read = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
fgets(buf, BUFSIZ, in);
|
||||
err_read = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
string const ISpell::nextMiss()
|
||||
{
|
||||
// Well, somebody is a sick fuck.
|
||||
|
||||
if (str == 0 || *(e+1) == '\0')
|
||||
return "";
|
||||
char * b = e + 2;
|
||||
@ -329,13 +344,7 @@ string const ISpell::nextMiss()
|
||||
|
||||
bool ISpell::alive()
|
||||
{
|
||||
return isp_pid != -1;
|
||||
}
|
||||
|
||||
|
||||
void ISpell::cleanUp()
|
||||
{
|
||||
::fclose(out);
|
||||
return child_.get() && child_->running();
|
||||
}
|
||||
|
||||
|
||||
@ -348,8 +357,18 @@ enum ISpell::Result ISpell::check(WordLangTuple const & word)
|
||||
::fputs(word.word().c_str(), out);
|
||||
::fputc('\n', out);
|
||||
|
||||
char buf[1024];
|
||||
::fgets(buf, 1024, in);
|
||||
bool err_read;
|
||||
bool error = select(err_read);
|
||||
|
||||
if (error) {
|
||||
error_ = _("Could not communicate with the spell-checker program");
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
if (err_read) {
|
||||
error_ = buf;
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
// I think we have to check if ispell is still alive here because
|
||||
// the signal-handler could have disabled blocking on the fd
|
||||
@ -396,20 +415,6 @@ enum ISpell::Result ISpell::check(WordLangTuple const & word)
|
||||
}
|
||||
|
||||
|
||||
void ISpell::close()
|
||||
{
|
||||
// Note: If you decide to optimize this out when it is not
|
||||
// needed please note that when Aspell is used this command
|
||||
// is also needed to save the replacement dictionary.
|
||||
// -- Kevin Atkinson (kevinatk@home.com)
|
||||
|
||||
fputs("#\n", out); // Save personal dictionary
|
||||
|
||||
fflush(out);
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
|
||||
void ISpell::insert(WordLangTuple const & word)
|
||||
{
|
||||
::fputc('*', out); // Insert word in personal dictionary
|
||||
@ -428,7 +433,5 @@ void ISpell::accept(WordLangTuple const & word)
|
||||
|
||||
string const ISpell::error()
|
||||
{
|
||||
if (error_)
|
||||
return error_;
|
||||
return "";
|
||||
return error_;
|
||||
}
|
||||
|
35
src/ispell.h
35
src/ispell.h
@ -10,11 +10,14 @@
|
||||
#ifndef SP_ISPELL_H
|
||||
#define SP_ISPELL_H
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "SpellBase.h"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
class BufferParams;
|
||||
class ForkedProcess;
|
||||
|
||||
/// i/a spell process-based spellchecker
|
||||
class ISpell : public SpellBase {
|
||||
@ -26,15 +29,9 @@ public:
|
||||
/// return true if the spellchecker instance still exists
|
||||
virtual bool alive();
|
||||
|
||||
/// clean up on messy exit
|
||||
virtual void cleanUp();
|
||||
|
||||
/// check the given word and return the result
|
||||
virtual enum Result check(WordLangTuple const & word);
|
||||
|
||||
/// finish this spellchecker instance
|
||||
virtual void close();
|
||||
|
||||
/// insert the given word into the personal dictionary
|
||||
virtual void insert(WordLangTuple const & word);
|
||||
|
||||
@ -48,17 +45,29 @@ public:
|
||||
virtual string const error();
|
||||
|
||||
private:
|
||||
///
|
||||
void setError();
|
||||
/// read some data. Returns true on an error. Sets err_read
|
||||
/// to true if the data was from stderr.
|
||||
bool select(bool & err_read);
|
||||
|
||||
/// instream to communicate with ispell
|
||||
FILE * in;
|
||||
/// outstream to communicate with ispell
|
||||
FILE * out;
|
||||
/// errstream for ispell
|
||||
FILE * inerr;
|
||||
|
||||
/// pipe fds
|
||||
int pipein[2];
|
||||
int pipeout[2];
|
||||
int pipeerr[2];
|
||||
|
||||
/// buffer for reading
|
||||
char buf[BUFSIZ];
|
||||
|
||||
/// spell error
|
||||
char const * error_;
|
||||
/// the fd of the outgoing pipe
|
||||
int isp_fd;
|
||||
string error_;
|
||||
|
||||
boost::scoped_ptr<ForkedProcess> child_;
|
||||
|
||||
// vileness below ... please FIXME
|
||||
/// str ???
|
||||
|
@ -454,6 +454,9 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & ev) const
|
||||
case LFUN_VC_HISTORY:
|
||||
disable = !buf->lyxvc.inUse();
|
||||
break;
|
||||
case LFUN_MENURELOAD:
|
||||
disable = buf->isUnnamed() || buf->isClean();
|
||||
break;
|
||||
case LFUN_BOOKMARK_GOTO:
|
||||
disable = !view()->
|
||||
isSavedPosition(strToUnsignedInt(ev.argument));
|
||||
|
35
src/pspell.C
35
src/pspell.C
@ -12,6 +12,7 @@
|
||||
#ifdef USE_PSPELL
|
||||
|
||||
#include "support/LAssert.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define USE_ORIGINAL_MANAGER_FUNCS 1
|
||||
// new aspell pspell missing extern "C"
|
||||
@ -22,38 +23,39 @@ extern "C" {
|
||||
#include "pspell.h"
|
||||
#include "WordLangTuple.h"
|
||||
|
||||
using std::endl;
|
||||
|
||||
PSpell::PSpell(BufferParams const &, string const & lang)
|
||||
: els(0), spell_error_object(0)
|
||||
{
|
||||
addManager(lang);
|
||||
lyxerr[Debug::GUI] << "created pspell" << endl;
|
||||
}
|
||||
|
||||
|
||||
PSpell::~PSpell()
|
||||
{
|
||||
cleanUp();
|
||||
close();
|
||||
lyxerr[Debug::GUI] << "killed pspell" << endl;
|
||||
|
||||
if (spell_error_object) {
|
||||
delete_pspell_can_have_error(spell_error_object);
|
||||
spell_error_object = 0;
|
||||
}
|
||||
|
||||
if (els)
|
||||
delete_pspell_string_emulation(els);
|
||||
|
||||
Managers::iterator it = managers_.begin();
|
||||
Managers::iterator end = managers_.end();
|
||||
|
||||
for (; it != end; ++it) {
|
||||
pspell_manager_save_all_word_lists(it->second.manager);
|
||||
delete_pspell_manager(it->second.manager);
|
||||
delete_pspell_config(it->second.config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSpell::cleanUp()
|
||||
{
|
||||
if (spell_error_object) {
|
||||
delete_pspell_can_have_error(spell_error_object);
|
||||
spell_error_object = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSpell::addManager(string const & lang)
|
||||
{
|
||||
PspellConfig * config = new_pspell_config();
|
||||
@ -108,17 +110,6 @@ enum PSpell::Result PSpell::check(WordLangTuple const & word)
|
||||
}
|
||||
|
||||
|
||||
void PSpell::close()
|
||||
{
|
||||
Managers::iterator it = managers_.begin();
|
||||
Managers::iterator end = managers_.end();
|
||||
|
||||
for (; it != end; ++it) {
|
||||
pspell_manager_save_all_word_lists(it->second.manager);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSpell::insert(WordLangTuple const & word)
|
||||
{
|
||||
Managers::iterator it = managers_.find(word.lang_code());
|
||||
|
@ -37,15 +37,9 @@ public:
|
||||
*/
|
||||
virtual bool alive() { return true; }
|
||||
|
||||
/// clean up on messy exit
|
||||
virtual void cleanUp();
|
||||
|
||||
/// check the given word and return the result
|
||||
virtual enum Result check(WordLangTuple const &);
|
||||
|
||||
/// finish this spellchecker instance
|
||||
virtual void close();
|
||||
|
||||
/// insert the given word into the personal dictionary
|
||||
virtual void insert(WordLangTuple const &);
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2003-02-17 John Levon <levon@movementarian.org>
|
||||
|
||||
* forkedcall.h:
|
||||
* forkedcall.C: add running()
|
||||
|
||||
2003-02-08 John Levon <levon@movementarian.org>
|
||||
|
||||
* Makefile.am:
|
||||
|
@ -143,6 +143,24 @@ int ForkedProcess::runNonBlocking()
|
||||
return retval_;
|
||||
}
|
||||
|
||||
|
||||
bool ForkedProcess::running() const
|
||||
{
|
||||
if (!pid())
|
||||
return false;
|
||||
|
||||
// Un-UNIX like, but we don't have much use for
|
||||
// knowing if a zombie exists, so just reap it first.
|
||||
int waitstatus;
|
||||
waitpid(pid(), &waitstatus, WNOHANG);
|
||||
|
||||
// Racy of course, but it will do.
|
||||
if (::kill(pid(), 0) && errno == ESRCH)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ForkedProcess::kill(int tol)
|
||||
{
|
||||
lyxerr << "ForkedProcess::kill(" << tol << ')' << endl;
|
||||
|
@ -94,6 +94,9 @@ public:
|
||||
/// Returns the identifying command (for display in the GUI perhaps).
|
||||
string const & command() const { return command_; }
|
||||
|
||||
/// is the process running ?
|
||||
bool running() const;
|
||||
|
||||
/** Kill child prematurely.
|
||||
* First, a SIGHUP is sent to the child.
|
||||
* If that does not end the child process within "tolerance"
|
||||
|
Loading…
Reference in New Issue
Block a user