lyx_mirror/src/frontends/controllers/ControlSpellchecker.C

258 lines
4.9 KiB
C++
Raw Normal View History

/* This file is part of
* ======================================================
*
* LyX, The Document Processor
*
* Copyright 2001 The LyX Team.
*
* ======================================================
*
* \file ControlSpellchecker.C
* \author Edwin Leuven <leuven@fee.uva.nl>
*/
#include <config.h>
#ifdef __GNUG__
#pragma implementation
#endif
#include <sys/types.h> // needed by <sys/select.h> at least on freebsd
#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 "buffer.h"
#include "lyxrc.h"
#include "BufferView.h"
#include "LyXView.h"
#include "gettext.h"
#include "support/lstrings.h"
#include "language.h"
#include "ViewBase.h"
#include "ButtonControllerBase.h"
#include "ControlSpellchecker.h"
#include "Dialogs.h"
#include "Liason.h"
# include "sp_ispell.h"
#ifdef USE_PSPELL
# include "sp_pspell.h"
#endif
#include "debug.h"
using SigC::slot;
ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
: ControlDialog<ControlConnectBD>(lv, d),
rtl_(false), newval_(0.0), oldval_(0), newvalue_(0), count_(0),
stop_(false), result_(SpellBase::ISP_OK), speller_(0)
{
d_.showSpellchecker.connect(SigC::slot(this, &ControlSpellchecker::show));
}
void ControlSpellchecker::setParams()
{
if (!speller_) {
// create spell object
string tmp;
#ifdef USE_PSPELL
if (lyxrc.use_pspell) {
tmp = (lyxrc.isp_use_alt_lang) ?
lyxrc.isp_alt_lang : lv_.buffer()->params.language->code();
speller_ = new PSpell(lv_.view()->buffer()->params, tmp);
} else {
#endif
tmp = (lyxrc.isp_use_alt_lang) ?
lyxrc.isp_alt_lang : lv_.buffer()->params.language->lang();
speller_ = new ISpell(lv_.view()->buffer()->params, tmp);
#ifdef USE_PSPELL
}
#endif
if (lyxrc.isp_use_alt_lang) {
Language const * lang = languages.getLanguage(tmp);
if (lang)
rtl_ = lang->RightToLeft();
} else {
rtl_ = lv_.buffer()->params.language->RightToLeft();
}
if (speller_->error() != 0) {
#if 0
message_ = speller_->error();
// show error message
view().partialUpdate(2);
#endif
clearParams();
return;
}
}
}
void ControlSpellchecker::check()
{
result_ = SpellBase::ISP_OK;
stop_ = false;
while ((result_==SpellBase::ISP_OK || result_==SpellBase::ISP_IGNORE) &&
!stop_) {
word_ = lv_.view()->nextWord(newval_);
if (word_.empty()) {
clearParams();
break;
}
++count_;
// Update slider if and only if value has changed
newvalue_ = int(100.0*newval_);
if (newvalue_!= oldval_) {
oldval_ = newvalue_;
// set progress bar
view().partialUpdate(0);
}
if (!speller_->alive()) clearParams();
result_ = speller_->check(word_);
}
if (!stop_ && !word_.empty())
lv_.view()->selectLastWord();
// set suggestions
if (result_!=SpellBase::ISP_OK && result_!=SpellBase::ISP_IGNORE) {
view().partialUpdate(1);
}
}
void ControlSpellchecker::replace(string const & replacement)
{
lv_.view()->replaceWord(replacement);
check();
}
void ControlSpellchecker::replaceAll(string const & replacement)
{
// TODO: add to list
replace(replacement);
}
void ControlSpellchecker::insert()
{
speller_->insert(word_);
check();
}
string ControlSpellchecker::getSuggestion()
{
// this is needed because string tmp = nextmiss()
// segfaults when nextMiss is 0
string tmp;
char const * w = speller_->nextMiss();
if (w!=0) {
tmp = w;
if (rtl_) std::reverse(tmp.begin(), tmp.end());
}
return tmp;
}
string ControlSpellchecker::getWord()
{
string tmp = word_;
if (rtl_) std::reverse(tmp.begin(), tmp.end());
return tmp;
}
void ControlSpellchecker::ignoreAll()
{
speller_->accept(word_);
check();
}
void ControlSpellchecker::stop()
{
stop_ = true;
lv_.view()->endOfSpellCheck();
}
void ControlSpellchecker::clearParams()
{
if (!speller_) return;
if (speller_->alive()) {
speller_->close();
message_ = tostr(count_);
if (count_ != 1) {
message_ += _(" words checked.");
} else {
message_ += _(" word checked.");
}
message_ = "\n" + message_;
message_ = _("Spellchecking completed! ") + message_;
} 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;
}
delete speller_;
lv_.view()->endOfSpellCheck();
// show closing message if any words were checked.
if (count_ > 0)
view().partialUpdate(2);
// reset values to initial
rtl_ = false;
word_.erase();
newval_ = 0.0;
oldval_ = 0;
newvalue_ = 0;
count_ = 0;
message_.erase();
stop_ = false;
result_ = SpellBase::ISP_OK;
speller_ = 0;
}
void ControlSpellchecker::options()
{
lv_.getDialogs()->showSpellcheckerPreferences();
}