/**
* \file ispell.C
- * Copyright 2002 the LyX Team
- * Read the file COPYING
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
*
* \author unknown
- * \author John Levon <levon@movementarian.org>
+ * \author Angus Leeming
+ * \author John Levon
+ *
+ * Full author contact details are available in file CREDITS.
*/
#include <config.h>
-#include "LString.h"
-#include "lyxrc.h"
-#include "language.h"
+#include "ispell.h"
+
+#include "bufferparams.h"
#include "debug.h"
#include "encoding.h"
-#include "ispell.h"
-#include "WordLangTuple.h"
#include "gettext.h"
+#include "language.h"
+#include "lyxrc.h"
+#include "WordLangTuple.h"
#include "support/forkedcall.h"
#include "support/lstrings.h"
+#include "support/unicode.h"
// HP-UX 11.x doesn't have this header
#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
+# include <sys/select.h>
#endif
-#include <sys/time.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
-using namespace lyx::support;
+namespace lyx {
+
+using support::bformat;
+
+using boost::shared_ptr;
#ifndef CXX_GLOBAL_CSTD
using std::strcpy;
using std::strlen;
using std::strpbrk;
-using std::strstr;
#endif
using std::endl;
using std::max;
+using std::string;
+
namespace {
-class LaunchIspell : public lyx::support::ForkedProcess {
+class LaunchIspell : public support::ForkedProcess {
+ typedef support::ForkedProcess ForkedProcess;
public:
///
LaunchIspell(BufferParams const & p, string const & l,
int * in, int * out, int * err)
: params(p), lang(l), pipein(in), pipeout(out), pipeerr(err) {}
///
- virtual lyx::support::ForkedProcess * clone() const {
- return new LaunchIspell(*this);
+ virtual shared_ptr<ForkedProcess> clone() const {
+ return shared_ptr<ForkedProcess>(new LaunchIspell(*this));
}
///
int start();
int LaunchIspell::start()
{
command_ = lyxrc.isp_command;
- return runNonBlocking();
+ return run(DontWait);
}
if (lyxrc.isp_use_input_encoding &&
params.inputenc != "default") {
string enc = (params.inputenc == "auto")
- ? params.language->encoding()->LatexName()
+ ? params.language->encoding()->latexName()
: params.inputenc;
- string::size_type n = enc.length();
+ size_t const n = enc.length();
tmp = new char[3];
string("-T").copy(tmp, 2);
tmp[2] = '\0';
}
+string const to_iconv_encoding(docstring const & s, string const & encoding)
+{
+ if (lyxrc.isp_use_input_encoding) {
+ std::vector<char> const encoded =
+ ucs4_to_eightbit(s.data(), s.length(), encoding);
+ return string(encoded.begin(), encoded.end());
+ }
+ // FIXME UNICODE: we don't need to convert to UTF8, but probably to the locale encoding
+ return to_utf8(s);
+}
+
+
+docstring const from_iconv_encoding(string const & s, string const & encoding)
+{
+ if (lyxrc.isp_use_input_encoding) {
+ std::vector<char_type> const ucs4 =
+ eightbit_to_ucs4(s.data(), s.length(), encoding);
+ return docstring(ucs4.begin(), ucs4.end());
+ }
+ // FIXME UNICODE: s is not in UTF8, but probably the locale encoding
+ return from_utf8(s);
+}
+
} // namespace anon
ISpell::ISpell(BufferParams const & params, string const & lang)
: in(0), out(0), inerr(0), str(0)
{
- lyxerr[Debug::GUI] << "Created ispell" << endl;
+ LYXERR(Debug::GUI) << "Created ispell" << endl;
+
+ encoding = params.encoding().iconvName();
// static due to the setvbuf. Ugly.
static char o_buf[BUFSIZ];
child_.reset(li);
if (li->start() == -1) {
error_ = _("Could not create an ispell process.\nYou may not have "
- " the right languages installed.");
+ "the right languages installed.");
child_.reset(0);
return;
}
- /* Parent process: Read ispells identification message */
+ // Parent process: Read ispells identification message
bool err_read;
bool error = select(err_read);
return;
}
- /* must have read something from stderr */
- error_ = buf;
+ // must have read something from stderr
+ // FIXME UNICODE: buf is not in UTF8, but probably the locale encoding
+ error_ = from_utf8(buf);
} else {
// select returned error
- error_ = _("The spell process returned an error.\nPerhaps "
- "it has been configured wrongly ?");
+ error_ = _("The ispell process returned an error.\nPerhaps "
+ "it has been configured wrongly ?");
}
close(pipein[0]);
ISpell::~ISpell()
{
- lyxerr[Debug::GUI] << "Killing ispell" << endl;
+ LYXERR(Debug::GUI) << "Killing ispell" << endl;
if (in)
fclose(in);
}
-string const ISpell::nextMiss()
+docstring const ISpell::nextMiss()
{
// Well, somebody is a sick fuck.
if (str == 0 || *(e+1) == '\0')
- return "";
+ return docstring();
char * b = e + 2;
e = strpbrk(b, ",\n");
*e = '\0';
if (b)
- return b;
- return "";
+ return from_iconv_encoding(b, encoding);
+ return docstring();
}
Result res;
- ::fputs(word.word().c_str(), out);
+ string const encoded = to_iconv_encoding(word.word(), encoding);
+ if (encoded.empty()) {
+ error_ = bformat(
+ _("Could not check word `%1$s' because it could not be converted to encoding `%2$s'."),
+ word.word(), from_ascii(encoding));
+ return UNKNOWN_WORD;
+ }
+ ::fputs(encoded.c_str(), out);
::fputc('\n', out);
bool err_read;
bool error = select(err_read);
if (error) {
- error_ = _("Could not communicate with the spell-checker program");
- return UNKNOWN;
+ error_ = _("Could not communicate with the ispell spellchecker process.");
+ return UNKNOWN_WORD;
}
if (err_read) {
- error_ = buf;
- return UNKNOWN;
+ // FIXME UNICODE: buf is not in UTF8, but probably the locale encoding
+ error_ = from_utf8(buf);
+ return UNKNOWN_WORD;
}
// I think we have to check if ispell is still alive here because
// the signal-handler could have disabled blocking on the fd
if (!alive())
- return UNKNOWN;
+ return UNKNOWN_WORD;
switch (*buf) {
case '*':
res = ROOT;
break;
case '-':
- res = COMPOUNDWORD;
+ res = COMPOUND_WORD;
break;
case '\n':
- res = IGNORE;
+ res = IGNORED_WORD;
break;
case '#': // Not found, no near misses and guesses
- res = UNKNOWN;
+ res = UNKNOWN_WORD;
break;
case '?': // Not found, and no near misses, but guesses (guesses are ignored)
case '&': // Not found, but we have near misses
{
- res = MISSED;
+ res = SUGGESTED_WORDS;
char * p = strpbrk(buf, ":");
str = new char[strlen(p) + 1];
e = str;
break;
}
default: // This shouldn't happen, but you know Murphy
- res = UNKNOWN;
+ res = UNKNOWN_WORD;
}
*buf = 0;
- if (res != IGNORE) {
+ if (res != IGNORED_WORD) {
/* wait for ispell to finish */
while (*buf!= '\n')
fgets(buf, 255, in);
void ISpell::insert(WordLangTuple const & word)
{
+ string const encoded = to_iconv_encoding(word.word(), encoding);
+ if (encoded.empty()) {
+ error_ = bformat(
+ _("Could not insert word `%1$s' because it could not be converted to encoding `%2$s'."),
+ word.word(), from_ascii(encoding));
+ return;
+ }
::fputc('*', out); // Insert word in personal dictionary
- ::fputs(word.word().c_str(), out);
+ ::fputs(encoded.c_str(), out);
::fputc('\n', out);
}
void ISpell::accept(WordLangTuple const & word)
{
+ string const encoded = to_iconv_encoding(word.word(), encoding);
+ if (encoded.empty()) {
+ error_ = bformat(
+ _("Could not accept word `%1$s' because it could not be converted to encoding `%2$s'."),
+ word.word(), from_ascii(encoding));
+ return;
+ }
::fputc('@', out); // Accept in this session
- ::fputs(word.word().c_str(), out);
+ ::fputs(encoded.c_str(), out);
::fputc('\n', out);
}
-string const ISpell::error()
+docstring const ISpell::error()
{
return error_;
}
+
+
+} // namespace lyx