#include "debug.h"
#include "LColor.h"
#include "Painter.h"
-#include "support.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_charinset.h"
#include "math_deliminset.h"
-#include "math_matrixinset.h"
+#include "math_hullinset.h"
#include "math_scriptinset.h"
#include "math_spaceinset.h"
#include "math_specialcharinset.h"
-#include "math_parser.h"
+#include "math_mathmlstream.h"
#define FILEDEBUG 0
MathCursorPos i1;
MathCursorPos i2;
cursor.getSelection(i1, i2);
- if (i1.idx_ == i2.idx_) {
+ if (i1.idx_ == i2.idx_)
i1.cell().erase(i1.pos_, i2.pos_);
- } else {
+ else {
std::vector<MathInset::idx_type> indices =
(*i1.par_)->idxBetween(i1.idx_, i2.idx_);
for (unsigned i = 0; i < indices.size(); ++i)
void MathCursor::push(MathAtom & t)
{
- //cerr << "Entering atom "; t->write(cerr, false); cerr << " left\n";
MathCursorPos p;
p.par_ = &t;
+ p.idx_ = 0;
+ p.pos_ = 0;
Cursor_.push_back(p);
}
#endif
+UpdatableInset * MathCursor::asHyperActiveInset() const
+{
+ return par()->asHyperActiveInset();
+}
+
+
bool MathCursor::isInside(MathInset const * p) const
{
for (unsigned i = 0; i < Cursor_.size(); ++i)
bool MathCursor::openable(MathAtom const & t, bool sel) const
{
+ if (t->isHyperActive())
+ return true;
+
if (!t->isActive())
return false;
{
if (pos() == 0)
return false;
-
--pos();
-
return true;
}
{
if (pos() == size())
return false;
-
++pos();
-
return true;
}
lastcode_ = LM_TC_VAR;
if (hasPrevAtom() && openable(prevAtom(), sel)) {
+ if (prevAtom()->isHyperActive()) {
+ lyxerr << "entering hyperactive inset\n";
+ }
pushRight(prevAtom());
return true;
}
-
- return posLeft() || idxLeft() || popLeft();
+
+ return posLeft() || idxLeft() || popLeft() || selection_;
}
lastcode_ = LM_TC_VAR;
if (hasNextAtom() && openable(nextAtom(), sel)) {
+ if (nextAtom()->isHyperActive()) {
+ lyxerr << "entering hyperactive inset\n";
+ int x, y;
+ getPos(x, y);
+ nextAtom()->edit(formula()->view(), x, y, 0);
+ }
pushLeft(nextAtom());
return true;
}
- return posRight() || idxRight() || popRight();
+ return posRight() || idxRight() || popRight() || selection_;
}
right(); // do not push for e.g. MathSymbolInset
selPaste();
}
- p->metrics(p->size());
+#ifdef WITH_WARNINGS
+#warning "redraw disabled"
+#endif
+ //p->metrics(p->size());
}
if (par()->nrows() > 1)
par()->delRow(row());
+
+ if (pos() > size())
+ pos() = size();
}
MathAtom & p = prevAtom();
if (p->asScriptInset() && p->asScriptInset()->hasUp()) {
pushRight(p);
+ idx() = 1;
pos() = size();
return true;
}
MathAtom & n = nextAtom();
if (n->asScriptInset() && n->asScriptInset()->hasUp()) {
pushLeft(n);
+ idx() = 1;
pos() = 0;
return true;
}
}
}
- return goUp();
+ return goUp() || selection_;
}
MathAtom & p = prevAtom();
if (p->asScriptInset() && p->asScriptInset()->hasDown()) {
pushRight(p);
+ idx() = 0;
pos() = size();
return true;
}
MathAtom & n = nextAtom();
if (n->asScriptInset() && n->asScriptInset()->hasDown()) {
pushLeft(n);
+ idx() = 0;
pos() = 0;
return true;
}
}
}
- return goDown();
+ return goDown() || selection_;
}
}
-void MathCursor::setSize(MathStyles size)
-{
- par()->userSetSize(size);
-}
-
-
void MathCursor::macroModeClose()
{
string s = macroName();
seldump("selDel");
if (selection_) {
theSelection.erase(*this);
+ if (pos() > size())
+ pos() = size();
selClear();
}
}
}
+void MathCursor::selGet(MathArray & ar)
+{
+ seldump("selGet");
+ if (!selection_)
+ return;
+
+ theSelection.grab(*this);
+ ar = theSelection.glue();
+}
+
+
+
void MathCursor::drawSelection(Painter & pain) const
{
if (!selection_)
MathCursorPos i1;
MathCursorPos i2;
getSelection(i1, i2);
-
//lyxerr << "selection from: " << i1 << " to " << i2 << "\n";
if (i1.idx_ == i2.idx_) {
pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
}
}
+
+#if 0
+ // draw anchor if different from selection boundary
+ MathCursorPos anc = Anchor_.back();
+ if (anc != i1 && anc != i2) {
+ MathXArray & c = anc.xcell();
+ int x = c.xo() + c.pos2x(anc.pos_);
+ int y1 = c.yo() - c.ascent();
+ int y2 = c.yo() + c.descent();
+ pain.line(x, y1, x, y2, LColor::mathline);
+ }
+#endif
}
}
-MathArrayInset * MathCursor::enclosingArray(MathCursor::idx_type & idx) const
+MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
{
for (int i = Cursor_.size() - 1; i >= 0; --i) {
- MathArrayInset * p = (*Cursor_[i].par_)->asArrayInset();
+ MathGridInset * p = (*Cursor_[i].par_)->asGridInset();
if (p) {
idx = Cursor_[i].idx_;
return p;
}
-MathStyles MathCursor::style() const
-{
- return xarray().style();
-}
-
-
void MathCursor::normalize() const
{
#ifdef WITH_WARNINGS
if (pos() > size()) {
lyxerr << "this should not really happen - 2: "
- << pos() << " " << size() << "\n";
+ << pos() << " " << size() << " in idx: " << it->idx()
+ << " in atom: '";
+ WriteStream wi(0, lyxerr, false);
+ it->par()->write(wi);
+ lyxerr << "\n";
dump("error 4");
}
it->pos() = min(pos(), size());
while (popRight())
;
- MathMatrixInset * p = formula()->par()->asMatrixInset();
+ MathHullInset * p = formula()->par()->asHullInset();
if (!p)
return;
// split line
const row_type r = row();
- for (col_type c = col() + 1; c < p->ncols(); ++c) {
- const MathMatrixInset::idx_type i1 = p->index(r, c);
- const MathMatrixInset::idx_type i2 = p->index(r + 1, c);
- lyxerr << "swapping cells " << i1 << " and " << i2 << "\n";
- p->cell(i1).swap(p->cell(i2));
- }
+ for (col_type c = col() + 1; c < p->ncols(); ++c)
+ p->cell(p->index(r, c)).swap(p->cell(p->index(r + 1, c)));
// split cell
splitCell();
}
+void MathCursor::readLine(MathArray & ar) const
+{
+ idx_type base = row() * par()->ncols();
+ for (idx_type off = 0; off < par()->ncols(); ++off)
+ ar.push_back(par()->cell(base + off));
+}
+
+
char MathCursor::valign() const
{
idx_type idx;
- MathArrayInset * p = enclosingArray(idx);
+ MathGridInset * p = enclosingGrid(idx);
return p ? p->valign() : '\0';
}
char MathCursor::halign() const
{
idx_type idx;
- MathArrayInset * p = enclosingArray(idx);
+ MathGridInset * p = enclosingGrid(idx);
return p ? p->halign(idx % p->ncols()) : '\0';
}
// leave subscript to the nearest side
MathScriptInset * p = par()->asScriptInset();
- if (p && p->hasDown()) {
+ if (p && idx() == 0) {
if (pos() <= size() / 2)
popLeft();
else
int y0;
getPos(x0, y0);
std::vector<MathCursorPos> save = Cursor_;
- MathAtom const & out = formula()->par();
y0 -= xarray().ascent();
- for (int y = y0 - 4; y > out->yo() - out->ascent(); y -= 4) {
+ for (int y = y0 - 4; y > formula()->upperY(); y -= 4) {
setPos(x0, y);
if (save != Cursor_ && xarray().yo() < y0)
return true;
// leave superscript to the nearest side
MathScriptInset * p = par()->asScriptInset();
- if (p && p->hasUp()) {
+ if (p && idx() == 1) {
if (pos() <= size() / 2)
popLeft();
else
int y0;
getPos(x0, y0);
std::vector<MathCursorPos> save = Cursor_;
- MathAtom const & out = formula()->par();
y0 += xarray().descent();
- for (int y = y0 + 4; y < out->yo() + out->descent(); y += 4) {
+ for (int y = y0 + 4; y < formula()->lowerY(); y += 4) {
setPos(x0, y);
if (save != Cursor_ && xarray().yo() > y0)
return true;
}
-void MathCursor::interpret(string const & s)
+bool MathCursor::interpret(string const & s)
{
//lyxerr << "interpret 1: '" << s << "'\n";
- //lyxerr << "in: " << in_word_set(s) << " \n";
-
if (s.empty())
- return;
+ return true;
- if (s.size() == 1) {
- interpret(s[0]);
- return;
- }
+ if (s.size() == 1)
+ return interpret(s[0]);
//lyxerr << "char: '" << s[0] << "' int: " << int(s[0]) << endl;
//owner_->getIntl()->getTrans().TranslateAndInsert(s[0], lt);
//lyxerr << "trans: '" << s[0] << "' int: " << int(s[0]) << endl;
- if (s.size() > 7 && s.substr(0, 7) == "matrix ") {
+ if (s.size() >= 5 && s.substr(0, 5) == "cases") {
+ unsigned int n = 1;
+ istringstream is(s.substr(6).c_str());
+ is >> n;
+ n = std::max(1u, n);
+ niceInsert(MathAtom(new MathCasesInset(n)));
+ return true;
+ }
+
+ if (s.size() >= 6 && s.substr(0, 6) == "matrix") {
unsigned int m = 1;
unsigned int n = 1;
string v_align;
n = std::max(1u, n);
v_align += 'c';
niceInsert(MathAtom(new MathArrayInset(m, n, v_align[0], h_align)));
- return;
+ return true;
}
if (s == "\\over" || s == "\\choose" || s == "\\atop") {
niceInsert(t);
popRight();
left();
- return;
+ return true;
}
niceInsert(createMathInset(s.substr(1)));
+ return true;
}
-void MathCursor::interpret(char c)
+bool MathCursor::interpret(char c)
{
//lyxerr << "interpret 2: '" << c << "'\n";
+ if (c == '^' || c == '_') {
+ macroModeClose();
+ const bool up = (c == '^');
+ selCut();
+ if (hasPrevAtom() && prevAtom()->asScriptInset()) {
+ prevAtom()->asScriptInset()->ensure(up);
+ pushRight(prevAtom());
+ idx() = up;
+ pos() = size();
+ } else if (hasNextAtom() && nextAtom()->asScriptInset()) {
+ nextAtom()->asScriptInset()->ensure(up);
+ pushLeft(nextAtom());
+ idx() = up;
+ pos() = 0;
+ } else {
+ plainInsert(MathAtom(new MathScriptInset(up)));
+ prevAtom()->asScriptInset()->ensure(up);
+ pushRight(prevAtom());
+ idx() = up;
+ pos() = 0;
+ }
+ selPaste();
+ dump("1");
+ return true;
+ }
+
+ // handle macroMode
if (inMacroMode()) {
string name = macroName();
if (name == "\\" && c == '#') {
insert(c, LM_TC_TEX);
- return;
+ return true;
}
if (name == "\\" && c == '\\') {
backspace();
interpret("\\backslash");
- return;
+ return true;
}
if (name == "\\#" && '1' <= c && c <= '9') {
insert(c, LM_TC_TEX);
macroModeClose();
- return;
+ return true;
}
if (isalpha(c)) {
insert(c, LM_TC_TEX);
- return;
+ return true;
}
if (name == "\\") {
insert(c, LM_TC_TEX);
macroModeClose();
- return;
+ return true;
}
macroModeClose();
- return;
- }
-
- // no macro mode
- if (c == '^' || c == '_') {
- const bool up = (c == '^');
- selCut();
- if (hasPrevAtom() && prevAtom()->asScriptInset()) {
- prevAtom()->asScriptInset()->ensure(up);
- pushRight(prevAtom());
- pos() = size();
- } else if (hasNextAtom() && nextAtom()->asScriptInset()) {
- nextAtom()->asScriptInset()->ensure(up);
- pushLeft(nextAtom());
- pos() = 0;
- } else {
- plainInsert(MathAtom(new MathScriptInset(up)));
- pushRight(prevAtom());
- }
- idx() = up;
- selPaste();
- return;
+ return true;
}
if (selection_)
selDel();
if (lastcode_ == LM_TC_TEXTRM) {
+ // suppress direct insertion of to spaces in a row
+ // the still allows typing '<space>a<space>' and deleting the 'a', but
+ // it is better than nothing
+ if (hasPrevAtom() && prevAtom()->getChar() == ' ')
+ return true;
insert(c, LM_TC_TEXTRM);
- return;
+ return true;
}
if (c == ' ') {
- MathSpaceInset * p = prevSpaceInset();
- if (p) {
- p->incSpace();
- return;
+ if (hasPrevAtom() && prevAtom()->asSpaceInset()) {
+ prevAtom()->asSpaceInset()->incSpace();
+ return true;
}
-
+
if (mathcursor->popRight())
- return;
+ return true;
-#warning look here
- // this would not work if the inset is in an table!
- //bv->text->cursorRight(bv, true);
- //result = FINISHED;
- return;
+ // if are at the very end, leave the formula
+ return pos() != size();
}
+/*
if (strchr("{}", c)) {
insert(c, LM_TC_TEX);
- return;
+ return true;
+ }
+*/
+
+ if (c == '{') {
+ niceInsert(MathAtom(new MathBraceInset));
+ return true;
+ }
+
+ if (c == '}') {
+ return true;
}
if (strchr("#$%", c)) {
insert(MathAtom(new MathSpecialCharInset(c)));
lastcode_ = LM_TC_VAR;
- return;
+ return true;
}
- if (isalpha(c) && (lastcode_ == LM_TC_GREEK || lastcode_ == LM_TC_GREEK1)) {
- static char const greekl[][26] =
- {"alpha", "beta", "chi", "delta", "epsilon", "phi",
- "gamma", "eta", "iota", "iota", "kappa", "lambda", "mu",
- "nu", "omikron", "pi", "omega", "rho", "sigma",
- "tau", "upsilon", "theta", "omega", "xi", "upsilon", "zeta"};
- static char const greeku[][26] =
- {"Alpha", "Beta", "Chi", "Delta", "Epsilon", "Phi",
- "Gamma", "Eta", "Iota", "Iota", "Kappa", "Lambda", "Mu",
- "Nu", "Omikron", "Pi", "Omega", "Rho", "Sigma", "Tau",
- "Upsilon", "Theta", "Omega", "xi", "Upsilon", "Zeta"};
-
- latexkeys const * l = 0;
- if ('a' <= c && c <= 'z')
- l = in_word_set(greekl[c - 'a']);
- if ('A' <= c && c <= 'Z')
- l = in_word_set(greeku[c - 'A']);
-
- if (l)
- insert(createMathInset(l));
- else
- insert(c, LM_TC_VAR);
+ if (isalpha(c) && lastcode_ == LM_TC_GREEK) {
+ insert(c, LM_TC_VAR);
+ return true;
+ }
-#warning greek insert problem? look here!
- if (lastcode_ == LM_TC_GREEK1)
- lastcode_ = LM_TC_VAR;
- return;
+ if (isalpha(c) && lastcode_ == LM_TC_GREEK1) {
+ insert(c, LM_TC_VAR);
+ lastcode_ = LM_TC_VAR;
+ return true;
}
if (c == '\\') {
insert(c, LM_TC_TEX);
//bv->owner()->message(_("TeX mode"));
- return;
+ return true;
}
// no special circumstances, so insert the character without any fuss
insert(c, LM_TC_MIN);
+ return true;
}
}
-MathSpaceInset * MathCursor::prevSpaceInset() const
+void MathCursor::stripFromLastEqualSign()
{
- if (!hasPrevAtom())
- return 0;
- return prevAtom()->asSpaceInset();
+ // 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();
}
+
+