X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_nestinset.C;h=79d058907e3ce0f105bca9010f9d95b3ddebe3d4;hb=183239b7def8ca0e51432f2d88891d4b9f055953;hp=632ee7c150ef49626c6957b3ac71e36984cf696c;hpb=52ed731842518e715da642fee562cf4bb056f0da;p=lyx.git diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index 632ee7c150..79d058907e 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -20,37 +20,49 @@ #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 "BufferView.h" +#include "CutAndPaste.h" #include "FuncStatus.h" +#include "LColor.h" #include "bufferview_funcs.h" #include "cursor.h" #include "debug.h" #include "dispatchresult.h" #include "funcrequest.h" #include "gettext.h" -#include "LColor.h" +#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 + +using lyx::cap::copySelection; +using lyx::cap::grabAndEraseSelection; +using lyx::cap::cutSelection; +using lyx::cap::pasteSelection; +using lyx::cap::replaceSelection; +using lyx::cap::selClearOrDel; using std::endl; using std::string; using std::istringstream; + namespace { // local global @@ -85,26 +97,18 @@ MathArray const & MathNestInset::cell(idx_type i) const } -void MathNestInset::getCursorPos(CursorSlice const & cur, - int & x, int & y) const +void MathNestInset::getCursorPos(LCursor const & cur, 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(); + y = ar.yo() + cur.bv().top_y(); // move cursor visually into empty cells ("blue rectangles"); if (cur.cell().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; @@ -181,19 +185,22 @@ void MathNestInset::dump() const } -//void MathNestInset::draw(PainterInfo & pi, int x, int y) const -void MathNestInset::draw(PainterInfo &, int, int) const +void MathNestInset::draw(PainterInfo & pi, int x, int y) const { #if 0 if (lock_) pi.pain.fillRectangle(x, y - ascent(), width(), height(), LColor::mathlockbg); #endif + setPosCache(pi, x, y); } -void MathNestInset::drawSelection(PainterInfo & pi, int, int) const +void MathNestInset::drawSelection(PainterInfo & pi, int x, int y) const { + // FIXME: hack to get position cache warm + draw(pi, x, y); + // this should use the x/y values given, not the cached values LCursor & cur = pi.base.bv->cursor(); if (!cur.selection()) @@ -202,6 +209,8 @@ void MathNestInset::drawSelection(PainterInfo & pi, int, int) const return; CursorSlice s1 = cur.selBegin(); CursorSlice s2 = cur.selEnd(); + //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()); @@ -209,6 +218,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())) { @@ -297,9 +309,44 @@ void MathNestInset::normalize(NormalStream & os) const } -void MathNestInset::notifyCursorLeaves(idx_type idx) +int MathNestInset::latex(Buffer const &, std::ostream & os, + OutputParams const & runparams) const { - cell(idx).notifyCursorLeaves(); + 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 } @@ -333,41 +380,36 @@ void MathNestInset::handleFont2(LCursor & cur, string const & arg) } -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); + 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); @@ -391,24 +433,20 @@ 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.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) @@ -416,7 +454,6 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) ; else cmd = FuncRequest(LFUN_FINISHED_RIGHT); - lyxerr << "mathnest RIGHT: to:\n" << cur << endl; break; case LFUN_LEFTSEL: @@ -424,9 +461,8 @@ 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); @@ -509,15 +545,11 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) case LFUN_PRIORSEL: case LFUN_PRIOR: - case LFUN_BEGINNINGBUFSEL: - case LFUN_BEGINNINGBUF: cmd = FuncRequest(LFUN_FINISHED_LEFT); break; case LFUN_NEXTSEL: case LFUN_NEXT: - case LFUN_ENDBUFSEL: - case LFUN_ENDBUF: cmd = FuncRequest(LFUN_FINISHED_RIGHT); break; @@ -537,19 +569,20 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) 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.selClear(); - else + 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 ... @@ -562,11 +595,7 @@ 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); + recordUndo(cur); if (cmd.argument.size() != 1) { cur.insert(cmd.argument); break; @@ -575,43 +604,20 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) cmd = FuncRequest(LFUN_FINISHED_RIGHT); break; -#if 0 -// -// this needs to be incorporated -// - // delete empty mathbox (LFUN_BACKSPACE and LFUN_DELETE) - bool remove_inset = false; + //case LFUN_GETXY: + // sprintf(dispatch_buffer, "%d %d",); + // break; - DispatchResult result(true); - bool was_macro = cur.inMacroMode(); - - 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: @@ -678,26 +684,29 @@ 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(); + selClearOrDel(cur); cur.plainInsert(MathAtom(new MathMBoxInset(cur.bv()))); 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; @@ -784,32 +793,8 @@ void MathNestInset::priv_dispatch(LCursor & cur, FuncRequest & cmd) break; } -#warning look here -#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; } } @@ -819,7 +804,7 @@ bool MathNestInset::getStatus(LCursor & /*cur*/, FuncRequest const & cmd, FuncStatus & flag) const { // the font related toggles - //string tc = mathcursor::getLastCode(); + //string tc = "mathnormal"; bool ret = true; switch (cmd.action) { #if 0 @@ -896,7 +881,7 @@ void MathNestInset::edit(LCursor & cur, bool left) } -InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) +InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) const { int idx_min = 0; int dist_min = 1000000; @@ -907,8 +892,8 @@ InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) idx_min = i; } } - MathArray & ar = cell(idx_min); - cur.push(*this); + MathArray const & ar = cell(idx_min); + cur.push(const_cast(*this)); cur.idx() = idx_min; cur.pos() = ar.x2pos(x - ar.xo()); lyxerr << "found cell : " << idx_min << " pos: " << cur.pos() << endl; @@ -918,37 +903,7 @@ InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) if (ar[i]->covers(x, y)) return ar[i].nucleus()->editXY(cur, x, y); } - return this; -} - - -void MathNestInset::lfunMouseRelease(LCursor & cur, FuncRequest & cmd) -{ - //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; - } - - if (cmd.button() == mouse_button::button2) { - MathArray ar; - asArray(cur.bv().getClipboard(), ar); - cur.selClear(); - 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(); + return const_cast(this); } @@ -958,9 +913,8 @@ void MathNestInset::lfunMousePress(LCursor & cur, FuncRequest & cmd) if (cmd.button() == mouse_button::button1) { first_x = cmd.x; first_y = cmd.y; - cur.selClear(); - //cur.setScreenPos(cmd.x + xo_, cmd.y + yo_); lyxerr << "lfunMousePress: setting cursor to: " << cur << endl; + cur.resetAnchor(); cur.bv().cursor() = cur; } @@ -973,66 +927,92 @@ void MathNestInset::lfunMousePress(LCursor & cur, FuncRequest & cmd) void MathNestInset::lfunMouseMotion(LCursor & cur, FuncRequest & cmd) { // only select with button 1 - if (cmd.button() != mouse_button::button1) - return; + 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 (abs(cmd.x - first_x) < 2 && abs(cmd.y - first_y) < 2) + if (cmd.button() == mouse_button::button1) { + //cur.bv().stuffClipboard(cur.grabSelection()); return; + } - first_x = cmd.x; - first_y = cmd.y; + 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 (!cur.selection()) - cur.selBegin(); + if (cmd.button() == mouse_button::button3) { + // try to dispatch to enclosed insets first + cur.bv().owner()->getDialogs().show("mathpanel"); + return; + } - //cur.setScreenPos(cmd.x + xo_, cmd.y + yo_); - cur.bv().cursor().setCursor(cur, true); + cur.undispatched(); } bool MathNestInset::interpret(LCursor & cur, char c) { - //lyxerr << "interpret 2: '" << c << "'" << endl; + lyxerr << "interpret 2: '" << c << "'" << endl; cur.clearTargetX(); - if (cur.inMacroArgMode()) { - cur.posLeft(); - cur.plainErase(); -#warning FIXME -#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; @@ -1064,7 +1044,7 @@ bool MathNestInset::interpret(LCursor & cur, char c) return true; } - cur.selClearOrDel(); + selClearOrDel(cur); if (c == '\\') { //lyxerr << "starting with macro" << endl; @@ -1108,13 +1088,13 @@ bool MathNestInset::interpret(LCursor & cur, char c) return true; } - if (c == '{' || c == '}' || c == '#' || c == '&' || c == '$') { + if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%') { cur.niceInsert(createMathInset(string(1, c))); return true; } - if (c == '%') { - cur.niceInsert(MathAtom(new MathCommentInset)); + if (c == '~') { + cur.niceInsert(createMathInset("sim")); return true; } @@ -1131,7 +1111,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) @@ -1142,7 +1122,7 @@ bool MathNestInset::script(LCursor & cur, bool up) } cur.macroModeClose(); - string safe = cur.grabAndEraseSelection(); + 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(); @@ -1160,16 +1140,21 @@ bool MathNestInset::script(LCursor & cur, bool up) // 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 { - --cur.pos(); - cur.cell()[cur.pos()] = MathAtom(new MathScriptInset(cur.nextAtom(), up)); + 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; }