]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathNest.cpp
Find: Renamend for_searchAdv to for_serach in src/OutputParams.h
[lyx.git] / src / mathed / InsetMathNest.cpp
index 896ca664c29cde0d2067a974637c1a29093e1f5a..d4759a0c0f16fdd345cd19fbf9b313efe0c8af05 100644 (file)
@@ -30,7 +30,6 @@
 #include "InsetMathUnknown.h"
 #include "MathAutoCorrect.h"
 #include "MathCompletionList.h"
-#include "MathData.h"
 #include "MathFactory.h"
 #include "InsetMathMacro.h"
 #include "InsetMathMacroArgument.h"
@@ -52,7 +51,6 @@
 #include "LyX.h"
 #include "LyXRC.h"
 #include "MetricsInfo.h"
-#include "OutputParams.h"
 #include "TexRow.h"
 #include "Text.h"
 
@@ -86,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);
 }
 
 
@@ -123,7 +125,7 @@ void InsetMathNest::setBuffer(Buffer & buffer)
 }
 
 
-InsetMath::idx_type InsetMathNest::nargs() const
+idx_type InsetMathNest::nargs() const
 {
        return cells_.size();
 }
@@ -185,10 +187,10 @@ void InsetMathNest::cellsMetrics(MetricsInfo const & mi) const
 }
 
 
-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);
 }
 
 
@@ -253,7 +255,7 @@ void InsetMathNest::dump() const
 {
        odocstringstream oss;
        otexrowstream ots(oss);
-       WriteStream os(ots);
+       TeXMathStream os(ots);
        os << "---------------------------------------------\n";
        write(os);
        os << "\n";
@@ -324,12 +326,13 @@ 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;
+       os.inMathClass(asClassInset());
        for (size_t i = 0; i < nargs(); ++i) {
                Changer dummy = os.changeRowEntry(TexRow::mathEntry(id(),i));
                os << '{' << cell(i) << '}';
@@ -340,6 +343,7 @@ void InsetMathNest::write(WriteStream & os) const
                os << "\\lyxlock";
                os.pendingSpace(true);
        }
+       os.inMathClass(false);
 }
 
 
@@ -354,28 +358,32 @@ void InsetMathNest::normalize(NormalStream & os) const
 
 void InsetMathNest::latex(otexstream & os, OutputParams const & runparams) const
 {
-       WriteStream wi(os, runparams.moving_arg, true,
-                       runparams.dryrun ? WriteStream::wsDryrun : WriteStream::wsDefault,
-                       runparams.encoding);
-       wi.strikeoutMath(runparams.inDeletedInset
-                        && (!LaTeXFeatures::isAvailable("dvipost")
-                               || (runparams.flavor != OutputParams::LATEX
-                                   && runparams.flavor != OutputParams::DVILUATEX)));
+       TeXMathStream::OutputType ot;
+       if (runparams.for_search != OutputParams::NoSearch)
+               ot = TeXMathStream::wsSearchAdv;
+       else if (runparams.dryrun)
+               ot = TeXMathStream::wsDryrun;
+       else
+               ot = TeXMathStream::wsDefault;
+       TeXMathStream wi(os, runparams.moving_arg, true, ot,
+                        runparams.encoding);
+       wi.strikeoutMath(runparams.inDeletedInset);
        if (runparams.inulemcmd) {
-               wi.ulemCmd(WriteStream::UNDERLINE);
+               wi.ulemCmd(TeXMathStream::UNDERLINE);
                if (runparams.local_font) {
                        FontInfo f = runparams.local_font->fontInfo();
                        if (f.strikeout() == FONT_ON)
-                               wi.ulemCmd(WriteStream::STRIKEOUT);
+                               wi.ulemCmd(TeXMathStream::STRIKEOUT);
                }
        }
        wi.canBreakLine(os.canBreakLine());
        Changer dummy = wi.changeRowEntry(TexRow::textEntry(runparams.lastid,
                                                            runparams.lastpos));
        write(wi);
-       // Reset parbreak status after a math inset.
+       // Reset parbreak and command termination status after a math inset.
        os.lastChar(0);
        os.canBreakLine(wi.canBreakLine());
+       os.terminateCommand(false);
 }
 
 
@@ -448,8 +456,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()) {
@@ -460,8 +468,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;
@@ -469,14 +478,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;
        }
@@ -484,24 +488,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();
                }
        }
 }
@@ -520,7 +520,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);
@@ -546,7 +545,8 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
                        size_t n = 0;
                        idocstringstream is(cmd.argument());
                        is >> n;
