X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathNest.cpp;h=8efa1181740653209fdd9757ec8c47895a223d42;hb=e438c0f90b2d903fe8a42667c27f492756c3300a;hp=c110e12a13db8cbc617196e5dfa999ca6e7c389f;hpb=acb7906fb5d3db88e43f61b3b25c841d3aac63a0;p=lyx.git diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp index c110e12a13..8efa118174 100644 --- a/src/mathed/InsetMathNest.cpp +++ b/src/mathed/InsetMathNest.cpp @@ -30,16 +30,15 @@ #include "InsetMathUnknown.h" #include "MathAutoCorrect.h" #include "MathCompletionList.h" -#include "MathData.h" #include "MathFactory.h" -#include "MathMacro.h" -#include "MathMacroArgument.h" +#include "InsetMathMacro.h" +#include "InsetMathMacroArgument.h" #include "MathParser.h" #include "MathStream.h" #include "MathSupport.h" -#include "Bidi.h" #include "Buffer.h" +#include "BufferParams.h" #include "BufferView.h" #include "CoordCache.h" #include "Cursor.h" @@ -48,21 +47,24 @@ #include "Encoding.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "LaTeXFeatures.h" #include "LyX.h" #include "LyXRC.h" -#include "OutputParams.h" +#include "MetricsInfo.h" +#include "TexRow.h" #include "Text.h" +#include "frontends/Application.h" #include "frontends/Clipboard.h" #include "frontends/Painter.h" #include "frontends/Selection.h" -#include "support/lassert.h" #include "support/debug.h" +#include "support/docstream.h" #include "support/gettext.h" +#include "support/lassert.h" #include "support/lstrings.h" #include "support/textutils.h" -#include "support/docstream.h" #include #include @@ -82,7 +84,11 @@ using cap::selClearOrDel; InsetMathNest::InsetMathNest(Buffer * buf, idx_type nargs) : InsetMath(buf), cells_(nargs), lock_(false) { - setBuffer(*buf); + // FIXME This should not really be necessary, but when we are + // initializing the table of global macros, we create macros + // with no associated Buffer. + if (buf) + setBuffer(*buf); } @@ -114,15 +120,12 @@ InsetMathNest & InsetMathNest::operator=(InsetMathNest const & inset) void InsetMathNest::setBuffer(Buffer & buffer) { InsetMath::setBuffer(buffer); - for (idx_type i = 0, n = nargs(); i != n; ++i) { - MathData & data = cell(i); - for (size_t j = 0; j != data.size(); ++j) - data[j].nucleus()->setBuffer(buffer); - } + for (MathData & data : cells_) + data.setBuffer(buffer); } -InsetMath::idx_type InsetMathNest::nargs() const +idx_type InsetMathNest::nargs() const { return cells_.size(); } @@ -167,25 +170,27 @@ void InsetMathNest::cursorPos(BufferView const & bv, // << " asc: " << ascent() << " des: " << descent() // << " ar.asc: " << ar.ascent() << " ar.des: " << ar.descent() << endl; // move cursor visually into empty cells ("blue rectangles"); - if (ar.empty()) - x += 2; + if (ar.empty()) { + Dimension const dim = coord_cache.getArrays().dim(&ar); + x += dim.wid / 3; + } } -void InsetMathNest::metrics(MetricsInfo const & mi) const +void InsetMathNest::cellsMetrics(MetricsInfo const & mi) const { MetricsInfo m = mi; - for (idx_type i = 0, n = nargs(); i != n; ++i) { + for (auto const & cell : cells_) { Dimension dim; - cell(i).metrics(m, dim); + cell.metrics(m, dim); } } -void InsetMathNest::updateBuffer(ParIterator const & it, UpdateType utype) +void InsetMathNest::updateBuffer(ParIterator const & it, UpdateType utype, bool const deleted) { for (idx_type i = 0, n = nargs(); i != n; ++i) - cell(i).updateBuffer(it, utype); + cell(i).updateBuffer(it, utype, deleted); } @@ -213,7 +218,7 @@ bool InsetMathNest::idxPrev(Cursor & cur) const if (cur.idx() == 0) return false; --cur.idx(); - cur.pos() = cur.lastpos(); + cur.pos() = lyxrc.mac_like_cursor_movement ? cur.lastpos() : 0; return true; } @@ -229,7 +234,7 @@ bool InsetMathNest::idxFirst(Cursor & cur) const LASSERT(&cur.inset() == this, return false); if (nargs() == 0) return false; - cur.idx() = 0; + cur.idx() = firstIdx(); cur.pos() = 0; return true; } @@ -240,7 +245,7 @@ bool InsetMathNest::idxLast(Cursor & cur) const LASSERT(&cur.inset() == this, return false); if (nargs() == 0) return false; - cur.idx() = cur.lastidx(); + cur.idx() = lastIdx(); cur.pos() = cur.lastpos(); return true; } @@ -249,7 +254,8 @@ bool InsetMathNest::idxLast(Cursor & cur) const void InsetMathNest::dump() const { odocstringstream oss; - WriteStream os(oss); + otexrowstream ots(oss); + TeXMathStream os(ots); os << "---------------------------------------------\n"; write(os); os << "\n"; @@ -260,62 +266,13 @@ void InsetMathNest::dump() const } -void InsetMathNest::draw(PainterInfo & pi, int x, int y) const +void InsetMathNest::draw(PainterInfo &, int, int) const { #if 0 if (lock_) pi.pain.fillRectangle(x, y - ascent(), width(), height(), Color_mathlockbg); #endif - setPosCache(pi, x, y); -} - - -void InsetMathNest::drawSelection(PainterInfo & pi, int x, int y) const -{ - BufferView & bv = *pi.base.bv; - // this should use the x/y values given, not the cached values - Cursor & cur = bv.cursor(); - if (!cur.selection()) - return; - if (&cur.inset() != this) - return; - - // FIXME: hack to get position cache warm - bool const original_drawing_state = pi.pain.isDrawingEnabled(); - pi.pain.setDrawingEnabled(false); - draw(pi, x, y); - pi.pain.setDrawingEnabled(original_drawing_state); - - CursorSlice s1 = cur.selBegin(); - CursorSlice s2 = cur.selEnd(); - - //lyxerr << "InsetMathNest::drawing selection: " - // << " s1: " << s1 << " s2: " << s2 << endl; - if (s1.idx() == s2.idx()) { - MathData const & c = cell(s1.idx()); - Geometry const & g = bv.coordCache().getArrays().geometry(&c); - int x1 = g.pos.x_ + c.pos2x(pi.base.bv, s1.pos()); - int y1 = g.pos.y_ - g.dim.ascent(); - int x2 = g.pos.x_ + c.pos2x(pi.base.bv, s2.pos()); - int y2 = g.pos.y_ + g.dim.descent(); - pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, Color_selection); - //lyxerr << "InsetMathNest::drawing selection 3: " - // << " x1: " << x1 << " x2: " << x2 - // << " y1: " << y1 << " y2: " << y2 << endl; - } else { - for (idx_type i = 0; i < nargs(); ++i) { - if (idxBetween(i, s1.idx(), s2.idx())) { - MathData const & c = cell(i); - Geometry const & g = bv.coordCache().getArrays().geometry(&c); - int x1 = g.pos.x_; - int y1 = g.pos.y_ - g.dim.ascent(); - int x2 = g.pos.x_ + g.dim.width(); - int y2 = g.pos.y_ + g.dim.descent(); - pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, Color_selection); - } - } - } } @@ -369,20 +326,24 @@ MathData InsetMathNest::glue() const } -void InsetMathNest::write(WriteStream & os) const +void InsetMathNest::write(TeXMathStream & os) const { MathEnsurer ensurer(os, currentMode() == MATH_MODE); ModeSpecifier specifier(os, currentMode(), lockedMode()); docstring const latex_name = name(); os << '\\' << latex_name; - for (size_t i = 0; i < nargs(); ++i) + os.inMathClass(asClassInset()); + for (size_t i = 0; i < nargs(); ++i) { + Changer dummy = os.changeRowEntry(TexRow::mathEntry(id(),i)); os << '{' << cell(i) << '}'; + } if (nargs() == 0) os.pendingSpace(true); if (lock_ && !os.latex()) { os << "\\lyxlock"; os.pendingSpace(true); } + os.inMathClass(false); } @@ -397,20 +358,26 @@ void InsetMathNest::normalize(NormalStream & os) const void InsetMathNest::latex(otexstream & os, OutputParams const & runparams) const { - WriteStream wi(os.os(), runparams.moving_arg, true, - runparams.dryrun ? WriteStream::wsDryrun : WriteStream::wsDefault, - runparams.encoding); + TeXMathStream wi(os, runparams.moving_arg, true, + runparams.dryrun ? TeXMathStream::wsDryrun : TeXMathStream::wsDefault, + runparams.encoding); + wi.strikeoutMath(runparams.inDeletedInset); + if (runparams.inulemcmd) { + wi.ulemCmd(TeXMathStream::UNDERLINE); + if (runparams.local_font) { + FontInfo f = runparams.local_font->fontInfo(); + if (f.strikeout() == FONT_ON) + wi.ulemCmd(TeXMathStream::STRIKEOUT); + } + } wi.canBreakLine(os.canBreakLine()); + Changer dummy = wi.changeRowEntry(TexRow::textEntry(runparams.lastid, + runparams.lastpos)); write(wi); + // Reset parbreak and command termination status after a math inset. + os.lastChar(0); os.canBreakLine(wi.canBreakLine()); - - int lf = wi.line(); - if (lf > 0 && runparams.lastid != -1) { - --lf; - os.texrow().newline(); - os.texrow().start(runparams.lastid, runparams.lastpos); - } - os.texrow().newlines(lf); + os.terminateCommand(false); } @@ -483,8 +450,8 @@ void InsetMathNest::handleNest(Cursor & cur, MathAtom const & nest) void InsetMathNest::handleNest(Cursor & cur, MathAtom const & nest, docstring const & arg) { - CursorSlice i1 = cur.selBegin(); - CursorSlice i2 = cur.selEnd(); + DocIterator const i1 = cur.selectionBegin(); + DocIterator const i2 = cur.selectionEnd(); if (!i1.inset().asInsetMath()) return; if (i1.idx() == i2.idx()) { @@ -495,8 +462,9 @@ void InsetMathNest::handleNest(Cursor & cur, MathAtom const & nest, } // multiple selected cells in a simple non-grid inset - if (i1.asInsetMath()->nrows() == 0 || i1.asInsetMath()->ncols() == 0) { + if (i1.inset().nrows() == 0 || i1.inset().ncols() == 0) { for (idx_type i = i1.idx(); i <= i2.idx(); ++i) { + cur.setCursor(i1); // select cell cur.idx() = i; cur.pos() = 0; @@ -504,14 +472,9 @@ void InsetMathNest::handleNest(Cursor & cur, MathAtom const & nest, cur.pos() = cur.lastpos(); cur.setSelection(); - // change font of cell + // do the real job cur.handleNest(nest); cur.insert(arg); - - // cur is in the font inset now. If the loop continues, - // we need to get outside again for the next cell - if (i + 1 <= i2.idx()) - cur.pop_back(); } return; } @@ -519,24 +482,20 @@ void InsetMathNest::handleNest(Cursor & cur, MathAtom const & nest, // the complicated case with multiple selected cells in a grid row_type r1, r2; col_type c1, c2; - cap::region(i1, i2, r1, r2, c1, c2); + cap::region(i1.top(), i2.top(), r1, r2, c1, c2); for (row_type row = r1; row <= r2; ++row) { for (col_type col = c1; col <= c2; ++col) { + cur.setCursor(i1); // select cell - cur.idx() = i1.asInsetMath()->index(row, col); + cur.idx() = i1.inset().index(row, col); cur.pos() = 0; cur.resetAnchor(); cur.pos() = cur.lastpos(); cur.setSelection(); - // + // do the real job cur.handleNest(nest); cur.insert(arg); - - // cur is in the font inset now. If the loop continues, - // we need to get outside again for the next cell - if (col + 1 <= c2 || row + 1 <= r2) - cur.pop_back(); } } } @@ -555,7 +514,6 @@ void InsetMathNest::handleFont2(Cursor & cur, docstring const & arg) // FIXME: support other font changes here as well? } - void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) { //LYXERR0("InsetMathNest: request: " << cmd); @@ -569,19 +527,19 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) parseflg |= Parse::VERBATIM; // fall through case LFUN_PASTE: { - if (cur.currentMode() <= TEXT_MODE) + if (cur.currentMode() != MATH_MODE) parseflg |= Parse::TEXTMODE; cur.recordUndoSelection(); cur.message(_("Paste")); replaceSelection(cur); docstring topaste; if (cmd.argument().empty() && !theClipboard().isInternal()) - topaste = theClipboard().getAsText(Clipboard::PlainTextType); + topaste = theClipboard().getAsText(frontend::Clipboard::PlainTextType); else { size_t n = 0; idocstringstream is(cmd.argument()); is >> n; - topaste = cap::selection(n); + topaste = cap::selection(n, buffer().params().documentClassPtr()); } cur.niceInsert(topaste, parseflg, false); cur.clearSelection(); // bug 393 @@ -592,7 +550,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CUT: cur.recordUndo(); - cutSelection(cur, true, true); + cutSelection(cur, true); cur.message(_("Cut")); // Prevent stale position >= size crash // Probably not necessary anymore, see eraseSelection (gb 2005-10-09) @@ -600,11 +558,6 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) cur.forceBufferUpdate(); break; - case LFUN_COPY: - copySelection(cur); - cur.message(_("Copy")); - break; - case LFUN_MOUSE_PRESS: lfunMousePress(cur, cmd); break; @@ -628,20 +581,42 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) cur.bv().cursor() = cur; break; + case LFUN_WORD_RIGHT: + case LFUN_WORD_LEFT: + case LFUN_WORD_BACKWARD: + case LFUN_WORD_FORWARD: case LFUN_CHAR_RIGHT: case LFUN_CHAR_LEFT: case LFUN_CHAR_BACKWARD: case LFUN_CHAR_FORWARD: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); + // fall through + case LFUN_WORD_RIGHT_SELECT: + case LFUN_WORD_LEFT_SELECT: + case LFUN_WORD_BACKWARD_SELECT: + case LFUN_WORD_FORWARD_SELECT: case LFUN_CHAR_RIGHT_SELECT: case LFUN_CHAR_LEFT_SELECT: case LFUN_CHAR_BACKWARD_SELECT: case LFUN_CHAR_FORWARD_SELECT: { // are we in a selection? - bool select = (act == LFUN_CHAR_RIGHT_SELECT + bool select = (act == LFUN_WORD_RIGHT_SELECT + || act == LFUN_WORD_LEFT_SELECT + || act == LFUN_WORD_BACKWARD_SELECT + || act == LFUN_WORD_FORWARD_SELECT + || act == LFUN_CHAR_RIGHT_SELECT || act == LFUN_CHAR_LEFT_SELECT || act == LFUN_CHAR_BACKWARD_SELECT || act == LFUN_CHAR_FORWARD_SELECT); + // select words + bool word = (act == LFUN_WORD_RIGHT_SELECT + || act == LFUN_WORD_LEFT_SELECT + || act == LFUN_WORD_BACKWARD_SELECT + || act == LFUN_WORD_FORWARD_SELECT + || act == LFUN_WORD_RIGHT + || act == LFUN_WORD_LEFT + || act == LFUN_WORD_BACKWARD + || act == LFUN_WORD_FORWARD); // are we moving forward or backwards? // If the command was RIGHT or LEFT, then whether we're moving forward // or backwards depends on the cursor movement mode (logical or visual): @@ -654,19 +629,25 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) FuncCode finish_lfun; if (act == LFUN_CHAR_FORWARD - || act == LFUN_CHAR_FORWARD_SELECT) { + || act == LFUN_CHAR_FORWARD_SELECT + || act == LFUN_WORD_FORWARD + || act == LFUN_WORD_FORWARD_SELECT) { forward = true; finish_lfun = LFUN_FINISHED_FORWARD; } else if (act == LFUN_CHAR_BACKWARD - || act == LFUN_CHAR_BACKWARD_SELECT) { + || act == LFUN_CHAR_BACKWARD_SELECT + || act == LFUN_WORD_BACKWARD + || act == LFUN_WORD_BACKWARD_SELECT) { forward = false; finish_lfun = LFUN_FINISHED_BACKWARD; } else { bool right = (act == LFUN_CHAR_RIGHT_SELECT - || act == LFUN_CHAR_RIGHT); - if (lyxrc.visual_cursor || !reverseDirectionNeeded(cur)) + || act == LFUN_CHAR_RIGHT + || act == LFUN_WORD_RIGHT_SELECT + || act == LFUN_WORD_RIGHT); + if (lyxrc.visual_cursor || !cur.reverseDirectionNeeded()) forward = right; else forward = !right; @@ -681,7 +662,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) cur.clearTargetX(); cur.macroModeClose(); // try moving forward or backwards as necessary... - if (!(forward ? cursorMathForward(cur) : cursorMathBackward(cur))) { + if (!(forward ? cur.mathForward(word) : cur.mathBackward(word))) { // ... and if movement failed, then finish forward or backwards // as necessary cmd = FuncRequest(finish_lfun); @@ -692,9 +673,14 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_DOWN: case LFUN_UP: + case LFUN_PARAGRAPH_UP: + case LFUN_PARAGRAPH_DOWN: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); + // fall through case LFUN_DOWN_SELECT: - case LFUN_UP_SELECT: { + case LFUN_UP_SELECT: + case LFUN_PARAGRAPH_UP_SELECT: + case LFUN_PARAGRAPH_DOWN_SELECT: { // close active macro if (cur.inMacroMode()) { cur.macroModeClose(); @@ -702,16 +688,15 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) } // stop/start the selection - bool select = act == LFUN_DOWN_SELECT || - act == LFUN_UP_SELECT; + bool select = act == LFUN_DOWN_SELECT + || act == LFUN_UP_SELECT + || act == LFUN_PARAGRAPH_DOWN_SELECT + || act == LFUN_PARAGRAPH_UP_SELECT; cur.selHandle(select); - // handle autocorrect: - cur.autocorrect() = false; - cur.message(_("Autocorrect Off ('!' to enter)")); - // go up/down - bool up = act == LFUN_UP || act == LFUN_UP_SELECT; + bool up = act == LFUN_UP || act == LFUN_UP_SELECT + || act == LFUN_PARAGRAPH_UP || act == LFUN_PARAGRAPH_UP_SELECT; bool successful = cur.upDownInMath(up); if (successful) break; @@ -727,31 +712,26 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_MOUSE_DOUBLE: - case LFUN_MOUSE_TRIPLE: case LFUN_WORD_SELECT: - case LFUN_INSET_SELECT_ALL: cur.pos() = 0; - cur.idx() = 0; - cur.resetAnchor(); - cur.setSelection(true); + cur.bv().mouseSetCursor(cur); cur.pos() = cur.lastpos(); - cur.idx() = cur.lastidx(); + cur.bv().mouseSetCursor(cur, true); break; - case LFUN_PARAGRAPH_UP: - case LFUN_PARAGRAPH_DOWN: - cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); - case LFUN_PARAGRAPH_UP_SELECT: - case LFUN_PARAGRAPH_DOWN_SELECT: + case LFUN_MOUSE_TRIPLE: + cur.idx() = 0; + cur.pos() = 0; + cur.bv().mouseSetCursor(cur); + cur.idx() = cur.lastidx(); + cur.pos() = cur.lastpos(); + cur.bv().mouseSetCursor(cur, true); break; case LFUN_LINE_BEGIN: - case LFUN_WORD_BACKWARD: - case LFUN_WORD_LEFT: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); + // fall through case LFUN_LINE_BEGIN_SELECT: - case LFUN_WORD_BACKWARD_SELECT: - case LFUN_WORD_LEFT_SELECT: cur.selHandle(act == LFUN_WORD_BACKWARD_SELECT || act == LFUN_WORD_LEFT_SELECT || act == LFUN_LINE_BEGIN_SELECT); @@ -770,12 +750,9 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) } break; - case LFUN_WORD_FORWARD: - case LFUN_WORD_RIGHT: case LFUN_LINE_END: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); - case LFUN_WORD_FORWARD_SELECT: - case LFUN_WORD_RIGHT_SELECT: + // fall through case LFUN_LINE_END_SELECT: cur.selHandle(act == LFUN_WORD_FORWARD_SELECT || act == LFUN_WORD_RIGHT_SELECT || @@ -798,12 +775,24 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_CELL_FORWARD: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); - cur.inset().idxNext(cur); + cur.selHandle(false); + cur.clearTargetX(); + cur.macroModeClose(); + if (!cur.inset().idxNext(cur)) { + cur.idx() = firstIdx(); + cur.pos() = 0; + } break; case LFUN_CELL_BACKWARD: cur.screenUpdateFlags(Update::Decoration | Update::FitCursor); - cur.inset().idxPrev(cur); + cur.selHandle(false); + cur.clearTargetX(); + cur.macroModeClose(); + if (!cur.inset().idxPrev(cur)) { + cur.idx() = lastIdx(); + cur.pos() = lyxrc.mac_like_cursor_movement ? cur.lastpos() : 0; + } break; case LFUN_WORD_DELETE_BACKWARD: @@ -814,9 +803,9 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) else if (!cur.inMacroMode()) cur.recordUndoSelection(); // if the inset can not be removed from within, delete it - if (!cur.backspace()) { - FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD); - cur.innerText()->dispatch(cur, cmd); + if (!cur.backspace(cmd.getArg(0) == "force")) { + FuncRequest newcmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD, "force"); + cur.innerText()->dispatch(cur, newcmd); } break; @@ -828,9 +817,9 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) else cur.recordUndoSelection(); // if the inset can not be removed from within, delete it - if (!cur.erase()) { - FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD); - cur.innerText()->dispatch(cur, cmd); + if (!cur.erase(cmd.getArg(0) == "force")) { + FuncRequest newcmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD, "force"); + cur.innerText()->dispatch(cur, newcmd); } break; @@ -838,8 +827,12 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) if (cur.selection()) cur.clearSelection(); else { - cmd = FuncRequest(LFUN_FINISHED_FORWARD); - cur.undispatched(); + if (cur.inMacroMode()) + cur.macroModeClose(true); + else { + cmd = FuncRequest(LFUN_FINISHED_FORWARD); + cur.undispatched(); + } } break; @@ -852,40 +845,37 @@ 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) + cur.editInsertedInset(); + 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; @@ -898,7 +888,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) int y = 0; istringstream is(to_utf8(cmd.argument())); is >> x >> y; - cur.setScreenPos(x, y); + cur.setTargetX(x); break; } @@ -936,37 +926,37 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) break; case LFUN_FONT_BOLD: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) handleFont(cur, cmd.argument(), "textbf"); else handleFont(cur, cmd.argument(), "mathbf"); break; case LFUN_FONT_BOLDSYMBOL: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) handleFont(cur, cmd.argument(), "textbf"); else handleFont(cur, cmd.argument(), "boldsymbol"); break; case LFUN_FONT_SANS: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) handleFont(cur, cmd.argument(), "textsf"); else handleFont(cur, cmd.argument(), "mathsf"); break; case LFUN_FONT_EMPH: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) handleFont(cur, cmd.argument(), "emph"); else handleFont(cur, cmd.argument(), "mathcal"); break; case LFUN_FONT_ROMAN: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) handleFont(cur, cmd.argument(), "textrm"); else handleFont(cur, cmd.argument(), "mathrm"); break; case LFUN_FONT_TYPEWRITER: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) handleFont(cur, cmd.argument(), "texttt"); else handleFont(cur, cmd.argument(), "mathtt"); @@ -975,13 +965,13 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) handleFont(cur, cmd.argument(), "mathfrak"); break; case LFUN_FONT_ITAL: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) handleFont(cur, cmd.argument(), "textit"); else handleFont(cur, cmd.argument(), "mathit"); break; case LFUN_FONT_NOUN: - if (currentMode() <= TEXT_MODE) + if (currentMode() != MATH_MODE) // FIXME: should be "noun" handleFont(cur, cmd.argument(), "textsc"); else @@ -990,11 +980,11 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_FONT_DEFAULT: handleFont(cur, cmd.argument(), "textnormal"); break; - case LFUN_FONT_UNDERLINE: cur.recordUndo(); cur.handleNest(createInsetMath("underline", cur.buffer())); break; + case LFUN_MATH_MODE: { #if 1 // ignore math-mode on when already in math mode @@ -1004,10 +994,10 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) cur.macroModeClose(); docstring const save_selection = grabAndEraseSelection(cur); selClearOrDel(cur); - if (currentMode() <= Inset::TEXT_MODE) + if (currentMode() != Inset::MATH_MODE) cur.plainInsert(MathAtom(new InsetMathEnsureMath(buffer_))); else - cur.plainInsert(MathAtom(new InsetMathBox(buffer_, from_ascii("mbox")))); + cur.plainInsert(createInsetMath("text", buffer_)); cur.posBackward(); cur.pushBackward(*cur.nextInset()); cur.niceInsert(save_selection); @@ -1028,7 +1018,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_REGEXP_MODE: { InsetMath * im = cur.inset().asInsetMath(); if (im) { - InsetMathHull * i = im->asHullInset(); + InsetMathHull * i = im->asHullInset(); if (i && i->getType() == hullRegexp) { cur.message(_("Already in regular expression mode")); break; @@ -1089,9 +1079,10 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) // check if we have a valid decoration if (name != "pmatrix" && name != "bmatrix" && name != "Bmatrix" && name != "vmatrix" - && name != "Vmatrix" && name != "matrix") + && name != "Vmatrix" && name != "matrix" + && name != "smallmatrix") name = from_ascii("matrix"); - + cur.niceInsert( MathAtom(new InsetMathAMSArray(buffer_, name, m, n))); break; @@ -1208,7 +1199,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) bool fold = act == LFUN_MATH_MACRO_FOLD; bool found = findMacroToFoldUnfold(it, fold); if (found) { - MathMacro * macro = it.nextInset()->asInsetMath()->asMacro(); + InsetMathMacro * macro = it.nextInset()->asInsetMath()->asMacro(); cur.recordUndoInset(); if (fold) macro->fold(cur); @@ -1231,10 +1222,12 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) cur.recordUndoSelection(); if (cmd.argument() == "^" || cmd.argument() == "_") interpretChar(cur, cmd.argument()[0]); + else if (!cur.selection()) + cur.niceInsert(cmd.argument()); else { - MathData ar; + MathData ar(cur.buffer()); asArray(cmd.argument(), ar); - if (cur.selection() && ar.size() == 1 + if (ar.size() == 1 && ar[0]->asNestInset() && ar[0]->asNestInset()->nargs() > 1) handleNest(cur, ar[0]); @@ -1244,22 +1237,6 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) break; } - case LFUN_UNICODE_INSERT: { - if (cmd.argument().empty()) - break; - docstring hexstring = cmd.argument(); - if (isHex(hexstring)) { - char_type c = hexToInt(hexstring); - if (c >= 32 && c < 0x10ffff) { - docstring s = docstring(1, c); - FuncCode code = currentMode() == MATH_MODE ? - LFUN_MATH_INSERT : LFUN_SELF_INSERT; - lyx::dispatch(FuncRequest(code, s)); - } - } - break; - } - case LFUN_DIALOG_SHOW_NEW_INSET: { docstring const & name = cmd.argument(); string data; @@ -1278,7 +1255,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) if (createInsetMath_fromDialogStr(cmd.argument(), ar)) { cur.recordUndoSelection(); cur.insert(ar); - cur.forceBufferUpdate(); + cur.forceBufferUpdate(); } else cur.undispatched(); break; @@ -1290,6 +1267,52 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) } break; + case LFUN_MATH_LIMITS: { + InsetMath * in = 0; + if (cur.pos() < cur.lastpos() && cur.nextMath().allowsLimitsChange()) + in = &cur.nextMath(); + else if (cur.pos() > 0 && cur.prevMath().allowsLimitsChange()) + in = &cur.prevMath(); + else if (cur.lastpos() > 0 && cur.cell().back()->allowsLimitsChange()) + in = cur.cell().back().nucleus(); + // only when nucleus allows this + if (!in) + return; + cur.recordUndoInset(); + if (!cmd.argument().empty()) { + if (cmd.argument() == "limits") + in->limits(LIMITS); + else if (cmd.argument() == "nolimits") + in->limits(NO_LIMITS); + else + in->limits(AUTO_LIMITS); + } else if (in->limits() != AUTO_LIMITS) + in->limits(AUTO_LIMITS); + else if (in->defaultLimits(cur.cell().displayStyle()) == LIMITS) + in->limits(NO_LIMITS); + else + in->limits(LIMITS); + return; + } + + case LFUN_PHANTOM_INSERT: { + docstring const & arg = cmd.argument(); + docstring newarg; + if (arg == "Phantom") + newarg = from_ascii("\\phantom"); + else if (arg == "HPhantom") + newarg = from_ascii("\\hphantom"); + else if (arg == "VPhantom") + newarg = from_ascii("\\vphantom"); + if (newarg.empty()) + LYXERR0("Unknown phantom type " + newarg); + else { + FuncRequest const newfunc(LFUN_MATH_INSERT, newarg); + lyx::dispatch(newfunc); + } + break; + } + default: InsetMath::doDispatch(cur, cmd); break; @@ -1304,7 +1327,7 @@ bool InsetMathNest::findMacroToFoldUnfold(Cursor & it, bool fold) const { // go backward through the current cell Inset * inset = it.nextInset(); while (inset && inset->asInsetMath()) { - MathMacro * macro = inset->asInsetMath()->asMacro(); + InsetMathMacro * macro = inset->asInsetMath()->asMacro(); if (macro) { // found the an macro to open/close? if (macro->folded() != fold) @@ -1339,9 +1362,6 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, bool ret = true; string const arg = to_utf8(cmd.argument()); switch (cmd.action()) { - case LFUN_INSET_MODIFY: - flag.setEnabled(false); - break; #if 0 case LFUN_INSET_MODIFY: // FIXME: check temporarily disabled @@ -1417,7 +1437,7 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_INSET_INSERT: { // Don't test createMathInset_fromDialogStr(), since // getStatus is not called with a valid reference and the - // dialog would not be applyable. + // dialog would not be applicable. string const name = cmd.getArg(0); flag.setEnabled(name == "ref" || name == "mathspace"); break; @@ -1454,7 +1474,7 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_CAPTION_INSERT: flag.setEnabled(false); break; - + case LFUN_SPACE_INSERT: { docstring const & name = cmd.argument(); if (name == "visible") @@ -1473,6 +1493,29 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, break; } + case LFUN_MATH_LIMITS: { + InsetMath * in = 0; + if (cur.pos() < cur.lastpos() && cur.nextMath().allowsLimitsChange()) + in = &cur.nextMath(); + else if (cur.pos() > 0 && cur.prevMath().allowsLimitsChange()) + in = &cur.prevMath(); + else if (cur.lastpos() > 0 && cur.cell().back()->allowsLimitsChange()) + in = cur.cell().back().nucleus(); + if (in) { + if (!cmd.argument().empty()) { + if (cmd.argument() == "limits") + flag.setOnOff(in->limits() == LIMITS); + else if (cmd.argument() == "nolimits") + flag.setOnOff(in->limits() == NO_LIMITS); + else + flag.setOnOff(in->limits() == AUTO_LIMITS); + } + flag.setEnabled(true); + } else + flag.setEnabled(false); + return true; + } + default: ret = false; break; @@ -1484,10 +1527,9 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, void InsetMathNest::edit(Cursor & cur, bool front, EntryDirection entry_from) { cur.push(*this); - bool enter_front = (entry_from == Inset::ENTRY_DIRECTION_RIGHT || + bool enter_front = (entry_from == Inset::ENTRY_DIRECTION_LEFT || (entry_from == Inset::ENTRY_DIRECTION_IGNORE && front)); - cur.idx() = enter_front ? 0 : cur.lastidx(); - cur.pos() = enter_front ? 0 : cur.lastpos(); + enter_front ? idxFirst(cur) : idxLast(cur); cur.resetAnchor(); //lyxerr << "InsetMathNest::edit, cur:\n" << cur << endl; } @@ -1495,7 +1537,7 @@ void InsetMathNest::edit(Cursor & cur, bool front, EntryDirection entry_from) Inset * InsetMathNest::editXY(Cursor & cur, int x, int y) { - int idx_min = 0; + int idx_min = -1; int dist_min = 1000000; for (idx_type i = 0, n = nargs(); i != n; ++i) { int const d = cell(i).dist(cur.bv(), x, y); @@ -1504,6 +1546,9 @@ Inset * InsetMathNest::editXY(Cursor & cur, int x, int y) idx_min = i; } } + if (idx_min == -1) + return this; + MathData & ar = cell(idx_min); cur.push(*this); cur.idx() = idx_min; @@ -1533,8 +1578,12 @@ void InsetMathNest::lfunMousePress(Cursor & cur, FuncRequest & cmd) return; } } + + // set cursor after the inset if x is nearer to that position (bug 9748) + cur.moveToClosestEdge(cmd.x(), true); + bool do_selection = cmd.button() == mouse_button::button1 - && cmd.argument() == "region-select"; + && cmd.modifier() == ShiftModifier; bv.mouseSetCursor(cur, do_selection); if (cmd.button() == mouse_button::button1) { //lyxerr << "## lfunMousePress: setting cursor to: " << cur << endl; @@ -1548,7 +1597,7 @@ void InsetMathNest::lfunMousePress(Cursor & cur, FuncRequest & cmd) // cur.result().update(): don't overwrite previously set flags. cur.screenUpdateFlags(Update::Decoration | Update::FitCursor | cur.result().screenUpdate()); - } else if (cmd.button() == mouse_button::button2) { + } else if (cmd.button() == mouse_button::button2 && lyxrc.mouse_middlebutton_paste) { if (cap::selection()) { // See comment in Text::dispatch why we do this cap::copySelectionToStack(); @@ -1566,16 +1615,32 @@ void InsetMathNest::lfunMousePress(Cursor & cur, FuncRequest & cmd) void InsetMathNest::lfunMouseMotion(Cursor & cur, FuncRequest & cmd) { // only select with button 1 - if (cmd.button() == mouse_button::button1) { - Cursor & bvcur = cur.bv().cursor(); - if (bvcur.realAnchor().hasPart(cur)) { - //lyxerr << "## lfunMouseMotion: cursor: " << cur << endl; - bvcur.setCursor(cur); - bvcur.setSelection(true); - //lyxerr << "MOTION " << bvcur << endl; - } else - cur.undispatched(); + if (cmd.button() != mouse_button::button1) + return; + + Cursor & bvcur = cur.bv().cursor(); + + // ignore motions deeper nested than the real anchor + if (!bvcur.realAnchor().hasPart(cur)) { + cur.undispatched(); + return; } + + // set cursor after the inset if x is nearer to that position (bug 9748) + cur.moveToClosestEdge(cmd.x()); + + CursorSlice old = bvcur.top(); + + // We continue with our existing selection or start a new one, so don't + // reset the anchor. + bvcur.setCursor(cur); + // Did we actually move? + if (cur.top() == old) + // We didn't move one iota, so no need to change selection status + // or update the screen. + cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor); + else + bvcur.setSelection(); } @@ -1588,7 +1653,7 @@ void InsetMathNest::lfunMouseRelease(Cursor & cur, FuncRequest & cmd) cur.noScreenUpdate(); else { Cursor & bvcur = cur.bv().cursor(); - bvcur.setSelection(true); + bvcur.selection(true); } return; } @@ -1599,6 +1664,11 @@ void InsetMathNest::lfunMouseRelease(Cursor & cur, FuncRequest & cmd) bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) { + // try auto-correction + if (lyxrc.autocorrection_math && cur.pos() != 0 + && math_autocorrect(cur, c)) + return true; + //lyxerr << "interpret 2: '" << c << "'" << endl; docstring save_selection; if (c == '^' || c == '_') @@ -1616,14 +1686,13 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) cur.backspace(); int n = c - '0'; if (n >= 1 && n <= 9) - cur.insert(new MathMacroArgument(n)); + cur.insert(new InsetMathMacroArgument(n)); return true; } // do not finish macro for known * commands - MathWordList const & mwl = mathedWordList(); bool star_macro = c == '*' - && (mwl.find(name.substr(1) + "*") != mwl.end() + && (in_word_set(name.substr(1) + '*') || cur.buffer()->getMacro(name.substr(1) + "*", cur, true)); if (isAlphaASCII(c) || star_macro) { cur.activeMacro()->setName(name + docstring(1, c)); @@ -1635,19 +1704,24 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) // remove the '\\' if (c == '\\') { cur.backspace(); - if (currentMode() <= InsetMath::TEXT_MODE) + if (currentMode() != InsetMath::MATH_MODE) cur.niceInsert(createInsetMath("textbackslash", buf)); else cur.niceInsert(createInsetMath("backslash", buf)); } else if (c == '^' && currentMode() == InsetMath::MATH_MODE) { cur.backspace(); cur.niceInsert(createInsetMath("mathcircumflex", buf)); - } else if (c == '{') { - cur.backspace(); - cur.niceInsert(MathAtom(new InsetMathBrace(buf))); - } else if (c == '%') { + } else if (c == '{' || c == '%') { + //using the saved selection as argument + InsetMathUnknown * p = cur.activeMacro(); + p->finalize(); + MathData sel(cur.buffer()); + asArray(p->selection(), sel); cur.backspace(); - cur.niceInsert(MathAtom(new InsetMathComment(buf))); + if (c == '{') + cur.niceInsert(MathAtom(new InsetMathBrace(sel))); + else + cur.niceInsert(MathAtom(new InsetMathComment(sel))); } else if (c == '#') { LASSERT(cur.activeMacro(), return false); cur.activeMacro()->setName(name + docstring(1, c)); @@ -1700,7 +1774,7 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) MathAtom const atom = cur.prevAtom(); if (atom->asNestInset() && atom->isActive()) { cur.posBackward(); - cur.pushBackward(*cur.nextInset()); + cur.nextInset()->edit(cur, true); } } if (c == '{') @@ -1711,21 +1785,9 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) } - // leave autocorrect mode if necessary - if (lyxrc.autocorrection_math && c == ' ' && cur.autocorrect()) { - cur.autocorrect() = false; - cur.message(_("Autocorrect Off ('!' to enter)")); - return true; - } - if (lyxrc.autocorrection_math && c == '!' && !cur.autocorrect()) { - cur.autocorrect() = true; - cur.message(_("Autocorrect On ( to exit)")); - return true; - } - // just clear selection on pressing the space bar if (cur.selection() && c == ' ') { - cur.setSelection(false); + cur.selection(false); return true; } @@ -1746,18 +1808,18 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) selClearOrDel(cur); if (c == '\n') { - if (currentMode() <= InsetMath::TEXT_MODE) + if (currentMode() != InsetMath::MATH_MODE) cur.insert(c); return true; } if (c == ' ') { - if (currentMode() <= InsetMath::TEXT_MODE) { + if (currentMode() != InsetMath::MATH_MODE) { // insert spaces in text or undecided mode, // but suppress direct insertion of two spaces in a row // the still allows typing 'a' and deleting the 'a', but // it is better than nothing... - if (!cur.pos() != 0 || cur.prevAtom()->getChar() != ' ') { + if (cur.pos() == 0 || cur.prevAtom()->getChar() != ' ') { cur.insert(c); // FIXME: we have to enable full redraw here because of the // visual box corners that define the inset. If we know for @@ -1793,9 +1855,6 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) // These should be treated differently when not in text mode: if (cur.inRegexped()) { switch (c) { - case '\\': - cur.niceInsert(createInsetMath("backslash", buf)); - break; case '^': cur.niceInsert(createInsetMath("mathcircumflex", buf)); break; @@ -1826,10 +1885,10 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) cur.niceInsert(createInsetMath("sim", buf)); return true; } - if (currentMode() == InsetMath::MATH_MODE && !isAsciiOrMathAlpha(c)) { + if (currentMode() == InsetMath::MATH_MODE && Encodings::isUnicodeTextOnly(c)) { MathAtom at = createInsetMath("text", buf); at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c))); - cur.niceInsert(at); + cur.insert(at); cur.posForward(); return true; } @@ -1850,26 +1909,23 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) return true; } - - // try auto-correction - if (lyxrc.autocorrection_math && cur.autocorrect() && cur.pos() != 0 - && math_autocorrect(cur.prevAtom(), c)) - return true; - // no special circumstances, so insert the character without any fuss cur.insert(c); - if (lyxrc.autocorrection_math) { - if (!cur.autocorrect()) - cur.message(_("Autocorrect Off ('!' to enter)")); - else - cur.message(_("Autocorrect On ( to exit)")); - } return true; } bool InsetMathNest::interpretString(Cursor & cur, docstring const & str) { + if (str == "\\limits" || str == "\\nolimits") { + if (cur.pos() > 0 && cur.prevMath().allowsLimitsChange()) { + cur.prevMath().limits(str == "\\limits" ? LIMITS : NO_LIMITS); + return true; + } else { + cur.message(bformat(_("Cannot apply %1$s here."), str)); + return false; + } + } // Create a InsetMathBig from cur.cell()[cur.pos() - 1] and t if // possible if (!cur.empty() && cur.pos() > 0 && @@ -1880,6 +1936,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; @@ -1979,7 +2036,7 @@ CompletionList const * InsetMathNest::createCompletionList(Cursor const & cur) const { if (!cur.inMacroMode()) - return 0; + return nullptr; return new MathCompletionList(cur); } @@ -2009,8 +2066,7 @@ bool InsetMathNest::insertCompletion(Cursor & cur, docstring const & s, #if 0 // FIXME: this creates duplicates in the completion popup // which looks ugly. Moreover the changes the list lengths - // which seems to - confuse the popup as well. + // which seems to confuse the popup as well. MathCompletionList::addToFavorites(inset->name()); #endif lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, " ")); @@ -2041,43 +2097,6 @@ void InsetMathNest::completionPosAndDim(Cursor const & cur, int & x, int & y, } -bool InsetMathNest::cursorMathForward(Cursor & cur) -{ - if (cur.pos() != cur.lastpos() && cur.openable(cur.nextAtom())) { - cur.pushBackward(*cur.nextAtom().nucleus()); - cur.inset().idxFirst(cur); - return true; - } - if (cur.posForward() || idxForward(cur)) - return true; - // try to pop forwards --- but don't pop out of math! leave that to - // the FINISH lfuns - int s = cur.depth() - 2; - if (s >= 0 && cur[s].inset().asInsetMath()) - return cur.popForward(); - return false; -} - - -bool InsetMathNest::cursorMathBackward(Cursor & cur) -{ - if (cur.pos() != 0 && cur.openable(cur.prevAtom())) { - cur.posBackward(); - cur.push(*cur.nextAtom().nucleus()); - cur.inset().idxLast(cur); - return true; - } - if (cur.posBackward() || idxBackward(cur)) - return true; - // try to pop backwards --- but don't pop out of math! leave that to - // the FINISH lfuns - int s = cur.depth() - 2; - if (s >= 0 && cur[s].inset().asInsetMath()) - return cur.popBackward(); - return false; -} - - //////////////////////////////////////////////////////////////////// MathCompletionList::MathCompletionList(Cursor const & cur) @@ -2097,7 +2116,7 @@ MathCompletionList::MathCompletionList(Cursor const & cur) // fill in global macros macros.clear(); - MacroTable::globalMacros().getMacroNames(macros); + MacroTable::globalMacros().getMacroNames(macros, false); //lyxerr << "Globals completion macros: "; for (it = macros.begin(); it != macros.end(); ++it) { //lyxerr << "\\" + *it << " "; @@ -2111,8 +2130,21 @@ MathCompletionList::MathCompletionList(Cursor const & cur) globals.push_back(from_ascii("\\framebox")); globals.push_back(from_ascii("\\makebox")); globals.push_back(from_ascii("\\kern")); + globals.push_back(from_ascii("\\xhookrightarrow")); + globals.push_back(from_ascii("\\xhookleftarrow")); globals.push_back(from_ascii("\\xrightarrow")); + globals.push_back(from_ascii("\\xRightarrow")); + globals.push_back(from_ascii("\\xrightharpoondown")); + globals.push_back(from_ascii("\\xrightharpoonup")); + globals.push_back(from_ascii("\\xrightleftharpoons")); globals.push_back(from_ascii("\\xleftarrow")); + globals.push_back(from_ascii("\\xLeftarrow")); + globals.push_back(from_ascii("\\xleftharpoondown")); + globals.push_back(from_ascii("\\xleftharpoonup")); + globals.push_back(from_ascii("\\xleftrightarrow")); + globals.push_back(from_ascii("\\xLeftrightarrow")); + globals.push_back(from_ascii("\\xleftrightharpoons")); + globals.push_back(from_ascii("\\xmapsto")); globals.push_back(from_ascii("\\split")); globals.push_back(from_ascii("\\gathered")); globals.push_back(from_ascii("\\aligned")); @@ -2126,6 +2158,7 @@ MathCompletionList::MathCompletionList(Cursor const & cur) globals.push_back(from_ascii("\\sqrt")); globals.push_back(from_ascii("\\root")); globals.push_back(from_ascii("\\tabular")); + globals.push_back(from_ascii("\\sideset")); globals.push_back(from_ascii("\\stackrel")); globals.push_back(from_ascii("\\stackrelthree")); globals.push_back(from_ascii("\\binom")); @@ -2165,12 +2198,16 @@ MathCompletionList::MathCompletionList(Cursor const & cur) globals.push_back(from_ascii("\\mathclap")); globals.push_back(from_ascii("\\mathllap")); globals.push_back(from_ascii("\\mathrlap")); + globals.push_back(from_ascii("\\ensuremath")); MathWordList const & words = mathedWordList(); MathWordList::const_iterator it2; //lyxerr << "Globals completion commands: "; for (it2 = words.begin(); it2 != words.end(); ++it2) { - globals.push_back("\\" + (*it2).first); - //lyxerr << "\\" + (*it2).first << " "; + if (it2->second.inset != "macro" && !it2->second.hidden) { + // macros are already read from MacroTable::globalMacros() + globals.push_back('\\' + it2->first); + //lyxerr << '\\' + it2->first << ' '; + } } //lyxerr << std::endl; sort(globals.begin(), globals.end()); @@ -2208,8 +2245,11 @@ std::string MathCompletionList::icon(size_t idx) const else cmd = locals[idx]; - // get the icon resource name by stripping the backslash - return "images/math/" + to_utf8(cmd.substr(1)) + ".png"; + // get the icon name by stripping the backslash + docstring icon_name = frontend::Application::mathIcon(cmd.substr(1)); + if (icon_name.empty()) + return std::string(); + return "math/" + to_utf8(icon_name); } std::vector MathCompletionList::globals;