+
+ case LFUN_INSET_APPLY: {
+ string const name = cmd.getArg(0);
+ InsetBase * base = cur.bv().owner()->getDialogs().getOpenInset(name);
+
+ if (base) {
+ FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument);
+ base->dispatch(cur, fr);
+ break;
+ }
+ MathArray ar;
+ if (createMathInset_fromDialogStr(cmd.argument, ar)) {
+ cur.insert(ar);
+ break;
+ }
+ cur.undispatched();
+ break;
+ }
+
+ default:
+ MathDimInset::doDispatch(cur, cmd);
+ break;
+ }
+}
+
+
+bool MathNestInset::getStatus(LCursor & /*cur*/, FuncRequest const & cmd,
+ FuncStatus & flag) const
+{
+ // the font related toggles
+ //string tc = "mathnormal";
+ bool ret = true;
+ switch (cmd.action) {
+#if 0
+ case LFUN_TABULAR_FEATURE:
+ // FIXME: check temporarily disabled
+ // valign code
+ char align = mathcursor::valign();
+ if (align == '\0') {
+ enable = false;
+ break;
+ }
+ if (cmd.argument.empty()) {
+ flag.clear();
+ break;
+ }
+ if (!contains("tcb", cmd.argument[0])) {
+ enable = false;
+ break;
+ }
+ flag.setOnOff(cmd.argument[0] == align);
+ break;
+ case LFUN_BOLD:
+ flag.setOnOff(tc == "mathbf");
+ break;
+ case LFUN_SANS:
+ flag.setOnOff(tc == "mathsf");
+ break;
+ case LFUN_EMPH:
+ flag.setOnOff(tc == "mathcal");
+ break;
+ case LFUN_ROMAN:
+ flag.setOnOff(tc == "mathrm");
+ break;
+ case LFUN_CODE:
+ flag.setOnOff(tc == "mathtt");
+ break;
+ case LFUN_NOUN:
+ flag.setOnOff(tc == "mathbb");
+ break;
+ case LFUN_DEFAULT:
+ flag.setOnOff(tc == "mathnormal");
+ break;
+#endif
+ case LFUN_MATH_MUTATE:
+ //flag.setOnOff(mathcursor::formula()->hullType() == cmd.argument);
+ flag.setOnOff(false);
+ break;
+
+ // we just need to be in math mode to enable that
+ case LFUN_MATH_SIZE:
+ case LFUN_MATH_SPACE:
+ case LFUN_MATH_LIMITS:
+ case LFUN_MATH_NONUMBER:
+ case LFUN_MATH_NUMBER:
+ case LFUN_MATH_EXTERN:
+ flag.enabled(true);
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+ return ret;
+}
+
+
+void MathNestInset::edit(LCursor & cur, bool left)
+{
+ cur.push(*this);
+ cur.idx() = left ? 0 : cur.lastidx();
+ cur.pos() = left ? 0 : cur.lastpos();
+ cur.resetAnchor();
+ lyxerr << "MathNestInset::edit, cur:\n" << cur << endl;
+}
+
+
+InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) const
+{
+ int idx_min = 0;
+ int dist_min = 1000000;
+ for (idx_type i = 0; i < nargs(); ++i) {
+ int d = cell(i).dist(x, y);
+ if (d < dist_min) {
+ dist_min = d;
+ idx_min = i;
+ }
+ }
+ MathArray const & ar = cell(idx_min);
+ cur.push(const_cast<MathNestInset&>(*this));
+ cur.idx() = idx_min;
+ cur.pos() = ar.x2pos(x - ar.xo());
+ lyxerr << "found cell : " << idx_min << " pos: " << cur.pos() << endl;
+ if (dist_min == 0) {
+ // hit inside cell
+ for (pos_type i = 0, n = ar.size(); i < n; ++i)
+ if (ar[i]->covers(x, y))
+ return ar[i].nucleus()->editXY(cur, x, y);
+ }
+ return const_cast<MathNestInset*>(this);
+}
+
+
+void MathNestInset::lfunMousePress(LCursor & cur, FuncRequest & cmd)
+{
+ lyxerr << "lfunMousePress: buttons: " << cmd.button() << endl;
+ if (cmd.button() == mouse_button::button1) {
+ first_x = cmd.x;
+ first_y = cmd.y;
+ lyxerr << "lfunMousePress: setting cursor to: " << cur << endl;
+ cur.resetAnchor();
+ cur.bv().cursor() = cur;
+ }
+
+ if (cmd.button() == mouse_button::button2) {
+ cur.dispatch(FuncRequest(LFUN_PASTESELECTION));
+ }
+}
+
+
+void MathNestInset::lfunMouseMotion(LCursor & cur, FuncRequest & cmd)
+{
+ // only select with button 1
+ if (cmd.button() == mouse_button::button1) {
+ LCursor & bvcur = cur.bv().cursor();
+ if (abs(cmd.x - first_x) + abs(cmd.y - first_y) > 4
+ && bvcur.anchor_.hasPart(cur)) {
+ first_x = cmd.x;
+ first_y = cmd.y;
+
+ bvcur.setCursor(cur);
+ bvcur.selection() = true;
+ }
+ }
+}
+
+
+void MathNestInset::lfunMouseRelease(LCursor & cur, FuncRequest & cmd)
+{
+ lyxerr << "lfunMouseRelease: buttons: " << cmd.button() << endl;
+
+ if (cmd.button() == mouse_button::button1) {
+ //cur.bv().stuffClipboard(cur.grabSelection());
+ return;
+ }
+
+ if (cmd.button() == mouse_button::button2) {
+ MathArray ar;
+ asArray(cur.bv().getClipboard(), ar);
+ cur.clearSelection();
+ cur.setScreenPos(cmd.x, cmd.y);
+ cur.insert(ar);
+ cur.bv().update();
+ return;
+ }
+
+ if (cmd.button() == mouse_button::button3) {
+ // try to dispatch to enclosed insets first
+ cur.bv().owner()->getDialogs().show("mathpanel");
+ return;
+ }
+
+ cur.undispatched();
+}
+
+
+bool MathNestInset::interpret(LCursor & cur, char c)
+{
+ lyxerr << "interpret 2: '" << c << "'" << endl;
+ cur.clearTargetX();
+
+ // handle macroMode
+ if (cur.inMacroMode()) {
+ string name = cur.macroName();
+
+ /// are we currently typing '#1' or '#2' or...?
+ if (name == "\\#") {
+ cur.backspace();
+ int n = c - '0';
+ if (n >= 1 && n <= 9)
+ cur.insert(new MathMacroArgument(n));
+ return true;
+ }
+
+ if (isalpha(c)) {
+ cur.activeMacro()->setName(name + c);
+ return true;
+ }
+
+ // handle 'special char' macros
+ if (name == "\\") {
+ // remove the '\\'
+ if (c == '\\') {
+ cur.backspace();
+ if (currentMode() == MathInset::TEXT_MODE)
+ cur.niceInsert(createMathInset("textbackslash"));
+ else
+ cur.niceInsert(createMathInset("backslash"));
+ } else if (c == '{') {
+ cur.backspace();
+ cur.niceInsert(MathAtom(new MathBraceInset));
+ } else if (c == '%') {
+ cur.backspace();
+ cur.niceInsert(MathAtom(new MathCommentInset));
+ } else if (c == '#') {
+ BOOST_ASSERT(cur.activeMacro());
+ cur.activeMacro()->setName(name + c);
+ } else {
+ cur.backspace();
+ cur.niceInsert(createMathInset(string(1, c)));
+ }
+ return true;
+ }
+
+ // leave macro mode and try again if necessary
+ cur.macroModeClose();
+ if (c == '{')
+ cur.niceInsert(MathAtom(new MathBraceInset));
+ else if (c != ' ')
+ interpret(cur, c);
+ return true;
+ }
+
+ // This is annoying as one has to press <space> far too often.
+ // Disable it.
+
+#if 0
+ // leave autocorrect mode if necessary
+ if (autocorrect() && c == ' ') {
+ autocorrect() = false;
+ return true;
+ }
+#endif
+
+ // just clear selection on pressing the space bar
+ if (cur.selection() && c == ' ') {
+ cur.selection() = false;
+ return true;
+ }
+
+ selClearOrDel(cur);
+
+ if (c == '\\') {
+ //lyxerr << "starting with macro" << endl;
+ cur.insert(MathAtom(new MathUnknownInset("\\", false)));
+ return true;
+ }
+
+ if (c == '\n') {
+ if (currentMode() == MathInset::TEXT_MODE)
+ cur.insert(c);
+ return true;
+ }
+
+ if (c == ' ') {
+ if (currentMode() == MathInset::TEXT_MODE) {
+ // insert spaces in text mode,
+ // 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() != ' ')
+ cur.insert(c);
+ return true;
+ }
+ if (cur.pos() != 0 && cur.prevAtom()->asSpaceInset()) {
+ cur.prevAtom().nucleus()->asSpaceInset()->incSpace();
+ return true;
+ }
+ if (cur.popRight())
+ return true;
+ // if are at the very end, leave the formula
+ return cur.pos() != cur.lastpos();
+ }
+
+ if (c == '_') {
+ script(cur, false);
+ return true;
+ }
+
+ if (c == '^') {
+ script(cur, true);
+ return true;
+ }
+
+ if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%') {
+ cur.niceInsert(createMathInset(string(1, c)));
+ return true;
+ }
+
+ if (c == '~') {
+ cur.niceInsert(createMathInset("sim"));
+ return true;
+ }
+
+ // try auto-correction
+ //if (autocorrect() && hasPrevAtom() && math_autocorrect(prevAtom(), c))
+ // return true;
+
+ // no special circumstances, so insert the character without any fuss
+ cur.insert(c);
+ cur.autocorrect() = true;
+ return true;
+}
+
+
+bool MathNestInset::script(LCursor & cur, bool up)
+{
+ // Hack to get \^ and \_ working
+ lyxerr << "handling script: up: " << up << endl;
+ if (cur.inMacroMode() && cur.macroName() == "\\") {
+ if (up)
+ cur.niceInsert(createMathInset("mathcircumflex"));
+ else
+ interpret(cur, '_');
+ return true;
+ }
+
+ cur.macroModeClose();
+ string safe = grabAndEraseSelection(cur);
+ if (asScriptInset() && cur.idx() == 0) {
+ // we are in a nucleus of a script inset, move to _our_ script
+ MathScriptInset * inset = asScriptInset();
+ lyxerr << " going to cell " << inset->idxOfScript(up) << endl;
+ inset->ensure(up);
+ cur.idx() = inset->idxOfScript(up);
+ cur.pos() = 0;
+ } else if (cur.pos() != 0 && cur.prevAtom()->asScriptInset()) {
+ --cur.pos();
+ MathScriptInset * inset = cur.nextAtom().nucleus()->asScriptInset();
+ cur.push(*inset);
+ cur.idx() = inset->idxOfScript(up);
+ cur.pos() = cur.lastpos();
+ } else {
+ // convert the thing to our left to a scriptinset or create a new
+ // one if in the very first position of the array
+ if (cur.pos() == 0) {
+ lyxerr << "new scriptinset" << endl;
+ cur.insert(new MathScriptInset(up));
+ } else {
+ lyxerr << "converting prev atom " << endl;
+ cur.prevAtom() = MathAtom(new MathScriptInset(cur.prevAtom(), up));
+ }
+ --cur.pos();
+ MathScriptInset * inset = cur.nextAtom().nucleus()->asScriptInset();
+ cur.push(*inset);
+ cur.idx() = 1;
+ cur.pos() = 0;
+ }
+ lyxerr << "pasting 1: safe:\n" << safe << endl;
+ cur.paste(safe);
+ cur.resetAnchor();
+ lyxerr << "pasting 2: safe:\n" << safe << endl;
+ return true;