X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathNest.cpp;h=0a7810784acb6520c0380ce029f6ef7a23588263;hb=b5049e769bba3923cf8e21c980c75b7c00187420;hp=12a0e2bcbf6d38cefa0ab2d0e75345fcddd95dcd;hpb=a1a9c4c4ba5c246e34def3a5c51ced24ce18e66a;p=features.git diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp index 12a0e2bcbf..0a7810784a 100644 --- a/src/mathed/InsetMathNest.cpp +++ b/src/mathed/InsetMathNest.cpp @@ -13,6 +13,7 @@ #include "InsetMathNest.h" #include "InsetMathArray.h" +#include "InsetMathAMSArray.h" #include "InsetMathBig.h" #include "InsetMathBox.h" #include "InsetMathBrace.h" @@ -20,6 +21,7 @@ #include "InsetMathColor.h" #include "InsetMathComment.h" #include "InsetMathDelim.h" +#include "InsetMathEnsureMath.h" #include "InsetMathHull.h" #include "InsetMathRef.h" #include "InsetMathScript.h" @@ -46,7 +48,7 @@ #include "Encoding.h" #include "FuncRequest.h" #include "FuncStatus.h" -#include "LyXFunc.h" +#include "LyX.h" #include "LyXRC.h" #include "OutputParams.h" #include "Text.h" @@ -77,9 +79,11 @@ using cap::replaceSelection; using cap::selClearOrDel; -InsetMathNest::InsetMathNest(idx_type nargs) - : cells_(nargs), lock_(false), mouse_hover_(false) -{} +InsetMathNest::InsetMathNest(Buffer * buf, idx_type nargs) + : InsetMath(buf), cells_(nargs), lock_(false), mouse_hover_(false) +{ + setBuffer(*buf); +} InsetMathNest::InsetMathNest(InsetMathNest const & inset) @@ -98,6 +102,17 @@ 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); + } +} + + InsetMath::idx_type InsetMathNest::nargs() const { return cells_.size(); @@ -158,6 +173,14 @@ void InsetMathNest::metrics(MetricsInfo const & mi) const } +void InsetMathNest::updateLabels(ParIterator const & it, UpdateType utype) +{ + for (idx_type i = 0, n = nargs(); i != n; ++i) + cell(i).updateLabels(it, utype); +} + + + bool InsetMathNest::idxNext(Cursor & cur) const { LASSERT(&cur.inset() == this, /**/); @@ -339,7 +362,7 @@ MathData InsetMathNest::glue() const void InsetMathNest::write(WriteStream & os) const { - ModeSpecifier specifier(os, currentMode()); + ModeSpecifier specifier(os, currentMode(), lockedMode()); docstring const latex_name = name(); os << '\\' << latex_name; for (size_t i = 0; i < nargs(); ++i) @@ -364,8 +387,9 @@ void InsetMathNest::normalize(NormalStream & os) const int InsetMathNest::latex(odocstream & os, OutputParams const & runparams) const { - WriteStream wi(os, runparams.moving_arg, true, runparams.dryrun, - runparams.encoding); + WriteStream wi(os, runparams.moving_arg, true, + runparams.dryrun ? WriteStream::wsDryrun : WriteStream::wsDefault, + runparams.encoding); write(wi); return wi.line(); } @@ -426,7 +450,7 @@ void InsetMathNest::handleFont(Cursor & cur, docstring const & arg, if (cur.inset().asInsetMath()->name() == font) cur.handleFont(to_utf8(font)); else - handleNest(cur, createInsetMath(font), arg); + handleNest(cur, createInsetMath(font, cur.buffer()), arg); } @@ -506,7 +530,7 @@ void InsetMathNest::handleFont2(Cursor & cur, docstring const & arg) font.fromString(to_utf8(arg), b); if (font.fontInfo().color() != Color_inherit && font.fontInfo().color() != Color_ignore) - handleNest(cur, MathAtom(new InsetMathColor(true, font.fontInfo().color()))); + handleNest(cur, MathAtom(new InsetMathColor(buffer_, true, font.fontInfo().color()))); // FIXME: support other font changes here as well? } @@ -514,7 +538,7 @@ void InsetMathNest::handleFont2(Cursor & cur, docstring const & arg) void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) { - //lyxerr << "InsetMathNest: request: " << cmd << endl; + //LYXERR0("InsetMathNest: request: " << cmd); Parse::flags parseflg = Parse::QUIET | Parse::USETEXT; @@ -524,7 +548,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) parseflg |= Parse::VERBATIM; // fall through case LFUN_PASTE: { - if (cur.currentMode() == TEXT_MODE) + if (cur.currentMode() <= TEXT_MODE) parseflg |= Parse::TEXTMODE; cur.recordUndoSelection(); cur.message(_("Paste")); @@ -538,8 +562,10 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) is >> n; topaste = cap::selection(n); } - cur.niceInsert(topaste, parseflg); + cur.niceInsert(topaste, parseflg, false); cur.clearSelection(); // bug 393 + // FIXME audit setBuffer/updateLabels calls + cur.buffer()->updateLabels(); cur.finishUndo(); break; } @@ -551,6 +577,8 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) // Prevent stale position >= size crash // Probably not necessary anymore, see eraseSelection (gb 2005-10-09) cur.normalize(); + // FIXME audit setBuffer/updateLabels calls + cur.buffer()->updateLabels(); break; case LFUN_COPY: @@ -807,7 +835,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) cur.insert(arg); break; } - // Don't record undo steps if we are in macro mode and + // 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, @@ -816,14 +844,9 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) // 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. - if (!cur.inMacroMode()) { - MathMacro const * macro = 0; - if (cur.pos() > 0 && cmd.argument() != "\\") - macro = cur.inset().asInsetMath()->asMacro(); - - if (!macro) - cur.recordUndoSelection(); - } + // 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 @@ -889,37 +912,37 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) break; case LFUN_FONT_BOLD: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) handleFont(cur, cmd.argument(), "textbf"); else handleFont(cur, cmd.argument(), "mathbf"); break; case LFUN_FONT_BOLDSYMBOL: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) handleFont(cur, cmd.argument(), "textbf"); else handleFont(cur, cmd.argument(), "boldsymbol"); break; case LFUN_FONT_SANS: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) handleFont(cur, cmd.argument(), "textsf"); else handleFont(cur, cmd.argument(), "mathsf"); break; case LFUN_FONT_EMPH: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) handleFont(cur, cmd.argument(), "emph"); else handleFont(cur, cmd.argument(), "mathcal"); break; case LFUN_FONT_ROMAN: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) handleFont(cur, cmd.argument(), "textrm"); else handleFont(cur, cmd.argument(), "mathrm"); break; case LFUN_FONT_TYPEWRITER: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) handleFont(cur, cmd.argument(), "texttt"); else handleFont(cur, cmd.argument(), "mathtt"); @@ -928,13 +951,13 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) handleFont(cur, cmd.argument(), "mathfrak"); break; case LFUN_FONT_ITAL: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) handleFont(cur, cmd.argument(), "textit"); else handleFont(cur, cmd.argument(), "mathit"); break; case LFUN_FONT_NOUN: - if (currentMode() == TEXT_MODE) + if (currentMode() <= TEXT_MODE) // FIXME: should be "noun" handleFont(cur, cmd.argument(), "textsc"); else @@ -944,6 +967,10 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) 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 @@ -954,14 +981,19 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) docstring const save_selection = grabAndEraseSelection(cur); selClearOrDel(cur); //cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv()))); - cur.plainInsert(MathAtom(new InsetMathBox(from_ascii("mbox")))); + if (currentMode() <= Inset::TEXT_MODE) + cur.plainInsert(MathAtom(new InsetMathEnsureMath(buffer_))); + else + cur.plainInsert(MathAtom(new InsetMathBox(buffer_, from_ascii("mbox")))); cur.posBackward(); cur.pushBackward(*cur.nextInset()); cur.niceInsert(save_selection); + // FIXME audit setBuffer/updateLabels calls + cur.buffer()->updateLabels(); #else if (currentMode() == Inset::TEXT_MODE) { cur.recordUndoSelection(); - cur.niceInsert(MathAtom(new InsetMathHull("simple"))); + cur.niceInsert(MathAtom(new InsetMathHull("simple", cur.buffer()))); cur.message(_("create new math text environment ($...$)")); } else { handleFont(cur, cmd.argument(), "textrm"); @@ -974,17 +1006,17 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_REGEXP_MODE: { InsetMathHull * i = dynamic_cast(cur.inset().asInsetMath()); if (i && i->getType() == hullRegexp) { - cur.message(_("Already in regexp mode")); + cur.message(_("Already in regular expression mode")); break; } cur.macroModeClose(); docstring const save_selection = grabAndEraseSelection(cur); selClearOrDel(cur); - cur.plainInsert(MathAtom(new InsetMathHull(hullRegexp))); + cur.plainInsert(MathAtom(new InsetMathHull(buffer_, hullRegexp))); cur.posBackward(); cur.pushBackward(*cur.nextInset()); cur.niceInsert(save_selection); - cur.message(_("Regexp editor mode")); + cur.message(_("Regular expression editor mode")); break; } @@ -1013,8 +1045,24 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) if (n < 1) n = 1; v_align += 'c'; + cur.niceInsert(MathAtom(new InsetMathArray(buffer_, + from_ascii("array"), m, n, (char)v_align[0], h_align))); + break; + } + + case LFUN_MATH_AMS_MATRIX: { + cur.recordUndo(); + unsigned int m = 1; + unsigned int n = 1; + docstring name; + idocstringstream is(cmd.argument()); + is >> m >> n >> name; + if (m < 1) + m = 1; + if (n < 1) + n = 1; cur.niceInsert( - MathAtom(new InsetMathArray(from_ascii("array"), m, n, (char)v_align[0], h_align))); + MathAtom(new InsetMathAMSArray(buffer_, name, m, n))); break; } @@ -1027,7 +1075,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) if (rs.empty()) rs = ')'; cur.recordUndo(); - cur.handleNest(MathAtom(new InsetMathDelim(ls, rs))); + cur.handleNest(MathAtom(new InsetMathDelim(buffer_, ls, rs))); break; } @@ -1127,8 +1175,9 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) else { MathData ar; asArray(cmd.argument(), ar); - if (ar.size() == 1 && ar[0]->asNestInset() - && ar[0]->asNestInset()->nargs() > 1) + if (cur.selection() && ar.size() == 1 + && ar[0]->asNestInset() + && ar[0]->asNestInset()->nargs() > 1) handleNest(cur, ar[0]); else cur.niceInsert(cmd.argument()); @@ -1140,7 +1189,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) docstring const & name = cmd.argument(); string data; if (name == "ref") { - InsetMathRef tmp(name); + InsetMathRef tmp(buffer_, name); data = tmp.createDialogStr(to_utf8(name)); } else if (name == "mathspace") { InsetMathSpace tmp; @@ -1155,6 +1204,8 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) if (createInsetMath_fromDialogStr(cmd.argument(), ar)) { cur.recordUndoSelection(); cur.insert(ar); + // FIXME audit setBuffer/updateLabels calls + cur.buffer()->updateLabels(); } else cur.undispatched(); break; @@ -1215,11 +1266,11 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, bool ret = true; string const arg = to_utf8(cmd.argument()); switch (cmd.action) { - case LFUN_TABULAR_FEATURE: + case LFUN_INSET_MODIFY: flag.setEnabled(false); break; #if 0 - case LFUN_TABULAR_FEATURE: + case LFUN_INSET_MODIFY: // FIXME: check temporarily disabled // valign code char align = mathcursor::valign(); @@ -1250,10 +1301,6 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_FONT_DEFAULT: flag.setEnabled(true); break; - case LFUN_MATH_MUTATE: - //flag.setOnOff(mathcursor::formula()->hullType() == to_utf8(cmd.argument())); - flag.setOnOff(false); - break; // we just need to be in math mode to enable that case LFUN_MATH_SIZE: @@ -1263,6 +1310,7 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, flag.setEnabled(true); break; + case LFUN_FONT_UNDERLINE: case LFUN_FONT_FRAK: flag.setEnabled(currentMode() != TEXT_MODE); break; @@ -1283,6 +1331,7 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd, flag.setEnabled(currentMode() != TEXT_MODE); break; + case LFUN_MATH_AMS_MATRIX: case LFUN_MATH_MATRIX: flag.setEnabled(currentMode() == MATH_MODE); break; @@ -1442,6 +1491,7 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) save_selection = grabAndEraseSelection(cur); cur.clearTargetX(); + Buffer * buf = cur.buffer(); // handle macroMode if (cur.inMacroMode()) { @@ -1471,25 +1521,25 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) // remove the '\\' if (c == '\\') { cur.backspace(); - if (currentMode() == InsetMath::TEXT_MODE) - cur.niceInsert(createInsetMath("textbackslash")); + if (currentMode() <= InsetMath::TEXT_MODE) + cur.niceInsert(createInsetMath("textbackslash", buf)); else - cur.niceInsert(createInsetMath("backslash")); + cur.niceInsert(createInsetMath("backslash", buf)); } else if (c == '^' && currentMode() == InsetMath::MATH_MODE) { cur.backspace(); - cur.niceInsert(createInsetMath("mathcircumflex")); + cur.niceInsert(createInsetMath("mathcircumflex", buf)); } else if (c == '{') { cur.backspace(); - cur.niceInsert(MathAtom(new InsetMathBrace)); + cur.niceInsert(MathAtom(new InsetMathBrace(buf))); } else if (c == '%') { cur.backspace(); - cur.niceInsert(MathAtom(new InsetMathComment)); + cur.niceInsert(MathAtom(new InsetMathComment(buf))); } else if (c == '#') { LASSERT(cur.activeMacro(), /**/); cur.activeMacro()->setName(name + docstring(1, c)); } else { cur.backspace(); - cur.niceInsert(createInsetMath(docstring(1, c))); + cur.niceInsert(createInsetMath(docstring(1, c), buf)); } return true; } @@ -1525,9 +1575,15 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) } // leave macro mode and try again if necessary - cur.macroModeClose(); + if (cur.macroModeClose()) { + MathAtom const atom = cur.prevAtom(); + if (atom->asNestInset() && atom->isActive()) { + cur.posBackward(); + cur.pushBackward(*cur.nextInset()); + } + } if (c == '{') - cur.niceInsert(MathAtom(new InsetMathBrace)); + cur.niceInsert(MathAtom(new InsetMathBrace(buf))); else if (c != ' ') interpretChar(cur, c); return true; @@ -1565,14 +1621,14 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) selClearOrDel(cur); if (c == '\n') { - if (currentMode() == InsetMath::TEXT_MODE) + if (currentMode() <= InsetMath::TEXT_MODE) cur.insert(c); return true; } if (c == ' ') { - if (currentMode() == InsetMath::TEXT_MODE) { - // insert spaces in text mode, + if (currentMode() <= InsetMath::TEXT_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... @@ -1620,11 +1676,11 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) return true; } if (c == '~') { - cur.niceInsert(createInsetMath("sim")); + cur.niceInsert(createInsetMath("sim", buf)); return true; } - if (!isAsciiOrMathAlpha(c)) { - MathAtom at = createInsetMath("text"); + if (currentMode() == InsetMath::MATH_MODE && !isAsciiOrMathAlpha(c)) { + MathAtom at = createInsetMath("text", buf); at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c))); cur.niceInsert(at); cur.posForward(); @@ -1632,18 +1688,18 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c) } } else { if (c == '^') { - cur.niceInsert(createInsetMath("textasciicircum")); + cur.niceInsert(createInsetMath("textasciicircum", buf)); return true; } if (c == '~') { - cur.niceInsert(createInsetMath("textasciitilde")); + cur.niceInsert(createInsetMath("textasciitilde", buf)); return true; } } if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%' || c == '_') { - cur.niceInsert(createInsetMath(docstring(1, c))); + cur.niceInsert(createInsetMath(docstring(1, c), buf)); return true; } @@ -1701,7 +1757,7 @@ bool InsetMathNest::script(Cursor & cur, bool up, //lyxerr << "handling script: up: " << up << endl; if (cur.inMacroMode() && cur.macroName() == "\\") { if (up) - cur.niceInsert(createInsetMath("mathcircumflex")); + cur.niceInsert(createInsetMath("mathcircumflex", cur.buffer())); else interpretChar(cur, '_'); return true; @@ -1727,10 +1783,10 @@ bool InsetMathNest::script(Cursor & cur, bool up, // one if in the very first position of the array if (cur.pos() == 0) { //lyxerr << "new scriptinset" << endl; - cur.insert(new InsetMathScript(up)); + cur.insert(new InsetMathScript(buffer_, up)); } else { //lyxerr << "converting prev atom " << endl; - cur.prevAtom() = MathAtom(new InsetMathScript(cur.prevAtom(), up)); + cur.prevAtom() = MathAtom(new InsetMathScript(buffer_, cur.prevAtom(), up)); } --cur.pos(); InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();