#include "math_nestinset.h"
#include "math_arrayinset.h"
+#include "math_boxinset.h"
#include "math_braceinset.h"
#include "math_commentinset.h"
#include "math_data.h"
#include "math_hullinset.h"
#include "math_mathmlstream.h"
#include "math_macroarg.h"
-#include "math_mboxinset.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_unknowninset.h"
#include "FuncStatus.h"
#include "LColor.h"
#include "bufferview_funcs.h"
+#include "coordcache.h"
#include "cursor.h"
#include "debug.h"
#include "dispatchresult.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 <sstream>
+
using lyx::cap::copySelection;
using lyx::cap::grabAndEraseSelection;
using lyx::cap::cutSelection;
using std::istringstream;
-
-namespace {
-
-// local global
-int first_x;
-int first_y;
-
-} // namespace anon
-
-
-
-
MathNestInset::MathNestInset(idx_type nargs)
: cells_(nargs), lock_(false)
{}
}
-void MathNestInset::getCursorPos(LCursor const & cur, int & x, int & y) const
+void MathNestInset::getCursorPos(CursorSlice const & sl,
+ 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() + cur.bv().top_y();
+// 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::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);
}
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";
}
}
-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())
return;
if (!ptr_cmp(&cur.inset(), this))
return;
+
CursorSlice s1 = cur.selBegin();
CursorSlice s2 = cur.selEnd();
//lyxerr << "MathNestInset::drawing selection: "
void MathNestInset::notifyCursorLeaves(LCursor & /*cur*/)
{
+#ifdef WITH_WARNINGS
#warning look here
+#endif
#if 0
MathArray & ar = cur.cell();
// remove base-only "scripts"
}
-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();
cur.message(_("Paste"));
replaceSelection(cur);
size_t n = 0;
- istringstream is(cmd.argument.c_str());
+ istringstream is(cmd.argument);
is >> n;
pasteSelection(cur, n);
cur.clearSelection(); // bug 393
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.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);
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())
cmd = FuncRequest(LFUN_FINISHED_UP);
+ // 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())
cmd = FuncRequest(LFUN_FINISHED_DOWN);
+ // fixes bug 1598. Please check!
+ cur.normalize();
break;
case LFUN_MOUSE_DOUBLE:
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()) {
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;
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_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.plainInsert(MathAtom(new MathMBoxInset(cur.bv())));
+ cur.plainInsert(MathAtom(new MathBoxInset("mbox")));
cur.posLeft();
cur.pushLeft(*cur.nextInset());
#else
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);
+ MathArray ar;
+ asArray(cmd.argument, ar);
+ if (ar.size() == 1 && (ar[0].nucleus()->asNestInset())) {
+ cur.handleNest(ar[0]);
+ } else
+ cur.niceInsert(cmd.argument);
break;
+ }
case LFUN_DIALOG_SHOW_NEW_INSET: {
string const & name = cmd.argument;
}
default:
- MathDimInset::priv_dispatch(cur, cmd);
+ MathDimInset::doDispatch(cur, cmd);
break;
}
}
}
-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;
idx_min = i;
}
}
- MathArray & ar = cell(idx_min);
- cur.push(*this);
+ 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 (ar[i]->covers(x, y))
return ar[i].nucleus()->editXY(cur, x, y);
}
- return this;
+ return const_cast<MathNestInset*>(this);
+}
+
+
+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;
+ }
+
+ 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;
}
}
-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;
// handle macroMode
if (cur.inMacroMode()) {
string name = cur.macroName();
- lyxerr << "interpret macro name: '" << name << "'" << endl;
/// are we currently typing '#1' or '#2' or...?
if (name == "\\#") {
} else if (c == '{') {
cur.backspace();
cur.niceInsert(MathAtom(new MathBraceInset));
+ } else if (c == '%') {
+ cur.backspace();
+ cur.niceInsert(MathAtom(new MathCommentInset));
} else if (c == '#') {
- lyxerr << "setting name to " << name + c << endl;
BOOST_ASSERT(cur.activeMacro());
cur.activeMacro()->setName(name + c);
- lyxerr << "set name to " << name + c << endl;
} else {
cur.backspace();
cur.niceInsert(createMathInset(string(1, 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;
}
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)
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;