]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathNest.C
BUG 686: delete empty math box with delete/backspace key
[lyx.git] / src / mathed / InsetMathNest.C
index 2ca97cde51311f60c3e99cd6a0769f6ad1b3ff71..49867f7fe3ba1612c39b4dfde4b3f981f5adc91d 100644 (file)
@@ -22,7 +22,7 @@
 #include "InsetMathDelim.h"
 #include "MathFactory.h"
 #include "InsetMathHull.h"
-#include "MathMLStream.h"
+#include "MathStream.h"
 #include "MathMacroArgument.h"
 //#include "InsetMathMBox.h"
 #include "MathParser.h"
@@ -52,7 +52,6 @@
 
 #include "frontends/Painter.h"
 #include "frontends/Selection.h"
-#include "frontends/nullpainter.h"
 
 #include "funcrequest.h"
 #include "lyxserver.h"
 
 #include <sstream>
 
-using lyx::CoordCache;
-using lyx::docstring;
-using lyx::odocstream;
-using lyx::Point;
 
-using lyx::cap::copySelection;
-using lyx::cap::grabAndEraseSelection;
-using lyx::cap::cutSelection;
-using lyx::cap::replaceSelection;
-using lyx::cap::selClearOrDel;
+namespace lyx {
+
+using cap::copySelection;
+using cap::grabAndEraseSelection;
+using cap::cutSelection;
+using cap::replaceSelection;
+using cap::selClearOrDel;
 
 using std::endl;
 using std::string;
@@ -209,7 +206,7 @@ bool InsetMathNest::idxLast(LCursor & cur) const
 
 void InsetMathNest::dump() const
 {
-       lyx::odocstringstream oss;
+       odocstringstream oss;
        WriteStream os(oss);
        os << "---------------------------------------------\n";
        write(os);
@@ -217,7 +214,7 @@ void InsetMathNest::dump() const
        for (idx_type i = 0, n = nargs(); i != n; ++i)
                os << cell(i) << "\n";
        os << "---------------------------------------------\n";
-       lyxerr << lyx::to_utf8(oss.str());
+       lyxerr << to_utf8(oss.str());
 }
 
 
@@ -243,10 +240,9 @@ void InsetMathNest::drawSelection(PainterInfo & pi, int x, int y) const
                return;
 
        // FIXME: hack to get position cache warm
-       static lyx::frontend::NullPainter nop;
-       PainterInfo pinop(pi);
-       pinop.pain = nop;
-       draw(pinop, x, y);
+       pi.pain.setDrawingEnabled(false);
+       draw(pi, x, y);
+       pi.pain.setDrawingEnabled(true);
 
        CursorSlice s1 = cur.selBegin();
        CursorSlice s2 = cur.selEnd();
@@ -394,14 +390,21 @@ bool InsetMathNest::notifyCursorLeaves(LCursor & /*cur*/)
 
 
 void InsetMathNest::handleFont
-       (LCursor & cur, string const & arg, string const & font)
+       (LCursor & cur, docstring const & arg, char const * const font)
+{
+       handleFont(cur, arg, from_ascii(font));
+}
+
+
+void InsetMathNest::handleFont
+       (LCursor & cur, docstring const & arg, docstring const & font)
 {
        // this whole function is a hack and won't work for incremental font
        // changes...
        recordUndo(cur, Undo::ATOMIC);
 
        if (cur.inset().asInsetMath()->name() == font)
-               cur.handleFont(font);
+               cur.handleFont(to_utf8(font));
        else {
                cur.handleNest(createInsetMath(font));
                cur.insert(arg);
@@ -409,12 +412,12 @@ void InsetMathNest::handleFont
 }
 
 
-void InsetMathNest::handleFont2(LCursor & cur, string const & arg)
+void InsetMathNest::handleFont2(LCursor & cur, docstring const & arg)
 {
        recordUndo(cur, Undo::ATOMIC);
        LyXFont font;
        bool b;
-       bv_funcs::string2font(arg, font, b);
+       bv_funcs::string2font(to_utf8(arg), font, b);
        if (font.color() != LColor::inherit) {
                MathAtom at = MathAtom(new InsetMathColor(true, font.color()));
                cur.handleNest(at, 0);
@@ -434,11 +437,10 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                cur.message(_("Paste"));
                replaceSelection(cur);
                size_t n = 0;
-               istringstream is(lyx::to_utf8(cmd.argument()));
+               istringstream is(to_utf8(cmd.argument()));
                is >> n;
-               docstring const selection = lyx::cap::getSelection(cur.buffer(), n);
-               // FIXME UNICODE
-               cur.niceInsert(lyx::to_utf8(selection));
+               docstring const selection = cap::getSelection(cur.buffer(), n);
+               cur.niceInsert(selection);
                cur.clearSelection(); // bug 393
                cur.bv().switchKeyMap();
                finishUndo();
@@ -646,7 +648,11 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                        recordUndoInset(cur, Undo::ATOMIC);
                else
                        recordUndo(cur, Undo::ATOMIC);
-               cur.backspace();
+               // if the inset can not be removed from within, delete it
+               if (!cur.backspace()) {
+                       FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
+                       cur.bv().getLyXText()->dispatch(cur, cmd);
+               }
                break;
 
        case LFUN_WORD_DELETE_FORWARD:
@@ -656,7 +662,11 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                        recordUndoInset(cur, Undo::ATOMIC);
                else
                        recordUndo(cur, Undo::ATOMIC);
-               cur.erase();
+               // if the inset can not be removed from within, delete it
+               if (!cur.erase()) {
+                       FuncRequest cmd = FuncRequest(LFUN_CHAR_DELETE_FORWARD);
+                       cur.bv().getLyXText()->dispatch(cur, cmd);
+               }
                break;
 
        case LFUN_ESCAPE:
@@ -677,7 +687,7 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
        case LFUN_SELF_INSERT:
                if (cmd.argument().size() != 1) {
                        recordUndo(cur);
-                       string const arg = lyx::to_utf8(cmd.argument());
+                       docstring const arg = cmd.argument();
                        if (!interpretString(cur, arg))
                                cur.insert(arg);
                        break;
@@ -719,7 +729,7 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                lyxerr << "LFUN_SERVER_SET_XY broken!" << endl;
                int x = 0;
                int y = 0;
-               istringstream is(lyx::to_utf8(cmd.argument()));
+               istringstream is(to_utf8(cmd.argument()));
                is >> x >> y;
                cur.setScreenPos(x, y);
                break;
@@ -755,60 +765,60 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
        //  Math fonts
        case LFUN_FONT_FREE_APPLY:
        case LFUN_FONT_FREE_UPDATE:
-               handleFont2(cur, lyx::to_utf8(cmd.argument()));
+               handleFont2(cur, cmd.argument());
                break;
 
        case LFUN_FONT_BOLD:
                if (currentMode() == TEXT_MODE)
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "textbf");
+                       handleFont(cur, cmd.argument(), "textbf");
                else
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "mathbf");
+                       handleFont(cur, cmd.argument(), "mathbf");
                break;
        case LFUN_FONT_SANS:
                if (currentMode() == TEXT_MODE)
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "textsf");
+                       handleFont(cur, cmd.argument(), "textsf");
                else
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "mathsf");
+                       handleFont(cur, cmd.argument(), "mathsf");
                break;
        case LFUN_FONT_EMPH:
                if (currentMode() == TEXT_MODE)
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "emph");
+                       handleFont(cur, cmd.argument(), "emph");
                else
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "mathcal");
+                       handleFont(cur, cmd.argument(), "mathcal");
                break;
        case LFUN_FONT_ROMAN:
                if (currentMode() == TEXT_MODE)
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "textrm");
+                       handleFont(cur, cmd.argument(), "textrm");
                else
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "mathrm");
+                       handleFont(cur, cmd.argument(), "mathrm");
                break;
        case LFUN_FONT_CODE:
                if (currentMode() == TEXT_MODE)
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "texttt");
+                       handleFont(cur, cmd.argument(), "texttt");
                else
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "mathtt");
+                       handleFont(cur, cmd.argument(), "mathtt");
                break;
        case LFUN_FONT_FRAK:
