X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathHull.cpp;h=cce029f6cedf25f98b3f3293ac45ea8cb8476974;hb=f1a388584fb2c043d17127d7db49c36cb8427cfa;hp=feefa87f048067383ffe7413093ebd94199b602d;hpb=70ed1095ec07d8e5d95e6a313adac755faa340c2;p=lyx.git diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index feefa87f04..cce029f6ce 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -14,6 +14,10 @@ #include "InsetMathChar.h" #include "InsetMathColor.h" +#include "InsetMathFrac.h" +#include "InsetMathGrid.h" +#include "InsetMathNest.h" +#include "InsetMathScript.h" #include "MathExtern.h" #include "MathFactory.h" #include "MathStream.h" @@ -28,11 +32,17 @@ #include "Exporter.h" #include "FuncRequest.h" #include "FuncStatus.h" +#include "Language.h" #include "LaTeXFeatures.h" #include "LyXRC.h" #include "MacroTable.h" +#include "MathMacro.h" +#include "MathMacroTemplate.h" #include "output_xhtml.h" +#include "Paragraph.h" +#include "ParIterator.h" #include "sgml.h" +#include "TextClass.h" #include "TextPainter.h" #include "TocBackend.h" @@ -40,13 +50,17 @@ #include "insets/InsetRef.h" #include "insets/RenderPreview.h" +#include "graphics/GraphicsImage.h" #include "graphics/PreviewImage.h" #include "graphics/PreviewLoader.h" +#include "frontends/alert.h" #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/lstrings.h" @@ -58,6 +72,7 @@ using namespace lyx::support; namespace lyx { using cap::grabAndEraseSelection; +using cap::reduceSelectionToOneCell; namespace { @@ -112,7 +127,7 @@ 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; + lyxerr << "unknown hull type '" << to_utf8(s) << "'" << endl; return HullType(-1); } @@ -132,7 +147,7 @@ docstring hullName(HullType type) case hullGather: return from_ascii("gather"); case hullFlAlign: return from_ascii("flalign"); case hullRegexp: return from_ascii("regexp"); - default: + default: lyxerr << "unknown hull type '" << type << "'" << endl; return from_ascii("none"); } @@ -141,8 +156,9 @@ docstring hullName(HullType type) static InsetLabel * dummy_pointer = 0; InsetMathHull::InsetMathHull(Buffer * buf) - : InsetMathGrid(buf, 1, 1), type_(hullNone), nonum_(1, true), - 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)), use_preview_(false) { //lyxerr << "sizeof InsetMath: " << sizeof(InsetMath) << endl; //lyxerr << "sizeof MetricsInfo: " << sizeof(MetricsInfo) << endl; @@ -155,8 +171,9 @@ InsetMathHull::InsetMathHull(Buffer * buf) InsetMathHull::InsetMathHull(Buffer * buf, HullType type) - : InsetMathGrid(buf, getCols(type), 1), type_(type), nonum_(1, true), - 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)), use_preview_(false) { buffer_ = buf; initMath(); @@ -189,7 +206,8 @@ InsetMathHull & InsetMathHull::operator=(InsetMathHull const & other) return *this; InsetMathGrid::operator=(other); type_ = other.type_; - nonum_ = other.nonum_; + numbered_ = other.numbered_; + numbers_ = other.numbers_; buffer_ = other.buffer_; for (size_t i = 0; i < label_.size(); ++i) delete label_[i]; @@ -215,6 +233,14 @@ void InsetMathHull::setBuffer(Buffer & buffer) } +// FIXME This should really be controlled by the TOC level, or +// something of the sort. +namespace { + const char * counters_to_save[] = {"section", "chapter"}; + unsigned int const numcnts = sizeof(counters_to_save)/sizeof(char *); +} + + void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) { if (!buffer_) { @@ -223,6 +249,40 @@ void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) // MathParser.cpp). return; } + + // if any of the equations are numbered, then we want to save the values + // of some of the counters. + if (haveNumbers()) { + BufferParams const & bp = buffer_->params(); + string const & lang = it->getParLanguage(bp)->code(); + Counters & cnts = + buffer_->masterBuffer()->params().documentClass().counters(); + + // right now, we only need to do this at export time + if (utype == OutputUpdate) { + for (size_t i = 0; i < numcnts; ++i) { + docstring const cnt = from_ascii(counters_to_save[i]); + if (cnts.hasCounter(cnt)) + counter_map[cnt] = cnts.value(cnt); + } + } + + // this has to be done separately + docstring const eqstr = from_ascii("equation"); + if (cnts.hasCounter(eqstr)) { + if (utype == OutputUpdate) + 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); + } else + numbers_[i] = empty_docstring(); + } + } + } + + // now the labels for (size_t i = 0; i != label_.size(); ++i) { if (label_[i]) label_[i]->updateBuffer(it, utype); @@ -232,7 +292,8 @@ void InsetMathHull::updateBuffer(ParIterator const & it, UpdateType utype) } -void InsetMathHull::addToToc(DocIterator const & pit) +void InsetMathHull::addToToc(DocIterator const & pit, bool output_active, + UpdateType utype) const { if (!buffer_) { //FIXME: buffer_ should be set at creation for this inset! Problem is @@ -241,14 +302,14 @@ void InsetMathHull::addToToc(DocIterator const & pit) return; } - Toc & toc = buffer().tocBackend().toc("equation"); + shared_ptr toc = buffer().tocBackend().toc("equation"); for (row_type row = 0; row != nrows(); ++row) { - if (nonum_[row]) + if (!numbered(row)) continue; if (label_[row]) - label_[row]->addToToc(pit); - toc.push_back(TocItem(pit, 0, nicelabel(row))); + label_[row]->addToToc(pit, output_active, utype); + toc->push_back(TocItem(pit, 0, nicelabel(row), output_active)); } } @@ -288,15 +349,36 @@ bool InsetMathHull::idxLast(Cursor & cur) const } +//FIXME: This has probably no effect and can be removed. char InsetMathHull::defaultColAlign(col_type col) { - if (type_ == hullEqnArray) - return "rcl"[col]; - 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 +{ + 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); } @@ -344,9 +426,11 @@ ColorCode InsetMathHull::standardColor() const } -bool InsetMathHull::previewState(BufferView * bv) const +bool InsetMathHull::previewState(const BufferView *const bv) const { - if (!editing(bv) && RenderPreview::status() == LyXRC::PREVIEW_ON) { + if (!editing(bv) && RenderPreview::previewMath() + && type_ != hullRegexp) + { graphics::PreviewImage const * pimage = preview_->getPreviewImage(bv->buffer()); return pimage && pimage->image(); @@ -355,14 +439,24 @@ 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(); + 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(); + } // Cache the inset dimension. setDimCache(mi, dim); return; @@ -389,6 +483,8 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const dim.wid += 30 + l; } + if (type_ == hullRegexp) + dim.wid += 2; // make it at least as high as the current font int asc = 0; int des = 0; @@ -401,10 +497,21 @@ void InsetMathHull::metrics(MetricsInfo & mi, Dimension & dim) const } +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; } @@ -412,23 +519,36 @@ ColorCode InsetMathHull::backgroundColor(PainterInfo const & pi) const 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; + use_preview_ = previewState(bv); if (type_ == hullRegexp) { - Dimension const dim = dimension(*pi.base.bv); + Dimension const dim = dimension(*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); + Dimension const dim = dimension(*bv); + 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); + } setPosCache(pi, x, y); return; } @@ -461,7 +581,9 @@ void InsetMathHull::metricsT(TextMetricsInfo const & mi, Dimension & dim) const InsetMathGrid::metricsT(mi, dim); } else { odocstringstream os; - WriteStream wi(os, false, true, WriteStream::wsDefault); + TexRow texrow(false); + otexrowstream ots(os,texrow); + WriteStream wi(ots, false, true, WriteStream::wsDefault); write(wi); dim.wid = os.str().size(); dim.asc = 1; @@ -476,7 +598,9 @@ 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); + TexRow texrow(false); + otexrowstream ots(os,texrow); + WriteStream wi(ots, false, true, WriteStream::wsDefault); write(wi); pain.draw(x, y, os.str().c_str()); } @@ -494,7 +618,9 @@ 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); + TexRow texrow(false); + otexrowstream ots(ls,texrow); + WriteStream wi(ots, false, true, WriteStream::wsPreview, encoding); inset.write(wi); return ls.str(); } @@ -510,37 +636,135 @@ 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) { + MathMacro const * mi = md[i].nucleus()->asMacro(); + MathMacroTemplate 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; + while (dit.inMathed()) + dit.pop_back(); + 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"); + CounterMap::const_iterator it = counter_map.find(eqstr); + if (it != counter_map.end()) { + int num = it->second; + if (num >= 0) + setcnt += from_ascii("\\setcounter{") + eqstr + '}' + + '{' + convert(num) + '}' + '\n'; + } + for (size_t i = 0; i != numcnts; ++i) { + docstring cnt = from_ascii(counters_to_save[i]); + it = counter_map.find(cnt); + if (it == counter_map.end()) + continue; + int num = it->second; + if (num > 0) + setcnt += from_ascii("\\setcounter{") + cnt + '}' + + '{' + convert(num) + '}'; } } - - docstring const snippet = macro_preamble.str() + latexString(*this); + docstring const snippet = macro_preamble + setfont + setcnt + + latexString(*this) + endfont; LYXERR(Debug::MACROS, "Preview snippet: " << snippet); preview_->addPreview(snippet, *buffer, forexport); } @@ -563,7 +787,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); } @@ -573,7 +797,7 @@ bool InsetMathHull::notifyCursorLeaves(Cursor const & old, Cursor & cur) docstring InsetMathHull::label(row_type row) const { - LASSERT(row < nrows(), /**/); + LASSERT(row < nrows(), return docstring()); if (InsetLabel * il = label_[row]) return il->screenLabel(); return docstring(); @@ -589,7 +813,7 @@ void InsetMathHull::label(row_type row, docstring const & label) label_[row] = dummy_pointer; } else { if (buffer_) - label_[row]->updateCommand(label); + label_[row]->updateLabelAndRefs(label); else label_[row]->setParam("name", label); } @@ -603,10 +827,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) { - nonum_[row] = !num; - if (nonum_[row] && label_[row]) { + numbered_[row] = num; + if (!numbered(row) && label_[row]) { delete label_[row]; label_[row] = 0; } @@ -615,19 +839,32 @@ void InsetMathHull::numbered(row_type row, bool num) bool InsetMathHull::numbered(row_type row) const { - return !nonum_[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 hullNone: + case hullSimple: + case hullEquation: + case hullEqnArray: + case hullRegexp: + break; + } + for (size_t row = 0; row < numbered_.size(); ++row) + if (numbered_[row] == NOTAG) + return true; + return false; } @@ -649,7 +886,7 @@ bool InsetMathHull::numberedType() const if (type_ == hullRegexp) return false; for (row_type row = 0; row < nrows(); ++row) - if (!nonum_[row]) + if (numbered(row)) return true; return false; } @@ -660,7 +897,7 @@ 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); @@ -668,25 +905,26 @@ void InsetMathHull::validate(LaTeXFeatures & features) const features.addPreambleSnippet( string("\\newcommand{\\regexp}[1]{\\fcolorbox{") + frcol + string("}{") - + bgcol + string("}{\\texttt{#1}}}")); + + bgcol + string("}{\\ensuremath{\\mathtt{#1}}}}")); + features.addPreambleSnippet( + string("\\newcommand{\\endregexp}{}")); } - + // 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 // InsetMathMatrix and we have no way, outside MathExtern, to know if // we even have any matrices. - features.addPreambleSnippet(""); + "td.rdelim{width: 0.5ex; border: thin solid black; border-left: none;}"); } InsetMathGrid::validate(features); } @@ -702,11 +940,14 @@ void InsetMathHull::header_write(WriteStream & os) const case hullSimple: os << '$'; + os.startOuterRow(); if (cell(0).empty()) os << ' '; break; case hullEquation: + os << "\n"; + os.startOuterRow(); if (n) os << "\\begin{equation" << star(n) << "}\n"; else @@ -718,26 +959,34 @@ void InsetMathHull::header_write(WriteStream & os) const case hullFlAlign: case hullGather: case hullMultline: + os << "\n"; + os.startOuterRow(); os << "\\begin{" << hullName(type_) << star(n) << "}\n"; break; case hullAlignAt: case hullXAlignAt: + os << "\n"; + os.startOuterRow(); os << "\\begin{" << hullName(type_) << star(n) << '}' << '{' << static_cast((ncols() + 1)/2) << "}\n"; break; case hullXXAlignAt: + os << "\n"; + os.startOuterRow(); os << "\\begin{" << hullName(type_) << '}' << '{' << static_cast((ncols() + 1)/2) << "}\n"; break; case hullRegexp: - os << "\\regexp{{{"; + os << "\\regexp{"; break; default: - os << "\\begin{unknown" << star(n) << '}'; + os << "\n"; + os.startOuterRow(); + os << "\\begin{unknown" << star(n) << "}\n"; break; } } @@ -757,6 +1006,8 @@ void InsetMathHull::footer_write(WriteStream & os) const break; case hullEquation: + os << "\n"; + os.startOuterRow(); if (n) os << "\\end{equation" << star(n) << "}\n"; else @@ -770,19 +1021,26 @@ void InsetMathHull::footer_write(WriteStream & os) const case hullXAlignAt: case hullGather: case hullMultline: + os << "\n"; + os.startOuterRow(); os << "\\end{" << hullName(type_) << star(n) << "}\n"; break; case hullXXAlignAt: + os << "\n"; + os.startOuterRow(); os << "\\end{" << hullName(type_) << "}\n"; break; case hullRegexp: - os << "}}}"; + // Only used as a heuristic to find the regexp termination, when searching in ignore-format mode + os << "\\endregexp{}}"; break; default: - os << "\\end{unknown" << star(n) << '}'; + os << "\n"; + os.startOuterRow(); + os << "\\end{unknown" << star(n) << "}\n"; break; } } @@ -812,19 +1070,21 @@ void InsetMathHull::addRow(row_type row) return; bool numbered = numberedType(); - docstring lab; + // Move the number and raw pointer, do not call label() (bug 7511) + InsetLabel * label = dummy_pointer; + docstring number = empty_docstring(); if (type_ == hullMultline) { if (row + 1 == nrows()) { - nonum_[row] = true; - lab = label(row); + numbered_[row] = NONUMBER; + swap(label, label_[row]); + swap(number, numbers_[row]); } else numbered = false; } - nonum_.insert(nonum_.begin() + row + 1, !numbered); - label_.insert(label_.begin() + row + 1, dummy_pointer); - if (!lab.empty()) - label(row + 1, lab); + 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); } @@ -835,14 +1095,8 @@ 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(nonum_[row], nonum_[row + 1]); - // so we do it manually: - bool const b = nonum_[row]; - nonum_[row] = nonum_[row + 1]; - nonum_[row + 1] = b; + swap(numbered_[row], numbered_[row + 1]); + swap(numbers_[row], numbers_[row + 1]); swap(label_[row], label_[row + 1]); InsetMathGrid::swapRow(row); } @@ -853,9 +1107,8 @@ void InsetMathHull::delRow(row_type row) if (nrows() <= 1 || !rowChangeOK()) return; if (row + 1 == nrows() && type_ == hullMultline) { - bool const b = nonum_[row - 1]; - nonum_[row - 1] = nonum_[row]; - nonum_[row] = b; + swap(numbered_[row - 1], numbered_[row]); + swap(numbers_[row - 1], numbers_[row]); swap(label_[row - 1], label_[row]); InsetMathGrid::delRow(row); return; @@ -865,7 +1118,8 @@ void InsetMathHull::delRow(row_type row) // Test nrows() + 1 because we have already erased the row. if (row == nrows() + 1) row--; - nonum_.erase(nonum_.begin() + row); + numbered_.erase(numbered_.begin() + row); + numbers_.erase(numbers_.begin() + row); delete label_[row]; label_.erase(label_.begin() + row); } @@ -889,11 +1143,12 @@ void InsetMathHull::delCol(col_type col) docstring InsetMathHull::nicelabel(row_type row) const { - if (nonum_[row]) + if (!numbered(row)) return docstring(); + docstring const & val = numbers_[row]; if (!label_[row]) - return from_ascii("(#)"); - return '(' + label_[row]->screenLabel() + from_ascii(", #)"); + return '(' + val + ')'; + return '(' + val + ',' + label_[row]->screenLabel() + ')'; } @@ -914,8 +1169,7 @@ void InsetMathHull::glueall(HullType type) } } *this = InsetMathHull(buffer_, hullSimple); - if (label) - label_[0] = label; + label_[0] = label; cell(0) = ar; setDefaults(); } @@ -923,7 +1177,7 @@ void InsetMathHull::glueall(HullType type) void InsetMathHull::splitTo2Cols() { - LASSERT(ncols() == 1, /**/); + LASSERT(ncols() == 1, return); InsetMathGrid::addCol(1); for (row_type row = 0; row < nrows(); ++row) { idx_type const i = 2 * row; @@ -936,13 +1190,13 @@ void InsetMathHull::splitTo2Cols() void InsetMathHull::splitTo3Cols() { - LASSERT(ncols() < 3, /**/); + LASSERT(ncols() < 3, return); if (ncols() < 2) splitTo2Cols(); InsetMathGrid::addCol(2); for (row_type row = 0; row < nrows(); ++row) { idx_type const i = 3 * row + 1; - if (cell(i).size()) { + if (!cell(i).empty()) { cell(i + 1) = MathData(buffer_, cell(i).begin() + 1, cell(i).end()); cell(i).erase(1, cell(i).size()); } @@ -993,6 +1247,27 @@ 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; + default: + return false; + } +} + + void InsetMathHull::mutate(HullType newtype) { //lyxerr << "mutating from '" << type_ << "' to '" << newtype << "'" << endl; @@ -1026,6 +1301,7 @@ void InsetMathHull::mutate(HullType newtype) numbered(0, false); } else { setType(hullEquation); + numbered(0, label_[0] ? true : false); mutate(newtype); } } @@ -1120,22 +1396,29 @@ void InsetMathHull::mutate(HullType newtype) } -docstring InsetMathHull::eolString(row_type row, bool fragile, bool last_eoln) const +docstring InsetMathHull::eolString(row_type row, bool fragile, bool latex, + bool last_eoln) const { docstring res; if (numberedType()) { - if (label_[row] && !nonum_[row]) - res += "\\label{" + - escape(label_[row]->getParam("name")) + '}'; - if (nonum_[row] && (type_ != hullMultline)) - res += "\\nonumber "; + if (label_[row] && numbered(row)) { + docstring const name = + latex ? escape(label_[row]->getParam("name")) + : label_[row]->getParam("name"); + res += "\\label{" + name + '}'; + } + 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, last_eoln); + return res + InsetMathGrid::eolString(row, fragile, latex, last_eoln); } - void InsetMathHull::write(WriteStream & os) const { ModeSpecifier specifier(os, MATH_MODE); @@ -1153,22 +1436,17 @@ void InsetMathHull::normalize(NormalStream & os) const } -void InsetMathHull::mathmlize(MathStream & os) const -{ - InsetMathGrid::mathmlize(os); -} - - void InsetMathHull::infoize(odocstream & os) const { - os << "Type: " << hullName(type_); + os << bformat(_("Type: %1$s"), hullName(type_)); } void InsetMathHull::check() const { - LASSERT(nonum_.size() == nrows(), /**/); - LASSERT(label_.size() == nrows(), /**/); + LATTEST(numbered_.size() == nrows()); + LATTEST(numbers_.size() == nrows()); + LATTEST(label_.size() == nrows()); } @@ -1182,14 +1460,23 @@ 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) { + frontend::Alert::warning(_("Bad math environment"), + _("Computation cannot be performed for AMS " + "math environments.\nChange the math " + "formula type and try again.")); + return; + } MathData eq; eq.push_back(MathAtom(new InsetMathChar('='))); @@ -1201,9 +1488,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().size()) { + if (pos == cur.cell().size()) { ar = cur.cell(); lyxerr << "use whole cell: " << ar << endl; } else { @@ -1259,10 +1544,9 @@ 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_BREAK_PARAGRAPH: + case LFUN_PARAGRAPH_BREAK: // just swallow this break; @@ -1271,7 +1555,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) if (type_ == hullSimple || type_ == hullEquation) { cur.recordUndoInset(); bool const align = - cur.bv().buffer().params().use_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(); @@ -1307,18 +1591,15 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_LABEL_INSERT: { - cur.recordUndoInset(); row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row(); docstring old_label = label(r); - // FIXME refstyle - // Allow customization of this separator docstring const default_label = from_ascii("eq:"); if (old_label.empty()) old_label = default_label; InsetCommandParams p(LABEL_CODE); p["name"] = cmd.argument().empty() ? old_label : cmd.argument(); - string const data = InsetCommand::params2string("label", p); + string const data = InsetCommand::params2string(p); if (cmd.argument().empty()) cur.bv().showDialog("label", data); @@ -1329,7 +1610,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 @@ -1339,7 +1620,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 (!nonum_[row] && label_[row] + if (numbered(row) && label_[row] && (cmd.argument().empty() || label(row) == cmd.argument())) break; } @@ -1382,7 +1663,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd) string const name = cmd.getArg(0); if (name == "label") { InsetCommandParams p(LABEL_CODE); - InsetCommand::string2params(name, to_utf8(cmd.argument()), p); + InsetCommand::string2params(to_utf8(cmd.argument()), p); docstring str = p["name"]; cur.recordUndoInset(); row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row(); @@ -1436,9 +1717,15 @@ 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; } @@ -1461,15 +1748,45 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_DOWN: case LFUN_NEWLINE_INSERT: case LFUN_MATH_EXTERN: - case LFUN_MATH_DISPLAY: // we handle these status.setEnabled(true); return true; + // we never allow this in math, and we want to bind enter + // to another actions in command-alternatives + case LFUN_PARAGRAPH_BREAK: + status.setEnabled(false); + return true; case LFUN_MATH_MUTATE: { - HullType ht = hullType(cmd.argument()); + HullType const ht = hullType(cmd.argument()); status.setOnOff(type_ == ht); status.setEnabled(true); + + 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(); + } + } + 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.setOnOff(display() != Inline); return true; } @@ -1485,7 +1802,7 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, // LABEL_INSERT? bool const enable = (type_ == hullMultline) ? (nrows() - 1 == cur.row()) - : display() != Inline && nrows() > 1; + : display() != Inline; row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row(); status.setEnabled(enable); status.setOnOff(enable && numbered(r)); @@ -1496,19 +1813,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] && !nonum_[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 (!nonum_[row] && label_[row] && + if (numbered(row) && label_[row] && (cmd.argument().empty() || label(row) == cmd.argument())) { enabled = true; break; @@ -1738,7 +2055,9 @@ bool InsetMathHull::searchForward(BufferView * bv, string const & str, void InsetMathHull::write(ostream & os) const { odocstringstream oss; - WriteStream wi(oss, false, false, WriteStream::wsDefault); + TexRow texrow(false); + otexrowstream ots(oss,texrow); + WriteStream wi(ots, false, false, WriteStream::wsDefault); oss << "Formula "; write(wi); os << to_utf8(oss.str()); @@ -1763,7 +2082,8 @@ bool InsetMathHull::readQuiet(Lexer & lex) } -int InsetMathHull::plaintext(odocstream & os, OutputParams const &) const +int InsetMathHull::plaintext(odocstringstream & os, + OutputParams const & op, size_t max_length) const { // disables ASCII-art for export of equations. See #2275. if (0 && display()) { @@ -1776,19 +2096,32 @@ int InsetMathHull::plaintext(odocstream & os, OutputParams const &) const // reset metrics cache to "real" values //metrics(); return tpain.textheight(); - } else { - odocstringstream oss; - Encoding const * const enc = encodings.fromLyXName("utf8"); - WriteStream wi(oss, false, true, WriteStream::wsDefault, enc); - // Fix Bug #6139 - if (type_ == hullRegexp) - write(wi); - else - wi << cell(0); - docstring const str = oss.str(); - os << str; - return str.size(); } + + odocstringstream oss; + TexRow texrow(false); + otexrowstream ots(oss,texrow); + Encoding const * const enc = encodings.fromLyXName("utf8"); + WriteStream wi(ots, false, true, WriteStream::wsDefault, enc); + + // Fix Bug #6139 + if (type_ == hullRegexp) + write(wi); + else { + for (row_type r = 0; r < nrows(); ++r) { + for (col_type c = 0; c < ncols(); ++c) + wi << (c == 0 ? "" : "\t") << cell(index(r, c)); + // if it's for the TOC, we write just the first line + // and do not include the newline. + if (op.for_toc || op.for_tooltip || oss.str().size() >= max_length) + break; + if (r < nrows() - 1) + wi << "\n"; + } + } + docstring const str = oss.str(); + os << str; + return str.size(); } @@ -1809,12 +2142,14 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons ++ms.tab(); ms.cr(); ms.os() << '<' << bname << '>'; odocstringstream ls; + TexRow texrow; + otexstream ols(ls, texrow); 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"); @@ -1825,7 +2160,8 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons ms << ETag("math"); } else { ms << MTag("alt role='tex'"); - res = latex(ls, runparams); + latex(ols, runparams); + res = texrow.rows(); ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&"), "<", "<")); ms << ETag("alt"); } @@ -1847,28 +2183,162 @@ int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) cons } +bool InsetMathHull::haveNumbers() const +{ + bool havenumbers = false; + // inline formulas are never numbered (bug 7351 part 3) + if (getType() == hullSimple) + return havenumbers; + for (size_t i = 0; i != numbered_.size(); ++i) { + if (numbered(i)) { + havenumbers = true; + break; + } + } + return havenumbers; +} + + +// FIXME XHTML +// We need to do something about alignment here. +// +// This duplicates code from InsetMathGrid, but +// we need access here to number information, +// and we simply do not have that in InsetMathGrid. +void InsetMathHull::htmlize(HtmlStream & os) const +{ + bool const havenumbers = haveNumbers(); + bool const havetable = havenumbers || nrows() > 1 || ncols() > 1; + + if (!havetable) { + os << cell(index(0, 0)); + return; + } + + os << MTag("table", "class='mathtable'"); + for (row_type row = 0; row < nrows(); ++row) { + os << MTag("tr"); + for (col_type col = 0; col < ncols(); ++col) { + os << MTag("td"); + os << cell(index(row, col)); + os << ETag("td"); + } + if (havenumbers) { + os << MTag("td"); + docstring const & num = numbers_[row]; + if (!num.empty()) + os << '(' << num << ')'; + os << ETag("td"); + } + os << ETag("tr"); + } + os << ETag("table"); +} + + +// this duplicates code from InsetMathGrid, but +// we need access here to number information, +// and we simply do not have that in InsetMathGrid. +void InsetMathHull::mathmlize(MathStream & os) const +{ + bool const havenumbers = haveNumbers(); + bool const havetable = havenumbers || nrows() > 1 || ncols() > 1; + + if (havetable) + os << MTag("mtable"); + char const * const celltag = havetable ? "mtd" : "mrow"; + // FIXME There does not seem to be wide support at the moment + // for mlabeledtr, so we have to use just mtr for now. + // char const * const rowtag = havenumbers ? "mlabeledtr" : "mtr"; + char const * const rowtag = "mtr"; + for (row_type row = 0; row < nrows(); ++row) { + if (havetable) + os << MTag(rowtag); + for (col_type col = 0; col < ncols(); ++col) { + os << MTag(celltag) + << cell(index(row, col)) + << ETag(celltag); + } + // fleqn? + if (havenumbers) { + os << MTag("mtd"); + docstring const & num = numbers_[row]; + if (!num.empty()) + os << '(' << num << ')'; + os << ETag("mtd"); + } + if (havetable) + os << ETag(rowtag); + } + if (havetable) + os << ETag("mtable"); +} + + +void InsetMathHull::mathAsLatex(WriteStream & os) const +{ + MathEnsurer ensurer(os, false); + bool havenumbers = haveNumbers(); + bool const havetable = havenumbers || nrows() > 1 || ncols() > 1; + + if (!havetable) { + os << cell(index(0, 0)); + return; + } + + os << ""; + for (row_type row = 0; row < nrows(); ++row) { + os << ""; + for (col_type col = 0; col < ncols(); ++col) { + os << ""; + } + if (havenumbers) { + os << ""; + } + os << ""; + } + os << "
"; + os << cell(index(row, col)); + os << ""; + docstring const & num = numbers_[row]; + if (!num.empty()) + os << '(' << num << ')'; + os << "
"; +} + + docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const { - BufferParams::MathOutput const mathtype = - buffer().params().html_math_output; - + BufferParams::MathOutput const mathtype = + buffer().masterBuffer()->params().html_math_output; + bool success = false; + + // we output all the labels just at the beginning of the equation. + // this should be fine. + for (size_t i = 0; i != label_.size(); ++i) { + InsetLabel const * const il = label_[i]; + if (!il) + continue; + il->xhtml(xs, op); + } + // FIXME Eventually we would like to do this inset by inset. if (mathtype == BufferParams::MathML) { odocstringstream os; MathStream ms(os); try { - InsetMathGrid::mathmlize(ms); + mathmlize(ms); success = true; } 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", - "display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); - xs << XHTMLStream::NextRaw() + else + xs << html::StartTag("math", + "display=\"block\" xmlns=\"http://www.w3.org/1998/Math/MathML\"", true); + xs << XHTMLStream::ESCAPE_NONE << os.str() << html::EndTag("math"); } @@ -1876,79 +2346,112 @@ docstring InsetMathHull::xhtml(XHTMLStream & xs, OutputParams const & op) const odocstringstream os; HtmlStream ms(os); try { - InsetMathGrid::htmlize(ms); + htmlize(ms); success = true; } catch (MathExportException const &) {} if (success) { string const tag = (getType() == hullSimple) ? "span" : "div"; xs << html::StartTag(tag, "class='formula'", true) - << XHTMLStream::NextRaw() - << os.str() - << html::EndTag(tag); + << XHTMLStream::ESCAPE_NONE + << os.str() + << 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. if (!success && mathtype != BufferParams::LaTeX) { - loadPreview(docit_); - graphics::PreviewImage const * pimage = preview_->getPreviewImage(buffer()); - if (pimage) { + graphics::PreviewImage const * pimage = 0; + if (!op.dryrun) { + loadPreview(docit_); + pimage = preview_->getPreviewImage(buffer()); // FIXME Do we always have png? + } + + if (pimage || op.dryrun) { + string const filename = pimage ? pimage->filename().onlyFileName() + : "previewimage.png"; + if (pimage) { + // if we are not in the master buffer, then we need to see that the + // generated image is copied there; otherwise, preview fails. + Buffer const * mbuf = buffer().masterBuffer(); + if (mbuf != &buffer()) { + string mbtmp = mbuf->temppath(); + FileName const mbufimg(support::addName(mbtmp, filename)); + pimage->filename().copyTo(mbufimg); + } + // add the file to the list of files to be exported + op.exportdata->addExternalFile("xhtml", pimage->filename()); + } + string const tag = (getType() == hullSimple) ? "span" : "div"; - FileName const & mathimg = pimage->filename(); - xs << html::StartTag(tag) - << html::CompTag("img", "src=\"" + mathimg.onlyFileName() + "\"") - << html::EndTag(tag); - xs.cr(); - // add the file to the list of files to be exported - op.exportdata->addExternalFile("xhtml", mathimg); + xs << html::CR() + << html::StartTag(tag) + << 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 if (!success /* || mathtype != BufferParams::LaTeX */) { - string const tag = (getType() == hullSimple) ? "span" : "div"; // Unfortunately, we cannot use latexString() because we do not want // $...$ or whatever. odocstringstream ls; - WriteStream wi(ls, false, true, WriteStream::wsPreview); + TexRow texrow(false); + otexrowstream ots(ls,texrow); + WriteStream wi(ots, false, true, WriteStream::wsPreview); ModeSpecifier specifier(wi, MATH_MODE); - InsetMathGrid::write(wi); + 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 - xs << html::StartTag(tag, "class='math'") - << latex - << html::EndTag(tag); - xs.cr(); + string const tag = (getType() == hullSimple) ? "span" : "div"; + xs << html::StartTag(tag, "class='math'") + << latex + << html::EndTag(tag) + << html::CR(); } return docstring(); } -void InsetMathHull::tocString(odocstream & os) const +void InsetMathHull::toString(odocstream & os) const +{ + odocstringstream ods; + plaintext(ods, OutputParams(0)); + os << ods.str(); +} + + +void InsetMathHull::forOutliner(docstring & os, size_t const, bool const) const { - plaintext(os, OutputParams(0)); + 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(); } -docstring InsetMathHull::contextMenu(BufferView const &, int, int) const +string InsetMathHull::contextMenuName() const { - return from_ascii("context-math"); + return "context-math"; }