1 #include "math_scriptinset.h"
2 #include "math_support.h"
3 #include "math_symbolinset.h"
4 #include "math_mathmlstream.h"
5 #include "funcrequest.h"
6 #include "support/LAssert.h"
9 using namespace lyx::support;
15 MathScriptInset::MathScriptInset()
16 : MathNestInset(3), limits_(0)
23 MathScriptInset::MathScriptInset(bool up)
24 : MathNestInset(3), limits_(0)
31 MathScriptInset::MathScriptInset(MathAtom const & at, bool up)
32 : MathNestInset(3), limits_(0)
36 cell(2).push_back(at);
41 auto_ptr<InsetBase> MathScriptInset::clone() const
43 return auto_ptr<InsetBase>(new MathScriptInset(*this));
47 MathScriptInset const * MathScriptInset::asScriptInset() const
53 MathScriptInset * MathScriptInset::asScriptInset()
59 bool MathScriptInset::idxFirst(idx_type & idx, pos_type & pos) const
67 bool MathScriptInset::idxLast(idx_type & idx, pos_type & pos) const
75 MathArray const & MathScriptInset::down() const
81 MathArray & MathScriptInset::down()
87 MathArray const & MathScriptInset::up() const
93 MathArray & MathScriptInset::up()
99 void MathScriptInset::ensure(bool up)
105 MathArray const & MathScriptInset::nuc() const
111 MathArray & MathScriptInset::nuc()
117 int MathScriptInset::dy0() const
122 int des = down().ascent();
131 int MathScriptInset::dy1() const
136 int asc = up().descent();
146 int MathScriptInset::dx0() const
149 return hasLimits() ? (dim_.wid - down().width()) / 2 : nwid();
153 int MathScriptInset::dx1() const
156 return hasLimits() ? (dim_.wid - up().width()) / 2 : nwid();
160 int MathScriptInset::dxx() const
162 return hasLimits() ? (dim_.wid - nwid()) / 2 : 0;
166 int MathScriptInset::nwid() const
168 return nuc().size() ? nuc().width() : 2;
172 int MathScriptInset::nasc() const
174 return nuc().size() ? nuc().ascent() : 5;
178 int MathScriptInset::ndes() const
180 return nuc().size() ? nuc().descent() : 0;
184 void MathScriptInset::metrics(MetricsInfo & mi, Dimension & dim) const
187 ScriptChanger dummy(mi.base);
194 dim_.wid = max(dim_.wid, up().width());
196 dim_.wid = max(dim_.wid, down().width());
199 dim_.wid = max(dim_.wid, up().width());
201 dim_.wid = max(dim_.wid, down().width());
204 dim_.asc = dy1() + (hasUp() ? up().ascent() : 0);
205 dim_.des = dy0() + (hasDown() ? down().descent() : 0);
211 void MathScriptInset::draw(PainterInfo & pi, int x, int y) const
214 nuc().draw(pi, x + dxx(), y);
216 nuc().setXY(x + dxx(), y);
218 drawStr(pi, pi.base.font, x + dxx(), y, ".");
220 ScriptChanger dummy(pi.base);
222 up().draw(pi, x + dx1(), y - dy1());
224 down().draw(pi, x + dx0(), y + dy0());
225 drawMarkers(pi, x, y);
229 void MathScriptInset::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
232 up().metricsT(mi, dim);
234 down().metricsT(mi, dim);
235 nuc().metricsT(mi, dim);
239 void MathScriptInset::drawT(TextPainter & pain, int x, int y) const
242 nuc().drawT(pain, x + dxx(), y);
244 up().drawT(pain, x + dx1(), y - dy1());
246 down().drawT(pain, x + dx0(), y + dy0());
251 bool MathScriptInset::hasLimits() const
259 // we can only display limits if the nucleus wants some
262 if (!nuc().back()->isScriptable())
265 // per default \int has limits beside the \int even in displayed formulas
266 if (nuc().back()->asSymbolInset())
267 if (nuc().back()->asSymbolInset()->name().find("int") != string::npos)
270 // assume "real" limits for everything else
275 void MathScriptInset::removeScript(bool up)
282 bool MathScriptInset::has(bool up) const
288 bool MathScriptInset::hasUp() const
294 bool MathScriptInset::hasDown() const
300 bool MathScriptInset::idxRight(idx_type &, pos_type &) const
306 bool MathScriptInset::idxLeft(idx_type &, pos_type &) const
312 bool MathScriptInset::idxUpDown(idx_type & idx, pos_type & pos, bool up,
316 // if we are 'up' we can't go further up
319 // otherwise go to last base position
321 pos = cell(2).size();
325 // if we are 'down' we can't go further down
329 pos = cell(2).size();
334 // don't go up/down if there is no cell.
337 // go up/down only if in the last position
338 // or in the first position of something with displayed limits
339 if (pos == cell(2).size() || (pos == 0 && hasLimits())) {
350 void MathScriptInset::write(WriteStream & os) const
354 //if (nuc().back()->takesLimits()) {
362 lyxerr[Debug::MATHED] << "suppressing {} when writing\n";
367 if (hasDown() && down().size())
368 os << "_{" << down() << '}';
370 if (hasUp() && up().size())
371 os << "^{" << up() << '}';
373 if (lock_ && !os.latex())
378 void MathScriptInset::normalize(NormalStream & os) const
380 bool d = hasDown() && down().size();
381 bool u = hasUp() && up().size();
396 os << down() << ' ' << up() << ']';
404 void MathScriptInset::maple(MapleStream & os) const
408 if (hasDown() && down().size())
409 os << '[' << down() << ']';
410 if (hasUp() && up().size())
411 os << "^(" << up() << ')';
415 void MathScriptInset::mathematica(MathematicaStream & os) const
417 bool d = hasDown() && down().size();
418 bool u = hasUp() && up().size();
422 os << "Subscript[" << nuc();
428 os << "^(" << up() << ')';
432 os << ',' << down() << ']';
436 void MathScriptInset::mathmlize( MathMLStream & os) const
438 bool d = hasDown() && down().size();
439 bool u = hasUp() && up().size();
442 os << MTag("msubsup");
454 os << down() << up() << ETag("msubsup");
456 os << up() << ETag("msup");
458 os << down() << ETag("msub");
462 void MathScriptInset::octave(OctaveStream & os) const
466 if (hasDown() && down().size())
467 os << '[' << down() << ']';
468 if (hasUp() && up().size())
469 os << "^(" << up() << ')';
473 void MathScriptInset::infoize(std::ostream & os) const
479 void MathScriptInset::infoize2(std::ostream & os) const
482 os << (limits_ == 1 ? ", Displayed limits" : ", Inlined limits");
486 void MathScriptInset::notifyCursorLeaves(idx_type idx)
488 MathNestInset::notifyCursorLeaves(idx);
490 // remove empty scripts if possible
491 if (idx != 2 && script_[idx] && cell(idx).empty()) {
493 script_[idx] = false;
498 dispatch_result MathScriptInset::dispatch
499 (FuncRequest const & cmd, idx_type & idx, pos_type & pos)
501 if (cmd.action == LFUN_MATH_LIMITS) {
502 if (!cmd.argument.empty()) {
503 if (cmd.argument == "limits")
505 else if (cmd.argument == "nolimits")
509 } else if (limits_ == 0)
510 limits_ = (hasLimits()) ? -1 : 1;
516 return MathNestInset::dispatch(cmd, idx, pos);