#include "debug.h"
#include "LColor.h"
#include "Painter.h"
-#include "math_support.h"
#include "formulabase.h"
-#include "math_cursor.h"
-#include "math_casesinset.h"
-#include "math_factory.h"
#include "math_arrayinset.h"
#include "math_braceinset.h"
+#include "math_casesinset.h"
#include "math_charinset.h"
+#include "math_cursor.h"
#include "math_deliminset.h"
+#include "math_factory.h"
#include "math_hullinset.h"
+#include "math_iterator.h"
+#include "math_mathmlstream.h"
+#include "math_parser.h"
+#include "math_replace.h"
#include "math_scriptinset.h"
#include "math_spaceinset.h"
#include "math_specialcharinset.h"
-#include "math_mathmlstream.h"
-#include "math_replace.h"
-#include "math_parser.h"
+#include "math_support.h"
#define FILEDEBUG 0
data_.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
else {
std::vector<MathInset::idx_type> indices =
- (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
+ i1.par_->idxBetween(i1.idx_, i2.idx_);
for (MathInset::idx_type i = 0; i < indices.size(); ++i)
data_.push_back(i1.cell(indices[i]));
}
i1.cell().erase(i1.pos_, i2.pos_);
else {
std::vector<MathInset::idx_type> indices =
- (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
+ i1.par_->idxBetween(i1.idx_, i2.idx_);
for (unsigned i = 0; i < indices.size(); ++i)
i1.cell(indices[i]).erase();
}
Selection theSelection;
-#if FILEDEBUG
-std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
-{
- os << "(par: " << p.par_ << " idx: " << p.idx_ << " pos: " << p.pos_ << ")";
- return os;
-}
-#endif
}
void MathCursor::push(MathAtom & t)
{
- MathCursorPos p;
- p.par_ = &t;
- p.idx_ = 0;
- p.pos_ = 0;
- Cursor_.push_back(p);
+ Cursor_.push_back(MathCursorPos(t.nucleus()));
}
#if FILEDEBUG
-void MathCursor::dump(char const * what) const
-{
- lyxerr << "MC: " << what << "\n";
- for (unsigned i = 0; i < Cursor_.size(); ++i)
- lyxerr << " i: " << i
- << " Cursor: pos: " << Cursor_[i].pos_
- << " idx: " << Cursor_[i].idx_
- << " par: " << Cursor_[i].par_ << "\n";
-
- for (unsigned i = 0; i < Anchor_.size(); ++i)
- lyxerr << " i: " << i
- << " Anchor: pos: " << Anchor_[i].pos_
- << " idx: " << Anchor_[i].idx_
- << " par: " << Anchor_[i].par_ << "\n";
-
- lyxerr << " sel: " << selection_ << "\n";
-}
-
-
-void MathCursor::seldump(char const * str) const
-{
- //lyxerr << "SEL: " << str << ": '" << theSelection << "'\n";
- //dump(" Pos");
-
- lyxerr << "\n\n\n=================vvvvvvvvvvvvv======================= "
- << str << "\ntheSelection: " << selection_
- << " '" /*<< theSelection.glue()*/ << "'\nCursor:";
- for (unsigned int i = 0; i < Cursor_.size(); ++i)
- lyxerr << Cursor_[i].par_ << "\n'" /*<< Cursor_[i].cell()*/ << "'\n";
- lyxerr << "\nAnchor: ";
- for (unsigned int i = 0; i < Anchor_.size(); ++i)
- lyxerr << Anchor_[i].par_ << "\n'" /*<< Anchor_[i].cell()*/ << "'\n";
- //lyxerr << "\ncursor.pos_: " << pos();
- //lyxerr << "\nanchor.pos_: " << anchor().pos_;
- lyxerr << "\n===================^^^^^^^^^^^^=====================\n\n\n";
-}
-
+ void MathCursor::dump(char const * what) const
+ {
+ lyxerr << "MC: " << what << "\n";
+ lyxerr << " Cursor: " << Cursor_.size() << "\n";
+ for (unsigned i = 0; i < Cursor_.size(); ++i)
+ lyxerr << " i: " << i << " " << Cursor_[i] << "\n";
+ lyxerr << " Anchor: " << Anchor_.size() << "\n";
+ for (unsigned i = 0; i < Anchor_.size(); ++i)
+ lyxerr << " i: " << i << " " << Anchor_[i] << "\n";
+ lyxerr << " sel: " << selection_ << "\n";
+ }
#else
-
-void MathCursor::seldump(char const *) const {}
-void MathCursor::dump(char const *) const {}
-
+ void MathCursor::dump(char const *) const {}
#endif
bool MathCursor::isInside(MathInset const * p) const
{
for (unsigned i = 0; i < Cursor_.size(); ++i)
- if (Cursor_[i].par_->nucleus() == p)
+ if (Cursor_[i].par_ == p)
return true;
return false;
}
// we can't move into anything new during selection
if (Cursor_.size() == Anchor_.size())
return false;
- if (&t != Anchor_[Cursor_.size()].par_)
+ if (t.nucleus() != Anchor_[Cursor_.size()].par_)
return false;
}
return true;
// we can't move into anything new during selection
if (Cursor_.size() >= Anchor_.size())
return false;
- if (&t != Anchor_[Cursor_.size()].par_)
+ if (t.nucleus() != Anchor_[Cursor_.size()].par_)
return false;
}
}
+#if 0
void MathCursor::setPos(int x, int y)
{
//dump("setPos 1");
//dump("setPos 2");
}
+#else
+
+void MathCursor::setPos(int x, int y)
+{
+ dump("setPos 1");
+ cursor_type best_cursor;
+ double best_dist = 1e10;
+
+ MathIterator it(formula()->par().nucleus());
+ MathIterator et;
+ for ( ; it != et; ++it) {
+ if (selection_) {
+ // avoid deeper nested insets when selecting
+ if (it.cursor().size() > Anchor_.size())
+ continue;
+ // anchor might be deeper!
+ if (it.cursor().size() == Anchor_.size())
+ if (it.par() != Anchor_.back().par_)
+ continue;
+ //if (it.par() != Anchor_[it.cursor().size()].par_)
+ // continue;
+ }
+ //lyxerr << it.position() << endl;
+ int xo = it.position().xpos();
+ int yo = it.position().ypos();
+ double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
+ if (d < best_dist) {
+ best_dist = d;
+ best_cursor = it.cursor();
+ }
+ }
+ if (best_dist < 1e10)
+ Cursor_ = best_cursor;
+ //lyxerr << "x: " << x << " y: " << y << " dist: " << best_dist << "\n";
+ dump("setPos 2");
+}
+
+#endif
+
+
+
void MathCursor::home(bool sel)
{
void MathCursor::selCopy()
{
- seldump("selCopy");
+ dump("selCopy");
if (selection_) {
theSelection.grab(*this);
selClear();
void MathCursor::selCut()
{
- seldump("selCut");
+ dump("selCut");
if (selection_) {
theSelection.grab(*this);
theSelection.erase(*this);
void MathCursor::selDel()
{
- seldump("selDel");
+ dump("selDel");
if (selection_) {
theSelection.erase(*this);
if (pos() > size())
void MathCursor::selPaste()
{
- seldump("selPaste");
+ dump("selPaste");
theSelection.paste(*this);
//theSelection.grab(*this);
//selClear();
void MathCursor::selStart()
{
- seldump("selStart");
+ dump("selStart 1");
//theSelection.clear();
Anchor_ = Cursor_;
selection_ = true;
+ dump("selStart 2");
}
void MathCursor::selClear()
{
- seldump("selClear");
+ dump("selClear 1");
selection_ = false;
+ dump("selClear 2");
}
void MathCursor::selGet(MathArray & ar)
{
- seldump("selGet");
+ dump("selGet");
if (!selection_)
return;
pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
} else {
std::vector<MathInset::idx_type> indices
- = (*i1.par_)->idxBetween(i1.idx_, i2.idx_);
+ = i1.par_->idxBetween(i1.idx_, i2.idx_);
for (unsigned i = 0; i < indices.size(); ++i) {
MathXArray & c = i1.xcell(indices[i]);
int x1 = c.xo();
#ifdef WITH_WARNINGS
#warning This should probably take cellXOffset and cellYOffset into account
#endif
+ dump("getPos 1");
x = xarray().xo() + xarray().pos2x(pos());
y = xarray().yo();
+ dump("getPos 2");
}
-MathAtom & MathCursor::par() const
+MathInset * MathCursor::par() const
{
- return *cursor().par_;
+ return cursor().par_;
}
MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
{
for (int i = Cursor_.size() - 1; i >= 0; --i) {
- MathGridInset * p = (*Cursor_[i].par_)->asGridInset();
+ MathGridInset * p = Cursor_[i].par_->asGridInset();
if (p) {
idx = Cursor_[i].idx_;
return p;
bool MathCursor::goUp()
{
// first ask the inset if it knows better then we
- if (par()->idxUp(idx(), pos()))
+ if (par()->idxUp(idx(), pos())) {
+ int xlow, xhigh, ylow, yhigh;
+ xarray().boundingBox(xlow, xhigh, ylow, yhigh);
+ bruteFind(xlow, xhigh, ylow, yhigh);
return true;
+ }
// leave subscript to the nearest side
MathScriptInset * p = par()->asScriptInset();
bool MathCursor::goDown()
{
// first ask the inset if it knows better then we
- if (par()->idxDown(idx(), pos()))
+ if (par()->idxDown(idx(), pos())) {
+ int xlow, xhigh, ylow, yhigh;
+ xarray().boundingBox(xlow, xhigh, ylow, yhigh);
+ bruteFind(xlow, xhigh, ylow, yhigh);
return true;
+ }
// leave superscript to the nearest side
MathScriptInset * p = par()->asScriptInset();
int x0;
int y0;
getPos(x0, y0);
- std::vector<MathCursorPos> save = Cursor_;
- std::vector<MathCursorPos> best;
+ cursor_type save = Cursor_;
+ cursor_type best;
double best_dist = 1e10; // large enough
bool found = false;
for (int y = ylow; y < yhigh; y += 4) {
}
+bool MathCursor::bruteFind(int xlow, int xhigh, int ylow, int yhigh)
+{
+ //lyxerr << "looking at range: " << ylow << " " << yhigh << "\n";
+ int x;
+ int y;
+ getPos(x, y);
+
+ cursor_type best_cursor;
+ double best_dist = 1e10;
+
+ MathIterator it(formula()->par().nucleus());
+ MathIterator et;
+ for ( ; it != et; ++it) {
+ int xo = it.position().xpos();
+ int yo = it.position().ypos();
+ if (xlow <= xo && xo <= xhigh && ylow <= yo && yo <= yhigh) {
+ double d = (x - xo) * (x - xo) + (y - yo) * (y - yo);
+ if (d < best_dist) {
+ best_dist = d;
+ best_cursor = it.cursor();
+ }
+ }
+ }
+ if (best_dist < 1e10)
+ Cursor_ = best_cursor;
+ return true;
+}
+
+
bool MathCursor::idxLeft()
{
return par()->idxLeft(idx(), pos());
-////////////////////////////////////////////////////////////////////////
-
-
-bool operator==(MathCursorPos const & ti, MathCursorPos const & it)
+MathCursorPos MathCursor::normalAnchor() const
{
- return ti.par_ == it.par_ && ti.idx_ == it.idx_ && ti.pos_ == it.pos_;
+ // use Anchor on the same level as Cursor
+ MathCursorPos normal = Anchor_[Cursor_.size() - 1];
+ if (Cursor_.size() < Anchor_.size() && !(normal < cursor())) {
+ // anchor is behind cursor -> move anchor behind the inset
+ ++normal.pos_;
+ }
+ return normal;
}
-bool operator<(MathCursorPos const & ti, MathCursorPos const & it)
+void MathCursor::stripFromLastEqualSign()
{
- if (ti.par_ != it.par_) {
- lyxerr << "can't compare cursor and anchor in different insets\n";
- return true;
- }
- if (ti.idx_ != it.idx_)
- return ti.idx_ < it.idx_;
- return ti.pos_ < it.pos_;
+ // find position of last '=' in the array
+ MathArray & ar = cursor().cell();
+ MathArray::const_iterator et = ar.end();
+ for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
+ if ((*it)->getChar() == '=')
+ et = it;
+
+ // delete everything behind this position
+ ar.erase(et - ar.begin(), ar.size());
+ pos() = ar.size();
}
+////////////////////////////////////////////////////////////////////////
+
+
+MathCursorPos::MathCursorPos()
+ : par_(0), idx_(0), pos_(0)
+{}
+
+
+MathCursorPos::MathCursorPos(MathInset * p)
+ : par_(p), idx_(0), pos_(0)
+{}
+
+
MathArray & MathCursorPos::cell(MathCursor::idx_type idx) const
{
- return (*par_)->cell(idx);
+ return par_->cell(idx);
}
MathArray & MathCursorPos::cell() const
{
- return (*par_)->cell(idx_);
+ return par_->cell(idx_);
}
MathXArray & MathCursorPos::xcell(MathCursor::idx_type idx) const
{
- return (*par_)->xcell(idx);
+ return par_->xcell(idx);
}
MathXArray & MathCursorPos::xcell() const
{
- return (*par_)->xcell(idx_);
+ return par_->xcell(idx_);
}
-MathCursorPos MathCursor::normalAnchor() const
+int MathCursorPos::xpos() const
{
- // use Anchor on the same level as Cursor
- MathCursorPos normal = Anchor_[Cursor_.size() - 1];
- if (Cursor_.size() < Anchor_.size() && !(normal < cursor())) {
- // anchor is behind cursor -> move anchor behind the inset
- ++normal.pos_;
- }
- return normal;
+ return xcell().xo() + xcell().pos2x(pos_);
}
-void MathCursor::stripFromLastEqualSign()
+int MathCursorPos::ypos() const
{
- // find position of last '=' in the array
- MathArray & ar = cursor().cell();
- MathArray::const_iterator et = ar.end();
- for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
- if ((*it)->getChar() == '=')
- et = it;
+ return xcell().yo();
+}
- // delete everything behind this position
- ar.erase(et - ar.begin(), ar.size());
- pos() = ar.size();
+std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
+{
+ os << "(par: " << p.par_ << " idx: " << p.idx_ << " pos: " << p.pos_ << ")";
+ return os;
+}
+
+
+bool operator==(MathCursorPos const & ti, MathCursorPos const & it)
+{
+ return ti.par_ == it.par_ && ti.idx_ == it.idx_ && ti.pos_ == it.pos_;
+}
+
+
+bool operator!=(MathCursorPos const & ti, MathCursorPos const & it)
+{
+ return ti.par_ != it.par_ || ti.idx_ != it.idx_ || ti.pos_ != it.pos_;
+}
+
+
+bool operator<(MathCursorPos const & ti, MathCursorPos const & it)
+{
+ if (ti.par_ != it.par_) {
+ lyxerr << "can't compare cursor and anchor in different insets\n";
+ return true;
+ }
+ if (ti.idx_ != it.idx_)
+ return ti.idx_ < it.idx_;
+ return ti.pos_ < it.pos_;
}