diff --git a/lib/Makefile.am b/lib/Makefile.am index a428b3d1a7..b0a160efeb 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1110,6 +1110,9 @@ dist_imagesmath_DATA = \ images/math/shortrightarrow.png \ images/math/shortuparrow.png \ images/math/sideset.png \ + images/math/sideset1.png \ + images/math/sideset2.png \ + images/math/sideset3.png \ images/math/sigma.png \ images/math/sigma2.png \ images/math/sim.png \ diff --git a/lib/images/math/sideset1.png b/lib/images/math/sideset1.png new file mode 100644 index 0000000000..a919e8fa64 Binary files /dev/null and b/lib/images/math/sideset1.png differ diff --git a/lib/images/math/sideset2.png b/lib/images/math/sideset2.png new file mode 100644 index 0000000000..7d47f515ef Binary files /dev/null and b/lib/images/math/sideset2.png differ diff --git a/lib/images/math/sideset3.png b/lib/images/math/sideset3.png new file mode 100644 index 0000000000..211c5f9144 Binary files /dev/null and b/lib/images/math/sideset3.png differ diff --git a/lib/ui/stdtoolbars.inc b/lib/ui/stdtoolbars.inc index 5f4e246fbf..416032a57b 100644 --- a/lib/ui/stdtoolbars.inc +++ b/lib/ui/stdtoolbars.inc @@ -183,7 +183,10 @@ ToolbarSet Item "Insert sum" "math-insert \sum" Item "Insert integral" "math-insert \int" Item "Insert product" "math-insert \prod" - Item "Insert side scripts" "math-insert \sideset" + Item "Insert left/right side scripts" "math-insert \sideset" + Item "Insert right side scripts" "math-insert \sideset1" + Item "Insert left side scripts" "math-insert \sideset2" + Item "Insert side scripts" "math-insert \sideset3" Separator Item "Insert ( )" "math-delim ( )" Item "Insert [ ]" "math-delim [ ]" diff --git a/src/mathed/InsetMathSideset.cpp b/src/mathed/InsetMathSideset.cpp index 9d1e51bd1b..9bcbf1f09e 100644 --- a/src/mathed/InsetMathSideset.cpp +++ b/src/mathed/InsetMathSideset.cpp @@ -39,13 +39,16 @@ namespace { namespace lyx { -InsetMathSideset::InsetMathSideset(Buffer * buf) - : InsetMathNest(buf, 5) +InsetMathSideset::InsetMathSideset(Buffer * buf, bool scriptl, bool scriptr) + : InsetMathNest(buf, 3 + scriptl + scriptr), scriptl_(scriptl), + scriptr_(scriptr) {} -InsetMathSideset::InsetMathSideset(Buffer * buf, MathAtom const & at) - : InsetMathNest(buf, 5) +InsetMathSideset::InsetMathSideset(Buffer * buf, bool scriptl, bool scriptr, + MathAtom const & at) + : InsetMathNest(buf, 3 + scriptl + scriptr), scriptl_(scriptl), + scriptr_(scriptr) { nuc().push_back(at); } @@ -76,7 +79,13 @@ bool InsetMathSideset::idxLast(Cursor & cur) const int InsetMathSideset::dybt(BufferView const & bv, int asc, int des, bool top) const { bool isCharBox = nuc().empty() ? false : isAlphaSymbol(nuc().back()); - int dasc = max(bl().dimension(bv).ascent(), br().dimension(bv).ascent()); + int dasc = 0; + if (scriptl_ && scriptr_) + dasc = max(bl().dimension(bv).ascent(), br().dimension(bv).ascent()); + else if (scriptl_) + dasc = bl().dimension(bv).ascent(); + else if (scriptr_) + dasc = br().dimension(bv).ascent(); int slevel = nuc().slevel(); int ascdrop = dasc - slevel; int desdrop = isCharBox ? 0 : des + nuc().sshift(); @@ -84,8 +93,20 @@ int InsetMathSideset::dybt(BufferView const & bv, int asc, int des, bool top) co des = max(desdrop, ascdrop); des = max(mindes, des); int minasc = nuc().minasc(); - ascdrop = isCharBox ? 0 : asc - min(tl().mindes(), tr().mindes()); - int udes = max(bl().dimension(bv).descent(), tr().dimension(bv).descent()); + ascdrop = 0; + if (!isCharBox && (scriptl_ || scriptr_)) { + if (scriptl_ && scriptr_) + ascdrop = asc - min(tl().mindes(), tr().mindes()); + else if (scriptl_) + ascdrop = asc - tl().mindes(); + else if (scriptr_) + ascdrop = asc - tr().mindes(); + } + int udes = 0; + if (scriptl_) + udes = bl().dimension(bv).descent(); + if (scriptr_) + udes = max(udes, br().dimension(bv).descent()); asc = udes + nuc().sshift(); asc = max(ascdrop, asc); asc = max(minasc, asc); @@ -106,7 +127,13 @@ int InsetMathSideset::dybt(BufferView const & bv, int asc, int des, bool top) co int InsetMathSideset::dyb(BufferView const & bv) const { int nd = ndes(bv); - int des = max(bl().dimension(bv).ascent(), br().dimension(bv).ascent()); + int des = 0; + if (scriptl_ && scriptr_) + des = max(bl().dimension(bv).ascent(), br().dimension(bv).ascent()); + else if (scriptl_) + des = bl().dimension(bv).ascent(); + else if (scriptr_) + des = br().dimension(bv).ascent(); int na = nasc(bv); des = dybt(bv, na, nd, false); return des; @@ -116,7 +143,13 @@ int InsetMathSideset::dyb(BufferView const & bv) const int InsetMathSideset::dyt(BufferView const & bv) const { int na = nasc(bv); - int asc = max(tl().dimension(bv).descent(), tr().dimension(bv).descent()); + int asc = 0; + if (scriptl_ && scriptr_) + asc = max(tl().dimension(bv).descent(), tr().dimension(bv).descent()); + else if (scriptl_) + asc = tl().dimension(bv).descent(); + else if (scriptr_) + asc = tr().dimension(bv).descent(); int nd = ndes(bv); asc = dybt(bv, na, nd, true); return asc; @@ -170,11 +203,23 @@ void InsetMathSideset::metrics(MetricsInfo & mi, Dimension & dim) const Dimension dimbr; Dimension dimtr; nuc().metrics(mi, dimn); + if (!scriptl_) { + bl().metrics(mi, dimbl); + dimtl = dimbl; + } + if (!scriptr_) { + br().metrics(mi, dimbr); + dimtr = dimbr; + } ScriptChanger dummy(mi.base); - bl().metrics(mi, dimbl); - tl().metrics(mi, dimtl); - br().metrics(mi, dimbr); - tr().metrics(mi, dimtr); + if (scriptl_) { + bl().metrics(mi, dimbl); + tl().metrics(mi, dimtl); + } + if (scriptr_) { + br().metrics(mi, dimbr); + tr().metrics(mi, dimtr); + } BufferView & bv = *mi.base.bv; // FIXME: data copying... not very efficient. @@ -196,11 +241,19 @@ void InsetMathSideset::draw(PainterInfo & pi, int x, int y) const { BufferView & bv = *pi.base.bv; nuc().draw(pi, x + dxn(bv), y); + if (!scriptl_) + bl().draw(pi, x , y); + if (!scriptr_) + br().draw(pi, x + dxr(bv), y); ScriptChanger dummy(pi.base); - bl().draw(pi, x , y + dyb(bv)); - tl().draw(pi, x , y - dyt(bv)); - br().draw(pi, x + dxr(bv), y + dyb(bv)); - tr().draw(pi, x + dxr(bv), y - dyt(bv)); + if (scriptl_) { + bl().draw(pi, x , y + dyb(bv)); + tl().draw(pi, x , y - dyt(bv)); + } + if (scriptr_) { + br().draw(pi, x + dxr(bv), y + dyb(bv)); + tr().draw(pi, x + dxr(bv), y - dyt(bv)); + } drawMarkers(pi, x, y); } @@ -227,14 +280,32 @@ void InsetMathSideset::drawT(TextPainter & pain, int x, int y) const -bool InsetMathSideset::idxForward(Cursor &) const +bool InsetMathSideset::idxForward(Cursor & cur) const { + if (!scriptl_ && cur.idx() == 1) { + // left => nucleus + cur.idx() = 0; + return true; + } else if (!scriptr_ && cur.idx() == 0) { + // nucleus => right + cur.idx() = 2 + scriptl_; + return true; + } return false; } -bool InsetMathSideset::idxBackward(Cursor &) const +bool InsetMathSideset::idxBackward(Cursor & cur) const { + if (!scriptr_ && cur.idx() == (scriptl_ ? 3 : 2)) { + // right => nucleus + cur.idx() = 0; + return true; + } else if (!scriptl_ && cur.idx() == 0) { + // nucleus => left + cur.idx() = 1; + return true; + } return false; } @@ -245,11 +316,12 @@ bool InsetMathSideset::idxUpDown(Cursor & cur, bool up) const if (cur.idx() == 0) { // go up/down only if in the last position // or in the first position - if (cur.pos() == cur.lastpos() || cur.pos() == 0) { + if ((scriptr_ && cur.pos() == cur.lastpos()) || + (scriptl_ && cur.pos() == 0)) { if (cur.pos() == 0) cur.idx() = up ? 2 : 1; else - cur.idx() = up ? 4 : 3; + cur.idx() = (up ? 3 : 2) + scriptl_; cur.pos() = 0; return true; } @@ -257,7 +329,8 @@ bool InsetMathSideset::idxUpDown(Cursor & cur, bool up) const } // Are we 'up'? - if (cur.idx() == 2 || cur.idx() == 4) { + if ((scriptl_ && cur.idx() == 2) || + (scriptr_ && cur.idx() == (scriptl_ ? 4 : 3))) { // can't go further up if (up) return false; @@ -271,7 +344,8 @@ bool InsetMathSideset::idxUpDown(Cursor & cur, bool up) const } // Are we 'down'? - if (cur.idx() == 1 || cur.idx() == 3) { + if ((scriptl_ && cur.idx() == 1) || + (scriptr_ && cur.idx() == (scriptl_ ? 3 : 2))) { // can't go further down if (!up) return false; @@ -293,15 +367,24 @@ void InsetMathSideset::write(WriteStream & os) const MathEnsurer ensurer(os); os << "\\sideset"; - for (int i = 0; i < 2; ++i) { - os << '{'; - if (!cell(2*i+1).empty()) - os << "_{" << cell(2*i+1) << '}'; - if (!cell(2*i+2).empty()) - os << "^{" << cell(2*i+2) << '}'; - os << '}'; - } - os << '{' << nuc() << '}'; + os << '{'; + if (scriptl_) { + if (!bl().empty()) + os << "_{" << bl() << '}'; + if (!tl().empty()) + os << "^{" << tl() << '}'; + } else + os << bl(); + os << "}{"; + if (scriptr_) { + if (!br().empty()) + os << "_{" << br() << '}'; + if (!tr().empty()) + os << "^{" << tr() << '}'; + } else + os << br(); + os << '}'; + os << nuc(); if (lock_ && !os.latex()) os << "\\lyxlock "; @@ -314,7 +397,7 @@ void InsetMathSideset::normalize(NormalStream & os) const if (!bl().empty()) os << bl() << ' '; - if (!tl().empty()) + if (scriptl_ && !tl().empty()) os << tl() << ' '; if (!nuc().empty()) @@ -324,7 +407,7 @@ void InsetMathSideset::normalize(NormalStream & os) const if (!br().empty()) os << br() << ' '; - if (!tr().empty()) + if (scriptr_ && !tr().empty()) os << tr() << ' '; os << ']'; } @@ -332,41 +415,52 @@ void InsetMathSideset::normalize(NormalStream & os) const void InsetMathSideset::mathmlize(MathStream & os) const { - os << MTag("mmultiscripts"); - - if (nuc().empty()) - os << ""; - else - os << MTag("mrow") << nuc() << ETag("mrow"); - - if (br().empty()) - os << ""; - else - os << MTag("mrow") << br() << ETag("mrow"); - if (tr().empty()) - os << ""; - else - os << MTag("mrow") << tr() << ETag("mrow"); - - if (bl().empty()) - os << ""; - else + // FIXME This is only accurate if both scriptl_ and scriptr_ are true + if (!scriptl_) os << MTag("mrow") << bl() << ETag("mrow"); - if (tl().empty()) - os << ""; - else - os << MTag("mrow") << tl() << ETag("mrow"); + if (scriptl_ || scriptr_) { + os << MTag("mmultiscripts"); - os << ETag("mmultiscripts"); + if (nuc().empty()) + os << ""; + else + os << MTag("mrow") << nuc() << ETag("mrow"); + + if (br().empty() || !scriptr_) + os << ""; + else + os << MTag("mrow") << br() << ETag("mrow"); + if (tr().empty() || !scriptr_) + os << ""; + else + os << MTag("mrow") << tr() << ETag("mrow"); + + if (bl().empty() || !scriptl_) + os << ""; + else + os << MTag("mrow") << bl() << ETag("mrow"); + if (tl().empty() || !scriptl_) + os << ""; + else + os << MTag("mrow") << tl() << ETag("mrow"); + + os << ETag("mmultiscripts"); + } + if (!scriptr_) + os << MTag("mrow") << br() << ETag("mrow"); } void InsetMathSideset::htmlize(HtmlStream & os) const { - bool const havebl = !bl().empty(); - bool const havetl = !tl().empty(); - bool const havebr = !br().empty(); - bool const havetr = !tr().empty(); + // FIXME This is only accurate if both scriptl_ and scriptr_ are true + bool const havebl = scriptl_ && !bl().empty(); + bool const havetl = scriptl_ && !tl().empty(); + bool const havebr = scriptr_ && !br().empty(); + bool const havetr = scriptr_ && !tr().empty(); + + if (!scriptl_ && !bl().empty()) + os << bl(); if (havebl && havetl) os << MTag("span", "class='scripts'") @@ -390,6 +484,9 @@ void InsetMathSideset::htmlize(HtmlStream & os) const os << MTag("sub", "class='math'") << br() << ETag("sub"); else if (havetr) os << MTag("sup", "class='math'") << tr() << ETag("sup"); + + if (!scriptr_ && !br().empty()) + os << br(); } diff --git a/src/mathed/InsetMathSideset.h b/src/mathed/InsetMathSideset.h index 67f7eaa06f..41dc8eb1b4 100644 --- a/src/mathed/InsetMathSideset.h +++ b/src/mathed/InsetMathSideset.h @@ -25,9 +25,10 @@ namespace lyx { class InsetMathSideset : public InsetMathNest { public: /// - InsetMathSideset(Buffer * buf); + InsetMathSideset(Buffer * buf, bool scriptl, bool scriptr); /// create inset with given nucleus - InsetMathSideset(Buffer * buf, MathAtom const & at); + InsetMathSideset(Buffer * buf, bool scriptl, bool scriptr, + MathAtom const & at); /// mode_type currentMode() const { return MATH_MODE; } /// @@ -63,22 +64,22 @@ public: MathData const & nuc() const { return cell(0); }; /// returns nucleus MathData & nuc() { return cell(0); }; - /// bottom left index + /// bottom left index or single left cell MathData const & bl() const { return cell(1); } - /// bottom left index + /// bottom left index or single left cell MathData & bl() { return cell(1); } - /// top left index - MathData const & tl() const { return cell(2); } - /// top left index - MathData & tl() { return cell(2); } - /// bottom right index - MathData const & br() const { return cell(3); } - /// bottom right index - MathData & br() { return cell(3); } - /// top right index - MathData const & tr() const { return cell(4); } - /// top right index - MathData & tr() { return cell(4); } + /// top left index or single left cell + MathData const & tl() const { return cell(1 + scriptl_); } + /// top left index or single left cell + MathData & tl() { return cell(1 + scriptl_); } + /// bottom right index or single right cell + MathData const & br() const { return cell(2 + scriptl_); } + /// bottom right index or single right cell + MathData & br() { return cell(2 + scriptl_); } + /// top right index or single right cell + MathData const & tr() const { return cell(2 + scriptl_ + scriptr_); } + /// top right index or single right cell + MathData & tr() { return cell(2 + scriptl_ + scriptr_); } /// say that we have scripts void infoize(odocstream & os) const; /// @@ -105,6 +106,10 @@ private: int ndes(BufferView const &) const; /// returns subscript and superscript kerning of nucleus if any int nker(BufferView const * bv) const; + /// Whether there are two left scripts or one single cell + bool scriptl_; + /// Whether there are two right scripts or one single cell + bool scriptr_; }; diff --git a/src/mathed/MathFactory.cpp b/src/mathed/MathFactory.cpp index d2bd2e8cb3..3bea8e9335 100644 --- a/src/mathed/MathFactory.cpp +++ b/src/mathed/MathFactory.cpp @@ -537,7 +537,14 @@ MathAtom createInsetMath(docstring const & s, Buffer * buf) if (s == "ensuremath") return MathAtom(new InsetMathEnsureMath(buf)); if (s == "sideset") - return MathAtom(new InsetMathSideset(buf)); + return MathAtom(new InsetMathSideset(buf, true, true)); + // The following 3 string values are only for math toolbar use, no LaTeX names + if (s == "sideset1") + return MathAtom(new InsetMathSideset(buf, false, true)); + if (s == "sideset2") + return MathAtom(new InsetMathSideset(buf, true, false)); + if (s == "sideset3") + return MathAtom(new InsetMathSideset(buf, false, false)); if (isSpecialChar(s)) return MathAtom(new InsetMathSpecialChar(s)); if (s == " ") diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp index 61e000ccc2..05ceed80f2 100644 --- a/src/mathed/MathParser.cpp +++ b/src/mathed/MathParser.cpp @@ -1445,23 +1445,29 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags, else if (t.cs() == "sideset") { // Here allowed formats are \sideset{_{bl}^{tl}}{_{br}^{tr}}{operator} - cell->push_back(MathAtom(new InsetMathSideset(buf))); + MathData ar[2]; + InsetMathScript * script[2] = {0, 0}; for (int i = 0; i < 2; ++i) { - MathData ar; - parse(ar, FLAG_ITEM, mode); - if (!ar.empty()) { - InsetMathScript * script = (ar.size() == 1) ? - ar[0].nucleus()->asScriptInset() : 0; - if (!script) { - error("found invalid sideset argument"); - break; - } - if (script->hasDown()) - cell->back().nucleus()->cell(2 * i + 1) = script->down(); - if (script->hasUp()) - cell->back().nucleus()->cell(2 * i + 2) = script->up(); - } + parse(ar[i], FLAG_ITEM, mode); + if (ar[i].size() == 1) + script[i] = ar[i][0].nucleus()->asScriptInset(); } + bool const hasscript[2] = {script[0] ? true : false, script[1] ? true : false}; + cell->push_back(MathAtom(new InsetMathSideset(buf, hasscript[0], hasscript[1]))); + if (hasscript[0]) { + if (script[0]->hasDown()) + cell->back().nucleus()->cell(1) = script[0]->down(); + if (script[0]->hasUp()) + cell->back().nucleus()->cell(2) = script[0]->up(); + } else + cell->back().nucleus()->cell(1) = ar[0]; + if (hasscript[1]) { + if (script[1]->hasDown()) + cell->back().nucleus()->cell(2 + hasscript[0]) = script[1]->down(); + if (script[1]->hasUp()) + cell->back().nucleus()->cell(3 + hasscript[0]) = script[1]->up(); + } else + cell->back().nucleus()->cell(2 + hasscript[0]) = ar[1]; parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode); }