+bool SpellcheckerWidget::Private::isCurrentBuffer(DocIterator const & cursor) const
+{
+ return start_.buffer() == cursor.buffer();
+}
+
+bool SpellcheckerWidget::Private::atLastPos(DocIterator const & cursor) const
+{
+ bool const valid_end = !end_.empty();
+ return cursor.depth() <= 1 && (
+ cursor.atEnd() ||
+ (valid_end && isCurrentBuffer(cursor) && cursor >= end_));
+}
+
+bool SpellcheckerWidget::Private::isWrapAround(DocIterator const & cursor) const
+{
+ return wrap_around_ && isCurrentBuffer(cursor) && start_ < cursor;
+}
+
+void SpellcheckerWidget::Private::fixPositionsIfBroken()
+{
+ DocIterator const current_ = cursor();
+ if (!isCurrentBuffer(current_)) {
+ LYXERR(Debug::GUI, "wrong document of current cursor position " << start_);
+ start_ = current_;
+ begin_ = DocIterator();
+ end_ = DocIterator();
+ }
+ if (start_.fixIfBroken())
+ LYXERR(Debug::GUI, "broken start position fixed " << start_);
+ if (begin_.fixIfBroken()) {
+ LYXERR(Debug::GUI, "broken selection begin position fixed " << begin_);
+ begin_ = DocIterator();
+ end_ = DocIterator();
+ }
+ if (end_.fixIfBroken())
+ LYXERR(Debug::GUI, "broken selection end position fixed " << end_);
+}
+
+void SpellcheckerWidget::Private::hide() const
+{
+ BufferView * bv = gv_->documentBufferView();
+ Cursor & bvcur = bv->cursor();
+ dv_->hide();
+ if (isCurrentBuffer(bvcur)) {
+ if (!begin_.empty() && !end_.empty()) {
+ // restore previous selection
+ setSelection(begin_, end_);
+ } else {
+ // restore cursor position
+ bvcur.setCursor(start_);
+ bvcur.clearSelection();
+ bv->processUpdateFlags(Update::Force | Update::FitCursor);
+ }
+ }
+}
+
+void SpellcheckerWidget::Private::setSelection(
+ DocIterator const & from, DocIterator const & to) const
+{
+ BufferView * bv = gv_->documentBufferView();
+ DocIterator end = to;
+
+ if (from.pit() != end.pit()) {
+ // there are multiple paragraphs in selection
+ Cursor & bvcur = bv->cursor();
+ bvcur.setCursor(from);
+ bvcur.clearSelection();
+ bvcur.selection(true);
+ bvcur.setCursor(end);
+ bvcur.selection(true);
+ } else {
+ // FIXME LFUN
+ // If we used a LFUN, dispatch would do all of this for us
+ int const size = end.pos() - from.pos();
+ bv->putSelectionAt(from, size, false);
+ }
+ bv->processUpdateFlags(Update::Force | Update::FitCursor);
+}
+
+void SpellcheckerWidget::Private::forward()
+{
+ DocIterator const from = cursor();
+
+ dispatch(FuncRequest(LFUN_ESCAPE));
+ fixPositionsIfBroken();
+ if (!atLastPos(cursor())) {
+ dispatch(FuncRequest(LFUN_CHAR_FORWARD));
+ }
+ if (atLastPos(cursor())) {
+ return;
+ }
+ if (from == cursor()) {
+ //FIXME we must be at the end of a cell
+ dispatch(FuncRequest(LFUN_CHAR_FORWARD));
+ }
+ if (isWrapAround(cursor())) {
+ hide();
+ }
+}
+
+
+void SpellcheckerWidget::on_languageCO_activated(int index)