MathCursorPos i1;
MathCursorPos i2;
cursor.getSelection(i1, i2);
- if (i1.idx_ == i2.idx_)
- data_.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
+ if (i1.idx_ == i2.idx_) {
+ MathArray ar;
+ if (i1.inner_) {
+ ar.push_back(*i1.at());
+ ar.back().removeNucleus();
+ ++i1.pos_;
+ }
+ ar.push_back(MathArray(i1.cell(), i1.pos_, i2.pos_));
+ if (i2.inner_) {
+ ar.push_back(*i2.at());
+ ar.back().removeUp();
+ ar.back().removeDown();
+ }
+ data_.push_back(ar);
+ }
else {
std::vector<MathInset::idx_type> indices =
i1.par_->idxBetween(i1.idx_, i2.idx_);
MathCursorPos i1;
MathCursorPos i2;
cursor.getSelection(i1, i2);
- if (i1.idx_ == i2.idx_)
+ if (i1.idx_ == i2.idx_) {
+ if (i1.inner_) {
+ i1.inner_ = false;
+ i1.at()->removeUp();
+ i1.at()->removeDown();
+ ++i1.pos_;
+ }
+ if (i2.inner_) {
+ i2.inner_ = false;
+ i2.at()->removeNucleus();
+ }
i1.cell().erase(i1.pos_, i2.pos_);
- else {
- std::vector<MathInset::idx_type> indices = i1.par_->idxBetween(i1.idx_, i2.idx_);
+ } else {
+ std::vector<MathInset::idx_type> indices =
+ i1.par_->idxBetween(i1.idx_, i2.idx_);
for (unsigned i = 0; i < indices.size(); ++i)
i1.cell(indices[i]).erase();
}
std::ostream & operator<<(std::ostream & os, MathCursorPos const & p)
{
os << "(par: " << p.par_ << " idx: " << p.idx_
- << " pos: " << p.pos_ << ")";
+ << " pos: " << p.pos_ << " inner: " << p.inner_ << ")";
return os;
}
#endif
void MathCursor::pushLeft(MathInset * par)
{
MathCursorPos p;
- p.par_ = par;
+ p.par_ = par;
+ p.inner_ = false;
par->idxFirst(p.idx_, p.pos_);
Cursor_.push_back(p);
}
{
posLeft();
MathCursorPos p;
- p.par_ = par;
+ p.par_ = par;
+ p.inner_ = false;
par->idxLast(p.idx_, p.pos_);
Cursor_.push_back(p);
}
bool MathCursor::posLeft()
{
+ if (inner()) {
+ inner() = false;
+ return true;
+ }
+
if (pos() == 0)
return false;
+
--pos();
+
+ if (nextAtom()->hasInner())
+ inner() = true;
+
return true;
}
bool MathCursor::posRight()
{
+ if (inner()) {
+ ++pos();
+ inner() = false;
+ return true;
+ }
+
if (pos() == size())
return false;
- ++pos();
+
+ if (nextAtom()->hasInner())
+ inner() = true;
+ else
+ ++pos();
+
return true;
}
int x1 = x - ar.xo();
int y1 = y - ar.yo();
MathXArray::size_type c = ar.x2pos(x1);
- int xx = abs(x1 - ar.pos2x(c));
+ int xx = abs(x1 - ar.pos2x(c, false));
int yy = abs(y1);
//lyxerr << "idx: " << i << " xx: " << xx << " yy: " << yy
// << " c: " << c << " xo: " << ar.xo() << "\n";
}
+void MathCursor::plainInsert(MathInset * p)
+{
+ if (inner()) {
+ array().insert(pos(), p);
+ ++pos();
+ swap(prevAtom()->nucleus(), nextAtom()->nucleus());
+ return;
+ }
+
+ MathAtom * n = nextAtom();
+
+ if (n && !n->nucleus()) {
+ n->nucleus() = p;
+ inner() = true;
+ return;
+ }
+
+ array().insert(pos(), p); // this invalidates the pointer!
+ ++pos();
+}
+
+
void MathCursor::insert(char c, MathTextCodes t)
{
//lyxerr << "inserting '" << c << "'\n";
- array().insert(pos(), new MathCharInset(c, t));
- posRight();
+ plainInsert(new MathCharInset(c, t));
}
{
macroModeClose();
- if (selection_) {
+ if (p && selection_) {
if (p->nargs())
selCut();
else
selDel();
}
- array().insert(pos(), p); // this invalidates the pointer!
- p = array().at(pos())->nucleus();
- posRight();
+ plainInsert(p);
}
}
+void MathCursor::glueAdjacentAtoms()
+{
+ MathAtom * p = prevAtom();
+ if (!p)
+ return;
+
+ MathAtom * n = nextAtom();
+ if (!n)
+ return;
+
+ if (p->up() && n->up())
+ return;
+
+ if (p->down() && n->down())
+ return;
+
+ // move everything to the previous atom
+ if (n->up())
+ swap(p->up(), n->up());
+
+ if (n->down())
+ swap(p->down(), n->down());
+
+ plainErase();
+ --pos();
+ inner() = nextAtom()->hasInner();
+}
+
+
void MathCursor::backspace()
{
- if (posLeft()) {
- erase();
+ if (inner()) {
+ nextAtom()->removeNucleus();
+ inner() = false;
+ glueAdjacentAtoms();
return;
}
- if (size()) {
- pullArg(false);
+ if (pos() == 0) {
+ if (size())
+ pullArg(false);
+ return;
+ }
+
+ if (prevAtom()->hasInner()) {
+ --pos();
+ inner() = true;
return;
}
- erase();
+ --pos();
+ plainErase();
}
void MathCursor::erase()
{
- dump("erase 1");
if (inMacroMode())
return;
}
// delete empty cells if necessary
- if (pos() == 0 && array().empty()) {
+ if (array().empty()) {
bool popit;
bool removeit;
par()->idxDelete(idx(), popit, removeit);
return;
}
- if (pos() == size())
+ MathAtom * n = nextAtom();
+
+ if (!n)
return;
- // delete nucleus, keep scripts if possible
- MathAtom * p = prevAtom();
- MathAtom * n = nextAtom();
- if (pos() > 0) {
- bool need_parans = (p->up() && n->up()) || (p->down() && n->down());
- if (need_parans) {
- // need empty block
- insert('{', LM_TC_TEX);
- insert('}', LM_TC_TEX);
- p = prevAtom();
- n = nextAtom();
- }
- // move indices to the left
+ if (inner()) {
if (n->up())
- swap(p->up(), n->up());
- if (n->down())
- swap(p->down(), n->down());
- plainErase();
+ n->removeUp();
+ else if (n->down())
+ n->removeDown();
+ if (!n->up() && !n->down()) {
+ ++pos();
+ inner() = false;
+ }
return;
}
- // pos == 0 now
- if (n->up() || n->down()) {
- insert('{', LM_TC_TEX);
- insert('}', LM_TC_TEX);
- p = prevAtom();
- n = nextAtom();
- swap(p->up(), n->up());
- swap(p->down(), n->down());
+ if (n->hasInner()) {
+ n->removeNucleus();
+ inner() = true;
+ return;
}
plainErase();
- dump("erase 2");
}
if (i1.idx_ == i2.idx_) {
MathXArray & c = i1.xcell();
- int x1 = c.xo() + c.pos2x(i1.pos_);
+ int x1 = c.xo() + c.pos2x(i1.pos_, i1.inner_);
int y1 = c.yo() - c.ascent();
- int x2 = c.xo() + c.pos2x(i2.pos_);
+ int x2 = c.xo() + c.pos2x(i2.pos_, i2.inner_);
int y2 = c.yo() + c.descent();
pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
} else {
#ifdef WITH_WARNINGS
#warning This should probably take cellXOffset and cellYOffset into account
#endif
- x = xarray().xo() + xarray().pos2x(pos());
+ x = xarray().xo() + xarray().pos2x(pos(), inner());
y = xarray().yo();
}
}
+bool MathCursor::inner() const
+{
+ return cursor().inner_;
+}
+
+
+bool & MathCursor::inner()
+{
+ return cursor().inner_;
+}
+
+
bool MathCursor::inMacroMode() const
{
return lastcode_ == LM_TC_TEX;
int MathCursor::xpos() const
{
- return cellXOffset() + xarray().pos2x(pos());
+ return cellXOffset() + xarray().pos2x(pos(), inner());
}
// we got just a single char now
if (c == '^' || c == '_') {
- bool const up = (s[0] == '^');
- selCut();
- if (!prevInset()) {
- insert('{', LM_TC_TEX);
- insert('}', LM_TC_TEX);
- }
+ const bool up = (s[0] == '^');
+ selCut();
+ if (inner())
+ ++pos();
+ if (!prevAtom())
+ insert(0);
MathInset * par = prevAtom()->ensure(up);
pushRight(par);
selPaste();
return;
}
- if (lastcode_ != LM_TC_TEX && strchr("#$%{}", c)) {
+ if (lastcode_ != LM_TC_TEX && strchr("{}", c)) {
+ insert(c, LM_TC_TEX);
+ return;
+ }
+
+ if (lastcode_ != LM_TC_TEX && strchr("#$%", c)) {
insert(new MathSpecialCharInset(c));
lastcode_ = LM_TC_VAR;
return;
macroModeClose();
lastcode_ = LM_TC_VAR;
}
- else if (isalpha(c))
+ else if (isalpha(c)) {
insert(c, LM_TC_TEX);
+ }
else {
macroModeClose();
lastcode_ = LM_TC_VAR;
}
// no special circumstances, so insert the character without any fuss
- insert(c);
+ insert(c, LM_TC_MIN);
}
}
+MathAtom * MathCursorPos::at() const
+{
+ return cell().at(pos_);
+}
+
+
MathCursorPos MathCursor::normalAnchor() const
{
// use Anchor on the same level as Cursor
MathInset::idx_type idx_;
/// cell position
MathInset::pos_type pos_;
+ /// faked position "inside an atom"
+ bool inner_;
+
/// returns cell corresponding to this position
MathArray & cell() const;
/// returns cell corresponding to this position
MathXArray & xcell() const;
/// returns xcell corresponding to this position
MathXArray & xcell(MathInset::idx_type idx) const;
+
+ /// returns atom corresponding to this position
+ MathAtom * at() const;
};
///
void first();
/// Put the cursor in the last position
void last();
- /// moves cursor position one cell to the left
- bool posLeft();
- /// moves cursor position one cell to the right
- bool posRight();
- /// moves cursor index one cell to the left
- bool idxLeft();
- /// moves cursor index one cell to the right
- bool idxRight();
- /// moves position somehow up
- bool goUp();
- /// moves position somehow down
- bool goDown();
///
void idxNext();
///
void plainInsert(MathInset * p);
///
void niceInsert(MathInset * p);
+
///
void delLine();
/// This is in pixels from (maybe?) the top of inset
///
InsetFormulaBase const * formula();
///
+ bool inner() const;
+ ///
pos_type pos() const;
///
idx_type idx() const;
MathScriptInset * prevScriptInset() const;
///
MathSpaceInset * prevSpaceInset() const;
+
private:
+ /// moves cursor position one cell to the left
+ bool posLeft();
+ /// moves cursor position one cell to the right
+ bool posRight();
+ /// moves cursor index one cell to the left
+ bool idxLeft();
+ /// moves cursor index one cell to the right
+ bool idxRight();
+ /// moves position somehow up
+ bool goUp();
+ /// moves position somehow down
+ bool goDown();
+ /// glue adjacent atoms if possible
+ void glueAdjacentAtoms();
+
///
string macroName() const;
///
- void insert(char, MathTextCodes t = LM_TC_MIN);
+ void insert(char, MathTextCodes t);
/// can we enter the inset?
bool openable(MathInset *, bool selection) const;
/// can the setPos routine enter that inset?
MathInset * positionable(MathAtom *, int x, int y) const;
+ /// write access to "inner" flag
+ bool & inner();
/// write access to cursor cell position
pos_type & pos();
/// write access to cursor cell index