X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathHull.cpp;h=78175f3f70d524f1145829c77afc17dbe2f07e05;hb=3561caa3a171a5984ee7a10b7ea82f7f4b7226e8;hp=08bbe414a966285b35c687d3cb73fc3278bcab11;hpb=d5a5fbb8ee87d4a8ae1c55f9ba72819251bb6fb7;p=lyx.git diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index 08bbe414a9..78175f3f70 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -15,7 +15,6 @@ #include "InsetMathChar.h" #include "InsetMathColor.h" #include "InsetMathFrac.h" -#include "InsetMathGrid.h" #include "InsetMathNest.h" #include "InsetMathScript.h" #include "MathExtern.h" @@ -36,12 +35,14 @@ #include "LaTeXFeatures.h" #include "LyXRC.h" #include "MacroTable.h" -#include "MathMacro.h" -#include "MathMacroTemplate.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" @@ -58,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 @@ -79,17 +81,25 @@ 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; } @@ -98,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(); } @@ -110,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) @@ -128,29 +169,30 @@ HullType hullType(docstring const & s) if (s == "flalign") return hullFlAlign; if (s == "regexp") return hullRegexp; lyxerr << "unknown hull type '" << to_utf8(s) << "'" << endl; - return HullType(-1); + 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; @@ -158,7 +200,7 @@ static InsetLabel * dummy_pointer = 0; InsetMathHull::InsetMathHull(Buffer * buf) : InsetMathGrid(buf, 1, 1), type_(hullNone), numbered_(1, NUMBER), numbers_(1, empty_docstring()), label_(1, dummy_pointer), - preview_(new RenderPreview(this)), use_preview_(false) + preview_(new RenderPreview(this)) { //lyxerr << "sizeof InsetMath: " << sizeof(InsetMath) << endl; //lyxerr << "sizeof MetricsInfo: " << sizeof(MetricsInfo) << endl; @@ -173,7 +215,7 @@ InsetMathHull::InsetMathHull(Buffer * buf) InsetMathHull::InsetMathHull(Buffer * buf, HullType type) : InsetMathGrid(buf, getCols(type), 1), type_(type), numbered_(1, NUMBER), numbers_(1, empty_docstring()), label_(1, dummy_pointer), - preview_(new RenderPreview(this)), use_preview_(false) + preview_(new RenderPreview(this)) { buffer_ = buf; initMath(); @@ -238,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) @@ -293,7 +335,7 @@ void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) void InsetMathHull::addToToc(DocIterator const & pit, bool output_active, - UpdateType utype) const + UpdateType utype, TocBackend & backend) const { if (!buffer_) { //FIXME: buffer_ should be set at creation for this inset! Problem is @@ -302,21 +344,48 @@ void InsetMathHull::addToToc(DocIterator const & pit, bool output_active, return; } - shared_ptr 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)) continue; if (label_[row]) - label_[row]->addToToc(pit, output_active, utype); - 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; } @@ -326,9 +395,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; } @@ -349,74 +435,79 @@ 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(idx_type idx) const { - if (type_ == hullMultline) { + switch (type_) { + case hullMultline: { row_type const r = row(idx); if (r == 0) return 'l'; if (r == nrows() - 1) return 'r'; + return 'c'; + } + 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; } @@ -451,13 +542,12 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const if (display()) dim.des += displayMargin(); } - // Cache the inset dimension. - setDimCache(mi, dim); 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); @@ -468,26 +558,25 @@ 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; + // reserve some space for marker. + 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); } @@ -526,16 +615,17 @@ void InsetMathHull::drawBackground(PainterInfo & pi, int x, int y) const void InsetMathHull::draw(PainterInfo & pi, int x, int y) const { BufferView const * const bv = pi.base.bv; - use_preview_ = previewState(bv); + Dimension const dim = dimension(*bv); - if (type_ == hullRegexp) { - Dimension const dim = dimension(*bv); - pi.pain.rectangle(x + 1, y - dim.ascent() + 1, - dim.width() - 2, dim.height() - 2, Color_regexpframe); - } + if (type_ == hullRegexp) + pi.pain.rectangle(x + 2, y - dim.ascent() + 1, + dim.width() - 3, dim.height() - 2, Color_regexpframe); - if (use_preview_) { - Dimension const dim = dimension(*bv); + 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); @@ -543,29 +633,52 @@ void InsetMathHull::draw(PainterInfo & pi, int x, int y) const // one pixel gap in front preview_->draw(pi, x + 1, y); } - setPosCache(pi, x, 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); + drawMarkers2(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); } @@ -575,7 +688,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; @@ -590,7 +704,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()); } @@ -608,7 +723,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(); } @@ -636,8 +752,8 @@ void InsetMathHull::usedMacros(MathData const & md, DocIterator const & pos, MacroNameSet::iterator const end = macros.end(); for (size_t i = 0; i < md.size(); ++i) { - MathMacro const * mi = md[i].nucleus()->asMacro(); - MathMacroTemplate const * mt = md[i].nucleus()->asMacroTemplate(); + 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(); @@ -713,6 +829,21 @@ void InsetMathHull::preparePreview(DocIterator const & pos, 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()) { docstring eqstr = from_ascii("equation"); @@ -734,7 +865,8 @@ void InsetMathHull::preparePreview(DocIterator const & pos, '{' + convert(num) + '}'; } } - docstring const snippet = macro_preamble + setcnt + latexString(*this); + docstring const snippet = macro_preamble + setfont + setcnt + + latexString(*this) + endfont; LYXERR(Debug::MACROS, "Preview snippet: " << snippet); preview_->addPreview(snippet, *buffer, forexport); } @@ -816,20 +948,22 @@ bool InsetMathHull::numbered(row_type row) const bool InsetMathHull::ams() const { switch (type_) { - case hullAlign: - case hullFlAlign: - case hullMultline: - case hullGather: - case hullAlignAt: - case hullXAlignAt: - case hullXXAlignAt: - return true; - case hullNone: - case hullSimple: - case hullEquation: - case hullEqnArray: - case hullRegexp: - break; + 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) @@ -838,23 +972,90 @@ bool InsetMathHull::ams() const } +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)) return true; @@ -870,14 +1071,17 @@ void InsetMathHull::validate(LaTeXFeatures & features) const 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. @@ -909,16 +1113,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: @@ -926,17 +1136,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; @@ -944,8 +1161,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; } } @@ -962,27 +1181,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: @@ -990,10 +1224,35 @@ 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; } @@ -1198,10 +1457,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 -+ // ^ | @@ -1210,22 +1505,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); @@ -1234,95 +1521,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 } @@ -1349,7 +1679,6 @@ docstring InsetMathHull::eolString(row_type row, bool fragile, bool latex, return res + InsetMathGrid::eolString(row, fragile, latex, last_eoln); } - void InsetMathHull::write(WriteStream & os) const { ModeSpecifier specifier(os, MATH_MODE); @@ -1401,7 +1730,12 @@ void InsetMathHull::doExtern(Cursor & cur, FuncRequest & func) } // 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 " @@ -1486,7 +1820,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(); @@ -1660,6 +1994,13 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) break; } + case LFUN_TABULAR_FEATURE: + if (!allowsTabularFeatures()) + cur.undispatched(); + else + InsetMathGrid::doDispatch(cur, cmd); + break; + default: InsetMathGrid::doDispatch(cur, cmd); break; @@ -1667,6 +2008,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 { @@ -1691,32 +2047,14 @@ 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; } @@ -1774,13 +2112,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" @@ -1801,16 +2136,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'")), @@ -1830,9 +2155,24 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, default: return InsetMathGrid::getStatus(cur, cmd, status); } +} + - // This cannot really happen, but inserted to shut-up gcc - return InsetMathGrid::getStatus(cur, cmd, status); +int InsetMathHull::leftMargin() const +{ + return (getType() == hullSimple) ? 0 : InsetMathGrid::leftMargin(); +} + + +int InsetMathHull::rightMargin() const +{ + return (getType() == hullSimple) ? 0 : InsetMathGrid::rightMargin(); +} + + +int InsetMathHull::border() const +{ + return (getType() == hullSimple) ? 0 : InsetMathGrid::border(); } @@ -1908,7 +2248,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 @@ -1986,7 +2326,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()); @@ -2028,8 +2369,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) @@ -2069,12 +2411,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"); @@ -2084,12 +2427,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"); } @@ -2294,7 +2634,9 @@ docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const // ) // 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) { @@ -2321,7 +2663,7 @@ 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(); @@ -2336,7 +2678,8 @@ 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(); @@ -2363,11 +2706,13 @@ void InsetMathHull::toString(odocstream & os) const } -void InsetMathHull::forOutliner(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(); } @@ -2384,4 +2729,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