X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathHull.cpp;h=cce029f6cedf25f98b3f3293ac45ea8cb8476974;hb=f1a388584fb2c043d17127d7db49c36cb8427cfa;hp=53a16e8d0f7b6d41a6f2746460b38ab92d4275b4;hpb=9c55af4a223ce4db29d643251109e245665344bd;p=lyx.git diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index 53a16e8d0f..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" @@ -32,6 +36,8 @@ #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" @@ -121,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); } @@ -141,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"); } @@ -151,8 +157,8 @@ 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) + 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; @@ -166,8 +172,8 @@ 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) + numbers_(1, empty_docstring()), label_(1, dummy_pointer), + preview_(new RenderPreview(this)), use_preview_(false) { buffer_ = buf; initMath(); @@ -286,7 +292,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) const { if (!buffer_) { //FIXME: buffer_ should be set at creation for this inset! Problem is @@ -295,14 +302,14 @@ void InsetMathHull::addToToc(DocIterator const & pit, bool output_active) const return; } - Toc & toc = buffer().tocBackend().toc("equation"); + shared_ptr toc = buffer().tocBackend().toc("equation"); for (row_type row = 0; row != nrows(); ++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); + toc->push_back(TocItem(pit, 0, nicelabel(row), output_active)); } } @@ -342,29 +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_ == 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'; + } + case hullEqnArray: + case hullGather: + case hullAlign: + case hullAlignAt: + case hullXAlignAt: + case hullXXAlignAt: + case hullFlAlign: + return colAlign(type_, col(idx)); + default: + break; } - return InsetMathGrid::displayColAlign(col, row); + return InsetMathGrid::displayColAlign(idx); } @@ -506,10 +520,10 @@ 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, + 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)); } @@ -567,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; @@ -582,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()); } @@ -600,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(); } @@ -622,6 +642,64 @@ void InsetMathHull::addPreview(DocIterator const & 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 { @@ -635,16 +713,34 @@ void InsetMathHull::preparePreview(DocIterator const & pos, // 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()) { @@ -667,8 +763,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); } @@ -844,15 +940,18 @@ 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 << "\n\\begin{equation" << star(n) << "}\n"; + os << "\\begin{equation" << star(n) << "}\n"; else - os << "\n\\[\n"; + os << "\\[\n"; break; case hullEqnArray: @@ -860,17 +959,23 @@ void InsetMathHull::header_write(WriteStream & os) const case hullFlAlign: case hullGather: case hullMultline: - os << "\n\\begin{" << hullName(type_) << star(n) << "}\n"; + 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; @@ -879,7 +984,9 @@ void InsetMathHull::header_write(WriteStream & os) const break; default: - os << "\n\\begin{unknown" << star(n) << "}\n"; + os << "\n"; + os.startOuterRow(); + os << "\\begin{unknown" << star(n) << "}\n"; break; } } @@ -899,10 +1006,12 @@ void InsetMathHull::footer_write(WriteStream & os) const 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"; break; case hullEqnArray: @@ -912,11 +1021,15 @@ void InsetMathHull::footer_write(WriteStream & os) const 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"; break; case hullXXAlignAt: - os << "\n\\end{" << hullName(type_) << "}\n"; + os << "\n"; + os.startOuterRow(); + os << "\\end{" << hullName(type_) << "}\n"; break; case hullRegexp: @@ -925,7 +1038,9 @@ void InsetMathHull::footer_write(WriteStream & os) const break; default: - os << "\n\\end{unknown" << star(n) << "}\n"; + os << "\n"; + os.startOuterRow(); + os << "\\end{unknown" << star(n) << "}\n"; break; } } @@ -1132,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; @@ -1283,7 +1419,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); @@ -1420,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_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(); @@ -1582,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; } @@ -1645,6 +1786,7 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd, enable = display() != Inline; } status.setEnabled(enable); + status.setOnOff(display() != Inline); return true; } @@ -1913,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()); @@ -1955,8 +2099,10 @@ int InsetMathHull::plaintext(odocstringstream & os, } odocstringstream oss; + TexRow texrow(false); + otexrowstream ots(oss,texrow); 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) @@ -1969,7 +2115,7 @@ int InsetMathHull::plaintext(odocstringstream & os, // and do not include the newline. if (op.for_toc || op.for_tooltip || oss.str().size() >= max_length) break; - if (r < nrows() - 1) + if (r < nrows() - 1) wi << "\n"; } } @@ -1996,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"); @@ -2011,9 +2159,6 @@ 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(); @@ -2263,7 +2408,9 @@ 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); + TexRow texrow(false); + otexrowstream ots(ls,texrow); + WriteStream wi(ots, false, true, WriteStream::wsPreview); ModeSpecifier specifier(wi, MATH_MODE); mathAsLatex(wi); docstring const latex = ls.str(); @@ -2290,11 +2437,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(); }