-               handleFont(cur, lyx::to_utf8(cmd.argument()), "mathfrak");
+               handleFont(cur, cmd.argument(), "mathfrak");
                break;
        case LFUN_FONT_ITAL:
                if (currentMode() == TEXT_MODE)
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "textit");
+                       handleFont(cur, cmd.argument(), "textit");
                else
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "mathit");
+                       handleFont(cur, cmd.argument(), "mathit");
                break;
        case LFUN_FONT_NOUN:
                if (currentMode() == TEXT_MODE)
                        // FIXME: should be "noun"
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "textsc");
+                       handleFont(cur, cmd.argument(), "textsc");
                else
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "mathbb");
+                       handleFont(cur, cmd.argument(), "mathbb");
                break;
        //case LFUN_FONT_FREE_APPLY:
-               handleFont(cur, lyx::to_utf8(cmd.argument()), "textrm");
+               handleFont(cur, cmd.argument(), "textrm");
                break;
        case LFUN_FONT_DEFAULT:
-               handleFont(cur, lyx::to_utf8(cmd.argument()), "textnormal");
+               handleFont(cur, cmd.argument(), "textnormal");
                break;
 
        case LFUN_MATH_MODE: {
@@ -817,10 +827,10 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                if (currentMode() == InsetBase::MATH_MODE && cmd.argument() == "on")
                        break;
                cur.macroModeClose();
-               string const save_selection = grabAndEraseSelection(cur);
+               docstring const save_selection = grabAndEraseSelection(cur);
                selClearOrDel(cur);
                //cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv())));
-               cur.plainInsert(MathAtom(new InsetMathBox("mbox")));
+               cur.plainInsert(MathAtom(new InsetMathBox(from_ascii("mbox"))));
                cur.posLeft();
                cur.pushLeft(*cur.nextInset());
                cur.niceInsert(save_selection);
@@ -829,7 +839,7 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                        cur.niceInsert(MathAtom(new InsetMathHull("simple")));
                        cur.message(_("create new math text environment ($...$)"));
                } else {
-                       handleFont(cur, lyx::to_utf8(cmd.argument()), "textrm");
+                       handleFont(cur, cmd.argument(), "textrm");
                        cur.message(_("entered math text mode (textrm)"));
                }
 #endif
