+ WriteStream wi(os, runparams.moving_arg, true);
+ write(wi);
+ return wi.line();
+}
+
+
+void MathNestInset::notifyCursorLeaves(LCursor & /*cur*/)
+{
+#ifdef WITH_WARNINGS
+#warning look here
+#endif
+#if 0
+ MathArray & ar = cur.cell();
+ // remove base-only "scripts"
+ for (pos_type i = 0; i + 1 < ar.size(); ++i) {
+ MathScriptInset * p = operator[](i).nucleus()->asScriptInset();
+ if (p && p->nargs() == 1) {
+ MathArray ar = p->nuc();
+ erase(i);
+ insert(i, ar);
+ cur.adjust(i, ar.size() - 1);
+ }
+ }
+
+ // glue adjacent font insets of the same kind
+ for (pos_type i = 0; i + 1 < size(); ++i) {
+ MathFontInset * p = operator[](i).nucleus()->asFontInset();
+ MathFontInset const * q = operator[](i + 1)->asFontInset();
+ if (p && q && p->name() == q->name()) {
+ p->cell(0).append(q->cell(0));
+ erase(i + 1);
+ cur.adjust(i, -1);
+ }
+ }
+#endif
+}
+
+
+void MathNestInset::handleFont
+ (LCursor & cur, string const & arg, string const & font)
+{
+ // this whole function is a hack and won't work for incremental font
+ // changes...
+ recordUndo(cur, Undo::ATOMIC);
+
+ if (cur.inset().asMathInset()->name() == font)
+ cur.handleFont(font);
+ else {
+ cur.handleNest(createMathInset(font));
+ cur.insert(arg);
+ }
+}
+
+
+void MathNestInset::handleFont2(LCursor & cur, string const & arg)
+{
+ recordUndo(cur, Undo::ATOMIC);
+ LyXFont font;
+ bool b;
+ bv_funcs::string2font(arg, font, b);
+ if (font.color() != LColor::inherit) {
+ MathAtom at = createMathInset("color");
+ asArray(lcolor.getGUIName(font.color()), at.nucleus()->cell(0));
+ cur.handleNest(at, 1);
+ }
+}
+
+
+void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd)
+{
+ //lyxerr << "MathNestInset: request: " << cmd << std::endl;
+ //CursorSlice sl = cur.current();
+
+ switch (cmd.action) {
+
+ case LFUN_PASTE: {
+ recordUndo(cur);
+ cur.message(_("Paste"));
+ replaceSelection(cur);
+ size_t n = 0;
+ istringstream is(cmd.argument);
+ is >> n;
+ pasteSelection(cur, n);
+ cur.clearSelection(); // bug 393
+ cur.bv().switchKeyMap();
+ finishUndo();
+ break;
+ }
+
+ case LFUN_CUT:
+ cutSelection(cur, true, true);
+ cur.message(_("Cut"));
+ break;
+
+ case LFUN_COPY:
+ copySelection(cur);
+ cur.message(_("Copy"));
+ break;
+
+ case LFUN_MOUSE_PRESS:
+ lfunMousePress(cur, cmd);
+ break;
+
+ case LFUN_MOUSE_MOTION:
+ lfunMouseMotion(cur, cmd);
+ break;
+
+ case LFUN_MOUSE_RELEASE:
+ lfunMouseRelease(cur, cmd);
+ break;
+
+ case LFUN_FINISHED_LEFT:
+ cur.bv().cursor() = cur;
+ break;
+
+ case LFUN_FINISHED_RIGHT:
+ ++cur.pos();
+ cur.bv().cursor() = cur;
+ break;
+
+ case LFUN_FINISHED_UP:
+ cur.bv().cursor() = cur;
+ break;
+
+ case LFUN_FINISHED_DOWN:
+ cur.bv().cursor() = cur;
+ break;
+
+ case LFUN_RIGHTSEL:
+ case LFUN_RIGHT:
+ cur.selHandle(cmd.action == LFUN_RIGHTSEL);
+ cur.autocorrect() = false;
+ cur.clearTargetX();
+ cur.macroModeClose();
+ if (cur.pos() != cur.lastpos() && cur.openable(cur.nextAtom())) {
+ cur.pushLeft(*cur.nextAtom().nucleus());
+ cur.inset().idxFirst(cur);
+ } else if (cur.posRight() || idxRight(cur)
+ || cur.popRight() || cur.selection())
+ ;
+ else
+ cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+ break;
+
+ case LFUN_LEFTSEL:
+ case LFUN_LEFT:
+ cur.selHandle(cmd.action == LFUN_LEFTSEL);
+ cur.autocorrect() = false;
+ cur.clearTargetX();
+ cur.macroModeClose();
+ if (cur.pos() != 0 && cur.openable(cur.prevAtom())) {
+ cur.posLeft();
+ cur.push(*cur.nextAtom().nucleus());
+ cur.inset().idxLast(cur);
+ } else if (cur.posLeft() || idxLeft(cur)
+ || cur.popLeft() || cur.selection())
+ ;
+ else
+ cmd = FuncRequest(LFUN_FINISHED_LEFT);
+ break;
+
+ case LFUN_UPSEL:
+ case LFUN_UP:
+ cur.selHandle(cmd.action == LFUN_UPSEL);
+ if (!cur.up())
+ cmd = FuncRequest(LFUN_FINISHED_UP);
+ break;
+
+ case LFUN_DOWNSEL:
+ case LFUN_DOWN:
+ cur.selHandle(cmd.action == LFUN_DOWNSEL);
+ if (!cur.down())
+ cmd = FuncRequest(LFUN_FINISHED_DOWN);
+ break;
+
+ case LFUN_MOUSE_DOUBLE:
+ case LFUN_MOUSE_TRIPLE:
+ case LFUN_WORDSEL:
+ cur.pos() = 0;
+ cur.idx() = 0;
+ cur.resetAnchor();
+ cur.selection() = true;
+ cur.pos() = cur.lastpos();
+ cur.idx() = cur.lastidx();
+ break;
+
+ case LFUN_UP_PARAGRAPHSEL:
+ case LFUN_UP_PARAGRAPH:
+ case LFUN_DOWN_PARAGRAPHSEL:
+ case LFUN_DOWN_PARAGRAPH:
+ break;
+
+ case LFUN_HOMESEL:
+ case LFUN_HOME:
+ case LFUN_WORDLEFTSEL:
+ case LFUN_WORDLEFT:
+ cur.selHandle(cmd.action == LFUN_WORDLEFTSEL || cmd.action == LFUN_HOMESEL);
+ cur.macroModeClose();
+ if (cur.pos() != 0) {
+ cur.pos() = 0;
+ } else if (cur.col() != 0) {
+ cur.idx() -= cur.col();
+ cur.pos() = 0;
+ } else if (cur.idx() != 0) {
+ cur.idx() = 0;
+ cur.pos() = 0;
+ } else {
+ cmd = FuncRequest(LFUN_FINISHED_LEFT);
+ }
+ break;
+
+ case LFUN_WORDRIGHTSEL:
+ case LFUN_WORDRIGHT:
+ case LFUN_ENDSEL:
+ case LFUN_END:
+ cur.selHandle(cmd.action == LFUN_WORDRIGHTSEL || cmd.action == LFUN_ENDSEL);
+ cur.macroModeClose();
+ cur.clearTargetX();
+ if (cur.pos() != cur.lastpos()) {
+ cur.pos() = cur.lastpos();
+ } else if (cur.col() != cur.lastcol()) {
+ cur.idx() = cur.idx() - cur.col() + cur.lastcol();
+ cur.pos() = cur.lastpos();
+ } else if (cur.idx() != cur.lastidx()) {
+ cur.idx() = cur.lastidx();
+ cur.pos() = cur.lastpos();
+ } else {
+ cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+ }
+ break;
+
+ case LFUN_PRIORSEL:
+ case LFUN_PRIOR:
+ cmd = FuncRequest(LFUN_FINISHED_LEFT);
+ break;
+
+ case LFUN_NEXTSEL:
+ case LFUN_NEXT:
+ cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+ break;
+
+ case LFUN_CELL_FORWARD:
+ cur.inset().idxNext(cur);
+ break;
+
+ case LFUN_CELL_BACKWARD:
+ cur.inset().idxPrev(cur);
+ break;
+
+ case LFUN_DELETE_WORD_BACKWARD:
+ case LFUN_BACKSPACE:
+ recordUndo(cur, Undo::ATOMIC);
+ cur.backspace();
+ break;
+
+ case LFUN_DELETE_WORD_FORWARD:
+ case LFUN_DELETE:
+ recordUndo(cur);
+ cur.erase();
+ cmd = FuncRequest(LFUN_FINISHED_LEFT);
+ break;
+
+ case LFUN_ESCAPE:
+ if (cur.selection())
+ cur.clearSelection();
+ else
+ cmd = FuncRequest(LFUN_FINISHED_LEFT);
+ break;
+
+ case LFUN_INSET_TOGGLE:
+ recordUndo(cur);
+ //lockToggle();
+ if (cur.pos() != cur.lastpos()) {
+ // toggle previous inset ...
+ cur.nextAtom().nucleus()->lock(!cur.nextAtom()->lock());
+ } else if (cur.popLeft() && cur.pos() != cur.lastpos()) {
+ // ... or enclosing inset if we are in the last inset position
+ cur.nextAtom().nucleus()->lock(!cur.nextAtom()->lock());
+ ++cur.pos();
+ }
+ break;
+
+ case LFUN_SELFINSERT:
+ recordUndo(cur);
+ if (cmd.argument.size() != 1) {
+ cur.insert(cmd.argument);
+ break;
+ }
+ if (!interpret(cur, cmd.argument[0]))
+ cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+ break;
+
+ //case LFUN_GETXY:
+ // sprintf(dispatch_buffer, "%d %d",);
+ // break;
+
+ case LFUN_SETXY: {
+ lyxerr << "LFUN_SETXY broken!" << endl;
+ int x = 0;
+ int y = 0;
+ istringstream is(cmd.argument);
+ is >> x >> y;
+ cur.setScreenPos(x, y);
+ break;
+ }
+
+ // Special casing for superscript in case of LyX handling
+ // dead-keys:
+ case LFUN_CIRCUMFLEX:
+ if (cmd.argument.empty()) {
+ // do superscript if LyX handles
+ // deadkeys
+ recordUndo(cur, Undo::ATOMIC);
+ script(cur, true);
+ }
+ break;
+
+ case LFUN_UMLAUT:
+ case LFUN_ACUTE:
+ case LFUN_GRAVE:
+ case LFUN_BREVE:
+ case LFUN_DOT:
+ case LFUN_MACRON:
+ case LFUN_CARON:
+ case LFUN_TILDE:
+ case LFUN_CEDILLA:
+ case LFUN_CIRCLE:
+ case LFUN_UNDERDOT:
+ case LFUN_TIE:
+ case LFUN_OGONEK:
+ case LFUN_HUNG_UMLAUT:
+ break;
+
+ // Math fonts
+ case LFUN_FREEFONT_APPLY:
+ case LFUN_FREEFONT_UPDATE:
+ handleFont2(cur, cmd.argument);
+ break;
+
+ case LFUN_BOLD:
+ handleFont(cur, cmd.argument, "mathbf");
+ break;
+ case LFUN_SANS:
+ handleFont(cur, cmd.argument, "mathsf");
+ break;
+ case LFUN_EMPH:
+ handleFont(cur, cmd.argument, "mathcal");
+ break;
+ case LFUN_ROMAN:
+ handleFont(cur, cmd.argument, "mathrm");
+ break;
+ case LFUN_CODE:
+ handleFont(cur, cmd.argument, "texttt");
+ break;
+ case LFUN_FRAK:
+ handleFont(cur, cmd.argument, "mathfrak");
+ break;
+ case LFUN_ITAL:
+ handleFont(cur, cmd.argument, "mathit");
+ break;
+ case LFUN_NOUN:
+ handleFont(cur, cmd.argument, "mathbb");
+ break;
+ //case LFUN_FREEFONT_APPLY:
+ handleFont(cur, cmd.argument, "textrm");
+ break;
+ case LFUN_DEFAULT:
+ handleFont(cur, cmd.argument, "textnormal");
+ break;
+
+ case LFUN_MATH_MODE:
+#if 1
+ // ignore math-mode on when already in math mode
+ if (currentMode() == InsetBase::MATH_MODE && cmd.argument == "on")
+ break;
+ cur.macroModeClose();
+ selClearOrDel(cur);
+ cur.plainInsert(MathAtom(new MathMBoxInset(cur.bv())));
+ cur.posLeft();
+ cur.pushLeft(*cur.nextInset());
+#else
+ if (currentMode() == InsetBase::TEXT_MODE) {
+ cur.niceInsert(MathAtom(new MathHullInset("simple")));
+ cur.message(_("create new math text environment ($...$)"));
+ } else {
+ handleFont(cur, cmd.argument, "textrm");
+ cur.message(_("entered math text mode (textrm)"));
+ }
+#endif
+ break;
+
+ case LFUN_MATH_SIZE:
+#if 0
+ recordUndo(cur);
+ cur.setSize(arg);
+#endif
+ break;
+
+ case LFUN_INSERT_MATRIX: {
+ recordUndo(cur, Undo::ATOMIC);
+ unsigned int m = 1;
+ unsigned int n = 1;
+ string v_align;
+ string h_align;
+ istringstream is(cmd.argument);
+ is >> m >> n >> v_align >> h_align;
+ if (m < 1)
+ m = 1;
+ if (n < 1)
+ n = 1;
+ v_align += 'c';
+ cur.niceInsert(
+ MathAtom(new MathArrayInset("array", m, n, v_align[0], h_align)));
+ break;
+ }
+
+ case LFUN_MATH_DELIM: {
+ lyxerr << "MathNestInset::LFUN_MATH_DELIM" << endl;
+ string ls;
+ string rs = lyx::support::split(cmd.argument, ls, ' ');
+ // Reasonable default values
+ if (ls.empty())
+ ls = '(';
+ if (rs.empty())
+ rs = ')';
+ recordUndo(cur, Undo::ATOMIC);
+ cur.handleNest(MathAtom(new MathDelimInset(ls, rs)));
+ break;
+ }
+
+ case LFUN_SPACE_INSERT:
+ case LFUN_MATH_SPACE:
+ recordUndo(cur, Undo::ATOMIC);
+ cur.insert(MathAtom(new MathSpaceInset(",")));
+ break;
+
+ case LFUN_INSET_ERT:
+ // interpret this as if a backslash was typed
+ recordUndo(cur, Undo::ATOMIC);
+ interpret(cur, '\\');
+ break;
+
+// FIXME: We probably should swap parts of "math-insert" and "self-insert"
+// handling such that "self-insert" works on "arbitrary stuff" too, and
+// math-insert only handles special math things like "matrix".
+ case LFUN_INSERT_MATH:
+ recordUndo(cur, Undo::ATOMIC);
+ cur.niceInsert(cmd.argument);
+ break;
+
+ case LFUN_DIALOG_SHOW_NEW_INSET: {
+ string const & name = cmd.argument;
+ string data;
+#if 0
+ if (name == "ref") {
+ RefInset tmp(name);
+ data = tmp.createDialogStr(name);
+ }
+#endif
+ cur.bv().owner()->getDialogs().show(name, data, 0);
+ break;
+ }
+
+ 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();