#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_symbolinset.h"
#include "math_support.h"
#include "math_unknowninset.h"
+#include "ref_inset.h"
#include "BufferView.h"
#include "CutAndPaste.h"
#include "frontends/Dialogs.h"
#include "frontends/LyXView.h"
#include "frontends/Painter.h"
+#include "frontends/nullpainter.h"
#include <sstream>
using lyx::cap::copySelection;
using lyx::cap::grabAndEraseSelection;
using lyx::cap::cutSelection;
-using lyx::cap::pasteSelection;
using lyx::cap::replaceSelection;
using lyx::cap::selClearOrDel;
}
-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
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())
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: "
}
-void MathNestInset::notifyCursorLeaves(LCursor & /*cur*/)
+void MathNestInset::notifyCursorLeaves(LCursor & cur)
{
#ifdef WITH_WARNINGS
#warning look here
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);
}
}
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();
}
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:
break;
case LFUN_FINISHED_DOWN:
+ ++cur.pos();
cur.bv().cursor() = cur;
break;
} else if (cur.posRight() || idxRight(cur)
|| cur.popRight() || cur.selection())
;
- else
+ else {
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
+ cur.undispatched();
+ }
break;
case LFUN_LEFTSEL:
} else if (cur.posLeft() || idxLeft(cur)
|| cur.popLeft() || cur.selection())
;
- else
+ else {
cmd = FuncRequest(LFUN_FINISHED_LEFT);
+ cur.undispatched();
+ }
break;
case LFUN_UPSEL:
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;
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_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:
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:
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:
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<space>".
+ 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:
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");
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;
}
int cell(0);
if (cmd.argument == "\\root")
cell = 1;
- if (ar.size() == 1 && (ar[0].nucleus()->asNestInset())) {
+ // math macros are nest insets and may have 0 cells.
+ // handleNest would crash in this case.
+ if (ar.size() == 1 && (ar[0].nucleus()->asNestInset()) &&
+ ar[0].nucleus()->nargs() > MathInset::idx_type(cell)) {
cur.handleNest(ar[0], cell);
} else
cur.niceInsert(cmd.argument);
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;
}
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);
case LFUN_MATH_EXTERN:
flag.enabled(true);
break;
+
+ case LFUN_FRAK:
+ flag.enabled(currentMode() != TEXT_MODE);
+ break;
+
case LFUN_INSERT_MATH: {
- bool const textarg =
+ 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() == MATH_MODE && !textarg)
- || (currentMode() == TEXT_MODE && textarg));
+ flag.enabled(currentMode() != TEXT_MODE || textarg);
break;
}
+
case LFUN_INSERT_MATRIX:
flag.enabled(currentMode() == MATH_MODE);
break;
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<MathNestInset&>(*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<MathNestInset*>(this);
+ return this;
}
//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) {
bool MathNestInset::interpret(LCursor & cur, char c)
{
- lyxerr << "interpret 2: '" << c << "'" << endl;
+ //lyxerr << "interpret 2: '" << c << "'" << endl;
cur.clearTargetX();
// handle macroMode
script(cur, false);
return true;
}
-
if (c == '^') {
script(cur, true);
return true;
}
}
- if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%') {
+ if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' || c == '%'
+ || c == '_' || c == '^') {
cur.niceInsert(createMathInset(string(1, c)));
return true;
}
--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();
cur.idx() = 1;
cur.pos() = 0;
}
- lyxerr << "pasting 1: safe:\n" << safe << endl;
+ //lyxerr << "pasting 1: safe:\n" << safe << endl;
cur.paste(safe);
cur.resetAnchor();
- lyxerr << "pasting 2: safe:\n" << safe << endl;
+ //lyxerr << "pasting 2: safe:\n" << safe << endl;
return true;
}