@@ -847,9 +857,9 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                recordUndo(cur, Undo::ATOMIC);
                unsigned int m = 1;
                unsigned int n = 1;
-               string v_align;
-               string h_align;
-               istringstream is(lyx::to_utf8(cmd.argument()));
+               docstring v_align;
+               docstring h_align;
+               idocstringstream is(cmd.argument());
                is >> m >> n >> v_align >> h_align;
                if (m < 1)
                        m = 1;
@@ -857,13 +867,13 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                        n = 1;
                v_align += 'c';
                cur.niceInsert(
-                       MathAtom(new InsetMathArray("array", m, n, v_align[0], h_align)));
+                       MathAtom(new InsetMathArray(from_ascii("array"), m, n, (char)v_align[0], h_align)));
                break;
        }
 
        case LFUN_MATH_DELIM: {
-               string ls;
-               string rs = lyx::support::split(lyx::to_utf8(cmd.argument()), ls, ' ');
+               docstring ls;
+               docstring rs = support::split(cmd.argument(), ls, ' ');
                // Reasonable default values
                if (ls.empty())
                        ls = '(';
@@ -875,10 +885,10 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
        }
 
        case LFUN_MATH_BIGDELIM: {
-               string const lname = cmd.getArg(0);
-               string const ldelim = cmd.getArg(1);
-               string const rname = cmd.getArg(2);
-               string const rdelim = cmd.getArg(3);
+               docstring const lname  = from_utf8(cmd.getArg(0));
+               docstring const ldelim = from_utf8(cmd.getArg(1));
+               docstring const rname  = from_utf8(cmd.getArg(2));
+               docstring const rdelim = from_utf8(cmd.getArg(3));
                latexkeys const * l = in_word_set(lname);
                bool const have_l = l && l->inset == "big" &&
                                    InsetMathBig::isBigInsetDelim(ldelim);
@@ -889,7 +899,7 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                // or right delimiter.
                if (have_l || have_r) {
                        recordUndo(cur, Undo::ATOMIC);
-                       string const selection = grabAndEraseSelection(cur);
+                       docstring const selection = grabAndEraseSelection(cur);
                        selClearOrDel(cur);
                        if (have_l)
                                cur.insert(MathAtom(new InsetMathBig(lname,
@@ -907,7 +917,7 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
        case LFUN_SPACE_INSERT:
        case LFUN_MATH_SPACE:
                recordUndo(cur, Undo::ATOMIC);
-               cur.insert(MathAtom(new InsetMathSpace(",")));
+               cur.insert(MathAtom(new InsetMathSpace(from_ascii(","))));
                break;
 
        case LFUN_ERT_INSERT:
@@ -936,24 +946,24 @@ void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
                if (cmd.argument() == "^" || cmd.argument() == "_") {
                        interpretChar(cur, cmd.argument()[0]);
                } else
-                       cur.niceInsert(lyx::to_utf8(cmd.argument()));
+                       cur.niceInsert(cmd.argument());
                break;
                }
 
        case LFUN_DIALOG_SHOW_NEW_INSET: {
-               string const & name = lyx::to_utf8(cmd.argument());
+               docstring const & name = cmd.argument();
                string data;
                if (name == "ref") {
                        RefInset tmp(name);
-                       data = tmp.createDialogStr(name);
+                       data = tmp.createDialogStr(to_utf8(name));
                }
-               cur.bv().showInsetDialog(name, data, 0);
+               cur.bv().showInsetDialog(to_utf8(name), data, 0);
                break;
        }
 
        case LFUN_INSET_INSERT: {
                MathArray ar;
-               if (createInsetMath_fromDialogStr(lyx::to_utf8(cmd.argument()), ar)) {
+               if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
                        recordUndo(cur);
                        cur.insert(ar);
                } else
@@ -974,7 +984,7 @@ bool InsetMathNest::getStatus(LCursor & cur, FuncRequest const & cmd,
        // the font related toggles
        //string tc = "mathnormal";
        bool ret = true;
-       string const arg = lyx::to_utf8(cmd.argument());
+       string const arg = to_utf8(cmd.argument());
        switch (cmd.action) {
        case LFUN_TABULAR_FEATURE:
                flag.enabled(false);
@@ -1011,7 +1021,7 @@ bool InsetMathNest::getStatus(LCursor & cur, FuncRequest const & cmd,
                flag.enabled(true);
                break;
        case LFUN_MATH_MUTATE:
-               //flag.setOnOff(mathcursor::formula()->hullType() == lyx::to_utf8(cmd.argument()));
+               //flag.setOnOff(mathcursor::formula()->hullType() == to_utf8(cmd.argument()));
                flag.setOnOff(false);
                break;
 
@@ -1162,10 +1172,10 @@ void InsetMathNest::lfunMouseRelease(LCursor & cur, FuncRequest & cmd)
 }
 
 
-bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
+bool InsetMathNest::interpretChar(LCursor & cur, char_type c)
 {
        //lyxerr << "interpret 2: '" << c << "'" << endl;
-       string save_selection;
+       docstring save_selection;
        if (c == '^' || c == '_')
                save_selection = grabAndEraseSelection(cur);
 
@@ -1173,7 +1183,7 @@ bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
 
        // handle macroMode
        if (cur.inMacroMode()) {
-               string name = cur.macroName();
+               docstring name = cur.macroName();
 
                /// are we currently typing '#1' or '#2' or...?
                if (name == "\\#") {
@@ -1185,7 +1195,7 @@ bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
                }
 
                if (isalpha(c)) {
-                       cur.activeMacro()->setName(name + lyx::to_ascii(docstring(1, c)));
+                       cur.activeMacro()->setName(name + docstring(1, c));
                        return true;
                }
 
@@ -1206,10 +1216,10 @@ bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
                                cur.niceInsert(MathAtom(new InsetMathComment));
                        } else if (c == '#') {
                                BOOST_ASSERT(cur.activeMacro());
-                               cur.activeMacro()->setName(name + lyx::to_ascii(docstring(1, c)));
+                               cur.activeMacro()->setName(name + docstring(1, c));
                        } else {
                                cur.backspace();
-                               cur.niceInsert(createInsetMath(lyx::to_ascii(docstring(1, c))));
+                               cur.niceInsert(createInsetMath(docstring(1, c)));
                        }
                        return true;
                }
@@ -1218,16 +1228,16 @@ bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
                // interpretString().
                latexkeys const * l = in_word_set(name.substr(1));
                if (name[0] == '\\' && l && l->inset == "big") {
-                       string delim;
+                       docstring delim;
                        switch (c) {
                        case '{':
-                               delim = "\\{";
+                               delim = from_ascii("\\{");
                                break;
                        case '}':
-                               delim = "\\}";
+                               delim = from_ascii("\\}");
                                break;
                        default:
-                               delim = lyx::to_ascii(docstring(1, c));
+                               delim = docstring(1, c);
                                break;
                        }
                        if (InsetMathBig::isBigInsetDelim(delim)) {
@@ -1274,7 +1284,7 @@ bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
 
        if (c == '\\') {
                //lyxerr << "starting with macro" << endl;
-               cur.insert(MathAtom(new InsetMathUnknown("\\", false)));
+               cur.insert(MathAtom(new InsetMathUnknown(from_ascii("\\"), false)));
                return true;
        }
 
@@ -1322,7 +1332,7 @@ bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
 
        if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' ||
            c == '%' || c == '_' || c == '^') {
-               cur.niceInsert(createInsetMath(lyx::to_ascii(docstring(1, c))));
+               cur.niceInsert(createInsetMath(docstring(1, c)));
                return true;
        }
 
@@ -1338,14 +1348,14 @@ bool InsetMathNest::interpretChar(LCursor & cur, lyx::char_type c)
 }
 
 
-bool InsetMathNest::interpretString(LCursor & cur, string const & str)
+bool InsetMathNest::interpretString(LCursor & cur, docstring const & str)
 {
        // Create a InsetMathBig from cur.cell()[cur.pos() - 1] and t if
        // possible
        if (!cur.empty() && cur.pos() > 0 &&
            cur.cell()[cur.pos() - 1]->asUnknownInset()) {
                if (InsetMathBig::isBigInsetDelim(str)) {
-                       string prev = asString(cur.cell()[cur.pos() - 1]);
+                       docstring prev = asString(cur.cell()[cur.pos() - 1]);
                        if (prev[0] == '\\') {
                                prev = prev.substr(1);
                                latexkeys const * l = in_word_set(prev);
@@ -1361,8 +1371,8 @@ bool InsetMathNest::interpretString(LCursor & cur, string const & str)
 }
 
 
-bool InsetMathNest::script(LCursor & cur, bool up, string const &
-               save_selection)
+bool InsetMathNest::script(LCursor & cur, bool up, 
+               docstring const & save_selection)
 {
        // Hack to get \^ and \_ working
        //lyxerr << "handling script: up: " << up << endl;
@@ -1401,11 +1411,7 @@ bool InsetMathNest::script(LCursor & cur, bool up, string const &
                }
                --cur.pos();
                InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();
-               // special handling of {}-bases
-               // is this always correct?
-               if (inset->nuc().size() == 1
-                   && inset->nuc().back()->asBraceInset())
-                       inset->nuc() = inset->nuc().back()->asNestInset()->cell(0);
+               // See comment in MathParser.C for special handling of {}-bases
 
                cur.push(*inset);
                cur.idx() = 1;
@@ -1417,3 +1423,6 @@ bool InsetMathNest::script(LCursor & cur, bool up, string const &
        //lyxerr << "inserting selection 2:\n" << save_selection << endl;
        return true;
 }
+
+
+} // namespace lyx