From ad5548cfe39a17389ca721aab896e876f2cd4124 Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Thu, 5 Jul 2018 14:01:56 +0200 Subject: [PATCH] Fixes to input method handling The goal of this patch is to make "self-insert " act as a sequence of individual self-insert calls. Once it is done, the insertion of the commit string in GuiWorkArea can use that, which fixes the issues described in bug 11183. 1/ in InsetMathNest, SELF_INSERT is rewritten to be a proper loop of interpretChar, instead of inserting the string as characters. This solves the issue of interpreting ^ properly. 2/ the text version does not need to be changed (the loop is rewritten using a range, though). 3/ Then {{{GuiWorkArea::inputMethodEvent}}} is changed to invoke directly self-insert. This removes the update issues. Fixes bug 11183. --- src/Text3.cpp | 7 +--- src/frontends/qt4/GuiWorkArea.cpp | 11 +++--- src/mathed/InsetMathNest.cpp | 64 ++++++++++++++++--------------- src/mathed/InsetMathNest.h | 2 +- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/Text3.cpp b/src/Text3.cpp index 619bbf8716..0f40ec2dc6 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -1920,13 +1920,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (lyxrc.auto_region_delete && cur.selection()) cutSelection(cur, false, false); - cur.clearSelection(); - docstring::const_iterator cit = cmd.argument().begin(); - docstring::const_iterator const end = cmd.argument().end(); - for (; cit != end; ++cit) - bv->translateAndInsert(*cit, this, cur); + for (char_type c : cmd.argument()) + bv->translateAndInsert(c, this, cur); cur.resetAnchor(); moveCursor(cur, false); diff --git a/src/frontends/qt4/GuiWorkArea.cpp b/src/frontends/qt4/GuiWorkArea.cpp index 43e7b576ec..e6d993c273 100644 --- a/src/frontends/qt4/GuiWorkArea.cpp +++ b/src/frontends/qt4/GuiWorkArea.cpp @@ -1293,12 +1293,13 @@ void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e) // insert the processed text in the document (handles undo) if (!e->commitString().isEmpty()) { - d->buffer_view_->cursor().beginUndoGroup(); - d->buffer_view_->cursor().insert(qstring_to_ucs4(e->commitString())); + FuncRequest cmd(LFUN_SELF_INSERT, + qstring_to_ucs4(e->commitString()), + FuncRequest::KEYBOARD); + dispatch(cmd); + // FIXME: this is supposed to remove traces from preedit + // string. Can we avoid calling it explicitely? d->buffer_view_->updateMetrics(); - d->buffer_view_->cursor().endUndoGroup(); - d->updateCaretGeometry(); - viewport()->update(); } // Hide the caret during the test transformation. diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp index b026b888f0..ca3b01e4db 100644 --- a/src/mathed/InsetMathNest.cpp +++ b/src/mathed/InsetMathNest.cpp @@ -854,40 +854,41 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) break; case LFUN_SELF_INSERT: - if (cmd.argument().size() != 1) { - cur.recordUndoSelection(); - docstring const arg = cmd.argument(); - if (!interpretString(cur, arg)) - cur.insert(arg); + // special case first for big delimiters + if (cmd.argument().size() != 1 && interpretString(cur, cmd.argument())) break; - } - // Don't record undo steps if we are in macro mode and thus - // cmd.argument is the next character of the macro name. - // Otherwise we'll get an invalid cursor if we undo after - // the macro was finished and the macro is a known command, - // e.g. sqrt. Cursor::macroModeClose replaces in this case - // the InsetMathUnknown with name "frac" by an empty - // InsetMathFrac -> a pos value > 0 is invalid. - // A side effect is that an undo before the macro is finished - // undoes the complete macro, not only the last character. - // At the time we hit '\' we are not in macro mode, still. - if (!cur.inMacroMode()) - cur.recordUndoSelection(); - // spacial handling of space. If we insert an inset - // via macro mode, we want to put the cursor inside it - // if relevant. Think typing "\frac". - if (cmd.argument()[0] == ' ' - && cur.inMacroMode() && cur.macroName() != "\\" - && cur.macroModeClose() && cur.pos() > 0) { - MathAtom const atom = cur.prevAtom(); - if (atom->asNestInset() && atom->isActive()) { - cur.posBackward(); - cur.pushBackward(*cur.nextInset()); + for (char_type c : cmd.argument()) { + // Don't record undo steps if we are in macro mode and thus + // cmd.argument is the next character of the macro name. + // Otherwise we'll get an invalid cursor if we undo after + // the macro was finished and the macro is a known command, + // e.g. sqrt. Cursor::macroModeClose replaces in this case + // the InsetMathUnknown with name "frac" by an empty + // InsetMathFrac -> a pos value > 0 is invalid. + // A side effect is that an undo before the macro is finished + // undoes the complete macro, not only the last character. + // At the time we hit '\' we are not in macro mode, still. + if (!cur.inMacroMode()) + cur.recordUndoSelection(); + + // special handling of space. If we insert an inset + // via macro mode, we want to put the cursor inside it + // if relevant. Think typing "\frac". + if (c == ' ' + && cur.inMacroMode() && cur.macroName() != "\\" + && cur.macroModeClose() && cur.pos() > 0) { + MathAtom const atom = cur.prevAtom(); + if (atom->asNestInset() && atom->isActive()) { + cur.posBackward(); + cur.pushBackward(*cur.nextInset()); + } + } else if (!interpretChar(cur, c)) { + cmd = FuncRequest(LFUN_FINISHED_FORWARD); + cur.undispatched(); + // FIXME: can we avoid skipping the end of the string? + break; } - } else if (!interpretChar(cur, cmd.argument()[0])) { - cmd = FuncRequest(LFUN_FINISHED_FORWARD); - cur.undispatched(); } break; @@ -1889,6 +1890,7 @@ bool InsetMathNest::interpretString(Cursor & cur, docstring const & str) prev = prev.substr(1); latexkeys const * l = in_word_set(prev); if (l && l->inset == "big") { + cur.recordUndoSelection(); cur.cell()[cur.pos() - 1] = MathAtom(new InsetMathBig(prev, str)); return true; diff --git a/src/mathed/InsetMathNest.h b/src/mathed/InsetMathNest.h index 57e7ab340f..a009bd3234 100644 --- a/src/mathed/InsetMathNest.h +++ b/src/mathed/InsetMathNest.h @@ -171,7 +171,7 @@ protected: public: /// interpret \p str and insert the result at the current position of /// \p cur if it is something known. Return whether \p cur was - /// inserted. + /// inserted. Handles undo. virtual bool interpretString(Cursor & cur, docstring const & str); private: -- 2.39.5