-                       topaste = cap::selection(n, buffer().params().documentClassPtr());
+                       topaste = cap::selection(n, make_pair(buffer().params().documentClassPtr(),
+                                                             buffer().params().authors()));
                }
                cur.niceInsert(topaste, parseflg, false);
                cur.clearSelection(); // bug 393
@@ -565,11 +565,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;
@@ -791,8 +786,12 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
                cur.clearTargetX();
                cur.macroModeClose();
                if (!cur.inset().idxNext(cur)) {
-                       cur.idx() = firstIdx();
-                       cur.pos() = 0;
+                       if (cur.lastidx() == 0)
+                               cur.popForward();
+                       else {
+                               cur.idx() = firstIdx();
+                               cur.pos() = 0;
+                       }
                }
                break;
 
@@ -802,8 +801,12 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
                cur.clearTargetX();
                cur.macroModeClose();
                if (!cur.inset().idxPrev(cur)) {
-                       cur.idx() = lastIdx();
-                       cur.pos() = lyxrc.mac_like_cursor_movement ? cur.lastpos() : 0;
+                       if (cur.lastidx() == 0)
+                               cur.popBackward();
+                       else {
+                               cur.idx() = cur.lastidx();
+                               cur.pos() = lyxrc.mac_like_cursor_movement ? cur.lastpos() : 0;
+                       }
                }
                break;
 
@@ -910,7 +913,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
                if (cmd.argument().empty()) {
                        // do superscript if LyX handles
                        // deadkeys
-                       cur.recordUndoSelection();
+                       cur.recordUndoInset();
                        script(cur, true, grabAndEraseSelection(cur));
                }
                break;
@@ -1234,10 +1237,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]);
@@ -1277,6 +1282,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;
@@ -1326,9 +1377,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
@@ -1404,7 +1452,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;
@@ -1460,6 +1508,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;
@@ -1608,10 +1679,10 @@ 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;
+       // try auto-correction
+       if (lyxrc.autocorrection_math && cur.pos() != 0 && !cur.selection()
+            && math_autocorrect(cur, c))
+               return true;
 
        //lyxerr << "interpret 2: '" << c << "'" << endl;
        docstring save_selection;
@@ -1763,7 +1834,13 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
                        // but suppress direct insertion of two spaces in a row
                        // the still allows typing  '<space>a<space>' and deleting the 'a', but
                        // it is better than nothing...
-                       if (cur.pos() == 0 || cur.prevAtom()->getChar() != ' ') {
+                       pos_type const pos = cur.pos();
+                       pos_type const lastpos = cur.lastpos();
+                       if ((pos == 0 && lastpos == 0)
+                           || (pos == 0 && cur.nextAtom()->getChar() != ' ')
+                           || (pos == lastpos && cur.prevAtom()->getChar() != ' ')
+                           || (pos > 0 && cur.prevAtom()->getChar() != ' '
+                                       && cur.nextAtom()->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
@@ -1818,10 +1895,12 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
                return true;
        } else if (currentMode() != InsetMath::TEXT_MODE) {
                if (c == '_') {
+                       cur.recordUndoInset();
                        script(cur, false, save_selection);
                        return true;
                }
                if (c == '^') {
+                       cur.recordUndoInset();
                        script(cur, true, save_selection);
                        return true;
                }
@@ -1830,10 +1909,16 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
                        return true;
                }
                if (currentMode() == InsetMath::MATH_MODE && Encodings::isUnicodeTextOnly(c)) {
-                       MathAtom at = createInsetMath("text", buf);
-                       at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c)));
-                       cur.insert(at);
-                       cur.posForward();
+                       MathAtom const atom(new InsetMathChar(c));
+                       if (cur.prevInset() && cur.prevInset()->asInsetMath()->name() == "text") {
+                               // reuse existing \text inset
+                               cur.prevInset()->asInsetMath()->cell(0).push_back(atom);
+                       } else {
+                               MathAtom at = createInsetMath("text", buf);
+                               at.nucleus()->cell(0).push_back(atom);
+                               cur.insert(at);
+                               cur.posForward();
+                       }
                        return true;
                }
        } else {
@@ -1861,6 +1946,15 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
 
 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 &&
@@ -1971,7 +2065,7 @@ CompletionList const *
 InsetMathNest::createCompletionList(Cursor const & cur) const
 {
        if (!cur.inMacroMode())
-               return 0;
+               return nullptr;
 
        return new MathCompletionList(cur);
 }
@@ -2180,11 +2274,11 @@ std::string MathCompletionList::icon(size_t idx) const
        else
                cmd = locals[idx];
 
-       // get the icon resource name by stripping the backslash
+       // 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 "images/math/" + to_utf8(icon_name);
+       return "math/" + to_utf8(icon_name);
 }
 
 std::vector<docstring> MathCompletionList::globals;