X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=inline;f=src%2Fmathed%2Fmath_cursor.C;h=1cb978decbc0cca3aba45956a242b6ecbf88ed56;hb=d76cb8f1cf799aba11cbb8b13a8baecd29b54dbe;hp=0129b4531e1cb1acd309590e950579648cc38629;hpb=3e2e63a4b40e2acab99fe68eef27f6b1c3ef0e3f;p=lyx.git diff --git a/src/mathed/math_cursor.C b/src/mathed/math_cursor.C index 0129b4531e..1cb978decb 100644 --- a/src/mathed/math_cursor.C +++ b/src/mathed/math_cursor.C @@ -28,18 +28,20 @@ #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 @@ -74,9 +76,9 @@ struct Selection 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 indices = (*i1.par_)->idxBetween(i1.idx_, i2.idx_); for (unsigned i = 0; i < indices.size(); ++i) @@ -132,9 +134,10 @@ MathCursor::MathCursor(InsetFormulaBase * formula, bool left) 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); } @@ -232,6 +235,12 @@ void MathCursor::dump(char const *) const {} #endif +UpdatableInset * MathCursor::asHyperActiveInset() const +{ + return par()->asHyperActiveInset(); +} + + bool MathCursor::isInside(MathInset const * p) const { for (unsigned i = 0; i < Cursor_.size(); ++i) @@ -243,6 +252,9 @@ bool MathCursor::isInside(MathInset const * p) const bool MathCursor::openable(MathAtom const & t, bool sel) const { + if (t->isHyperActive()) + return true; + if (!t->isActive()) return false; @@ -278,9 +290,7 @@ bool MathCursor::posLeft() { if (pos() == 0) return false; - --pos(); - return true; } @@ -289,9 +299,7 @@ bool MathCursor::posRight() { if (pos() == size()) return false; - ++pos(); - return true; } @@ -308,11 +316,14 @@ bool MathCursor::left(bool sel) 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_; } @@ -328,11 +339,17 @@ bool MathCursor::right(bool sel) 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_; } @@ -463,7 +480,10 @@ void MathCursor::niceInsert(MathAtom const & t) right(); // do not push for e.g. MathSymbolInset selPaste(); } - p->metrics(p->size()); +#ifdef WITH_WARNINGS +#warning "redraw disabled" +#endif + //p->metrics(p->size()); } @@ -558,6 +578,9 @@ void MathCursor::delLine() if (par()->nrows() > 1) par()->delRow(row()); + + if (pos() > size()) + pos() = size(); } @@ -573,6 +596,7 @@ bool MathCursor::up(bool sel) MathAtom & p = prevAtom(); if (p->asScriptInset() && p->asScriptInset()->hasUp()) { pushRight(p); + idx() = 1; pos() = size(); return true; } @@ -582,13 +606,14 @@ bool MathCursor::up(bool sel) MathAtom & n = nextAtom(); if (n->asScriptInset() && n->asScriptInset()->hasUp()) { pushLeft(n); + idx() = 1; pos() = 0; return true; } } } - return goUp(); + return goUp() || selection_; } @@ -604,6 +629,7 @@ bool MathCursor::down(bool sel) MathAtom & p = prevAtom(); if (p->asScriptInset() && p->asScriptInset()->hasDown()) { pushRight(p); + idx() = 0; pos() = size(); return true; } @@ -613,13 +639,14 @@ bool MathCursor::down(bool sel) MathAtom & n = nextAtom(); if (n->asScriptInset() && n->asScriptInset()->hasDown()) { pushLeft(n); + idx() = 0; pos() = 0; return true; } } } - return goDown(); + return goDown() || selection_; } @@ -636,12 +663,6 @@ bool MathCursor::toggleLimits() } -void MathCursor::setSize(MathStyles size) -{ - par()->userSetSize(size); -} - - void MathCursor::macroModeClose() { string s = macroName(); @@ -702,6 +723,8 @@ void MathCursor::selDel() seldump("selDel"); if (selection_) { theSelection.erase(*this); + if (pos() > size()) + pos() = size(); selClear(); } } @@ -746,6 +769,18 @@ void MathCursor::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_) @@ -754,7 +789,6 @@ void MathCursor::drawSelection(Painter & pain) const MathCursorPos i1; MathCursorPos i2; getSelection(i1, i2); - //lyxerr << "selection from: " << i1 << " to " << i2 << "\n"; if (i1.idx_ == i2.idx_) { @@ -776,6 +810,18 @@ void MathCursor::drawSelection(Painter & pain) const 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 } @@ -871,10 +917,10 @@ bool MathCursor::selection() const } -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; @@ -911,12 +957,6 @@ void MathCursor::pullArg(bool goright) } -MathStyles MathCursor::style() const -{ - return xarray().style(); -} - - void MathCursor::normalize() const { #ifdef WITH_WARNINGS @@ -933,7 +973,11 @@ void MathCursor::normalize() const 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()); @@ -1048,7 +1092,7 @@ void MathCursor::breakLine() while (popRight()) ; - MathMatrixInset * p = formula()->par()->asMatrixInset(); + MathHullInset * p = formula()->par()->asHullInset(); if (!p) return; @@ -1061,12 +1105,8 @@ void MathCursor::breakLine() // 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(); @@ -1075,10 +1115,18 @@ void MathCursor::breakLine() } +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'; } @@ -1086,7 +1134,7 @@ char MathCursor::valign() const char MathCursor::halign() const { idx_type idx; - MathArrayInset * p = enclosingArray(idx); + MathGridInset * p = enclosingGrid(idx); return p ? p->halign(idx % p->ncols()) : '\0'; } @@ -1155,7 +1203,7 @@ bool MathCursor::goUp() // leave subscript to the nearest side MathScriptInset * p = par()->asScriptInset(); - if (p && p->hasDown()) { + if (p && idx() == 0) { if (pos() <= size() / 2) popLeft(); else @@ -1168,9 +1216,8 @@ bool MathCursor::goUp() int y0; getPos(x0, y0); std::vector 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; @@ -1188,7 +1235,7 @@ bool MathCursor::goDown() // leave superscript to the nearest side MathScriptInset * p = par()->asScriptInset(); - if (p && p->hasUp()) { + if (p && idx() == 1) { if (pos() <= size() / 2) popLeft(); else @@ -1201,9 +1248,8 @@ bool MathCursor::goDown() int y0; getPos(x0, y0); std::vector 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; @@ -1225,24 +1271,29 @@ bool MathCursor::idxRight() } -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; @@ -1253,7 +1304,7 @@ void MathCursor::interpret(string const & s) 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") { @@ -1264,146 +1315,148 @@ void MathCursor::interpret(string const & s) 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 'a' 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; } @@ -1465,9 +1518,18 @@ MathCursorPos MathCursor::normalAnchor() const } -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(); } + +