(static_cast<int>(uc1) | static_cast<int>(uc2));
}
+
bool BufferView::dispatch(kb_action action, string const & argument)
{
return pimpl_->dispatch(action, argument);
// -*- C++ -*-
-/** \file
- * Copyright 2002 the LyX Team
- * Read the file COPYING
+/**
+ * \file BufferView.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
*
* \author Lars Gullik Bjønnes
*/
// Copyright CHT Software Service GmbH
// Uwe C. Schroeder
//
- // Insert a Lyxformat - file into current buffer
+ // Insert a LyXformat - file into current buffer
//
// Moved from lyx_cb.C (Lgb)
{
break;
case LFUN_GOTONOTE:
- gotoInset(Inset::IGNORE_CODE, false);
+ gotoInset(Inset::NOTE_CODE, false);
break;
case LFUN_REFERENCE_GOTO:
}
break;
- case LFUN_INSET_TABULAR:
+ case LFUN_TABULAR_INSERT:
{
+ if (argument.empty()) {
+ owner_->getDialogs()->showTabularCreate();
+ break;
+ }
+
int r = 2;
int c = 2;
- if (!argument.empty())
- ::sscanf(argument.c_str(),"%d%d", &r, &c);
+ ::sscanf(argument.c_str(),"%d%d", &r, &c);
InsetTabular * new_inset =
new InsetTabular(*buffer_, r, c);
bool const rtl =
+2002-08-04 John Levon <levon@movementarian.org>
+
+ * BufferView.h:
+ * BufferView.C: cosmetic change
+
+ * BufferView_pimpl.C: s/IGNORE_CODE/NOTE_CODE/
+
+ * bufferlist.C:
+ * buffer.h:
+ * buffer.C:
+ * lyxcb.h:
+ * lyxcb.C:
+ * lyxserver.C:
+ * lyxvc.C:
+ * vc-backend.C:
+ * BufferView2.C: purge all "Lyx" not "LyX" strings
+
+ * lyxcursor.h:
+ * lyxcursor.C: attempt to add some documentation
+
+ * lyxfunc.C:
+ * commandtags.h:
+ * LyXAction.C:
+ * ToolbarDefaults.C:
+ * BufferView_pimpl.C: remove LFUN_DIALOG_TABULAR_INSERT and
+ merge with LFUN_TABULAR_INSERT
+
+ * Makefile.am:
+ * SpellBase.h:
+ * ispell.h:
+ * ispell.C:
+ * pspell.h:
+ * pspell.C: split up i/pspell implementations into separate
+ files, many cleanups
+
+ * lyxlex.C: unrevert, with a proper fix for prefix.length() == 0
+
+ * text2.C: some cleanup
+
+ * lyxfunc.C: don't check for isp_command == "none" any more, it
+ didn't make any sense
+
2002-08-02 John Levon <levon@movementarian.org>
* buffer.C: s/lyxconvert/lyx2lyx/
{ LFUN_SHIFT_TAB, "tab-backward", "", Noop },
{ LFUN_TAB, "tab-forward", "", Noop },
{ LFUN_TABINSERT, "tab-insert", "", Noop },
- { LFUN_DIALOG_TABULAR_INSERT, "dialog-tabular-insert",
- N_("Insert Table"), Noop },
+ { LFUN_TABULAR_INSERT, "table-insert", N_("Insert Table"), Noop },
{ LFUN_TABULAR_FEATURE, "tabular-feature",
N_("Tabular Features"), Noop },
- { LFUN_INSET_TABULAR, "tabular-insert",
- N_("Insert a new Tabular Inset"), Noop },
#if 0
{ LFUN_INSET_THEOREM, "theorem-insert", "", Noop },
#endif
paragraph.h \
paragraph_pimpl.C \
paragraph_pimpl.h \
- sp_base.h \
- sp_spell.C \
- sp_ispell.h \
- sp_pspell.h \
+ SpellBase.h \
+ ispell.h \
+ ispell.C \
+ pspell.h \
+ pspell.C \
tabular.C \
tabular.h \
tabular-old.C \
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file SpellBase.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author unknown
+ */
+
+#ifndef SPELL_BASE_H
+#define SPELL_BASE_H
+
+#include "LString.h" // can't forward declare...
+
+class BufferParams;
+
+/**
+ * Base class of all spell checker implementations.
+ */
+class SpellBase {
+public:
+
+ /// the result from checking a single word
+ enum Result {
+ OK = 1, //< word is correct
+ ROOT, //< root of given word was found
+ COMPOUNDWORD, //< word found through compound formation
+ UNKNOWN, //< word not found
+ MISSED, //< not found, with suggestions
+ IGNORE //< number of other ignored "word"
+ };
+
+ virtual ~SpellBase() {}
+
+ /// 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 and return the result
+ virtual enum Result check(string const &) = 0;
+
+ /// finish this spellchecker instance
+ virtual void close() = 0;
+
+ /// insert the given word into the personal dictionary
+ virtual void insert(string const &) = 0;
+
+ /// accept the given word temporarily
+ virtual void accept(string const &) = 0;
+
+ /// return the next near miss after a MISSED result
+ virtual string const nextMiss() = 0;
+
+ /// give an error message on messy exit
+ virtual string const error() = 0;
+
+};
+
+#endif // SPELL_BASE_H
add(SEPARATOR);
add(LFUN_INSET_GRAPHICS);
- add(LFUN_DIALOG_TABULAR_INSERT);
+ add(LFUN_TABULAR_INSERT);
}
}
if (writeFile(fileName())) {
- markLyxClean();
+ markClean();
removeAutosaveFile(fileName());
} else {
// Saving failed, so backup is not backup
class Language;
class ParIterator;
-// When lyx 1.3.x starts we should enable this
-// btw. we should also test this with 1.2 so that we
-// do not get any surprises. (Lgb)
#define NO_COMPABILITY 1
///
Language const * getLanguage() const;
///
int runChktex();
- ///
- bool isLyxClean() const;
+ /// return true if the main lyx file does not need saving
+ bool isClean() const;
///
bool isBakClean() const;
///
bool isDepClean(string const & name) const;
- ///
- void markLyxClean() const;
+ /// mark the main lyx file as not needing saving
+ void markClean() const;
///
void markBakClean();
}
return tmp;
}
+
///
Inset * operator*() { return *it; }
inline
-bool Buffer::isLyxClean() const
+bool Buffer::isClean() const
{
return lyx_clean;
}
inline
-void Buffer::markLyxClean() const
+void Buffer::markClean() const
{
if (!lyx_clean) {
lyx_clean = true;
BufferStorage::iterator it = bstore.begin();
BufferStorage::iterator end = bstore.end();
for (; it != end; ++it) {
- if (!(*it)->isLyxClean()) {
+ if (!(*it)->isClean()) {
string fname;
if ((*it)->isUnnamed())
fname = OnlyFilename((*it)->fileName());
if (buf->getUser())
buf->getUser()->insetUnlock();
- if (buf->paragraph && !buf->isLyxClean() && !quitting) {
+ if (buf->paragraph && !buf->isClean() && !quitting) {
if (buf->getUser())
buf->getUser()->owner()->prohibitInput();
string fname;
// No need to save if the buffer has not changed.
- if (buf->isLyxClean())
+ if (buf->isClean())
return;
lyxerr << fmt(_("lyx: Attempting to save document %s as..."),
s += ".emergency";
lyxerr << " " << s << endl;
if (buf->writeFile(s)) {
- buf->markLyxClean();
+ buf->markClean();
lyxerr << _(" Save seems successful. Phew.") << endl;
return;
} else {
s += ".emergency";
lyxerr << " " << s << endl;
if (buf->writeFile(s)) {
- buf->markLyxClean();
+ buf->markClean();
lyxerr << _(" Save seems successful. Phew.") << endl;
return;
}
s += ".emergency";
lyxerr << " " << s << endl;
if (buf->writeFile(s)) {
- buf->markLyxClean();
+ buf->markClean();
lyxerr << _(" Save seems successful. Phew.") << endl;
return;
}
LFUN_INSET_GRAPHICS, // Lgb 20000226
LFUN_INSET_FOOTNOTE, // Jug 20000307
LFUN_PARAGRAPH_SPACING, // Lgb 20000411
- LFUN_INSET_TABULAR, // Jug 20000412
+ LFUN_TABULAR_INSERT, // Jug 20000412
LFUN_LOFVIEW, // 230 // Dekel 20000519
LFUN_LOTVIEW, // Dekel 20000519
LFUN_LOAVIEW, // Dekel 20000519
LFUN_UPDATE, // Dekel 20000805
LFUN_INDEX_INSERT, // Angus 20000803
LFUN_SCREEN_FONT_UPDATE, // ARRae 20000813
- LFUN_DIALOG_TABULAR_INSERT, // 250 // Jug 20000825 (old table-insert)
LFUN_GOTO_PARAGRAPH, // Dekel 20000826
LFUN_REFERENCE_GOTO, // Dekel 20010114
LFUN_BOOKMARK_SAVE, // Dekel 20010127
+2002-08-04 John Levon <levon@movementarian.org>
+
+ * LyXView.C: isLyxClean->isClean
+
2002-08-02 Edwin Leuven <leuven@fee.uva.nl>
* Dialogs.[Ch] (updateParagraph): converted back to a signal again.
string const cur_title = buffer()->fileName();
if (!cur_title.empty()) {
title += ": " + MakeDisplayPath(cur_title, 30);
- if (!buffer()->isLyxClean())
+ if (!buffer()->isClean())
title += _(" (changed)");
if (buffer()->isReadonly())
title += _(" (read only)");
+2002-08-04 John Levon <levon@movementarian.org>
+
+ * ControlSpellchecker.h:
+ * ControlSpellchecker.C: some cleanups
+
+ * ControlTabularCreate.C: s/LFUN_INSET_TABULAR/LFUN_TABULAR_INSERT/
+
2002-08-02 Edwin Leuven <leuven@fee.uva.nl>
* ControlParagraph.[Ch] (changedParagraph): new method invoked when
-/* This file is part of
- * ======================================================
- *
- * LyX, The Document Processor
- *
- * Copyright 2001 The LyX Team.
- *
- * ======================================================
- *
+/**
* \file ControlSpellchecker.C
+ * Copyright 2001 the LyX Team
+ * Read the file COPYING
+ *
* \author Edwin Leuven <leuven@fee.uva.nl>
*/
#include "support/lstrings.h"
-# include "sp_ispell.h"
+#include "ispell.h"
#ifdef USE_PSPELL
-# include "sp_pspell.h"
-#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>
+# include "pspell.h"
#endif
ControlSpellchecker::ControlSpellchecker(LyXView & lv, Dialogs & d)
: ControlDialogBD(lv, d),
rtl_(false), newval_(0.0), oldval_(0), newvalue_(0), count_(0),
- stop_(false), result_(SpellBase::ISP_OK), speller_(0)
+ stop_(false), speller_(0)
{}
rtl_ = lv_.buffer()->params.language->RightToLeft();
}
- if (speller_->error() != 0) {
-#if 0
- message_ = speller_->error();
- // show error message
- view().partialUpdate(2);
-#endif
+ if (!speller_->error().empty()) {
clearParams();
return;
}
void ControlSpellchecker::check()
{
- result_ = SpellBase::ISP_OK;
+ SpellBase::Result res = SpellBase::OK;
stop_ = false;
// clear any old selection
lv_.view()->toggleSelection(true);
lv_.view()->update(text, BufferView::SELECT);
- while ((result_==SpellBase::ISP_OK || result_==SpellBase::ISP_IGNORE) &&
- !stop_) {
+ while ((res == SpellBase::OK || res == SpellBase::IGNORE) && !stop_) {
word_ = lv_.view()->nextWord(newval_);
if (word_.empty()) {
if (!speller_->alive()) clearParams();
- result_ = speller_->check(word_);
+ res = speller_->check(word_);
}
if (!stop_ && !word_.empty())
lv_.view()->selectLastWord();
// set suggestions
- if (result_!=SpellBase::ISP_OK && result_!=SpellBase::ISP_IGNORE) {
+ if (res != SpellBase::OK && res != SpellBase::IGNORE) {
view().partialUpdate(1);
}
}
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());
- }
+ string miss(speller_->nextMiss());
- return tmp;
+ if (rtl_)
+ std::reverse(miss.begin(), miss.end());
+
+ return miss;
}
string ControlSpellchecker::getWord()
{
string tmp = word_;
- if (rtl_) std::reverse(tmp.begin(), tmp.end());
+ if (rtl_)
+ std::reverse(tmp.begin(), tmp.end());
return tmp;
}
count_ = 0;
message_.erase();
stop_ = false;
- result_ = SpellBase::ISP_OK;
speller_ = 0;
}
#endif
#include "ControlDialog_impl.h"
-#include "sp_base.h"
+class SpellBase;
+
/** A controller for Spellchecker dialogs.
*/
class ControlSpellchecker : public ControlDialogBD {
/// set to true to stop checking
bool stop_;
- /// spellchecker status
- enum SpellBase::spellStatus result_;
-
/// The actual spellchecker object
SpellBase * speller_;
string const val(tostr(params().first) + " " + tostr(params().second));
- lv_.getLyXFunc()->dispatch(LFUN_INSET_TABULAR, val);
+ lv_.getLyXFunc()->dispatch(LFUN_TABULAR_INSERT, val);
}
void FormBase::show()
{
+ lyxerr << "show" << endl;
if (!form()) {
build();
}
FormSpellchecker::FormSpellchecker(ControlSpellchecker & c, Dialogs & d)
: base_class(c, d, _("LyX: Spellchecker"), false)
-{}
+{
+}
void FormSpellchecker::build()
case 2:
// show exit message
fl_show_messages(controller().getMessage().c_str());
- hide();
+ //hide();
}
-
}
// placed in BufferView. If "all BufferViews" then LyXGUI (I think) should
// run "prohibitInput" on all LyXViews which will run prohibitInput on all
// BufferViews. Or is it perhaps just the (input in) BufferViews in the
-// current LyxView that should be prohibited (Lgb) (This applies to
+// current LyXView that should be prohibited (Lgb) (This applies to
// "allowInput" as well.)
void XFormsView::prohibitInput() const
{
+2002-08-04 John Levon <levon@movementarian.org>
+
+ * inset.h:
+ * insetnote.h: s/IGNORE_CODE/NOTE_CODE/
+
2002-08-02 Angus Leeming <leeming@lyx.org>
* insetcommandparams.[Ch] (preview): new methods returning and setting
///
LABEL_CODE, // 10
///
- IGNORE_CODE,
+ NOTE_CODE,
///
ACCENT_CODE,
///
///
string const editMessage() const;
///
- Inset::Code lyxCode() const { return Inset::IGNORE_CODE; }
+ Inset::Code lyxCode() const { return Inset::NOTE_CODE; }
///
void write(Buffer const *, std::ostream &) const;
///
--- /dev/null
+/**
+ * \file ispell.C
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author unknown
+ * \author John Levon <levon@movementarian.org>
+ */
+
+#include <config.h>
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+#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 "support/lstrings.h"
+#include "lyxrc.h"
+#include "language.h"
+#include "debug.h"
+#include "encoding.h"
+#include "ispell.h"
+
+#ifndef CXX_GLOBAL_CSTD
+using std::strcpy;
+using std::strlen;
+using std::strpbrk;
+using std::strstr;
+#endif
+
+using std::endl;
+
+namespace {
+ /// pid for the `ispell' process.
+ pid_t isp_pid = -1;
+}
+
+
+ISpell::ISpell(BufferParams const & params, string const & lang)
+ : str(0)
+{
+ static char o_buf[BUFSIZ]; // jc: it could be smaller
+ int pipein[2];
+ int pipeout[2];
+ char * argv[14];
+ int argc;
+
+ isp_pid = -1;
+
+ if (pipe(pipein) == -1 || pipe(pipeout) == -1) {
+ lyxerr << "LyX: Can't create pipe for spellchecker!" << endl;
+ goto END;
+ }
+
+ if ((out = fdopen(pipein[1], "w")) == 0) {
+ lyxerr << "LyX: Can't create stream for pipe for spellchecker!"
+ << endl;
+ goto END;
+ }
+
+ if ((in = fdopen(pipeout[0], "r")) == 0) {
+ lyxerr <<"LyX: Can't create stream for pipe for spellchecker!"
+ << endl;
+ goto END;
+ }
+
+ setvbuf(out, o_buf, _IOLBF, BUFSIZ);
+
+ isp_fd = pipeout[0];
+
+ isp_pid = fork();
+
+ if (isp_pid == -1) {
+ lyxerr << "LyX: Can't create child process for spellchecker!"
+ << endl;
+ goto END;
+ }
+
+ if (isp_pid == 0) {
+ /* child process */
+ dup2(pipein[0], STDIN_FILENO);
+ dup2(pipeout[1], STDOUT_FILENO);
+ ::close(pipein[0]);
+ ::close(pipein[1]);
+ ::close(pipeout[0]);
+ ::close(pipeout[1]);
+
+ argc = 0;
+ char * tmp = new char[lyxrc.isp_command.length() + 1];
+ lyxrc.isp_command.copy(tmp, lyxrc.isp_command.length());
+ tmp[lyxrc.isp_command.length()] = '\0';
+ argv[argc++] = tmp;
+ tmp = new char[3];
+ string("-a").copy(tmp, 2); tmp[2] = '\0'; // pipe mode
+ argv[argc++] = tmp;
+
+ if (lang != "default") {
+ tmp = new char[3];
+ string("-d").copy(tmp, 2); tmp[2] = '\0'; // Dictionary file
+ argv[argc++] = tmp;
+ tmp = new char[lang.length() + 1];
+ lang.copy(tmp, lang.length()); tmp[lang.length()] = '\0';
+ argv[argc++] = tmp;
+ }
+
+ if (lyxrc.isp_accept_compound) {
+ // Consider run-together words as legal compounds
+ tmp = new char[3];
+ string("-C").copy(tmp, 2); tmp[2] = '\0';
+ argv[argc++] = tmp;
+ } else {
+ // Report run-together words with
+ // missing blanks as errors
+ tmp = new char[3];
+ string("-B").copy(tmp, 2); tmp[2] = '\0';
+ argv[argc++] = tmp;
+ }
+ if (lyxrc.isp_use_esc_chars) {
+ // Specify additional characters that
+ // can be part of a word
+ tmp = new char[3];
+ string("-w").copy(tmp, 2); tmp[2] = '\0';
+ argv[argc++] = tmp;
+ // Put the escape chars in ""s
+ string tms = "\"" + lyxrc.isp_esc_chars + "\"";
+ tmp = new char[tms.length() + 1];
+ tms.copy(tmp, tms.length()); tmp[tms.length()] = '\0';
+ argv[argc++] = tmp;
+ }
+ if (lyxrc.isp_use_pers_dict) {
+ // Specify an alternate personal dictionary
+ tmp = new char[3];
+ string("-p").copy(tmp, 2);
+ tmp[2]= '\0';
+ argv[argc++] = tmp;
+ tmp = new char[lyxrc.isp_pers_dict.length() + 1];
+ lyxrc.isp_pers_dict.copy(tmp, lyxrc.isp_pers_dict.length());
+ tmp[lyxrc.isp_pers_dict.length()] = '\0';
+ argv[argc++] = tmp;
+ }
+ if (lyxrc.isp_use_input_encoding &&
+ params.inputenc != "default") {
+ string enc = (params.inputenc == "auto")
+ ? params.language->encoding()->LatexName()
+ : params.inputenc;
+ string::size_type n = enc.length();
+ tmp = new char[3];
+ string("-T").copy(tmp, 2);
+ tmp[2] = '\0';
+ argv[argc++] = tmp; // Input encoding
+ tmp = new char[n + 1];
+ enc.copy(tmp, n);
+ tmp[n] = '\0';
+ argv[argc++] = tmp;
+ }
+
+ argv[argc++] = 0;
+
+ execvp(argv[0], const_cast<char * const *>(argv));
+
+ // free the memory used by string::copy in the
+ // setup of argv
+ for (int i = 0; i < argc - 1; ++i)
+ delete[] argv[i];
+
+ lyxerr << "LyX: Failed to start ispell!" << endl;
+ _exit(0);
+ }
+ {
+ /* 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));
+
+ 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);
+
+ 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;
+ } else {
+ // Select returned error
+ lyxerr << "Select on ispell returned error, what now?" << endl;
+ }
+ }
+ END:
+ 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;
+ }
+}
+
+
+ISpell::~ISpell()
+{
+ delete[] str;
+}
+
+
+/* FIXME: this is a minimalist solution until the above
+ * code is able to work with forkedcall.h. We only need
+ * to reap the zombies here.
+ */
+void reapSpellchecker(void)
+{
+ if (isp_pid == -1)
+ return;
+
+ waitpid(isp_pid, 0, WNOHANG);
+}
+
+
+string const ISpell::nextMiss()
+{
+ if (str == 0 || *(e+1) == '\0')
+ return "";
+ char * b = e + 2;
+ e = strpbrk(b, ",\n");
+ *e = '\0';
+ if (b)
+ return b;
+ return "";
+}
+
+
+bool ISpell::alive()
+{
+ return isp_pid != -1;
+}
+
+
+void ISpell::cleanUp()
+{
+ ::fclose(out);
+}
+
+
+enum ISpell::Result ISpell::check(string const & word)
+{
+ // FIXME Please rewrite to use string.
+
+ Result res;
+
+ ::fputs(word.c_str(), out);
+ ::fputc('\n', out);
+
+ char buf[1024];
+ ::fgets(buf, 1024, in);
+
+ // 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;
+
+ switch (*buf) {
+ case '*':
+ res = OK;
+ break;
+ case '+':
+ res = ROOT;
+ break;
+ case '-':
+ res = COMPOUNDWORD;
+ break;
+ case '\n':
+ res = IGNORE;
+ break;
+ case '#': // Not found, no near misses and guesses
+ res = UNKNOWN;
+ break;
+ case '?': // Not found, and no near misses, but guesses (guesses are ignored)
+ case '&': // Not found, but we have near misses
+ {
+ res = MISSED;
+ char * p = strpbrk(buf, ":");
+ str = new char[strlen(p) + 1];
+ e = str;
+ strcpy(str, p);
+ break;
+ }
+ default: // This shouldn't happen, but you know Murphy
+ res = UNKNOWN;
+ }
+
+ *buf = 0;
+ if (res != IGNORE) {
+ /* wait for ispell to finish */
+ while (*buf!= '\n')
+ fgets(buf, 255, in);
+ }
+ return res;
+}
+
+
+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(string const & word)
+{
+ ::fputc('*', out); // Insert word in personal dictionary
+ ::fputs(word.c_str(), out);
+ ::fputc('\n', out);
+}
+
+
+void ISpell::accept(string const & word)
+{
+ ::fputc('@', out); // Accept in this session
+ ::fputs(word.c_str(), out);
+ ::fputc('\n', out);
+}
+
+
+string const ISpell::error()
+{
+ if (error_)
+ return error_;
+ return "";
+}
--- /dev/null
+// -*- C++ -*-
+/**
+ * \file sp_ispell.h
+ * Copyright 2002 the LyX Team
+ * Read the file COPYING
+ *
+ * \author unknown
+ */
+
+#ifndef SP_ISPELL_H
+#define SP_ISPELL_H
+
+#include <cstdio>
+
+#include "SpellBase.h"
+
+class BufferParams;
+
+/// i/a spell process-based spellchecker
+class ISpell : public SpellBase {
+public:
+ ISpell(BufferParams const & params, string const & lang);
+
+ ~ISpell();
+
+ /// 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(string const & word);
+
+ /// finish this spellchecker instance
+ virtual void close();
+
+ /// insert the given word into the personal dictionary
+ virtual void insert(string const & word);
+
+ /// accept the given word temporarily
+ virtual void accept(string const & word);
+
+ /// return the next near miss after a MISSED result
+ virtual string const nextMiss();
+
+ /// give an error message on messy exit
+ virtual string const error();
+
+private:
+ /// instream to communicate with ispell
+ FILE * in;
+ /// outstream to communicate with ispell
+ FILE * out;
+ /// spell error
+ char const * error_;
+ /// the fd of the outgoing pipe
+ int isp_fd;
+
+ // vileness below ... please FIXME
+ /// str ???
+ char * str;
+ /// e ???
+ char * e;
+
+};
+
+#endif // ISPELL_H
// create new file with template
// SERVERCMD !
//
-Buffer * NewLyxFile(string const & filename)
+Buffer * NewFile(string const & filename)
{
// Split argument by :
string name;
///
void AutoSave(BufferView * bv);
///
-Buffer * NewLyxFile(string const & filename);
+Buffer * NewFile(string const & filename);
///
void InsertAsciiFile(BufferView * bv, string const & f, bool asParagraph);
///
-/* This file is part of
- * ======================================================
+/**
+ * \file lyxcursor.C
+ * Copyright 1995-2001 the LyX Team
+ * Read the file COPYING
*
- * LyX, The Document Processor
- *
- * Copyright 1995 Matthias Ettrich
- * Copyright 1995-2001 The LyX Team.
- *
- * ====================================================== */
+ * \author Matthias Ettrich
+ */
#include <config.h>
// -*- C++ -*-
-/* This file is part of
- * ======================================================
+/**
+ * \file lyxcursor.h
+ * Copyright 1995-2001 the LyX Team
+ * Read the file COPYING
*
- * LyX, The Document Processor
- *
- * Copyright 1995 Matthias Ettrich
- * Copyright 1995-2001 The LyX Team.
- *
- * ====================================================== */
+ * \author Matthias Ettrich
+ */
#ifndef LYXCURSOR_H
#define LYXCURSOR_H
class Paragraph;
class Row;
-/** All these variables should be explained. Matthias?
+/**
+ * The cursor class describes the position of a cursor within a document.
+ * Several cursors exist within LyX; for example, when locking an inset,
+ * the position of the cursor in the containing inset is stored.
+ *
+ * FIXME: true ?
*/
class LyXCursor {
public:
- ///
LyXCursor();
- ///
+ /// set the paragraph that contains this cursor
void par(Paragraph * p);
- ///
+ /// return the paragraph this cursor is in
Paragraph * par() const;
- ///
+ /// set the position within the paragraph
void pos(lyx::pos_type p);
- ///
+ /// return the position within the paragraph
lyx::pos_type pos() const;
- ///
+ /// FIXME
void boundary(bool b);
- ///
+ /// FIXME
bool boundary() const;
- ///
+ /// set the x position in pixels
void x(int i);
- ///
+ /// return the x position in pixels
int x() const;
- ///
+ /// set the stored next-line position when at the end of a row
void ix(int i);
- ///
+ /**
+ * Return the x position of the start of the next row, when this
+ * cursor is at the end of the previous row, for insets that take
+ * a full row.
+ *
+ * FIXME: explain why we need this ?
+ */
int ix() const;
- ///
+ /// set the cached x position
void x_fix(int i);
- ///
+ /**
+ * Return the cached x position of the cursor. This is used for when
+ * we have text like :
+ *
+ * blah blah blah blah| blah blah blah
+ * blah blah blah
+ * blah blah blah blah blah blah
+ *
+ * When we move onto row 3, we would like to be vertically aligned
+ * with where we were in row 1, despite the fact that row 2 is
+ * shorter than x()
+ */
int x_fix() const;
- ///
+ /// set the y position in pixels
void y(int i);
- ///
+ /// return the y position in pixels
int y() const;
- ///
+ /// set the stored next-line y position when at the end of a row
void iy(int i);
- ///
+ /**
+ * Return the y position of the start of the next row, when this
+ * cursor is at the end of the previous row, for insets that take
+ * a full row.
+ *
+ * FIXME: explain why we need this ? especially for y...
+ */
int iy() const;
- ///
+ /// set the row of the paragraph the cursor is in
void row(Row * r);
- ///
+ /// return the row of the paragraph this cursor is in
Row * row() const;
- ///
+ /// set the stored next row
void irow(Row * r);
- ///
+ /**
+ * Return the next row, when this
+ * cursor is at the end of the previous row, for insets that take
+ * a full row.
+ *
+ * FIXME: explain why we need this ? especially for y...
+ */
Row * irow() const;
private:
/// The paragraph the cursor is in.
Paragraph * par_;
/// The position inside the paragraph
lyx::pos_type pos_;
- ///
+ /// FIXME
bool boundary_;
- ///
+ /// the pixel x position
int x_;
- /// the x position of the position before the inset when we put
- /// the cursor on the end of the row before, otherwise equal to x.
+ /// the stored next-row x position
int ix_;
- ///
+ /// the cached x position
int x_fix_;
- ///
+ /// the pixel y position
int y_;
- /// the y position of the position before the inset when we put
- /// the cursor on the end of the row before, otherwise equal to y.
+ /// the stored next-row y position
int iy_;
- ///
+ /// the containing row
Row * row_;
- /// the row of the position before the inset when we put
- /// the cursor on the end of the row before, otherwise equal to row.
+ /// the containing row for the next line
Row * irow_;
};
-///
+/// these three dictate the others
inline
bool operator==(LyXCursor const & a, LyXCursor const & b)
{
&& a.boundary() == b.boundary();
}
-///
inline
bool operator!=(LyXCursor const & a, LyXCursor const & b)
{
return !(a == b);
}
-///
+/// only compares y() and pos(). Can this be done in another way?
inline
bool operator<(LyXCursor const & a, LyXCursor const & b)
{
- // Can this be done in a nother way?
return (a.y() < b.y() && a.pos() < b.pos());
}
-///
inline
bool operator>(LyXCursor const & a, LyXCursor const & b)
{
return b < a;
}
-///
inline
bool operator>=(LyXCursor const & a, LyXCursor const & b)
{
}
-///
inline
bool operator<=(LyXCursor const & a, LyXCursor const & b)
{
return !(a > b);
}
-#endif
+#endif // LYXCURSOR_H
case LFUN_REDO:
disable = buf->redostack.empty();
break;
- case LFUN_SPELLCHECK:
- disable = lyxrc.isp_command == "none";
- break;
#ifndef HAVE_LIBAIKSAURUS
case LFUN_THESAURUS_ENTRY:
disable = true;
case LFUN_INSET_FOOTNOTE:
code = Inset::FOOT_CODE;
break;
- case LFUN_DIALOG_TABULAR_INSERT:
- case LFUN_INSET_TABULAR:
+ case LFUN_TABULAR_INSERT:
code = Inset::TABULAR_CODE;
break;
case LFUN_INSET_EXTERNAL:
code = Inset::CAPTION_CODE;
break;
case LFUN_INSERT_NOTE:
- code = Inset::IGNORE_CODE;
+ code = Inset::NOTE_CODE;
break;
case LFUN_INSERT_LABEL:
code = Inset::LABEL_CODE;
break;
}
- case LFUN_DIALOG_TABULAR_INSERT:
- owner->getDialogs()->showTabularCreate();
- break;
-
case LFUN_AUTOSAVE:
AutoSave(owner->view().get());
break;
case LFUN_FILE_NEW:
{
// servercmd: argument must be <file>:<template>
- Buffer * tmpbuf = NewLyxFile(argument);
+ Buffer * tmpbuf = NewFile(argument);
if (tmpbuf)
owner->view()->buffer(tmpbuf);
}
break; // RVDK_PATCH_5
case LFUN_SPELLCHECK:
- if (lyxrc.isp_command != "none")
- owner->getDialogs()->showSpellchecker();
+ owner->getDialogs()->showSpellchecker();
break;
// --- lyxserver commands ----------------------------
-/* This file is part of
- * ======================================================
+/**
+ * \file lyxlex.C
+ * Copyright 1996-2002 the LyX Team
+ * Read the file COPYING
*
- * LyX, The Document Processor
+ * Generalized simple lexical analyzer.
+ * It can be used for simple syntax parsers, like lyxrc,
+ * texclass and others to come.
*
- * Copyright 1996-2001 The LyX Team.
- *
- * Generalized simple lexical analizer.
- * It can be used for simple syntax parsers, like lyxrc,
- * texclass and others to come. [asierra30/03/96]
- *
- * ====================================================== */
+ * \author Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
+ */
#include <config.h>
// We do a case independent comparison, like search_kw
// does.
- if (compare_ascii_no_case(token, endtoken) != 0) {
- string tmpstr = getString();
- if (firstline) {
- unsigned int i = 0;
- while (i < tmpstr.length()
- && tmpstr[i] == ' ') {
- ++i;
- prefix += ' ';
- }
- firstline = false;
- lyxerr[Debug::PARSER] << "Prefix = `" << prefix
- << '\'' << endl;
- }
-
- if (!prefix.empty()
- && prefixIs(tmpstr, prefix)) {
- tmpstr.erase(0, prefix.length() - 1);
- }
- str += ltrim(tmpstr, "\t") + '\n';
- }
- else // token == endtoken
+ if (compare_ascii_no_case(token, endtoken) == 0)
break;
+
+ string tmpstr = getString();
+ if (firstline) {
+ string::size_type i(tmpstr.find_first_not_of(' '));
+ if (i != string::npos)
+ prefix = tmpstr.substr(0, i);
+ firstline = false;
+ lyxerr[Debug::PARSER]
+ << "Prefix = `" << prefix << "\'" << endl;
+ }
+
+ // further lines in long strings may have the same
+ // whitespace prefix as the first line. Remove it.
+ if (prefix.length() && prefixIs(tmpstr, prefix)) {
+ tmpstr.erase(0, prefix.length() - 1);
+ }
+
+ str += ltrim(tmpstr, "\t") + '\n';
}
+
if (!isOK()) {
printError("Long string not ended by `" + endtoken + '\'');
}
if (rerrno != 0) {
lyxerr << "LyXComm: " << strerror(rerrno) << endl;
if (!lsbuf.empty()) {
- lyxerr << "LyxComm: truncated command: "
+ lyxerr << "LyXComm: truncated command: "
<< lsbuf << endl;
lsbuf.erase();
}
/* ---F+------------------------------------------------------------------ *\
- Function : LyxNotifyClient
+ Function : LyXNotifyClient
Called by : WorkAreaKeyPress
Purpose : send a notify messge to a client
Parameters: s - string to send
}
// If the document is changed, we might want to save it
- if (!vcs->owner()->isLyxClean() &&
+ if (!vcs->owner()->isClean() &&
Alert::askQuestion(_("Changes in document:"),
MakeDisplayPath(filename, 50),
_("Save document and proceed?"))) {
// Maybe the save fails, or we answered "no". In both cases,
// the document will be dirty, and we abort.
- if (!vcs->owner()->isLyxClean()) {
+ if (!vcs->owner()->isClean()) {
return;
}
void LyXVC::checkIn()
{
// If the document is changed, we might want to save it
- if (!vcs->owner()->isLyxClean() &&
+ if (!vcs->owner()->isClean() &&
Alert::askQuestion(_("Changes in document:"),
MakeDisplayPath(vcs->owner()->fileName(), 50),
_("Save document and proceed?"))) {
// Maybe the save fails, or we answered "no". In both cases,
// the document will be dirty, and we abort.
- if (!vcs->owner()->isLyxClean()) {
+ if (!vcs->owner()->isClean()) {
return;
}
void LyXVC::checkOut()
{
lyxerr[Debug::LYXVC] << "LyXVC: checkOut" << endl;
- if (!vcs->owner()->isLyxClean()
+ if (!vcs->owner()->isClean()
&& !Alert::askQuestion(_("Changes in document:"),
MakeDisplayPath(vcs->owner()->fileName(), 50),
_("Ignore changes and proceed with check out?"))) {
--- /dev/null
+/**
+ * \file pspell.C
+ * Copyright 2001 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Kevin Atkinson
+ * \author John Levon <levon@movementarian.org>
+ */
+
+#include <config.h>
+
+#ifdef __GNUG__
+#pragma implementation
+#endif
+
+#ifdef USE_PSPELL
+
+#include "support/LAssert.h"
+
+#define USE_ORIGINAL_MANAGER_FUNCS 1
+#include <pspell/pspell.h>
+
+#include "pspell.h"
+
+
+PSpell::PSpell(BufferParams const & params, string const & lang)
+ : sc(0), els(0), spell_error_object(0), alive_(false)
+{
+ PspellConfig * config = new_pspell_config();
+ config->replace("language-tag", lang.c_str());
+ spell_error_object = new_pspell_manager(config);
+ if (pspell_error_number(spell_error_object) == 0) {
+ sc = to_pspell_manager(spell_error_object);
+ spell_error_object = 0;
+ alive_ = true;
+ }
+}
+
+
+PSpell::~PSpell()
+{
+ cleanUp();
+ close();
+ if (els)
+ delete_pspell_string_emulation(els);
+}
+
+
+void PSpell::cleanUp()
+{
+ if (spell_error_object) {
+ delete_pspell_can_have_error(spell_error_object);
+ spell_error_object = 0;
+ }
+}
+
+
+enum PSpell::Result PSpell::check(string const & word)
+{
+ Result res = UNKNOWN;
+
+ if (!sc)
+ return res;
+
+ int word_ok = pspell_manager_check(sc, word.c_str());
+ lyx::Assert(word_ok != -1);
+
+ if (word_ok) {
+ res = OK;
+ } else {
+ PspellWordList const * sugs =
+ pspell_manager_suggest(sc, word.c_str());
+ lyx::Assert(sugs != 0);
+ els = pspell_word_list_elements(sugs);
+ if (pspell_word_list_empty(sugs))
+ res = UNKNOWN;
+ else
+ res = MISSED;
+ }
+ return res;
+}
+
+
+void PSpell::close()
+{
+ if (sc)
+ pspell_manager_save_all_word_lists(sc);
+}
+
+
+void PSpell::insert(string const & word)
+{
+ if (sc)
+ pspell_manager_add_to_personal(sc, word.c_str());
+}
+
+
+void PSpell::accept(string const & word)
+{
+ if (sc)
+ pspell_manager_add_to_session(sc, word.c_str());
+}
+
+
+string const PSpell::nextMiss()
+{
+ char const * str = 0;
+
+ if (els)
+ str = pspell_string_emulation_next(els);
+ if (str)
+ return str;
+ return "";
+}
+
+
+string const PSpell::error()
+{
+ char const * err = 0;
+
+ if (pspell_error_number(spell_error_object) != 0) {
+ err = pspell_error_message(spell_error_object);
+ }
+
+ if (err)
+ return err;
+ return "";
+}
+
+#endif // USE_PSPELL
--- /dev/null
+/**
+ * \file pspell.h
+ * Copyright 2001 the LyX Team
+ * Read the file COPYING
+ *
+ * \author Kevin Atkinson
+ * \author John Levon <levon@movementarian.org>
+ */
+
+#ifndef LYX_PSPELL_H
+#define LYX_PSPELL_H
+
+#include "SpellBase.h"
+
+class PspellManager;
+class PspellStringEmulation;
+class PspellCanHaveError;
+
+class BufferParams;
+
+
+class PSpell : public SpellBase {
+public:
+ /**
+ * Initialise the spellchecker with the given buffer params and language.
+ */
+ PSpell(BufferParams const & params, string const & lang);
+
+ virtual ~PSpell();
+
+ /// return true if the spellchecker instance still exists
+ virtual bool alive() { return alive_; }
+
+ /// clean up on messy exit
+ virtual void cleanUp();
+
+ /// check the given word and return the result
+ virtual enum Result check(string const & word);
+
+ /// finish this spellchecker instance
+ virtual void close();
+
+ /// insert the given word into the personal dictionary
+ virtual void insert(string const & word);
+
+ /// accept the given word temporarily
+ virtual void accept(string const & word);
+
+ /// return the next near miss after a MISSED result
+ virtual string const nextMiss();
+
+ /// give an error message on messy exit
+ virtual string const error();
+
+private:
+ /// main manager
+ PspellManager * sc;
+ /// FIXME
+ PspellStringEmulation * els;
+ /// FIXME
+ PspellCanHaveError * spell_error_object;
+ /// initialised properly ?
+ bool alive_;
+};
+
+#endif // PSPELL_H
+++ /dev/null
-// -*- C++ -*-
-#ifndef SP_BASE_H
-#define SP_BASE_H
-
-// needed for pid_t typedef
-#include <sys/types.h>
-#include "LString.h" // can't forward declare...
-
-class BufferParams;
-
-class SpellBase
-{
- public:
-
- /// status
- enum spellStatus {
- ISP_OK = 1,
- ISP_ROOT,
- ISP_COMPOUNDWORD,
- ISP_UNKNOWN,
- ISP_MISSED,
- ISP_IGNORE
- };
-
- virtual ~SpellBase() {}
-
- virtual void initialize(BufferParams const & , string const &) = 0;
-
- virtual bool alive() = 0;
-
- virtual void cleanUp() = 0;
-
- virtual enum spellStatus check(string const &) = 0;
-
- virtual void close() = 0;
-
- virtual void insert(string const &) = 0;
-
- virtual void accept(string const &) = 0;
-
- virtual void store(string const & , string const &) = 0;
-
- virtual char const * error() = 0;
-
- virtual char const * nextMiss() = 0;
-
-};
-
-#endif
+++ /dev/null
-#ifndef SP_ISPELL_H
-#define SP_ISPELL_H
-
-#include <cstdio>
-
-#include "sp_base.h"
-
-class BufferParams;
-
-
-class ISpell : public SpellBase
-{
-public:
- ///
- enum ActualSpellChecker {
- ASC_ISPELL,
- ASC_ASPELL
- };
- ///
- ISpell();
- ///
- ISpell(BufferParams const & params, string const & lang);
- ///
- ~ISpell();
-
- /// initialize spell checker
- void initialize(BufferParams const & params, string const & lang);
- ///
- bool alive();
- /// clean up after error
- void cleanUp();
- /// check word
- enum spellStatus check(string const & word);
- /// close spellchecker
- void close();
- ///
- void insert(string const & word);
- ///
- void accept(string const & word);
- /// store replacement
- void store(string const & mis, string const & cor);
- ///
- char const * nextMiss();
- ///
- char const * error();
-
-private:
- ///
- ActualSpellChecker actual_spell_checker;
- /// instream to communicate with ispell
- FILE * in;
- /// outstream to communicate with ispell
- FILE * out;
- /// spell error
- char const * error_;
- /// ?
- int isp_fd;
- ///
- char * str;
- ///
- spellStatus flag;
- ///
- char * b;
- ///
- char * e;
-
-};
-
-#endif
+++ /dev/null
-#ifndef SP_PSPELL_H
-#define SP_PSPELL_H
-
-#include "sp_base.h"
-
-class PspellManager;
-class PspellStringEmulation;
-class PspellCanHaveError;
-
-class BufferParams;
-
-
-class PSpell : public SpellBase
-{
-public:
- ///
- PSpell();
- ///
- PSpell(BufferParams const & params, string const & lang);
- ///
- ~PSpell();
- /// initialize spell checker
- void initialize(BufferParams const & params, string const & lang);
- ///
- bool alive() { return alive_; }
- /// clean up after error
- void cleanUp();
- /// check word
- enum spellStatus check(string const & word);
- /// close spellchecker
- void close();
- ///
- void insert(string const & word);
- ///
- void accept(string const & word);
- /// store replacement
- void store(string const & mis, string const & cor);
- ///
- char const * nextMiss();
- ///
- char const * error();
-
-private:
- ///
- PspellManager * sc;
- ///
- PspellStringEmulation * els;
- ///
- PspellCanHaveError * spell_error_object;
- ///
- spellStatus flag;
- ///
- const char * error_;
- ///
- bool alive_;
-};
-
-#endif
+++ /dev/null
-/* This file is part of
- * ======================================================
- *
- * LyX, The Document Processor
- *
- * Copyright 2001 The LyX Team.
- *
- * ======================================================
- *
- * \file sp_pspell.C
- * \author Kevin Atkinson
- */
-
-#include <config.h>
-
-#ifdef __GNUG__
-#pragma implementation
-#endif
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <cstdio>
-
-#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 "support/lstrings.h"
-#include "lyxrc.h"
-#include "language.h"
-#include "debug.h"
-#include "encoding.h"
-#include "sp_ispell.h"
-
-#ifndef CXX_GLOBAL_CSTD
-using std::strcpy;
-using std::strlen;
-using std::strpbrk;
-using std::strstr;
-#endif
-
-using std::endl;
-
-namespace {
- /// pid for the `ispell' process.
- pid_t isp_pid = -1;
-}
-
-///
-// ------------------- start special pspell code/class --------------------
-///
-#ifdef USE_PSPELL
-
-#include "support/LAssert.h"
-
-#define USE_ORIGINAL_MANAGER_FUNCS 1
-# include <pspell/pspell.h>
-
-#include "sp_pspell.h"
-
-
-PSpell::PSpell()
- : sc(0), els(0), spell_error_object(0), flag(ISP_UNKNOWN),
- alive_(false)
-{
-}
-
-
-PSpell::PSpell(BufferParams const & params, string const & lang)
- : sc(0), els(0), spell_error_object(0), flag(ISP_UNKNOWN),
- alive_(false)
-{
- initialize(params, lang);
-}
-
-
-PSpell::~PSpell()
-{
- cleanUp();
- close();
- if (els)
- delete_pspell_string_emulation(els);
-}
-
-
-void PSpell::initialize(BufferParams const &, string const & lang)
-{
- PspellConfig * config = new_pspell_config();
- config->replace("language-tag", lang.c_str());
- spell_error_object = new_pspell_manager(config);
- if (pspell_error_number(spell_error_object) != 0) {
- error_ = pspell_error_message(spell_error_object);
- } else {
- error_ = 0;
- sc = to_pspell_manager(spell_error_object);
- spell_error_object = 0;
- alive_ = true;
- }
-}
-
-
-void PSpell::cleanUp()
-{
- if (spell_error_object) {
- delete_pspell_can_have_error(spell_error_object);
- spell_error_object = 0;
- }
-}
-
-
-enum PSpell::spellStatus PSpell::check(string const & word)
-{
- if (!sc)
- return flag;
-
- int word_ok = pspell_manager_check(sc, word.c_str());
- lyx::Assert(word_ok != -1);
-
- if (word_ok) {
- flag = ISP_OK;
- } else {
- PspellWordList const * sugs =
- pspell_manager_suggest(sc, word.c_str());
- lyx::Assert(sugs != 0);
- els = pspell_word_list_elements(sugs);
- if (pspell_word_list_empty(sugs))
- flag = ISP_UNKNOWN;
- else
- flag = ISP_MISSED;
- }
- return flag;
-}
-
-
-void PSpell::close()
-{
- if (sc)
- pspell_manager_save_all_word_lists(sc);
-}
-
-
-void PSpell::insert(string const & word)
-{
- if (sc)
- pspell_manager_add_to_personal(sc, word.c_str());
-}
-
-
-void PSpell::accept(string const & word)
-{
- if (sc)
- pspell_manager_add_to_session(sc, word.c_str());
-}
-
-
-void PSpell::store(string const & mis, string const & cor)
-{
- if (sc)
- pspell_manager_store_replacement(sc, mis.c_str(), cor.c_str());
-}
-
-
-char const * PSpell::nextMiss()
-{
- if (els)
- return pspell_string_emulation_next(els);
- return "";
-}
-
-
-char const * PSpell::error()
-{
- return error_;
-}
-
-
-#endif
-
-///
-// ------------------- start special ispell code/class --------------------
-///
-
-ISpell::ISpell()
- : str(0), flag(ISP_UNKNOWN)
-{}
-
-
-ISpell::ISpell(BufferParams const & params, string const & lang)
- : str(0), flag(ISP_UNKNOWN)
-{
- initialize(params, lang);
-}
-
-
-ISpell::~ISpell()
-{
- delete[] str;
-}
-
-
-char const * ISpell::nextMiss()
-{
- if (str == 0 || *(e+1) == '\0') return 0;
- b = e + 2;
- e = strpbrk(b, ",\n");
- *e = '\0';
- return b;
-}
-
-
-void ISpell::initialize(BufferParams const & params, string const & lang)
-{
- static char o_buf[BUFSIZ]; // jc: it could be smaller
- int pipein[2];
- int pipeout[2];
- char * argv[14];
- int argc;
-
- isp_pid = -1;
-
- if (pipe(pipein) == -1 || pipe(pipeout) == -1) {
- lyxerr << "LyX: Can't create pipe for spellchecker!" << endl;
- goto END;
- }
-
- if ((out = fdopen(pipein[1], "w")) == 0) {
- lyxerr << "LyX: Can't create stream for pipe for spellchecker!"
- << endl;
- goto END;
- }
-
- if ((in = fdopen(pipeout[0], "r")) == 0) {
- lyxerr <<"LyX: Can't create stream for pipe for spellchecker!"
- << endl;
- goto END;
- }
-
- setvbuf(out, o_buf, _IOLBF, BUFSIZ);
-
- isp_fd = pipeout[0];
-
- isp_pid = fork();
-
- if (isp_pid == -1) {
- lyxerr << "LyX: Can't create child process for spellchecker!"
- << endl;
- goto END;
- }
-
- if (isp_pid == 0) {
- /* child process */
- dup2(pipein[0], STDIN_FILENO);
- dup2(pipeout[1], STDOUT_FILENO);
- ::close(pipein[0]);
- ::close(pipein[1]);
- ::close(pipeout[0]);
- ::close(pipeout[1]);
-
- argc = 0;
- char * tmp = new char[lyxrc.isp_command.length() + 1];
- lyxrc.isp_command.copy(tmp, lyxrc.isp_command.length());
- tmp[lyxrc.isp_command.length()] = '\0';
- argv[argc++] = tmp;
- tmp = new char[3];
- string("-a").copy(tmp, 2); tmp[2] = '\0'; // pipe mode
- argv[argc++] = tmp;
-
- if (lang != "default") {
- tmp = new char[3];
- string("-d").copy(tmp, 2); tmp[2] = '\0'; // Dictionary file
- argv[argc++] = tmp;
- tmp = new char[lang.length() + 1];
- lang.copy(tmp, lang.length()); tmp[lang.length()] = '\0';
- argv[argc++] = tmp;
- }
-
- if (lyxrc.isp_accept_compound) {
- // Consider run-together words as legal compounds
- tmp = new char[3];
- string("-C").copy(tmp, 2); tmp[2] = '\0';
- argv[argc++] = tmp;
- } else {
- // Report run-together words with
- // missing blanks as errors
- tmp = new char[3];
- string("-B").copy(tmp, 2); tmp[2] = '\0';
- argv[argc++] = tmp;
- }
- if (lyxrc.isp_use_esc_chars) {
- // Specify additional characters that
- // can be part of a word
- tmp = new char[3];
- string("-w").copy(tmp, 2); tmp[2] = '\0';
- argv[argc++] = tmp;
- // Put the escape chars in ""s
- string tms = "\"" + lyxrc.isp_esc_chars + "\"";
- tmp = new char[tms.length() + 1];
- tms.copy(tmp, tms.length()); tmp[tms.length()] = '\0';
- argv[argc++] = tmp;
- }
- if (lyxrc.isp_use_pers_dict) {
- // Specify an alternate personal dictionary
- tmp = new char[3];
- string("-p").copy(tmp, 2);
- tmp[2]= '\0';
- argv[argc++] = tmp;
- tmp = new char[lyxrc.isp_pers_dict.length() + 1];
- lyxrc.isp_pers_dict.copy(tmp, lyxrc.isp_pers_dict.length());
- tmp[lyxrc.isp_pers_dict.length()] = '\0';
- argv[argc++] = tmp;
- }
- if (lyxrc.isp_use_input_encoding &&
- params.inputenc != "default") {
- string enc = (params.inputenc == "auto")
- ? params.language->encoding()->LatexName()
- : params.inputenc;
- string::size_type n = enc.length();
- tmp = new char[3];
- string("-T").copy(tmp, 2);
- tmp[2] = '\0';
- argv[argc++] = tmp; // Input encoding
- tmp = new char[n + 1];
- enc.copy(tmp, n);
- tmp[n] = '\0';
- argv[argc++] = tmp;
- }
-
- argv[argc++] = 0;
-
- execvp(argv[0], const_cast<char * const *>(argv));
-
- // free the memory used by string::copy in the
- // setup of argv
- for (int i = 0; i < argc - 1; ++i)
- delete[] argv[i];
-
- lyxerr << "LyX: Failed to start ispell!" << endl;
- _exit(0);
- }
- {
- /* 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)
- 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));
-
- 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);
-
- // determine if the spell checker is really Aspell
- if (strstr(buf, "Aspell"))
- actual_spell_checker = ASC_ASPELL;
- else
- actual_spell_checker = ASC_ISPELL;
-
- 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;
- } else {
- // Select returned error
- lyxerr << "Select on ispell returned error, what now?" << endl;
- }
- }
- END:
- 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;
- }
-}
-
-
-/* FIXME: this is a minimalist solution until the above
- * code is able to work with forkedcall.h. We only need
- * to reap the zombies here.
- */
-void reapSpellchecker(void)
-{
- if (isp_pid == -1)
- return;
-
- waitpid(isp_pid, 0, WNOHANG);
-}
-
-
-bool ISpell::alive()
-{
- return isp_pid != -1;
-}
-
-
-void ISpell::cleanUp()
-{
- ::fclose(out);
-}
-
-
-enum ISpell::spellStatus ISpell::check(string const & word)
-{
- //Please rewrite to use string.
-
- ::fputs(word.c_str(), out);
- ::fputc('\n', out);
-
- char buf[1024];
- ::fgets(buf, 1024, in);
-
- // 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 ISP_UNKNOWN;
-
- switch (*buf) {
- case '*': // Word found
- flag = ISP_OK;
- break;
- case '+': // Word found through affix removal
- flag = ISP_ROOT;
- break;
- case '-': // Word found through compound formation
- flag = ISP_COMPOUNDWORD;
- break;
- case '\n': // Number or when in terse mode: no problems
- flag = ISP_IGNORE;
- break;
- case '#': // Not found, no near misses and guesses
- flag = ISP_UNKNOWN;
- break;
- case '?': // Not found, and no near misses, but guesses (guesses are ignored)
- case '&': // Not found, but we have near misses
- {
- flag = ISP_MISSED;
- char * p = strpbrk(buf, ":");
- str = new char[strlen(p) + 1];
- e = str;
- strcpy(str, p);
- break;
- }
- default: // This shouldn't happend, but you know Murphy
- flag = ISP_UNKNOWN;
- }
-
- *buf = 0;
- if (flag!= ISP_IGNORE) {
- while (*buf!= '\n') fgets(buf, 255, in); /* wait for ispell to finish */
- }
- return flag;
-}
-
-
-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(string const & word)
-{
- ::fputc('*', out); // Insert word in personal dictionary
- ::fputs(word.c_str(), out);
- ::fputc('\n', out);
-}
-
-
-void ISpell::accept(string const & word)
-{
- ::fputc('@', out); // Accept in this session
- ::fputs(word.c_str(), out);
- ::fputc('\n', out);
-}
-
-
-void ISpell::store(string const & mis, string const & cor)
-{
- if (actual_spell_checker == ASC_ASPELL) {
- ::fputs("$$ra ", out);
- ::fputs(mis.c_str(), out);
- ::fputc(',', out);
- ::fputs(cor.c_str(), out);
- ::fputc('\n', out);
- }
-}
-
-
-char const * ISpell::error()
-{
- return error_;
-}
using std::vector;
using std::copy;
-using std::find;
using std::endl;
using std::find;
using std::pair;
bool label) const
{
if (!selection.set()) return string();
- string result;
- // Special handling if the whole selection is within one paragraph
- if (selection.start.par() == selection.end.par()) {
- result += selection.start.par()->asString(buffer,
- selection.start.pos(),
- selection.end.pos(),
- label);
- return result;
+ // should be const ...
+ Paragraph * startpar(selection.start.par());
+ Paragraph * endpar(selection.end.par());
+ pos_type const startpos(selection.start.pos());
+ pos_type const endpos(selection.end.pos());
+
+ if (startpar == endpar) {
+ return startpar->asString(buffer, startpos, endpos, label);
}
- // The selection spans more than one paragraph
+ string result;
// First paragraph in selection
- result += selection.start.par()->asString(buffer,
- selection.start.pos(),
- selection.start.par()->size(),
- label)
- + "\n\n";
+ result += startpar->asString(buffer, startpos, startpar->size(), label) + "\n\n";
// The paragraphs in between (if any)
LyXCursor tmpcur(selection.start);
tmpcur.par(tmpcur.par()->next());
- while (tmpcur.par() != selection.end.par()) {
+ while (tmpcur.par() != endpar) {
result += tmpcur.par()->asString(buffer, 0,
tmpcur.par()->size(),
label) + "\n\n";
}
// Last paragraph in selection
- result += selection.end.par()->asString(buffer, 0,
- selection.end.pos(), label);
+ result += endpar->asString(buffer, 0, endpos, label);
return result;
}
}
+namespace {
+
+ /**
+ * return true if the cursor given is at the end of a row,
+ * and the next row is filled by an inset that spans an entire
+ * row.
+ */
+ bool beforeFullRowInset(Row & row, LyXCursor & cur) {
+ if (!row.next())
+ return false;
+ Row const & next = *row.next();
+
+ if (next.pos() != cur.pos() || next.par() != cur.par())
+ return false;
+ if (!cur.par()->isInset(cur.pos()))
+ return false;
+ Inset const * inset = cur.par()->getInset(cur.pos());
+ if (inset->needFullRow() || inset->display())
+ return true;
+ return false;
+ }
+}
+
+
void LyXText::setCursorFromCoordinates(BufferView * bview, LyXCursor & cur,
int x, int y) const
{
cur.x(x);
cur.y(y + row->baseline());
cur.row(row);
- Inset * ins;
- if (row->next() && row->next()->pos() == cur.pos() &&
- cur.par() == row->next()->par() &&
- cur.par()->getChar(cur.pos()) == Paragraph::META_INSET &&
- (ins=cur.par()->getInset(cur.pos())) &&
- (ins->needFullRow() || ins->display()))
- {
- // we enter here if we put the cursor on the end of the row before
- // a inset which uses a full row and in that case we HAVE to calculate
- // the right (i) values.
+
+ if (beforeFullRowInset(*row, cur)) {
pos_type last = rowLastPrintable(row);
float x = getCursorX(bview, row->next(), cur.pos(), last, bound);
cur.ix(int(x));
void RCS::checkOut()
{
- owner_->markLyxClean();
+ owner_->markClean();
doVCCommand("co -q -l \""
+ OnlyFilename(owner_->fileName()) + "\"", owner_->filePath());
owner_->getUser()->owner()->getLyXFunc()->dispatch(LFUN_MENURELOAD);
doVCCommand("co -f -u" + version() + " \""
+ OnlyFilename(owner_->fileName()) + "\"", owner_->filePath());
// We ignore changes and just reload!
- owner_->markLyxClean();
+ owner_->markClean();
owner_->getUser()->owner()
->getLyXFunc()->dispatch(LFUN_MENURELOAD);
}
doVCCommand("rm -f \"" + fil + "\"; cvs update \"" + fil + "\"",
owner_->filePath());
- owner_->markLyxClean();
+ owner_->markClean();
owner_->getUser()->owner()
->getLyXFunc()->dispatch(LFUN_MENURELOAD);
}