X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathNest.cpp;h=0a7810784acb6520c0380ce029f6ef7a23588263;hb=b5049e769bba3923cf8e21c980c75b7c00187420;hp=837b6234e1364d191fe4170469639a02786b64d1;hpb=a9f29e6f6c3aa2b3b747b49d264bb71b44b16c66;p=features.git diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp index 837b6234e1..0a7810784a 100644 --- a/src/mathed/InsetMathNest.cpp +++ b/src/mathed/InsetMathNest.cpp @@ -10,26 +10,25 @@ #include -//#define AUTOCORRECT - #include "InsetMathNest.h" #include "InsetMathArray.h" +#include "InsetMathAMSArray.h" #include "InsetMathBig.h" #include "InsetMathBox.h" #include "InsetMathBrace.h" +#include "InsetMathChar.h" #include "InsetMathColor.h" #include "InsetMathComment.h" #include "InsetMathDelim.h" +#include "InsetMathEnsureMath.h" #include "InsetMathHull.h" #include "InsetMathRef.h" #include "InsetMathScript.h" #include "InsetMathSpace.h" #include "InsetMathSymbol.h" #include "InsetMathUnknown.h" -#ifdef AUTOCORRECT #include "MathAutoCorrect.h" -#endif #include "MathCompletionList.h" #include "MathData.h" #include "MathFactory.h" @@ -46,9 +45,10 @@ #include "Cursor.h" #include "CutAndPaste.h" #include "DispatchResult.h" +#include "Encoding.h" #include "FuncRequest.h" #include "FuncStatus.h" -#include "LyXFunc.h" +#include "LyX.h" #include "LyXRC.h" #include "OutputParams.h" #include "Text.h" @@ -79,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) @@ -100,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(); @@ -160,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, /**/); @@ -341,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) @@ -366,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(); } @@ -428,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); } @@ -508,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? } @@ -516,9 +538,9 @@ 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::flags parseflg = Parse::QUIET | Parse::USETEXT; switch (cmd.action) { @@ -526,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")); @@ -540,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; } @@ -553,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: @@ -633,7 +659,6 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd) } // Now that we know exactly what we want to do, let's do it! cur.selHandle(select); - cur.autocorrect() = false; cur.clearTargetX(); cur.macroModeClose(); // try moving forward or backwards as necessary... @@ -810,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, @@ -819,6 +844,7 @@ 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. + // At the time we hit '\' we are not in macro mode, still. if (!cur.inMacroMode()) cur.recordUndoSelection(); @@ -886,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"); @@ -925,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 @@ -941,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 @@ -951,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"); @@ -971,17 +1006,23 @@ 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; + } + + case LFUN_MATH_FONT_STYLE: { + FuncRequest fr = FuncRequest(LFUN_MATH_INSERT, '\\' + cmd.argument()); + doDispatch(cur, fr); break; } @@ -1004,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; } @@ -1018,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; } @@ -1118,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()); @@ -1131,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; @@ -1146,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; @@ -1206,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(); @@ -1241,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: @@ -1254,22 +1310,28 @@ 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; - case LFUN_MATH_INSERT: { + case LFUN_MATH_FONT_STYLE: { bool const textarg = - arg == "\\textbf" || arg == "\\textsf" || - arg == "\\textrm" || arg == "\\textmd" || - arg == "\\textit" || arg == "\\textsc" || - arg == "\\textsl" || arg == "\\textup" || - arg == "\\texttt" || arg == "\\textbb" || - arg == "\\textnormal"; + arg == "textbf" || arg == "textsf" || + arg == "textrm" || arg == "textmd" || + arg == "textit" || arg == "textsc" || + arg == "textsl" || arg == "textup" || + arg == "texttt" || arg == "textbb" || + arg == "textnormal"; flag.setEnabled(currentMode() != TEXT_MODE || textarg); break; } + case LFUN_MATH_INSERT: + flag.setEnabled(currentMode() != TEXT_MODE); + break; + + case LFUN_MATH_AMS_MATRIX: case LFUN_MATH_MATRIX: flag.setEnabled(currentMode() == MATH_MODE); break; @@ -1429,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()) { @@ -1458,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; } @@ -1512,24 +1575,32 @@ 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; } - // This is annoying as one has to press far too often. - // Disable it. -#ifdef AUTOCORRECT - // leave autocorrect mode if necessary - if (cur.autocorrect() && c == ' ') { - cur.autocorrect() = false; - return true; - } -#endif + // 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 == ' ') { @@ -1550,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... @@ -1605,36 +1676,47 @@ 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 (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(); return true; } } 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; } -#ifdef AUTOCORRECT // try auto-correction - if (cur.autocorrect() && cur.pos() != 0 && math_autocorrect(cur.prevAtom(), c)) + if (lyxrc.autocorrection_math && cur.autocorrect() && cur.pos() != 0 + && math_autocorrect(cur.prevAtom(), c)) return true; -#endif // no special circumstances, so insert the character without any fuss cur.insert(c); - cur.autocorrect() = true; + if (lyxrc.autocorrection_math) { + if (!cur.autocorrect()) + cur.message(_("Autocorrect Off ('!' to enter)")); + else + cur.message(_("Autocorrect On ( to exit)")); + } return true; } @@ -1675,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; @@ -1701,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(); @@ -1917,6 +1999,9 @@ MathCompletionList::MathCompletionList(Cursor const & cur) globals.push_back(from_ascii("\\color")); globals.push_back(from_ascii("\\normalcolor")); globals.push_back(from_ascii("\\textcolor")); + globals.push_back(from_ascii("\\cfrac")); + globals.push_back(from_ascii("\\cfracleft")); + globals.push_back(from_ascii("\\cfracright")); globals.push_back(from_ascii("\\dfrac")); globals.push_back(from_ascii("\\tfrac")); globals.push_back(from_ascii("\\dbinom"));