X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_nestinset.C;h=3d54c3f35b9f77f7021e34e2b1b8647cd9959bc8;hb=2c30e9b17afc036515a3d23fb657c4f55815d7c5;hp=9c6552c43feee5df4fd0e7952948cac64c475dee;hpb=2bdaf96dfbcb95931a21ca7377f3dc24e3f5ea8d;p=lyx.git diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index 9c6552c43f..3d54c3f35b 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -13,24 +13,31 @@ #include "math_nestinset.h" #include "math_arrayinset.h" +#include "math_boxinset.h" #include "math_braceinset.h" +#include "math_colorinset.h" #include "math_commentinset.h" #include "math_data.h" #include "math_deliminset.h" #include "math_factory.h" #include "math_hullinset.h" #include "math_mathmlstream.h" +#include "math_macroarg.h" +//#include "math_mboxinset.h" #include "math_parser.h" #include "math_scriptinset.h" #include "math_spaceinset.h" +#include "math_symbolinset.h" #include "math_support.h" -#include "math_mboxinset.h" #include "math_unknowninset.h" +#include "ref_inset.h" #include "BufferView.h" +#include "CutAndPaste.h" #include "FuncStatus.h" #include "LColor.h" #include "bufferview_funcs.h" +#include "coordcache.h" #include "cursor.h" #include "debug.h" #include "dispatchresult.h" @@ -39,30 +46,26 @@ #include "outputparams.h" #include "undo.h" -#include "support/std_sstream.h" #include "support/lstrings.h" #include "frontends/Dialogs.h" #include "frontends/LyXView.h" #include "frontends/Painter.h" +#include "frontends/nullpainter.h" +#include + +using lyx::cap::copySelection; +using lyx::cap::grabAndEraseSelection; +using lyx::cap::cutSelection; +using lyx::cap::replaceSelection; +using lyx::cap::selClearOrDel; using std::endl; using std::string; using std::istringstream; -namespace { - -// local global -int first_x; -int first_y; - -} // namespace anon - - - - MathNestInset::MathNestInset(idx_type nargs) : cells_(nargs), lock_(false) {} @@ -86,30 +89,52 @@ MathArray const & MathNestInset::cell(idx_type i) const } -void MathNestInset::getCursorPos(CursorSlice const & cur, +void MathNestInset::cursorPos(CursorSlice const & sl, bool /*boundary*/, int & x, int & y) const { - BOOST_ASSERT(ptr_cmp(&cur.inset(), this)); - MathArray const & ar = cur.cell(); - x = ar.xo() + ar.pos2x(cur.pos()); - y = ar.yo(); +// FIXME: This is a hack. Ideally, the coord cache should not store +// absolute positions, but relative ones. This would mean to call +// setXY() not in MathArray::draw(), but in the parent insets' draw() +// with the correctly adjusted x,y values. But this means that we'd have +// to touch all (math)inset's draw() methods. Right now, we'll store +// absolute value, and make them here relative, only to make them +// absolute again when actually drawing the cursor. What a mess. + BOOST_ASSERT(ptr_cmp(&sl.inset(), this)); + MathArray const & ar = sl.cell(); + if (!theCoords.getArrays().has(&ar)) { + // this can (semi-)legally happen if we just created this cell + // and it never has been drawn before. So don't ASSERT. + //lyxerr << "no cached data for array " << &ar << endl; + x = 0; + y = 0; + return; + } + Point const pt = theCoords.getArrays().xy(&ar); + if (!theCoords.getInsets().has(this)) { + // same as above + //lyxerr << "no cached data for inset " << this << endl; + x = 0; + y = 0; + return; + } + Point const pt2 = theCoords.getInsets().xy(this); + //lyxerr << "retrieving position cache for MathArray " + // << pt.x_ << ' ' << pt.y_ << std::endl; + x = pt.x_ - pt2.x_ + ar.pos2x(sl.pos()); + y = pt.y_ - pt2.y_; +// lyxerr << "pt.y_ : " << pt.y_ << " pt2_.y_ : " << pt2.y_ +// << " asc: " << ascent() << " des: " << descent() +// << " ar.asc: " << ar.ascent() << " ar.des: " << ar.descent() << endl; // move cursor visually into empty cells ("blue rectangles"); - if (cur.cell().empty()) + if (ar.empty()) x += 2; } -void MathNestInset::substitute(MathMacro const & m) -{ - for (idx_type i = 0; i < nargs(); ++i) - cell(i).substitute(m); -} - - void MathNestInset::metrics(MetricsInfo const & mi) const { MetricsInfo m = mi; - for (idx_type i = 0; i < nargs(); ++i) + for (idx_type i = 0, n = nargs(); i != n; ++i) cell(i).metrics(m); } @@ -176,7 +201,7 @@ void MathNestInset::dump() const os << "---------------------------------------------\n"; write(os); os << "\n"; - for (idx_type i = 0; i < nargs(); ++i) + for (idx_type i = 0, n = nargs(); i != n; ++i) os << cell(i) << "\n"; os << "---------------------------------------------\n"; } @@ -193,20 +218,25 @@ void MathNestInset::draw(PainterInfo & pi, int x, int y) const } -void MathNestInset::drawSelection(PainterInfo & pi, int, int) const +void MathNestInset::drawSelection(PainterInfo & pi, int x, int y) const { - //lyxerr << "MathNestInset::drawing selection: " - // << " x: " << x << " y: " << y << endl; // this should use the x/y values given, not the cached values LCursor & cur = pi.base.bv->cursor(); if (!cur.selection()) return; if (!ptr_cmp(&cur.inset(), this)) return; + + // FIXME: hack to get position cache warm + static NullPainter nop; + PainterInfo pinop(pi); + pinop.pain = nop; + draw(pinop, x, y); + CursorSlice s1 = cur.selBegin(); CursorSlice s2 = cur.selEnd(); - lyxerr << "MathNestInset::drawing selection: " - << " s1: " << s1 << " s2: " << s2 << endl; + //lyxerr << "MathNestInset::drawing selection: " + // << " s1: " << s1 << " s2: " << s2 << endl; if (s1.idx() == s2.idx()) { MathArray const & c = cell(s1.idx()); int x1 = c.xo() + c.pos2x(s1.pos()); @@ -214,6 +244,9 @@ void MathNestInset::drawSelection(PainterInfo & pi, int, int) const int x2 = c.xo() + c.pos2x(s2.pos()); int y2 = c.yo() + c.descent(); pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection); + //lyxerr << "MathNestInset::drawing selection 3: " + // << " x1: " << x1 << " x2: " << x2 + // << " y1: " << y1 << " y2: " << y2 << endl; } else { for (idx_type i = 0; i < nargs(); ++i) { if (idxBetween(i, s1.idx(), s2.idx())) { @@ -313,11 +346,13 @@ int MathNestInset::latex(Buffer const &, std::ostream & os, 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 < size(); ++i) { + 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(); @@ -364,48 +399,47 @@ void MathNestInset::handleFont2(LCursor & cur, string const & arg) 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); + MathAtom at = MathAtom(new MathColorInset(true, font.color())); + cur.handleNest(at, 0); } } -void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) +void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) { //lyxerr << "MathNestInset: request: " << cmd << std::endl; //CursorSlice sl = cur.current(); switch (cmd.action) { - case LFUN_PASTESELECTION: { - MathArray ar; - mathed_parse_cell(ar, cur.bv().getClipboard()); - cur.cell().insert(cur.pos(), ar); - cur.pos() += ar.size(); - break; - } - - case LFUN_PASTE: - if (!cmd.argument.empty()) { - MathArray ar; - mathed_parse_cell(ar, cmd.argument); - cur.cell().insert(cur.pos(), ar); - cur.pos() += ar.size(); - } - break; -/* case LFUN_PASTE: { + recordUndo(cur); + cur.message(_("Paste")); + replaceSelection(cur); size_t n = 0; - istringstream is(cmd.argument.c_str()); + istringstream is(cmd.argument); is >> n; - if (was_macro) - cur.macroModeClose(); - recordUndo(cur, Undo::ATOMIC); - cur.selPaste(n); + string const selection = lyx::cap::getSelection(cur.buffer(), n); + cur.niceInsert(selection); + cur.clearSelection(); // bug 393 + cur.bv().switchKeyMap(); + finishUndo(); break; } -*/ + + case LFUN_CUT: + recordUndo(cur); + cutSelection(cur, true, true); + cur.message(_("Cut")); + // Prevent stale position >= size crash + // Probably not necessary anymore, see eraseSelection (gb 2005-10-09) + cur.normalize(); + break; + + case LFUN_COPY: + copySelection(cur); + cur.message(_("Copy")); + break; case LFUN_MOUSE_PRESS: lfunMousePress(cur, cmd); @@ -429,32 +463,30 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) break; case LFUN_FINISHED_UP: - //idxUpDown(cur, true); cur.bv().cursor() = cur; break; case LFUN_FINISHED_DOWN: - //idxUpDown(cur, false); + ++cur.pos(); cur.bv().cursor() = cur; break; case LFUN_RIGHTSEL: case LFUN_RIGHT: - lyxerr << "mathnest RIGHT: from:\n" << cur << endl; cur.selHandle(cmd.action == LFUN_RIGHTSEL); cur.autocorrect() = false; cur.clearTargetX(); - if (cur.inMacroMode()) - cur.macroModeClose(); - else if (cur.pos() != cur.lastpos() && cur.openable(cur.nextAtom())) { + 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 + else { cmd = FuncRequest(LFUN_FINISHED_RIGHT); - lyxerr << "mathnest RIGHT: to:\n" << cur << endl; + cur.undispatched(); + } break; case LFUN_LEFTSEL: @@ -462,31 +494,50 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) cur.selHandle(cmd.action == LFUN_LEFTSEL); cur.autocorrect() = false; cur.clearTargetX(); - if (cur.inMacroMode()) - cur.macroModeClose(); - else if (cur.pos() != 0 && cur.openable(cur.prevAtom())) { + 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 + else { cmd = FuncRequest(LFUN_FINISHED_LEFT); + cur.undispatched(); + } break; case LFUN_UPSEL: case LFUN_UP: + // FIXME Tried to use clearTargetX and macroModeClose, crashed on cur.up() + if (cur.inMacroMode()) { + // Make Helge happy + cur.macroModeClose(); + break; + } cur.selHandle(cmd.action == LFUN_UPSEL); - if (!cur.up()) + if (!cur.up()) { cmd = FuncRequest(LFUN_FINISHED_UP); + cur.undispatched(); + } + // fixes bug 1598. Please check! + cur.normalize(); break; case LFUN_DOWNSEL: case LFUN_DOWN: + if (cur.inMacroMode()) { + cur.macroModeClose(); + break; + } cur.selHandle(cmd.action == LFUN_DOWNSEL); - if (!cur.down()) + if (!cur.down()) { cmd = FuncRequest(LFUN_FINISHED_DOWN); + cur.undispatched(); + } + // fixes bug 1598. Please check! + cur.normalize(); break; case LFUN_MOUSE_DOUBLE: @@ -522,6 +573,7 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) cur.pos() = 0; } else { cmd = FuncRequest(LFUN_FINISHED_LEFT); + cur.undispatched(); } break; @@ -534,7 +586,7 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) cur.clearTargetX(); if (cur.pos() != cur.lastpos()) { cur.pos() = cur.lastpos(); - } else if (cur.col() != cur.lastcol()) { + } else if (ncols() && (cur.col() != cur.lastcol())) { cur.idx() = cur.idx() - cur.col() + cur.lastcol(); cur.pos() = cur.lastpos(); } else if (cur.idx() != cur.lastidx()) { @@ -542,21 +594,20 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) cur.pos() = cur.lastpos(); } else { cmd = FuncRequest(LFUN_FINISHED_RIGHT); + cur.undispatched(); } break; case LFUN_PRIORSEL: case LFUN_PRIOR: - case LFUN_BEGINNINGBUFSEL: - case LFUN_BEGINNINGBUF: cmd = FuncRequest(LFUN_FINISHED_LEFT); + cur.undispatched(); break; case LFUN_NEXTSEL: case LFUN_NEXT: - case LFUN_ENDBUFSEL: - case LFUN_ENDBUF: cmd = FuncRequest(LFUN_FINISHED_RIGHT); + cur.undispatched(); break; case LFUN_CELL_FORWARD: @@ -569,25 +620,31 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) case LFUN_DELETE_WORD_BACKWARD: case LFUN_BACKSPACE: - recordUndo(cur, Undo::ATOMIC); + if (cur.pos() == 0) + // delete whole cell + recordUndoInset(cur, Undo::ATOMIC); + else + recordUndo(cur, Undo::ATOMIC); cur.backspace(); break; case LFUN_DELETE_WORD_FORWARD: case LFUN_DELETE: - recordUndo(cur, Undo::ATOMIC); + recordUndo(cur); cur.erase(); - cmd = FuncRequest(LFUN_FINISHED_LEFT); break; case LFUN_ESCAPE: if (cur.selection()) cur.clearSelection(); - else - cmd = FuncRequest(LFUN_FINISHED_LEFT); + else { + cmd = FuncRequest(LFUN_FINISHED_RIGHT); + cur.undispatched(); + } break; case LFUN_INSET_TOGGLE: + recordUndo(cur); //lockToggle(); if (cur.pos() != cur.lastpos()) { // toggle previous inset ... @@ -600,56 +657,54 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) break; case LFUN_SELFINSERT: - if (cmd.argument.empty()) { - cmd = FuncRequest(LFUN_FINISHED_RIGHT); - break; - } - recordUndo(cur, Undo::ATOMIC); if (cmd.argument.size() != 1) { + recordUndo(cur); cur.insert(cmd.argument); break; } - if (!interpret(cur, cmd.argument[0])) + // Don't record undo steps if we are in macro mode and + // 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, + // e.g. sqrt. LCursor::macroModeClose replaces in this case + // the MathUnknownInset with name "frac" by an empty + // MathFracInset -> 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. + if (!cur.inMacroMode()) + recordUndo(cur); + + // spacial handling of space. If we insert an inset + // via macro mode, we want to put the cursor inside it + // if relevant. Think typing "\frac". + if (cmd.argument[0] == ' ' + && cur.inMacroMode() && cur.macroName() != "\\" + && cur.macroModeClose()) { + MathAtom const atom = cur.prevAtom(); + if (atom->asNestInset() && atom->nargs() > 0) { + cur.posLeft(); + cur.pushLeft(*cur.nextInset()); + } + } else if (!interpret(cur, cmd.argument[0])) { cmd = FuncRequest(LFUN_FINISHED_RIGHT); + cur.undispatched(); + } break; -#if 0 -// -// this needs to be incorporated -// - // delete empty mathbox (LFUN_BACKSPACE and LFUN_DELETE) - bool remove_inset = false; - - DispatchResult result(true); - bool was_macro = cur.inMacroMode(); + //case LFUN_GETXY: + // sprintf(dispatch_buffer, "%d %d",); + // break; - cur.normalize(); - cur.touch(); -#endif - - // case LFUN_GETXY: - // sprintf(dispatch_buffer, "%d %d",); - // DispatchResult= dispatch_buffer; - // break; case LFUN_SETXY: { lyxerr << "LFUN_SETXY broken!" << endl; int x = 0; int y = 0; - istringstream is(cmd.argument.c_str()); + istringstream is(cmd.argument); is >> x >> y; cur.setScreenPos(x, y); break; } - case LFUN_CUT: - recordUndo(cur, Undo::DELETE); - cur.selCut(); - break; - - case LFUN_COPY: - cur.selCopy(); - break; - // Special casing for superscript in case of LyX handling // dead-keys: case LFUN_CIRCUMFLEX: @@ -657,6 +712,7 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) // do superscript if LyX handles // deadkeys recordUndo(cur, Undo::ATOMIC); + safe_ = grabAndEraseSelection(cur); script(cur, true); } break; @@ -684,28 +740,50 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) break; case LFUN_BOLD: - handleFont(cur, cmd.argument, "mathbf"); + if (currentMode() == TEXT_MODE) + handleFont(cur, cmd.argument, "textbf"); + else + handleFont(cur, cmd.argument, "mathbf"); break; case LFUN_SANS: - handleFont(cur, cmd.argument, "mathsf"); + if (currentMode() == TEXT_MODE) + handleFont(cur, cmd.argument, "textsf"); + else + handleFont(cur, cmd.argument, "mathsf"); break; case LFUN_EMPH: - handleFont(cur, cmd.argument, "mathcal"); + if (currentMode() == TEXT_MODE) + handleFont(cur, cmd.argument, "emph"); + else + handleFont(cur, cmd.argument, "mathcal"); break; case LFUN_ROMAN: - handleFont(cur, cmd.argument, "mathrm"); + if (currentMode() == TEXT_MODE) + handleFont(cur, cmd.argument, "textrm"); + else + handleFont(cur, cmd.argument, "mathrm"); break; case LFUN_CODE: - handleFont(cur, cmd.argument, "texttt"); + if (currentMode() == TEXT_MODE) + handleFont(cur, cmd.argument, "texttt"); + else + handleFont(cur, cmd.argument, "mathtt"); break; case LFUN_FRAK: handleFont(cur, cmd.argument, "mathfrak"); break; case LFUN_ITAL: - handleFont(cur, cmd.argument, "mathit"); + if (currentMode() == TEXT_MODE) + handleFont(cur, cmd.argument, "textit"); + else + handleFont(cur, cmd.argument, "mathit"); break; case LFUN_NOUN: - handleFont(cur, cmd.argument, "mathbb"); + if (currentMode() == TEXT_MODE) + // FIXME: should be "noun" + handleFont(cur, cmd.argument, "textsc"); + else + handleFont(cur, cmd.argument, "mathbb"); break; //case LFUN_FREEFONT_APPLY: handleFont(cur, cmd.argument, "textrm"); @@ -716,26 +794,30 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) 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(); - cur.selClearOrDel(); - cur.plainInsert(MathAtom(new MathMBoxInset(cur.bv()))); + selClearOrDel(cur); + //cur.plainInsert(MathAtom(new MathMBoxInset(cur.bv()))); + cur.plainInsert(MathAtom(new MathBoxInset("mbox"))); cur.posLeft(); cur.pushLeft(*cur.nextInset()); #else - if (currentMode() == InsetBase::TEXT_MODE) + if (currentMode() == InsetBase::TEXT_MODE) { cur.niceInsert(MathAtom(new MathHullInset("simple"))); - else + cur.message(_("create new math text environment ($...$)")); + } else { handleFont(cur, cmd.argument, "textrm"); - //cur.owner()->message(_("math text mode toggled")); + cur.message(_("entered math text mode (textrm)")); + } #endif break; case LFUN_MATH_SIZE: #if 0 - if (!arg.empty()) { - recordUndo(cur, Undo::ATOMIC); - cur.setSize(arg); - } + recordUndo(cur); + cur.setSize(arg); #endif break; @@ -767,7 +849,9 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) if (rs.empty()) rs = ')'; recordUndo(cur, Undo::ATOMIC); - cur.handleNest(MathAtom(new MathDelimInset(ls, rs))); + // Don't do this with multi-cell selections + if (cur.selBegin().idx() == cur.selEnd().idx()) + cur.handleNest(MathAtom(new MathDelimInset(ls, rs))); break; } @@ -783,73 +867,43 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) interpret(cur, '\\'); break; + case LFUN_SUBSCRIPT: + // interpret this as if a _ was typed + recordUndo(cur, Undo::ATOMIC); + interpret(cur, '_'); + break; + + case LFUN_SUPERSCRIPT: + // interpret this as if a ^ 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: + case LFUN_INSERT_MATH: { recordUndo(cur, Undo::ATOMIC); - cur.niceInsert(cmd.argument); + if (cmd.argument == "^" || cmd.argument == "_") { + interpret(cur, cmd.argument[0]); + } else + 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; - } - -#ifdef WITH_WARNINGS -#warning look here -#endif -#if 0 - - case LFUN_WORD_REPLACE: - case LFUN_WORD_FIND: - if (!searchForward(&cur.bv(), cmd.getArg(0), false, false)) - cur.undispatched(); - break; - - cur.normalize(); - cur.touch(); - - BOOST_ASSERT(cur.inMathed()); - - if (result.dispatched()) { - revealCodes(cur); - cur.bv().stuffClipboard(cur.grabSelection()); - } else { - if (remove_inset) - cur.bv().owner()->dispatch(FuncRequest(LFUN_DELETE)); - } - break; -#endif - default: - MathDimInset::priv_dispatch(cur, cmd); + MathDimInset::doDispatch(cur, cmd); break; } } @@ -859,9 +913,13 @@ bool MathNestInset::getStatus(LCursor & /*cur*/, FuncRequest const & cmd, FuncStatus & flag) const { // the font related toggles - //string tc = "mathnormal"; + //string tc = "mathnormal"; bool ret = true; + string const arg = cmd.argument; switch (cmd.action) { + case LFUN_TABULAR_FEATURE: + flag.enabled(false); + break; #if 0 case LFUN_TABULAR_FEATURE: // FIXME: check temporarily disabled @@ -881,28 +939,18 @@ bool MathNestInset::getStatus(LCursor & /*cur*/, FuncRequest const & cmd, } flag.setOnOff(cmd.argument[0] == align); break; +#endif + /// We have to handle them since 1.4 blocks all unhandled actions + case LFUN_ITAL: 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_ROMAN: case LFUN_DEFAULT: - flag.setOnOff(tc == "mathnormal"); + flag.enabled(true); break; -#endif case LFUN_MATH_MUTATE: //flag.setOnOff(mathcursor::formula()->hullType() == cmd.argument); flag.setOnOff(false); @@ -918,6 +966,25 @@ bool MathNestInset::getStatus(LCursor & /*cur*/, FuncRequest const & cmd, flag.enabled(true); break; + case LFUN_FRAK: + flag.enabled(currentMode() != TEXT_MODE); + break; + + case LFUN_INSERT_MATH: { + 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"; + flag.enabled(currentMode() != TEXT_MODE || textarg); + break; + } + + case LFUN_INSERT_MATRIX: + flag.enabled(currentMode() == MATH_MODE); + break; default: ret = false; break; @@ -932,7 +999,7 @@ void MathNestInset::edit(LCursor & cur, bool left) cur.idx() = left ? 0 : cur.lastidx(); cur.pos() = left ? 0 : cur.lastpos(); cur.resetAnchor(); - lyxerr << "MathNestInset::edit, cur:\n" << cur << endl; + //lyxerr << "MathNestInset::edit, cur:\n" << cur << endl; } @@ -940,8 +1007,8 @@ InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) { int idx_min = 0; int dist_min = 1000000; - for (idx_type i = 0; i < nargs(); ++i) { - int d = cell(i).dist(x, y); + for (idx_type i = 0, n = nargs(); i != n; ++i) { + int const d = cell(i).dist(x, y); if (d < dist_min) { dist_min = d; idx_min = i; @@ -951,7 +1018,7 @@ InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) cur.push(*this); cur.idx() = idx_min; cur.pos() = ar.x2pos(x - ar.xo()); - lyxerr << "found cell : " << idx_min << " pos: " << cur.pos() << endl; + //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) @@ -962,12 +1029,43 @@ InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) } +void MathNestInset::lfunMousePress(LCursor & cur, FuncRequest & cmd) +{ + //lyxerr << "## lfunMousePress: buttons: " << cmd.button() << endl; + if (cmd.button() == mouse_button::button1) { + //lyxerr << "## lfunMousePress: setting cursor to: " << cur << endl; + cur.bv().mouseSetCursor(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 (bvcur.anchor_.hasPart(cur)) { + //lyxerr << "## lfunMouseMotion: cursor: " << cur << endl; + bvcur.setCursor(cur); + bvcur.selection() = true; + //lyxerr << "MOTION " << bvcur << endl; + } + else { + cur.undispatched(); + } + } +} + + void MathNestInset::lfunMouseRelease(LCursor & cur, FuncRequest & cmd) { - //lyxerr << "lfunMouseRelease: buttons: " << cmd.button() << endl; + //lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl; if (cmd.button() == mouse_button::button1) { - // try to dispatch to enclosed insets first //cur.bv().stuffClipboard(cur.grabSelection()); return; } @@ -992,86 +1090,52 @@ void MathNestInset::lfunMouseRelease(LCursor & cur, FuncRequest & cmd) } -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; - //cur.setScreenPos(cmd.x + xo_, cmd.y + yo_); - 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) - return; - - if (abs(cmd.x - first_x) < 2 && abs(cmd.y - first_y) < 2) - return; - - first_x = cmd.x; - first_y = cmd.y; - - cur.bv().cursor().setCursor(cur, true); -} - - bool MathNestInset::interpret(LCursor & cur, char c) { - lyxerr << "interpret 2: '" << c << "'" << endl; + //lyxerr << "interpret 2: '" << c << "'" << endl; + if (c == '^' || c == '_') + safe_ = grabAndEraseSelection(cur); + cur.clearTargetX(); - /// are we currently typing '#1' or '#2' or...? - if (cur.pos() > 0 && cur.prevAtom()->getChar() == '#') { - cur.posLeft(); - cur.plainErase(); -#ifdef WITH_WARNINGS -#warning FIXME -#endif -#if 0 - int n = c - '0'; - MathMacroTemplate const * p = formula()->asMacroTemplate(); - if (p && 1 <= n && n <= p->numargs()) - cur.insert(MathAtom(new MathMacroArgument(c - '0'))); - else { - cur.insert(createMathInset("#")); - interpret(cur, c); // try again - } -#endif - return true; - } // handle macroMode if (cur.inMacroMode()) { string name = cur.macroName(); - //lyxerr << "interpret name: '" << name << "'" << endl; + + /// 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(cur.activeMacro()->name() + c); + cur.activeMacro()->setName(name + c); return true; } // handle 'special char' macros if (name == "\\") { // remove the '\\' - cur.backspace(); 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; @@ -1103,7 +1167,7 @@ bool MathNestInset::interpret(LCursor & cur, char c) return true; } - cur.selClearOrDel(); + selClearOrDel(cur); if (c == '\\') { //lyxerr << "starting with macro" << endl; @@ -1137,25 +1201,28 @@ bool MathNestInset::interpret(LCursor & cur, char c) return cur.pos() != cur.lastpos(); } - if (c == '_') { - script(cur, false); - return true; - } - - if (c == '^') { - script(cur, true); - return true; + // These shouldn't work in text mode: + if (currentMode() != MathInset::TEXT_MODE) { + if (c == '_') { + script(cur, false); + return true; + } + if (c == '^') { + script(cur, true); + return true; + } + if (c == '~') { + cur.niceInsert(createMathInset("sim")); + return true; + } } - if (c == '{' || c == '}' || c == '#' || c == '&' || c == '$') { + if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%' + || c == '_' || c == '^') { cur.niceInsert(createMathInset(string(1, c))); return true; } - if (c == '%') { - cur.niceInsert(MathAtom(new MathCommentInset)); - return true; - } // try auto-correction //if (autocorrect() && hasPrevAtom() && math_autocorrect(prevAtom(), c)) @@ -1170,7 +1237,7 @@ bool MathNestInset::interpret(LCursor & cur, char c) bool MathNestInset::script(LCursor & cur, bool up) { - // Hack to get \\^ and \\_ working + // Hack to get \^ and \_ working lyxerr << "handling script: up: " << up << endl; if (cur.inMacroMode() && cur.macroName() == "\\") { if (up) @@ -1181,7 +1248,6 @@ bool MathNestInset::script(LCursor & cur, bool up) } cur.macroModeClose(); - string safe = cur.grabAndEraseSelection(); if (asScriptInset() && cur.idx() == 0) { // we are in a nucleus of a script inset, move to _our_ script MathScriptInset * inset = asScriptInset(); @@ -1193,30 +1259,28 @@ bool MathNestInset::script(LCursor & cur, bool up) --cur.pos(); MathScriptInset * inset = cur.nextAtom().nucleus()->asScriptInset(); cur.push(*inset); + inset->ensure(up); 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; + //lyxerr << "new scriptinset" << endl; cur.insert(new MathScriptInset(up)); } else { - lyxerr << "converting prev atom " << endl; + //lyxerr << "converting prev atom " << endl; cur.prevAtom() = MathAtom(new MathScriptInset(cur.prevAtom(), up)); } - lyxerr << "new scriptinset 2: cur:\n" << cur << endl; --cur.pos(); - lyxerr << "new scriptinset 3: cur:\n" << cur << endl; MathScriptInset * inset = cur.nextAtom().nucleus()->asScriptInset(); - lyxerr << "new scriptinset 3: inset:\n" << inset << endl; cur.push(*inset); cur.idx() = 1; cur.pos() = 0; } - lyxerr << "pasting 1: safe:\n" << safe << endl; - cur.paste(safe); + //lyxerr << "inserting 1: safe:\n" << safe_ << endl; + cur.niceInsert(safe_); cur.resetAnchor(); - lyxerr << "pasting 2: safe:\n" << safe << endl; + //lyxerr << "inserting 2: safe:\n" << safe_ << endl; return true; }