X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FCursor.cpp;h=b20e981b32c506cab09c2e7cc34e1989bc0a55b9;hb=ab8a290040dc28f39ebb230ab4b8a43467df0906;hp=16067119e3eb376586b450d0349277b6084f7ba7;hpb=6a80ce62cab3b2623479da70fa90e65db346d152;p=lyx.git diff --git a/src/Cursor.cpp b/src/Cursor.cpp index 16067119e3..b20e981b32 100644 --- a/src/Cursor.cpp +++ b/src/Cursor.cpp @@ -26,6 +26,7 @@ #include "FuncCode.h" #include "FuncRequest.h" #include "Language.h" +#include "Layout.h" #include "LyXAction.h" #include "LyXRC.h" #include "Paragraph.h" @@ -94,20 +95,18 @@ DocIterator bruteFind2(Cursor const & c, int x, int y) int xo; int yo; Inset const * inset = &it.inset(); - map const & data = - c.bv().coordCache().getInsets().getData(); - map::const_iterator I = data.find(inset); + CoordCache const & cache = c.bv().coordCache(); // FIXME: in the case where the inset is not in the cache, this // means that no part of it is visible on screen. In this case // we don't do elaborate search and we just return the forwarded // DocIterator at its beginning. - if (I == data.end()) { + if (!cache.getInsets().has(inset)) { it.top().pos() = 0; return it; } - Point o = I->second.pos; + Point const o = cache.getInsets().xy(inset); inset->cursorPos(c.bv(), it.top(), c.boundary(), xo, yo); // Convert to absolute xo += o.x_; @@ -153,7 +152,7 @@ bool bruteFind(Cursor & cursor, else ++et.pit(); - double best_dist = numeric_limits::max();; + double best_dist = numeric_limits::max(); DocIterator best_cursor = et; for ( ; it != et; it.forwardPos(true)) { @@ -332,9 +331,11 @@ void Cursor::dispatch(FuncRequest const & cmd0) fixIfBroken(); FuncRequest cmd = cmd0; Cursor safe = *this; + Cursor old = *this; + disp_ = DispatchResult(); buffer()->undo().beginUndoGroup(); - + // Is this a function that acts on inset at point? if (lyxaction.funcHasFlag(cmd.action(), LyXAction::AtPoint) && nextInset()) { @@ -391,6 +392,18 @@ void Cursor::dispatch(FuncRequest const & cmd0) beforeDispatchCursor_ = safe.beforeDispatchCursor_; } buffer()->undo().endUndoGroup(); + + // notify insets we just left + if (*this != old) { + old.beginUndoGroup(); + old.fixIfBroken(); + bool badcursor = notifyCursorLeavesOrEnters(old, *this); + if (badcursor) { + fixIfBroken(); + bv().resetInlineCompletionPos(); + } + old.endUndoGroup(); + } } @@ -488,6 +501,7 @@ Row const & Cursor::textRow() const void Cursor::resetAnchor() { anchor_ = *this; + checkNewWordPosition(); } @@ -504,6 +518,67 @@ void Cursor::setCursorToAnchor() } +void Cursor::markNewWordPosition() +{ + if (lyxrc.spellcheck_continuously && inTexted() && new_word_.empty()) { + FontSpan nw = locateWord(WHOLE_WORD); + if (nw.size() == 1) { + LYXERR(Debug::DEBUG, "start new word: " + << " par: " << pit() + << " pos: " << nw.first); + new_word_ = *this; + } + } +} + + +void Cursor::clearNewWordPosition() +{ + if (!new_word_.empty()) { + LYXERR(Debug::DEBUG, "clear new word: " + << " par: " << pit() + << " pos: " << pos()); + new_word_.resize(0); + } +} + + +void Cursor::checkNewWordPosition() +{ + if (!lyxrc.spellcheck_continuously || new_word_.empty()) + return ; + if (!inTexted()) + clearNewWordPosition(); + else { + // forget the position of the current new word if + // 1) the paragraph changes or + // 2) the count of nested insets changes or + // 3) the cursor pos is out of paragraph bound + if (pit() != new_word_.pit() || + depth() != new_word_.depth() || + new_word_.pos() > new_word_.lastpos()) { + clearNewWordPosition(); + } else if (new_word_.fixIfBroken()) + // 4) or the remembered position was "broken" + clearNewWordPosition(); + else { + FontSpan nw = locateWord(WHOLE_WORD); + if (nw.size()) { + FontSpan ow = new_word_.locateWord(WHOLE_WORD); + if (nw.intersect(ow).empty()) + clearNewWordPosition(); + else + LYXERR(Debug::DEBUG, "new word: " + << " par: " << pit() + << " pos: " << nw.first << ".." << nw.last); + } else { + clearNewWordPosition(); + } + } + } +} + + bool Cursor::posBackward() { if (pos() == 0) @@ -1200,9 +1275,6 @@ LyXErr & operator<<(LyXErr & os, Cursor const & cur) namespace lyx { -//#define FILEDEBUG 1 - - bool Cursor::isInside(Inset const * p) const { for (size_t i = 0; i != depth(); ++i) @@ -1314,7 +1386,7 @@ void Cursor::insert(Inset * inset0) { LASSERT(inset0, /**/); if (inMathed()) - insert(MathAtom(inset0)); + insert(MathAtom(inset0->asInsetMath())); else { text()->insertInset(*this, inset0); inset0->setBuffer(bv_->buffer()); @@ -1325,7 +1397,7 @@ void Cursor::insert(Inset * inset0) } -void Cursor::niceInsert(docstring const & t, Parse::flags f, bool enter) +int Cursor::niceInsert(docstring const & t, Parse::flags f, bool enter) { MathData ar(buffer()); asArray(t, ar, f); @@ -1333,6 +1405,7 @@ void Cursor::niceInsert(docstring const & t, Parse::flags f, bool enter) niceInsert(ar[0]); else insert(ar); + return ar.size(); } @@ -1351,6 +1424,15 @@ void Cursor::niceInsert(MathAtom const & t) MathData ar(buffer()); asArray(safe, ar); insert(ar); + } else if (t->asMacro() && !safe.empty()) { + MathData ar(buffer()); + asArray(safe, ar); + docstring const name = t->asMacro()->name(); + MacroData const * data = buffer()->getMacro(name); + if (data && data->numargs() - data->optionals() > 0) { + plainInsert(MathAtom(new InsetMathBrace(ar))); + posBackward(); + } } } @@ -1603,7 +1685,7 @@ bool Cursor::inMacroMode() const { if (!inMathed()) return false; - if (pos() == 0) + if (pos() == 0 || cell().empty()) return false; InsetMathUnknown const * p = prevAtom()->asUnknownInset(); return p && !p->final(); @@ -2015,15 +2097,18 @@ void Cursor::errorMessage(docstring const & msg) const } -static docstring parbreak(InsetCode code) +namespace { +docstring parbreak(Cursor const * cur) { odocstringstream os; os << '\n'; - // only add blank line if we're not in an ERT or Listings inset - if (code != ERT_CODE && code != LISTINGS_CODE) + // only add blank line if we're not in a ParbreakIsNewline situation + if (!cur->inset().getLayout().parbreakIsNewline() + && !cur->paragraph().layout().parbreak_is_newline) os << '\n'; return os.str(); } +} docstring Cursor::selectionAsString(bool with_label) const @@ -2059,13 +2144,13 @@ docstring Cursor::selectionAsString(bool with_label) const // First paragraph in selection docstring result = pars[startpit]. asString(startpos, pars[startpit].size(), label) - + parbreak(inset().lyxCode()); + + parbreak(this); // The paragraphs in between (if any) for (pit_type pit = startpit + 1; pit != endpit; ++pit) { Paragraph const & par = pars[pit]; result += par.asString(0, par.size(), label) - + parbreak(inset().lyxCode()); + + parbreak(this); } // Last paragraph in selection @@ -2108,31 +2193,31 @@ Encoding const * Cursor::getEncoding() const } -void Cursor::undispatched() +void Cursor::undispatched() const { disp_.dispatched(false); } -void Cursor::dispatched() +void Cursor::dispatched() const { disp_.dispatched(true); } -void Cursor::screenUpdateFlags(Update::flags f) +void Cursor::screenUpdateFlags(Update::flags f) const { disp_.screenUpdate(f); } -void Cursor::forceBufferUpdate() +void Cursor::forceBufferUpdate() const { disp_.forceBufferUpdate(); } -void Cursor::clearBufferUpdate() +void Cursor::clearBufferUpdate() const { disp_.clearBufferUpdate(); } @@ -2144,7 +2229,7 @@ bool Cursor::needBufferUpdate() const } -void Cursor::noScreenUpdate() +void Cursor::noScreenUpdate() const { disp_.screenUpdate(Update::None); } @@ -2190,6 +2275,7 @@ bool Cursor::fixIfBroken() bool const broken_anchor = anchor_.fixIfBroken(); if (broken_cursor || broken_anchor) { + clearNewWordPosition(); clearSelection(); return true; } @@ -2344,9 +2430,9 @@ void Cursor::recordUndo(UndoKind kind) const } -void Cursor::recordUndoInset(UndoKind kind) const +void Cursor::recordUndoInset(UndoKind kind, Inset const * inset) const { - buffer()->undo().recordUndoInset(*this, kind); + buffer()->undo().recordUndoInset(*this, kind, inset); }