X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathHull.cpp;h=0f7e9a85df7fbd1b39362121b8f326772999a8f9;hb=ebe6612e2661f49dcfae6103f056c27afd47751f;hp=f0fc1b41e10338dd0cf9d53e0f4b802e3f390ebe;hpb=0b6edb0b2fb3773af8506a17ddcadf219dfc7e5b;p=lyx.git diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index f0fc1b41e1..0f7e9a85df 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -14,6 +14,9 @@ #include "InsetMathChar.h" #include "InsetMathColor.h" +#include "InsetMathFrac.h" +#include "InsetMathNest.h" +#include "InsetMathScript.h" #include "MathExtern.h" #include "MathFactory.h" #include "MathStream.h" @@ -32,10 +35,14 @@ #include "LaTeXFeatures.h" #include "LyXRC.h" #include "MacroTable.h" +#include "InsetMathMacro.h" +#include "InsetMathMacroTemplate.h" +#include "MetricsInfo.h" #include "output_xhtml.h" #include "Paragraph.h" #include "ParIterator.h" #include "sgml.h" +#include "TexRow.h" #include "TextClass.h" #include "TextPainter.h" #include "TocBackend.h" @@ -44,6 +51,7 @@ #include "insets/InsetRef.h" #include "insets/RenderPreview.h" +#include "graphics/GraphicsImage.h" #include "graphics/PreviewImage.h" #include "graphics/PreviewLoader.h" @@ -51,11 +59,12 @@ #include "frontends/Painter.h" #include "support/convert.h" -#include "support/lassert.h" #include "support/debug.h" -#include "support/filetools.h" #include "support/gettext.h" +#include "support/filetools.h" +#include "support/lassert.h" #include "support/lstrings.h" +#include "support/RefChanger.h" #include @@ -65,23 +74,32 @@ using namespace lyx::support; namespace lyx { using cap::grabAndEraseSelection; +using cap::reduceSelectionToOneCell; namespace { int getCols(HullType type) { switch (type) { - case hullEqnArray: - return 3; - case hullAlign: - case hullFlAlign: - case hullAlignAt: - case hullXAlignAt: - case hullXXAlignAt: - return 2; - default: - return 1; + case hullEqnArray: + return 3; + case hullAlign: + case hullFlAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + return 2; + case hullUnknown: + case hullNone: + case hullSimple: + case hullEquation: + case hullMultline: + case hullGather: + case hullRegexp: + return 1; } + // avoid warning + return 0; } @@ -90,7 +108,7 @@ namespace { size_t firstRelOp(MathData const & ar) { for (MathData::const_iterator it = ar.begin(); it != ar.end(); ++it) - if ((*it)->isRelOp()) + if ((*it)->mathClass() == MC_REL) return it - ar.begin(); return ar.size(); } @@ -102,7 +120,38 @@ namespace { } -} // end anon namespace + // writes a preamble for underlined or struck out math display + void writeMathdisplayPreamble(WriteStream & os) + { + if (os.strikeoutMath()) { + if (os.ulemCmd() == WriteStream::UNDERLINE) + os << "\\raisebox{-\\belowdisplayshortskip}{" + "\\lyxmathsout{\\parbox[b]{\\linewidth}{"; + else + os << "\\lyxmathsout{\\parbox{\\linewidth}{"; + } else if (os.ulemCmd() == WriteStream::UNDERLINE) + os << "\\raisebox{-\\belowdisplayshortskip}{" + "\\parbox[b]{\\linewidth}{"; + else if (os.ulemCmd() == WriteStream::STRIKEOUT) + os << "\\parbox{\\linewidth}{"; + } + + + // writes a postamble for underlined or struck out math display + void writeMathdisplayPostamble(WriteStream & os) + { + if (os.strikeoutMath()) { + if (os.ulemCmd() == WriteStream::UNDERLINE) + os << "}"; + os << "}}\\\\\n"; + } else if (os.ulemCmd() == WriteStream::UNDERLINE) + os << "}}\\\\\n"; + else if (os.ulemCmd() == WriteStream::STRIKEOUT) + os << "}\\\\\n"; + } + + +} // namespace HullType hullType(docstring const & s) @@ -119,38 +168,39 @@ HullType hullType(docstring const & s) if (s == "gather") return hullGather; if (s == "flalign") return hullFlAlign; if (s == "regexp") return hullRegexp; - lyxerr << "unknown hull type '" << to_utf8(s) << "'" << endl; - return HullType(-1); + lyxerr << "unknown hull type '" << to_utf8(s) << "'" << endl; + return hullUnknown; } docstring hullName(HullType type) { switch (type) { - case hullNone: return from_ascii("none"); - case hullSimple: return from_ascii("simple"); - case hullEquation: return from_ascii("equation"); - case hullEqnArray: return from_ascii("eqnarray"); - case hullAlign: return from_ascii("align"); - case hullAlignAt: return from_ascii("alignat"); - case hullXAlignAt: return from_ascii("xalignat"); - case hullXXAlignAt: return from_ascii("xxalignat"); - case hullMultline: return from_ascii("multline"); - case hullGather: return from_ascii("gather"); - case hullFlAlign: return from_ascii("flalign"); - case hullRegexp: return from_ascii("regexp"); - default: - lyxerr << "unknown hull type '" << type << "'" << endl; - return from_ascii("none"); + case hullNone: return from_ascii("none"); + case hullSimple: return from_ascii("simple"); + case hullEquation: return from_ascii("equation"); + case hullEqnArray: return from_ascii("eqnarray"); + case hullAlign: return from_ascii("align"); + case hullAlignAt: return from_ascii("alignat"); + case hullXAlignAt: return from_ascii("xalignat"); + case hullXXAlignAt: return from_ascii("xxalignat"); + case hullMultline: return from_ascii("multline"); + case hullGather: return from_ascii("gather"); + case hullFlAlign: return from_ascii("flalign"); + case hullRegexp: return from_ascii("regexp"); + case hullUnknown: + lyxerr << "unknown hull type" << endl; + break; } + return from_ascii("none"); } static InsetLabel * dummy_pointer = 0; InsetMathHull::InsetMathHull(Buffer * buf) - : InsetMathGrid(buf, 1, 1), type_(hullNone), numbered_(1, true), - numbers_(1, empty_docstring()), label_(1, dummy_pointer), - preview_(new RenderPreview(this)) + : InsetMathGrid(buf, 1, 1), type_(hullNone), numbered_(1, NUMBER), + numbers_(1, empty_docstring()), label_(1, dummy_pointer), + preview_(new RenderPreview(this)) { //lyxerr << "sizeof InsetMath: " << sizeof(InsetMath) << endl; //lyxerr << "sizeof MetricsInfo: " << sizeof(MetricsInfo) << endl; @@ -163,9 +213,9 @@ InsetMathHull::InsetMathHull(Buffer * buf) InsetMathHull::InsetMathHull(Buffer * buf, HullType type) - : InsetMathGrid(buf, getCols(type), 1), type_(type), numbered_(1, true), - numbers_(1, empty_docstring()), label_(1, dummy_pointer), - preview_(new RenderPreview(this)) + : InsetMathGrid(buf, getCols(type), 1), type_(type), numbered_(1, NUMBER), + numbers_(1, empty_docstring()), label_(1, dummy_pointer), + preview_(new RenderPreview(this)) { buffer_ = buf; initMath(); @@ -230,7 +280,7 @@ void InsetMathHull::setBuffer(Buffer & buffer) namespace { const char * counters_to_save[] = {"section", "chapter"}; unsigned int const numcnts = sizeof(counters_to_save)/sizeof(char *); -} +} // namespace void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) @@ -266,8 +316,12 @@ void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) counter_map[eqstr] = cnts.value(eqstr); for (size_t i = 0; i != label_.size(); ++i) { if (numbered(i)) { - cnts.step(eqstr, utype); - numbers_[i] = cnts.theCounter(eqstr, lang); + Paragraph const & par = it.paragraph(); + if (!par.isDeleted(it.pos())) { + cnts.step(eqstr, utype); + numbers_[i] = cnts.theCounter(eqstr, lang); + } else + numbers_[i] = from_ascii("#"); } else numbers_[i] = empty_docstring(); } @@ -284,7 +338,8 @@ void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) } -void InsetMathHull::addToToc(DocIterator const & pit, bool output_active) const +void InsetMathHull::addToToc(DocIterator const & pit, bool output_active, + UpdateType utype, TocBackend & backend) const { if (!buffer_) { //FIXME: buffer_ should be set at creation for this inset! Problem is @@ -293,21 +348,48 @@ void InsetMathHull::addToToc(DocIterator const & pit, bool output_active) const return; } - Toc & toc = buffer().tocBackend().toc("equation"); - + TocBuilder & b = backend.builder("equation"); + // compute first and last item + row_type first = nrows(); + for (row_type row = 0; row != nrows(); ++row) + if (numbered(row)) { + first = row; + break; + } + if (first == nrows()) + // no equation + return; + row_type last = nrows() - 1; + for (; last != 0; --last) + if (numbered(last)) + break; + // add equation numbers + b.pushItem(pit, docstring(), output_active); + if (first != last) + b.argumentItem(bformat(from_ascii("(%1$s-%2$s)"), + numbers_[first], numbers_[last])); for (row_type row = 0; row != nrows(); ++row) { - if (!numbered_[row]) + if (!numbered(row)) continue; if (label_[row]) - label_[row]->addToToc(pit, output_active); - toc.push_back(TocItem(pit, 0, nicelabel(row), output_active)); + label_[row]->addToToc(pit, output_active, utype, backend); + docstring label = nicelabel(row); + if (first == last) + // this is the only equation + b.argumentItem(label); + else { + // insert as sub-items + b.pushItem(pit, label, output_active); + b.pop(); + } } + b.pop(); } Inset * InsetMathHull::editXY(Cursor & cur, int x, int y) { - if (use_preview_) { + if (previewState(&cur.bv())) { edit(cur, true); return this; } @@ -317,9 +399,26 @@ Inset * InsetMathHull::editXY(Cursor & cur, int x, int y) InsetMath::mode_type InsetMathHull::currentMode() const { - if (type_ == hullNone) + switch (type_) { + case hullNone: return UNDECIDED_MODE; + // definitely math mode ... + case hullUnknown: + case hullSimple: + case hullEquation: + case hullMultline: + case hullGather: + case hullEqnArray: + case hullAlign: + case hullFlAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullRegexp: + return MATH_MODE; + } + // avoid warning return MATH_MODE; } @@ -340,80 +439,86 @@ bool InsetMathHull::idxLast(Cursor & cur) const } +// FIXME: InsetMathGrid should be changed to let the real column alignment be +// given by a virtual method like displayColAlign, because the values produced +// by defaultColAlign can be invalidated by lfuns such as add-column. For the +// moment the values produced by defaultColAlign are not used, notably because +// alignment is not implemented in the LyXHTML output. char InsetMathHull::defaultColAlign(col_type col) { - if (type_ == hullEqnArray) - return "rcl"[col]; - if (type_ == hullMultline) - return 'c'; - if (type_ == hullGather) - return 'c'; - if (type_ >= hullAlign) - return "rl"[col & 1]; - return 'c'; + return colAlign(type_, col); } -char InsetMathHull::displayColAlign(col_type col, row_type row) const +char InsetMathHull::displayColAlign(idx_type idx) const { - if (type_ == hullMultline) { - if (row == 0) + switch (type_) { + case hullMultline: { + row_type const r = row(idx); + if (r == 0) return 'l'; - if (row == nrows() - 1) + if (r == nrows() - 1) return 'r'; + return 'c'; } - return InsetMathGrid::displayColAlign(col, row); + case hullEqnArray: + case hullGather: + case hullAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullFlAlign: + return colAlign(type_, col(idx)); + default: + break; + } + return InsetMathGrid::displayColAlign(idx); } +int InsetMathHull::displayColSpace(col_type col) const +{ + return colSpace(type_, col); +} + + +// FIXME: same comment as for defaultColAlign applies. int InsetMathHull::defaultColSpace(col_type col) { - if (type_ == hullAlign || type_ == hullAlignAt) - return 0; - if (type_ == hullXAlignAt) - return (col & 1) ? 20 : 0; - if (type_ == hullXXAlignAt || type_ == hullFlAlign) - return (col & 1) ? 40 : 0; - return 0; + return colSpace(type_, col); } -docstring InsetMathHull::standardFont() const +string InsetMathHull::standardFont() const { - docstring font_name; switch (type_) { case hullRegexp: - font_name = from_ascii("texttt"); - break; + return "texttt"; case hullNone: - font_name = from_ascii("lyxnochange"); - break; + return "lyxnochange"; default: - font_name = from_ascii("mathnormal"); + return "mathnormal"; } - return font_name; } ColorCode InsetMathHull::standardColor() const { - ColorCode color; switch (type_) { case hullRegexp: case hullNone: - color = Color_foreground; - break; + return Color_foreground; + default: - color = Color_math; + return Color_math; } - return color; } -bool InsetMathHull::previewState(BufferView * bv) const +bool InsetMathHull::previewState(const BufferView *const bv) const { - if (!editing(bv) && RenderPreview::status() == LyXRC::PREVIEW_ON - && type_ != hullRegexp) + if (!editing(bv) && RenderPreview::previewMath() + && type_ != hullRegexp) { graphics::PreviewImage const * pimage = preview_->getPreviewImage(bv->buffer()); @@ -423,21 +528,30 @@ bool InsetMathHull::previewState(BufferView * bv) const } +namespace { +static const int ERROR_FRAME_WIDTH = 2; +} + void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const { if (previewState(mi.base.bv)) { preview_->metrics(mi, dim); - // insert a one pixel gap in front of the formula - dim.wid += 1; - if (display()) - dim.des += displayMargin(); - // Cache the inset dimension. - setDimCache(mi, dim); + if (previewTooSmall(dim)) { + // preview image is too small + dim.wid += 2 * ERROR_FRAME_WIDTH; + dim.asc += 2 * ERROR_FRAME_WIDTH; + } else { + // insert a one pixel gap in front of the formula + dim.wid += 1; + if (display()) + dim.des += displayMargin(); + } return; } - FontSetChanger dummy1(mi.base, standardFont()); - StyleChanger dummy2(mi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT); + Changer dummy1 = mi.base.changeFontSet(standardFont()); + Changer dummy2 = mi.base.font.changeStyle(display() ? LM_ST_DISPLAY + : LM_ST_TEXT); // let the cells adjust themselves InsetMathGrid::metrics(mi, dim); @@ -448,80 +562,139 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const } if (numberedType()) { - FontSetChanger dummy(mi.base, from_ascii("mathbf")); + Changer dummy = mi.base.changeFontSet("mathrm"); int l = 0; for (row_type row = 0; row < nrows(); ++row) l = max(l, mathed_string_width(mi.base.font, nicelabel(row))); if (l) - dim.wid += 30 + l; + // Value was hardcoded to 30 pixels + dim.wid += Length(0.3, Length::IN).inPixels(mi.base) + l; } - if (type_ == hullRegexp) - dim.wid += 2; - // make it at least as high as the current font - int asc = 0; - int des = 0; - math_font_max_dim(mi.base.font, asc, des); - dim.asc = max(dim.asc, asc); - dim.des = max(dim.des, des); - // Cache the inset dimension. - // FIXME: This will overwrite InsetMathGrid dimension, is that OK? - setDimCache(mi, dim); + // reserve some space for marker. + dim.wid += 2; +} + + +bool InsetMathHull::previewTooSmall(Dimension const & dim) const +{ + return dim.width() <= 10 && dim.height() <= 10; } ColorCode InsetMathHull::backgroundColor(PainterInfo const & pi) const { - if (previewState(pi.base.bv)) + BufferView const * const bv = pi.base.bv; + if (previewState(bv)) { + Dimension const dim = dimension(*pi.base.bv); + if (previewTooSmall(dim)) + return Color_error; return graphics::PreviewLoader::backgroundColor(); + } return Color_mathbg; } +void InsetMathHull::drawMarkers(PainterInfo & pi, int x, int y) const +{ + ColorCode pen_color = mouseHovered(pi.base.bv) || editing(pi.base.bv)? + Color_mathframe : Color_mathcorners; + // If the corners have the same color as the background, do not paint them. + if (lcolor.getX11Name(Color_mathbg) == lcolor.getX11Name(pen_color)) + return; + + Inset::drawMarkers(pi, x, y); + Dimension const dim = dimension(*pi.base.bv); + int const t = x + dim.width() - 1; + int const a = y - dim.ascent(); + pi.pain.line(x, a + 3, x, a, pen_color); + pi.pain.line(t, a + 3, t, a, pen_color); + pi.pain.line(x, a, x + 3, a, pen_color); + pi.pain.line(t - 3, a, t, a, pen_color); +} + + void InsetMathHull::drawBackground(PainterInfo & pi, int x, int y) const { Dimension const dim = dimension(*pi.base.bv); + if (previewTooSmall(dim)) { + pi.pain.fillRectangle(x, y - 2 * ERROR_FRAME_WIDTH, + dim.wid, dim.asc + dim.des, backgroundColor(pi)); + return; + } pi.pain.fillRectangle(x + 1, y - dim.asc + 1, dim.wid - 2, - dim.asc + dim.des - 1, pi.backgroundColor(this)); + dim.asc + dim.des - 1, pi.backgroundColor(this)); } void InsetMathHull::draw(PainterInfo & pi, int x, int y) const { - use_preview_ = previewState(pi.base.bv); + BufferView const * const bv = pi.base.bv; + Dimension const dim = dimension(*bv); - if (type_ == hullRegexp) { - Dimension const dim = dimension(*pi.base.bv); - pi.pain.rectangle(x + 1, y - dim.ascent() + 1, - dim.width() - 2, dim.height() - 2, Color_regexpframe); - } - if (use_preview_) { - // one pixel gap in front - preview_->draw(pi, x + 1, y); - setPosCache(pi, x, y); + if (type_ == hullRegexp) + pi.pain.rectangle(x + 2, y - dim.ascent() + 1, + dim.width() - 3, dim.height() - 2, Color_regexpframe); + + if (previewState(bv)) { + // Do not draw change tracking cue if taken care of by RowPainter + // already. + Changer dummy = !canPaintChange(*bv) ? make_change(pi.change_, Change()) + : Changer(); + if (previewTooSmall(dim)) { + // we have an extra frame + preview_->draw(pi, x + ERROR_FRAME_WIDTH, y); + } else { + // one pixel gap in front + preview_->draw(pi, x + 1, y); + } return; } ColorCode color = pi.selected && lyxrc.use_system_colors ? Color_selectiontext : standardColor(); bool const really_change_color = pi.base.font.color() == Color_none; - ColorChanger dummy0(pi.base.font, color, really_change_color); - FontSetChanger dummy1(pi.base, standardFont()); - StyleChanger dummy2(pi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT); + Changer dummy0 = really_change_color ? pi.base.font.changeColor(color) + : Changer(); + Changer dummy1 = pi.base.changeFontSet(standardFont()); + Changer dummy2 = pi.base.font.changeStyle(display() ? LM_ST_DISPLAY + : LM_ST_TEXT); + + int xmath = x; + BufferParams::MathNumber const math_number = buffer().params().getMathNumber(); + if (numberedType() && math_number == BufferParams::LEFT) { + Changer dummy = pi.base.changeFontSet("mathrm"); + int l = 0; + for (row_type row = 0; row < nrows(); ++row) + l = max(l, mathed_string_width(pi.base.font, nicelabel(row))); + + if (l) + // Value was hardcoded to 30 pixels + xmath += Length(0.3, Length::IN).inPixels(pi.base) + l; + } - InsetMathGrid::draw(pi, x + 1, y); + InsetMathGrid::draw(pi, xmath + 1, y); + drawMarkers(pi, x, y); if (numberedType()) { - int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20; + Changer dummy = pi.base.changeFontSet("mathrm"); for (row_type row = 0; row < nrows(); ++row) { int const yy = y + rowinfo_[row].offset_; - FontSetChanger dummy(pi.base, from_ascii("mathrm")); docstring const nl = nicelabel(row); - pi.draw(xx, yy, nl); + if (math_number == BufferParams::LEFT) + pi.draw(x, yy, nl); + else { + int l = mathed_string_width(pi.base.font, nl); + pi.draw(x + dim.wid - l, yy, nl); + } } } - setPosCache(pi, x, y); + + // drawing change line + if (canPaintChange(*bv)) + pi.change_.paintCue(pi, x + 1, y + 1 - dim.asc, + x + dim.wid, y + dim.des); } @@ -531,7 +704,8 @@ void InsetMathHull::metricsT(TextMetricsInfo const & mi, Dimension & dim) const InsetMathGrid::metricsT(mi, dim); } else { odocstringstream os; - WriteStream wi(os, false, true, WriteStream::wsDefault); + otexrowstream ots(os); + WriteStream wi(ots, false, true, WriteStream::wsDefault); write(wi); dim.wid = os.str().size(); dim.asc = 1; @@ -546,7 +720,8 @@ void InsetMathHull::drawT(TextPainter & pain, int x, int y) const InsetMathGrid::drawT(pain, x, y); } else { odocstringstream os; - WriteStream wi(os, false, true, WriteStream::wsDefault); + otexrowstream ots(os); + WriteStream wi(ots, false, true, WriteStream::wsDefault); write(wi); pain.draw(x, y, os.str().c_str()); } @@ -564,7 +739,8 @@ static docstring latexString(InsetMathHull const & inset) static Encoding const * encoding = 0; if (inset.isBufferValid()) encoding = &(inset.buffer().params().encoding()); - WriteStream wi(ls, false, true, WriteStream::wsPreview, encoding); + otexrowstream ots(ls); + WriteStream wi(ots, false, true, WriteStream::wsPreview, encoding); inset.write(wi); return ls.str(); } @@ -580,35 +756,109 @@ void InsetMathHull::initUnicodeMath() const void InsetMathHull::addPreview(DocIterator const & inset_pos, graphics::PreviewLoader & /*ploader*/) const { - if (RenderPreview::status() == LyXRC::PREVIEW_ON) { + if (RenderPreview::previewMath()) { preparePreview(inset_pos); } } +void InsetMathHull::usedMacros(MathData const & md, DocIterator const & pos, + MacroNameSet & macros, MacroNameSet & defs) const +{ + MacroNameSet::iterator const end = macros.end(); + + for (size_t i = 0; i < md.size(); ++i) { + InsetMathMacro const * mi = md[i].nucleus()->asMacro(); + InsetMathMacroTemplate const * mt = md[i].nucleus()->asMacroTemplate(); + InsetMathScript const * si = md[i].nucleus()->asScriptInset(); + InsetMathFracBase const * fi = md[i].nucleus()->asFracBaseInset(); + InsetMathGrid const * gi = md[i].nucleus()->asGridInset(); + InsetMathNest const * ni = md[i].nucleus()->asNestInset(); + if (mi) { + // Look for macros in the arguments of this macro. + for (idx_type idx = 0; idx < mi->nargs(); ++idx) + usedMacros(mi->cell(idx), pos, macros, defs); + // Make sure this is a macro defined in the document + // (as we also spot the macros in the symbols file) + // or that we have not already accounted for it. + docstring const name = mi->name(); + if (macros.find(name) == end) + continue; + macros.erase(name); + // Look for macros in the definition of this macro. + MathData ar(pos.buffer()); + MacroData const * data = + pos.buffer()->getMacro(name, pos, true); + if (data) { + odocstringstream macro_def; + data->write(macro_def, true); + macro_def << endl; + defs.insert(macro_def.str()); + asArray(data->definition(), ar); + } + usedMacros(ar, pos, macros, defs); + } else if (mt) { + MathData ar(pos.buffer()); + asArray(mt->definition(), ar); + usedMacros(ar, pos, macros, defs); + } else if (si) { + if (!si->nuc().empty()) + usedMacros(si->nuc(), pos, macros, defs); + if (si->hasDown()) + usedMacros(si->down(), pos, macros, defs); + if (si->hasUp()) + usedMacros(si->up(), pos, macros, defs); + } else if (fi || gi) { + idx_type nidx = fi ? fi->nargs() : gi->nargs(); + for (idx_type idx = 0; idx < nidx; ++idx) + usedMacros(fi ? fi->cell(idx) : gi->cell(idx), + pos, macros, defs); + } else if (ni) { + usedMacros(ni->cell(0), pos, macros, defs); + } + } +} + + void InsetMathHull::preparePreview(DocIterator const & pos, - bool forexport) const + bool forexport) const { // there is no need to do all the macro stuff if we're not // actually going to generate the preview. - if (RenderPreview::status() != LyXRC::PREVIEW_ON && !forexport) + if (!RenderPreview::previewMath() && !forexport) return; - + Buffer const * buffer = pos.buffer(); // collect macros at this position MacroNameSet macros; buffer->listMacroNames(macros); - MacroNameSet::iterator it = macros.begin(); - MacroNameSet::iterator end = macros.end(); - odocstringstream macro_preamble; - for (; it != end; ++it) { - MacroData const * data = buffer->getMacro(*it, pos, true); - if (data) { - data->write(macro_preamble, true); - macro_preamble << endl; - } - } + + // collect definitions only for the macros used in this inset + MacroNameSet defs; + for (idx_type idx = 0; idx < nargs(); ++idx) + usedMacros(cell(idx), pos, macros, defs); + + MacroNameSet::iterator it = defs.begin(); + MacroNameSet::iterator end = defs.end(); + docstring macro_preamble; + for (; it != end; ++it) + macro_preamble.append(*it); + + // set the font series and size for this snippet + DocIterator dit = pos.getInnerText(); + Paragraph const & par = dit.paragraph(); + Font font = par.getFontSettings(buffer->params(), dit.pos()); + font.fontInfo().realize(par.layout().font); + string const lsize = font.latexSize(); + docstring setfont; + docstring endfont; + if (font.fontInfo().series() == BOLD_SERIES) { + setfont += from_ascii("\\textbf{"); + endfont += '}'; + } + if (lsize != "normalsize" && !prefixIs(lsize, "error")) + setfont += from_ascii("\\" + lsize + '\n'); docstring setcnt; if (forexport && haveNumbers()) { @@ -631,8 +881,8 @@ void InsetMathHull::preparePreview(DocIterator const & pos, '{' + convert(num) + '}'; } } - docstring const snippet = macro_preamble.str() + - setcnt + latexString(*this); + docstring const snippet = macro_preamble + setfont + setcnt + + latexString(*this) + endfont; LYXERR(Debug::MACROS, "Preview snippet: " << snippet); preview_->addPreview(snippet, *buffer, forexport); } @@ -655,7 +905,7 @@ void InsetMathHull::loadPreview(DocIterator const & pos) const bool InsetMathHull::notifyCursorLeaves(Cursor const & old, Cursor & cur) { - if (RenderPreview::status() == LyXRC::PREVIEW_ON) { + if (RenderPreview::previewMath()) { reloadPreview(old); cur.screenUpdateFlags(Update::Force); } @@ -695,10 +945,10 @@ void InsetMathHull::label(row_type row, docstring const & label) } -void InsetMathHull::numbered(row_type row, bool num) +void InsetMathHull::numbered(row_type row, Numbered num) { numbered_[row] = num; - if (!numbered_[row] && label_[row]) { + if (!numbered(row) && label_[row]) { delete label_[row]; label_[row] = 0; } @@ -707,41 +957,123 @@ void InsetMathHull::numbered(row_type row, bool num) bool InsetMathHull::numbered(row_type row) const { - return numbered_[row]; + return numbered_[row] == NUMBER; } bool InsetMathHull::ams() const { - return type_ == hullAlign - || type_ == hullFlAlign - || type_ == hullMultline - || type_ == hullGather - || type_ == hullAlignAt - || type_ == hullXAlignAt - || type_ == hullXXAlignAt; + switch (type_) { + case hullAlign: + case hullFlAlign: + case hullMultline: + case hullGather: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + return true; + case hullUnknown: + case hullRegexp: + return false; + case hullNone: + case hullSimple: + case hullEquation: + case hullEqnArray: + break; + } + for (size_t row = 0; row < numbered_.size(); ++row) + if (numbered_[row] == NOTAG) + return true; + return false; +} + + +bool InsetMathHull::outerDisplay() const +{ + switch (type_) { + case hullEquation: + case hullEqnArray: + case hullAlign: + case hullFlAlign: + case hullGather: + case hullMultline: + return true; + case hullNone: + case hullSimple: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullUnknown: + case hullRegexp: + break; + } + return false; } Inset::DisplayType InsetMathHull::display() const { - if (type_ == hullSimple || type_ == hullNone || type_ == hullRegexp) + switch (type_) { + case hullUnknown: + case hullSimple: + case hullNone: + case hullRegexp: return Inline; + case hullEqnArray: + case hullAlign: + case hullFlAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullEquation: + case hullMultline: + case hullGather: + if (buffer().params().is_math_indent) + return AlignLeft; + else + return AlignCenter; + } + // avoid warning return AlignCenter; } + +int InsetMathHull::indent(BufferView const & bv) const +{ + // FIXME: set this in the textclass. This value is what the article class uses. + static Length default_indent(2.5, Length::EM); + if (display() != Inline && buffer().params().is_math_indent) { + Length const & len = buffer().params().getMathIndent(); + if (len.empty()) + return bv.inPixels(default_indent); + else + return bv.inPixels(len); + } else + return Inset::indent(bv); +} + + bool InsetMathHull::numberedType() const { - if (type_ == hullNone) - return false; - if (type_ == hullSimple) - return false; - if (type_ == hullXXAlignAt) - return false; - if (type_ == hullRegexp) + switch (type_) { + case hullUnknown: + case hullNone: + case hullSimple: + case hullXXAlignAt: + case hullRegexp: return false; + case hullEqnArray: + case hullAlign: + case hullFlAlign: + case hullAlignAt: + case hullXAlignAt: + case hullEquation: + case hullMultline: + case hullGather: + break; + } for (row_type row = 0; row < nrows(); ++row) - if (numbered_[row]) + if (numbered(row)) return true; return false; } @@ -752,24 +1084,27 @@ void InsetMathHull::validate(LaTeXFeatures & features) const if (features.runparams().isLaTeX()) { if (ams()) features.require("amsmath"); - + if (type_ == hullRegexp) { features.require("color"); - string frcol = lcolor.getLaTeXName(Color_regexpframe); - string bgcol = "white"; + docstring frcol = from_utf8(lcolor.getLaTeXName(Color_regexpframe)); + docstring bgcol = from_ascii("white"); features.addPreambleSnippet( - string("\\newcommand{\\regexp}[1]{\\fcolorbox{") - + frcol + string("}{") - + bgcol + string("}{\\ensuremath{\\mathtt{#1}}}}")); + "\\newcommand{\\regexp}[1]{\\fcolorbox{" + + frcol + "}{" + + bgcol + "}{\\ensuremath{\\mathtt{#1}}}}"); features.addPreambleSnippet( - string("\\newcommand{\\endregexp}{}")); + from_ascii("\\newcommand{\\endregexp}{}")); + } else if (outerDisplay() && features.inDeletedInset() + && !features.mustProvide("ct-dvipost")) { + features.require("ct-tikz-math-sout"); } - + // Validation is necessary only if not using AMS math. // To be safe, we will always run mathedvalidate. //if (features.amsstyle) // return; - + //features.binom = true; } else if (features.runparams().math_flavor == OutputParams::MathAsHTML) { // it would be better to do this elsewhere, but we can't validate in @@ -794,16 +1129,22 @@ void InsetMathHull::header_write(WriteStream & os) const break; case hullSimple: + if (os.ulemCmd()) + os << "\\mbox{"; os << '$'; + os.startOuterRow(); if (cell(0).empty()) os << ' '; break; case hullEquation: + writeMathdisplayPreamble(os); + os << "\n"; + os.startOuterRow(); if (n) - os << "\n\\begin{equation" << star(n) << "}\n"; + os << "\\begin{equation" << star(n) << "}\n"; else - os << "\n\\[\n"; + os << "\\[\n"; break; case hullEqnArray: @@ -811,17 +1152,24 @@ void InsetMathHull::header_write(WriteStream & os) const case hullFlAlign: case hullGather: case hullMultline: - os << "\n\\begin{" << hullName(type_) << star(n) << "}\n"; + writeMathdisplayPreamble(os); + os << "\n"; + os.startOuterRow(); + os << "\\begin{" << hullName(type_) << star(n) << "}\n"; break; case hullAlignAt: case hullXAlignAt: - os << "\n\\begin{" << hullName(type_) << star(n) << '}' + os << "\n"; + os.startOuterRow(); + os << "\\begin{" << hullName(type_) << star(n) << '}' << '{' << static_cast((ncols() + 1)/2) << "}\n"; break; case hullXXAlignAt: - os << "\n\\begin{" << hullName(type_) << '}' + os << "\n"; + os.startOuterRow(); + os << "\\begin{" << hullName(type_) << '}' << '{' << static_cast((ncols() + 1)/2) << "}\n"; break; @@ -829,8 +1177,10 @@ void InsetMathHull::header_write(WriteStream & os) const os << "\\regexp{"; break; - default: - os << "\n\\begin{unknown" << star(n) << "}\n"; + case hullUnknown: + os << "\n"; + os.startOuterRow(); + os << "\\begin{unknown" << star(n) << "}\n"; break; } } @@ -847,27 +1197,42 @@ void InsetMathHull::footer_write(WriteStream & os) const case hullSimple: os << '$'; + if (os.ulemCmd()) + os << "}"; break; case hullEquation: + os << "\n"; + os.startOuterRow(); if (n) - os << "\n\\end{equation" << star(n) << "}\n"; + os << "\\end{equation" << star(n) << "}\n"; else - os << "\n\\]\n"; + os << "\\]\n"; + writeMathdisplayPostamble(os); break; case hullEqnArray: case hullAlign: case hullFlAlign: - case hullAlignAt: - case hullXAlignAt: case hullGather: case hullMultline: - os << "\n\\end{" << hullName(type_) << star(n) << "}\n"; + os << "\n"; + os.startOuterRow(); + os << "\\end{" << hullName(type_) << star(n) << "}\n"; + writeMathdisplayPostamble(os); + break; + + case hullAlignAt: + case hullXAlignAt: + os << "\n"; + os.startOuterRow(); + os << "\\end{" << hullName(type_) << star(n) << "}\n"; break; case hullXXAlignAt: - os << "\n\\end{" << hullName(type_) << "}\n"; + os << "\n"; + os.startOuterRow(); + os << "\\end{" << hullName(type_) << "}\n"; break; case hullRegexp: @@ -875,13 +1240,38 @@ void InsetMathHull::footer_write(WriteStream & os) const os << "\\endregexp{}}"; break; - default: - os << "\n\\end{unknown" << star(n) << "}\n"; + case hullUnknown: + os << "\n"; + os.startOuterRow(); + os << "\\end{unknown" << star(n) << "}\n"; break; } } +bool InsetMathHull::allowsTabularFeatures() const +{ + switch (type_) { + case hullEqnArray: + case hullAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullFlAlign: + case hullMultline: + case hullGather: + return true; + case hullNone: + case hullSimple: + case hullEquation: + case hullRegexp: + case hullUnknown: + break; + } + return false; +} + + bool InsetMathHull::rowChangeOK() const { return @@ -911,14 +1301,14 @@ void InsetMathHull::addRow(row_type row) docstring number = empty_docstring(); if (type_ == hullMultline) { if (row + 1 == nrows()) { - numbered_[row] = false; + numbered_[row] = NONUMBER; swap(label, label_[row]); swap(number, numbers_[row]); } else numbered = false; } - numbered_.insert(numbered_.begin() + row + 1, numbered); + numbered_.insert(numbered_.begin() + row + 1, numbered ? NUMBER : NONUMBER); numbers_.insert(numbers_.begin() + row + 1, number); label_.insert(label_.begin() + row + 1, label); InsetMathGrid::addRow(row); @@ -931,14 +1321,7 @@ void InsetMathHull::swapRow(row_type row) return; if (row + 1 == nrows()) --row; - // gcc implements the standard std::vector which is *not* a container: - // http://www.gotw.ca/publications/N1185.pdf - // As a results, it doesn't like this: - // swap(numbered_[row], numbered_[row + 1]); - // so we do it manually: - bool const b = numbered_[row]; - numbered_[row] = numbered_[row + 1]; - numbered_[row + 1] = b; + swap(numbered_[row], numbered_[row + 1]); swap(numbers_[row], numbers_[row + 1]); swap(label_[row], label_[row + 1]); InsetMathGrid::swapRow(row); @@ -950,9 +1333,7 @@ void InsetMathHull::delRow(row_type row) if (nrows() <= 1 || !rowChangeOK()) return; if (row + 1 == nrows() && type_ == hullMultline) { - bool const b = numbered_[row - 1]; - numbered_[row - 1] = numbered_[row]; - numbered_[row] = b; + swap(numbered_[row - 1], numbered_[row]); swap(numbers_[row - 1], numbers_[row]); swap(label_[row - 1], label_[row]); InsetMathGrid::delRow(row); @@ -988,7 +1369,7 @@ void InsetMathHull::delCol(col_type col) docstring InsetMathHull::nicelabel(row_type row) const { - if (!numbered_[row]) + if (!numbered(row)) return docstring(); docstring const & val = numbers_[row]; if (!label_[row]) @@ -1092,10 +1473,46 @@ void InsetMathHull::setType(HullType type) } +bool InsetMathHull::isMutable(HullType type) +{ + switch (type) { + case hullNone: + case hullSimple: + case hullEquation: + case hullEqnArray: + case hullAlign: + case hullFlAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullMultline: + case hullGather: + return true; + case hullUnknown: + case hullRegexp: + return false; + } + // avoid warning + return false; +} + + void InsetMathHull::mutate(HullType newtype) { //lyxerr << "mutating from '" << type_ << "' to '" << newtype << "'" << endl; + if (newtype == type_) + return; + + // This guards the algorithm below it, which is designed with certain types + // in mind. + if (!isMutable(newtype) || !isMutable(type_)) { + lyxerr << "mutation from '" << to_utf8(hullName(type_)) + << "' to '" << to_utf8(hullName(newtype)) + << "' not implemented" << endl; + return; + } + // we try to move along the chain // none <-> simple <-> equation <-> eqnarray -> *align* -> multline, gather -+ // ^ | @@ -1104,22 +1521,14 @@ void InsetMathHull::mutate(HullType newtype) // directly supported because it handles labels and numbering for // "down mutation". - if (newtype == type_) { - // done - } - - else if (newtype < hullNone) { - // unknown type - dump(); - } - - else if (type_ == hullNone) { + switch (type_) { + case hullNone: setType(hullSimple); numbered(0, false); mutate(newtype); - } + break; - else if (type_ == hullSimple) { + case hullSimple: if (newtype == hullNone) { setType(hullNone); numbered(0, false); @@ -1128,95 +1537,138 @@ void InsetMathHull::mutate(HullType newtype) numbered(0, label_[0] ? true : false); mutate(newtype); } - } + break; - else if (type_ == hullEquation) { - if (newtype < type_) { + case hullEquation: + switch (newtype) { + case hullNone: + case hullSimple: setType(hullSimple); numbered(0, false); mutate(newtype); - } else if (newtype == hullEqnArray) { + break; + case hullEqnArray: // split it "nicely" on the first relop splitTo3Cols(); setType(hullEqnArray); - } else if (newtype == hullMultline || newtype == hullGather) { + break; + case hullMultline: + case hullGather: setType(newtype); - } else { + break; + default: + // *align* // split it "nicely" splitTo2Cols(); setType(hullAlign); mutate(newtype); + break; } - } + break; - else if (type_ == hullEqnArray) { - if (newtype < type_) { + case hullEqnArray: + switch (newtype) { + case hullNone: + case hullSimple: + case hullEquation: glueall(newtype); mutate(newtype); - } else { // align & Co. + break; + default: + // align & Co. changeCols(2); setType(hullAlign); mutate(newtype); + break; } - } + break; - else if (type_ == hullAlign || type_ == hullAlignAt || - type_ == hullXAlignAt || type_ == hullFlAlign) { - if (newtype < hullAlign) { + case hullAlign: + case hullAlignAt: + case hullXAlignAt: + case hullFlAlign: + switch (newtype) { + case hullNone: + case hullSimple: + case hullEquation: + case hullEqnArray: changeCols(3); setType(hullEqnArray); mutate(newtype); - } else if (newtype == hullGather || newtype == hullMultline) { + break; + case hullGather: + case hullMultline: changeCols(1); setType(newtype); - } else if (newtype == hullXXAlignAt) { + break; + case hullXXAlignAt: for (row_type row = 0; row < nrows(); ++row) numbered(row, false); setType(newtype); - } else { + break; + default: setType(newtype); + break; } - } + break; - else if (type_ == hullXXAlignAt) { + case hullXXAlignAt: for (row_type row = 0; row < nrows(); ++row) numbered(row, false); - if (newtype < hullAlign) { + switch (newtype) { + case hullNone: + case hullSimple: + case hullEquation: + case hullEqnArray: changeCols(3); setType(hullEqnArray); mutate(newtype); - } else if (newtype == hullGather || newtype == hullMultline) { + break; + case hullGather: + case hullMultline: changeCols(1); setType(newtype); - } else { + break; + default: setType(newtype); + break; } - } + break; - else if (type_ == hullMultline || type_ == hullGather) { - if (newtype == hullGather || newtype == hullMultline) + case hullMultline: + case hullGather: + switch (newtype) { + case hullGather: + case hullMultline: setType(newtype); - else if (newtype == hullAlign || newtype == hullFlAlign || - newtype == hullAlignAt || newtype == hullXAlignAt) { + break; + case hullAlign: + case hullFlAlign: + case hullAlignAt: + case hullXAlignAt: splitTo2Cols(); setType(newtype); - } else if (newtype == hullXXAlignAt) { + break; + case hullXXAlignAt: splitTo2Cols(); for (row_type row = 0; row < nrows(); ++row) numbered(row, false); setType(newtype); - } else { + break; + default: + // first we mutate to EqnArray splitTo3Cols(); setType(hullEqnArray); mutate(newtype); + break; } - } + break; - else { - lyxerr << "mutation from '" << to_utf8(hullName(type_)) - << "' to '" << to_utf8(hullName(newtype)) - << "' not implemented" << endl; - } + default: + // we passed the guard so we should not be here + LASSERT("Mutation not implemented, but should have been.", return); + break; + }// switch } @@ -1225,21 +1677,24 @@ docstring InsetMathHull::eolString(row_type row, bool fragile, bool latex, { docstring res; if (numberedType()) { - if (label_[row] && numbered_[row]) { + if (label_[row] && numbered(row)) { docstring const name = latex ? escape(label_[row]->getParam("name")) : label_[row]->getParam("name"); res += "\\label{" + name + '}'; } - if (!numbered_[row] && (type_ != hullMultline)) - res += "\\nonumber "; + if (type_ != hullMultline) { + if (numbered_[row] == NONUMBER) + res += "\\nonumber "; + else if (numbered_[row] == NOTAG) + res += "\\notag "; + } } // Never add \\ on the last empty line of eqnarray and friends last_eoln = false; return res + InsetMathGrid::eolString(row, fragile, latex, last_eoln); } - void InsetMathHull::write(WriteStream & os) const { ModeSpecifier specifier(os, MATH_MODE); @@ -1259,7 +1714,7 @@ void InsetMathHull::normalize(NormalStream & os) const void InsetMathHull::infoize(odocstream & os) const { - os << "Type: " << hullName(type_); + os << bformat(_("Type: %1$s"), hullName(type_)); } @@ -1281,17 +1736,22 @@ void InsetMathHull::doExtern(Cursor & cur, FuncRequest & func) extra = from_ascii("noextra"); string const lang = to_ascii(dlang); - // FIXME: temporarily disabled - //if (cur.selection()) { - // MathData ar; - // selGet(cur.ar); - // lyxerr << "use selection: " << ar << endl; - // insert(pipeThroughExtern(lang, extra, ar)); - // return; - //} + // replace selection with result of computation + if (reduceSelectionToOneCell(cur)) { + MathData ar; + asArray(grabAndEraseSelection(cur), ar); + lyxerr << "use selection: " << ar << endl; + cur.insert(pipeThroughExtern(lang, extra, ar)); + return; + } // only inline, display or eqnarray math is allowed - if (getType() > hullEqnArray) { + switch (getType()) { + case hullSimple: + case hullEquation: + case hullEqnArray: + break; + default: frontend::Alert::warning(_("Bad math environment"), _("Computation cannot be performed for AMS " "math environments.\nChange the math " @@ -1309,9 +1769,7 @@ void InsetMathHull::doExtern(Cursor & cur, FuncRequest & func) if (getType() == hullSimple) { size_type pos = cur.cell().find_last(eq); MathData ar; - if (cur.inMathed() && cur.selection()) { - asArray(grabAndEraseSelection(cur), ar); - } else if (!pos == cur.cell().empty()) { + if (pos == cur.cell().size()) { ar = cur.cell(); lyxerr << "use whole cell: " << ar << endl; } else { @@ -1367,7 +1825,6 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_FINISHED_LEFT: //lyxerr << "action: " << cmd.action() << endl; InsetMathGrid::doDispatch(cur, cmd); - cur.undispatched(); break; case LFUN_PARAGRAPH_BREAK: @@ -1379,7 +1836,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) if (type_ == hullSimple || type_ == hullEquation) { cur.recordUndoInset(); bool const align = - cur.bv().buffer().params().use_package("amsmath") == BufferParams::package_on; + cur.bv().buffer().params().use_package("amsmath") != BufferParams::package_off; mutate(align ? hullAlign : hullEqnArray); // mutate() may change labels and such. cur.forceBufferUpdate(); @@ -1434,7 +1891,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) break; } - case LFUN_LABEL_COPY_AS_REF: { + case LFUN_LABEL_COPY_AS_REFERENCE: { row_type row; if (cmd.argument().empty() && &cur.inset() == this) // if there is no argument and we're inside math, we retrieve @@ -1444,7 +1901,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) // if there is an argument, find the corresponding label, else // check whether there is at least one label. for (row = 0; row != nrows(); ++row) - if (numbered_[row] && label_[row] + if (numbered(row) && label_[row] && (cmd.argument().empty() || label(row) == cmd.argument())) break; } @@ -1541,12 +1998,25 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_MATH_DISPLAY: { cur.recordUndoInset(); mutate(type_ == hullSimple ? hullEquation : hullSimple); - cur.idx() = 0; - cur.pos() = cur.lastpos(); - //cur.dispatched(FINISHED); + // if the cursor is in a cell that got merged, move it to + // start of the hull inset. + if (cur.idx() > 0) { + cur.idx() = 0; + cur.pos() = 0; + } + if (cur.pos() > cur.lastpos()) + cur.pos() = cur.lastpos(); + break; } + case LFUN_TABULAR_FEATURE: + if (!allowsTabularFeatures()) + cur.undispatched(); + else + InsetMathGrid::doDispatch(cur, cmd); + break; + default: InsetMathGrid::doDispatch(cur, cmd); break; @@ -1554,6 +2024,21 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) } +namespace { + +bool allowDisplayMath(Cursor const & cur) +{ + LATTEST(cur.depth() > 1); + Cursor tmpcur = cur; + tmpcur.pop(); + FuncStatus status; + FuncRequest cmd(LFUN_MATH_DISPLAY); + return tmpcur.getStatus(cmd, status) && status.enabled(); +} + +} // namespace + + bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus & status) const { @@ -1578,32 +2063,15 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_MATH_MUTATE: { HullType const ht = hullType(cmd.argument()); status.setOnOff(type_ == ht); - status.setEnabled(true); + status.setEnabled(isMutable(ht) && isMutable(type_)); - if (ht != hullSimple) { - Cursor tmpcur = cur; - while (!tmpcur.empty()) { - InsetCode code = tmpcur.inset().lyxCode(); - if (code == BOX_CODE) { - return true; - } else if (code == TABULAR_CODE) { - FuncRequest tmpcmd(LFUN_MATH_DISPLAY); - if (tmpcur.getStatus(tmpcmd, status) && !status.enabled()) - return true; - } - tmpcur.pop_back(); - } - } + if (ht != hullSimple && status.enabled()) + status.setEnabled(allowDisplayMath(cur)); return true; } case LFUN_MATH_DISPLAY: { - bool enable = true; - if (cur.depth() > 1) { - Inset const & in = cur[cur.depth()-2].inset(); - if (in.lyxCode() == SCRIPT_CODE) - enable = display() != Inline; - } - status.setEnabled(enable); + status.setEnabled(display() != Inline || allowDisplayMath(cur)); + status.setOnOff(display() != Inline); return true; } @@ -1630,19 +2098,19 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, status.setEnabled(type_ != hullSimple); return true; - case LFUN_LABEL_COPY_AS_REF: { + case LFUN_LABEL_COPY_AS_REFERENCE: { bool enabled = false; row_type row; if (cmd.argument().empty() && &cur.inset() == this) { // if there is no argument and we're inside math, we retrieve // the row number from the cursor position. row = (type_ == hullMultline) ? nrows() - 1 : cur.row(); - enabled = numberedType() && label_[row] && numbered_[row]; + enabled = numberedType() && label_[row] && numbered(row); } else { // if there is an argument, find the corresponding label, else // check whether there is at least one label. for (row_type row = 0; row != nrows(); ++row) { - if (numbered_[row] && label_[row] && + if (numbered(row) && label_[row] && (cmd.argument().empty() || label(row) == cmd.argument())) { enabled = true; break; @@ -1660,13 +2128,10 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, } return InsetMathGrid::getStatus(cur, cmd, status); - case LFUN_INSET_MODIFY: { - istringstream is(to_utf8(cmd.argument())); - string s; - is >> s; - if (s != "tabular") - return InsetMathGrid::getStatus(cur, cmd, status); - is >> s; + case LFUN_TABULAR_FEATURE: { + if (!allowsTabularFeatures()) + return false; + string s = cmd.getArg(0); if (!rowChangeOK() && (s == "append-row" || s == "delete-row" @@ -1687,16 +2152,6 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, status.setEnabled(false); return true; } - if ((type_ == hullSimple - || type_ == hullEquation - || type_ == hullNone) && - (s == "add-hline-above" || s == "add-hline-below")) { - status.message(bformat( - from_utf8(N_("Can't add horizontal grid lines in '%1$s'")), - hullName(type_))); - status.setEnabled(false); - return true; - } if (s == "add-vline-left" || s == "add-vline-right") { status.message(bformat( from_utf8(N_("Can't add vertical grid lines in '%1$s'")), @@ -1716,9 +2171,24 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, default: return InsetMathGrid::getStatus(cur, cmd, status); } +} + + +int InsetMathHull::leftMargin() const +{ + return (getType() == hullSimple) ? 0 : InsetMathGrid::leftMargin(); +} + - // This cannot really happen, but inserted to shut-up gcc - return InsetMathGrid::getStatus(cur, cmd, status); +int InsetMathHull::rightMargin() const +{ + return (getType() == hullSimple) ? 0 : InsetMathGrid::rightMargin(); +} + + +int InsetMathHull::border() const +{ + return (getType() == hullSimple) ? 0 : InsetMathGrid::border(); } @@ -1794,7 +2264,7 @@ void InsetMathHull::revealCodes(Cursor & cur) const if (!cur.inMathed()) return; odocstringstream os; - cur.info(os); + cur.info(os, false); cur.message(os.str()); /* // write something to the minibuffer @@ -1872,7 +2342,8 @@ bool InsetMathHull::searchForward(BufferView * bv, string const & str, void InsetMathHull::write(ostream & os) const { odocstringstream oss; - WriteStream wi(oss, false, false, WriteStream::wsDefault); + otexrowstream ots(oss); + WriteStream wi(ots, false, false, WriteStream::wsDefault); oss << "Formula "; write(wi); os << to_utf8(oss.str()); @@ -1914,8 +2385,9 @@ int InsetMathHull::plaintext(odocstringstream & os, } odocstringstream oss; + otexrowstream ots(oss); Encoding const * const enc = encodings.fromLyXName("utf8"); - WriteStream wi(oss, false, true, WriteStream::wsDefault, enc); + WriteStream wi(ots, false, true, WriteStream::wsDefault, enc); // Fix Bug #6139 if (type_ == hullRegexp) @@ -1928,7 +2400,8 @@ int InsetMathHull::plaintext(odocstringstream & os, // and do not include the newline. if (op.for_toc || op.for_tooltip || oss.str().size() >= max_length) break; - wi << "\n"; + if (r < nrows() - 1) + wi << "\n"; } } docstring const str = oss.str(); @@ -1954,12 +2427,13 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons ++ms.tab(); ms.cr(); ms.os() << '<' << bname << '>'; odocstringstream ls; + otexstream ols(ls); if (runparams.flavor == OutputParams::XML) { ms << MTag("alt role='tex' "); // Workaround for db2latex: db2latex always includes equations with // \ensuremath{} or \begin{display}\end{display} // so we strip LyX' math environment - WriteStream wi(ls, false, false, WriteStream::wsDefault, runparams.encoding); + WriteStream wi(ols, false, false, WriteStream::wsDefault, runparams.encoding); InsetMathGrid::write(wi); ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&"), "<", "<")); ms << ETag("alt"); @@ -1969,12 +2443,9 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons InsetMathGrid::mathmlize(ms); ms << ETag("math"); } else { - TexRow texrow; - texrow.reset(); - otexstream ols(ls, texrow); ms << MTag("alt role='tex'"); latex(ols, runparams); - res = texrow.rows(); + res = ols.texrow().rows(); ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&"), "<", "<")); ms << ETag("alt"); } @@ -2003,7 +2474,7 @@ bool InsetMathHull::haveNumbers() const if (getType() == hullSimple) return havenumbers; for (size_t i = 0; i != numbered_.size(); ++i) { - if (numbered_[i]) { + if (numbered(i)) { havenumbers = true; break; } @@ -2122,7 +2593,7 @@ void InsetMathHull::mathAsLatex(WriteStream & os) const docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const { - BufferParams::MathOutput const mathtype = + BufferParams::MathOutput const mathtype = buffer().masterBuffer()->params().html_math_output; bool success = false; @@ -2146,10 +2617,10 @@ docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const } catch (MathExportException const &) {} if (success) { if (getType() == hullSimple) - xs << html::StartTag("math", + xs << html::StartTag("math", "xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); - else - xs << html::StartTag("math", + else + xs << html::StartTag("math", "display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); xs << XHTMLStream::ESCAPE_NONE << os.str() @@ -2170,16 +2641,18 @@ docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const << html::EndTag(tag); } } - + // what we actually want is this: // if ( - // ((mathtype == BufferParams::MathML || mathtype == BufferParams::HTML) + // ((mathtype == BufferParams::MathML || mathtype == BufferParams::HTML) // && !success) // || mathtype == BufferParams::Images // ) - // but what follows is equivalent, since we'll enter only if either (a) we + // but what follows is equivalent, since we'll enter only if either (a) we // tried and failed with MathML or HTML or (b) didn't try yet at all but - // aren't doing LaTeX, in which case we are doing Images. + // aren't doing LaTeX. + // + // so this is for Images. if (!success && mathtype != BufferParams::LaTeX) { graphics::PreviewImage const * pimage = 0; if (!op.dryrun) { @@ -2206,14 +2679,14 @@ docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const string const tag = (getType() == hullSimple) ? "span" : "div"; xs << html::CR() - << html::StartTag(tag) + << html::StartTag(tag, "style = \"text-align: center;\"") << html::CompTag("img", "src=\"" + filename + "\" alt=\"Mathematical Equation\"") << html::EndTag(tag) << html::CR(); success = true; } } - + // so we'll pass this test if we've failed everything else, or // if mathtype was LaTeX, since we won't have entered any of the // earlier branches @@ -2221,18 +2694,19 @@ docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const // Unfortunately, we cannot use latexString() because we do not want // $...$ or whatever. odocstringstream ls; - WriteStream wi(ls, false, true, WriteStream::wsPreview); + otexrowstream ots(ls); + WriteStream wi(ots, false, true, WriteStream::wsPreview); ModeSpecifier specifier(wi, MATH_MODE); mathAsLatex(wi); docstring const latex = ls.str(); - + // class='math' allows for use of jsMath // http://www.math.union.edu/~dpvc/jsMath/ // FIXME XHTML // probably should allow for some kind of customization here string const tag = (getType() == hullSimple) ? "span" : "div"; xs << html::StartTag(tag, "class='math'") - << latex + << latex << html::EndTag(tag) << html::CR(); } @@ -2248,11 +2722,13 @@ void InsetMathHull::toString(odocstream & os) const } -void InsetMathHull::forToc(docstring & os, size_t) const +void InsetMathHull::forOutliner(docstring & os, size_t const, bool const) const { odocstringstream ods; OutputParams op(0); op.for_toc = true; + // FIXME: this results in spilling TeX into the LyXHTML output since the + // outliner is used to generate the LyXHTML list of figures/etc. plaintext(ods, op); os += ods.str(); } @@ -2269,4 +2745,12 @@ void InsetMathHull::recordLocation(DocIterator const & di) docit_ = di; } + +bool InsetMathHull::canPaintChange(BufferView const &) const +{ + // We let RowPainter do it seamlessly for inline insets + return display() != Inline; +} + + } // namespace lyx