X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2Fmath_nestinset.C;h=3d54c3f35b9f77f7021e34e2b1b8647cd9959bc8;hb=2c30e9b17afc036515a3d23fb657c4f55815d7c5;hp=a22bed8089d9aa012c74133db2d6c9eff73c89fc;hpb=02ab1bf675bec2f1f2f101da1a22bbb2aeee01ca;p=lyx.git diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index a22bed8089..3d54c3f35b 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -30,6 +30,7 @@ #include "math_symbolinset.h" #include "math_support.h" #include "math_unknowninset.h" +#include "ref_inset.h" #include "BufferView.h" #include "CutAndPaste.h" @@ -50,13 +51,13 @@ #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::pasteSelection; using lyx::cap::replaceSelection; using lyx::cap::selClearOrDel; @@ -88,7 +89,7 @@ MathArray const & MathNestInset::cell(idx_type i) const } -void MathNestInset::getCursorPos(CursorSlice const & sl, +void MathNestInset::cursorPos(CursorSlice const & sl, bool /*boundary*/, int & x, int & y) const { // FIXME: This is a hack. Ideally, the coord cache should not store @@ -219,9 +220,6 @@ void MathNestInset::draw(PainterInfo & pi, int x, int y) 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()) @@ -229,6 +227,12 @@ void MathNestInset::drawSelection(PainterInfo & pi, int x, int y) const 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: " @@ -340,7 +344,7 @@ int MathNestInset::latex(Buffer const &, std::ostream & os, } -void MathNestInset::notifyCursorLeaves(LCursor & /*cur*/) +void MathNestInset::notifyCursorLeaves(LCursor & cur) { #ifdef WITH_WARNINGS #warning look here @@ -415,7 +419,8 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) size_t n = 0; istringstream is(cmd.argument); is >> n; - pasteSelection(cur, n); + string const selection = lyx::cap::getSelection(cur.buffer(), n); + cur.niceInsert(selection); cur.clearSelection(); // bug 393 cur.bv().switchKeyMap(); finishUndo(); @@ -423,8 +428,12 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) } 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: @@ -458,6 +467,7 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) break; case LFUN_FINISHED_DOWN: + ++cur.pos(); cur.bv().cursor() = cur; break; @@ -473,8 +483,10 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) } else if (cur.posRight() || idxRight(cur) || cur.popRight() || cur.selection()) ; - else + else { cmd = FuncRequest(LFUN_FINISHED_RIGHT); + cur.undispatched(); + } break; case LFUN_LEFTSEL: @@ -490,8 +502,10 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) } else if (cur.posLeft() || idxLeft(cur) || cur.popLeft() || cur.selection()) ; - else + else { cmd = FuncRequest(LFUN_FINISHED_LEFT); + cur.undispatched(); + } break; case LFUN_UPSEL: @@ -503,8 +517,10 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) 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; @@ -516,8 +532,10 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) 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; @@ -583,11 +601,13 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) case LFUN_PRIORSEL: case LFUN_PRIOR: cmd = FuncRequest(LFUN_FINISHED_LEFT); + cur.undispatched(); break; case LFUN_NEXTSEL: case LFUN_NEXT: cmd = FuncRequest(LFUN_FINISHED_RIGHT); + cur.undispatched(); break; case LFUN_CELL_FORWARD: @@ -600,7 +620,11 @@ void MathNestInset::doDispatch(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; @@ -608,14 +632,15 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) 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); + else { + cmd = FuncRequest(LFUN_FINISHED_RIGHT); + cur.undispatched(); + } break; case LFUN_INSET_TOGGLE: @@ -632,13 +657,38 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) break; case LFUN_SELFINSERT: - recordUndo(cur); 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; //case LFUN_GETXY: @@ -662,6 +712,7 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) // do superscript if LyX handles // deadkeys recordUndo(cur, Undo::ATOMIC); + safe_ = grabAndEraseSelection(cur); script(cur, true); } break; @@ -689,28 +740,50 @@ void MathNestInset::doDispatch(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"); @@ -776,7 +849,9 @@ void MathNestInset::doDispatch(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; } @@ -809,13 +884,8 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) // math-insert only handles special math things like "matrix". case LFUN_INSERT_MATH: { recordUndo(cur, Undo::ATOMIC); - MathArray ar; - asArray(cmd.argument, ar); - int cell(0); - if (cmd.argument == "\\root") - cell = 1; - if (ar.size() == 1 && (ar[0].nucleus()->asNestInset())) { - cur.handleNest(ar[0], cell); + if (cmd.argument == "^" || cmd.argument == "_") { + interpret(cur, cmd.argument[0]); } else cur.niceInsert(cmd.argument); break; @@ -824,34 +894,14 @@ void MathNestInset::doDispatch(LCursor & cur, FuncRequest & cmd) 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; @@ -889,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); @@ -925,6 +965,11 @@ bool MathNestInset::getStatus(LCursor & /*cur*/, FuncRequest const & cmd, case LFUN_MATH_EXTERN: flag.enabled(true); break; + + case LFUN_FRAK: + flag.enabled(currentMode() != TEXT_MODE); + break; + case LFUN_INSERT_MATH: { bool const textarg = arg == "\\textbf" || arg == "\\textsf" || @@ -933,10 +978,10 @@ bool MathNestInset::getStatus(LCursor & /*cur*/, FuncRequest const & cmd, arg == "\\textsl" || arg == "\\textup" || arg == "\\texttt" || arg == "\\textbb" || arg == "\\textnormal"; - flag.enabled((currentMode() == MATH_MODE && !textarg) - || (currentMode() == TEXT_MODE && textarg)); + flag.enabled(currentMode() != TEXT_MODE || textarg); break; } + case LFUN_INSERT_MATRIX: flag.enabled(currentMode() == MATH_MODE); break; @@ -954,33 +999,33 @@ 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; } -InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y) const +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; } } - MathArray const & ar = cell(idx_min); - cur.push(const_cast(*this)); + MathArray & ar = cell(idx_min); + 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) if (ar[i]->covers(x, y)) return ar[i].nucleus()->editXY(cur, x, y); } - return const_cast(this); + return this; } @@ -989,8 +1034,7 @@ 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.resetAnchor(); - cur.bv().cursor() = cur; + cur.bv().mouseSetCursor(cur); } if (cmd.button() == mouse_button::button2) { @@ -1048,7 +1092,10 @@ void MathNestInset::lfunMouseRelease(LCursor & cur, FuncRequest & cmd) 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(); // handle macroMode @@ -1160,7 +1207,6 @@ bool MathNestInset::interpret(LCursor & cur, char c) script(cur, false); return true; } - if (c == '^') { script(cur, true); return true; @@ -1171,7 +1217,8 @@ bool MathNestInset::interpret(LCursor & cur, char c) } } - if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%') { + if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%' + || c == '_' || c == '^') { cur.niceInsert(createMathInset(string(1, c))); return true; } @@ -1201,7 +1248,6 @@ bool MathNestInset::script(LCursor & cur, bool up) } 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(); @@ -1213,16 +1259,17 @@ 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)); } --cur.pos(); @@ -1231,9 +1278,9 @@ bool MathNestInset::script(LCursor & cur, bool up) 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; }