Adding TexRow information on math latex output (#4725)

WriteStream is now built from an otexstream instead of an odocstream, and
therefore counts lines in a TexRow. Calls to TexRow are added in relevant places
in math insets.

This finishes adding line tracking for math in the source panel and for forward
search.
This commit is contained in:
Guillaume Munch 2015-10-07 04:13:21 +01:00
parent 65d61e7a27
commit 460a764b7f
20 changed files with 180 additions and 59 deletions

View File

@ -1684,7 +1684,9 @@ void Cursor::normalize()
<< pos() << ' ' << lastpos() << " in idx: " << idx()
<< " in atom: '";
odocstringstream os;
WriteStream wi(os, false, true, WriteStream::wsDefault);
TexRow texrow(false);
otexrowstream ots(os,texrow);
WriteStream wi(ots, false, true, WriteStream::wsDefault);
inset().asInsetMath()->write(wi);
lyxerr << to_utf8(os.str()) << endl;
pos() = lastpos();

View File

@ -1072,7 +1072,7 @@ docstring latexifyFromCursor(DocIterator const & cur, int len)
for (int s = cur.depth() - 1; s >= 0; --s) {
CursorSlice const & cs = cur[s];
if (cs.asInsetMath() && cs.asInsetMath()->asHullInset()) {
WriteStream ws(ods);
WriteStream ws(os);
cs.asInsetMath()->asHullInset()->header_write(ws);
break;
}
@ -1094,7 +1094,7 @@ docstring latexifyFromCursor(DocIterator const & cur, int len)
CursorSlice const & cs = cur[s];
InsetMath * inset = cs.asInsetMath();
if (inset && inset->asHullInset()) {
WriteStream ws(ods);
WriteStream ws(os);
inset->asHullInset()->footer_write(ws);
break;
}

View File

@ -53,7 +53,9 @@ void InsetMath::dump() const
{
lyxerr << "---------------------------------------------" << endl;
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);
lyxerr << to_utf8(os.str());
lyxerr << "\n---------------------------------------------" << endl;
@ -156,7 +158,9 @@ HullType InsetMath::getType() const
ostream & operator<<(ostream & os, MathAtom const & at)
{
odocstringstream oss;
WriteStream wi(oss, false, false, WriteStream::wsDefault);
TexRow texrow(false);
otexrowstream ots(oss,texrow);
WriteStream wi(ots, false, false, WriteStream::wsDefault);
at->write(wi);
return os << to_utf8(oss.str());
}
@ -164,7 +168,9 @@ ostream & operator<<(ostream & os, MathAtom const & at)
odocstream & operator<<(odocstream & os, MathAtom const & at)
{
WriteStream wi(os, false, false, WriteStream::wsDefault);
TexRow texrow(false);
otexrowstream ots(os,texrow);
WriteStream wi(ots, false, false, WriteStream::wsDefault);
at->write(wi);
return os;
}

View File

@ -134,8 +134,11 @@ void InsetMathAMSArray::write(WriteStream & os) const
{
MathEnsurer ensurer(os);
os << "\\begin{" << name_ << '}';
bool open = os.startOuterRow();
InsetMathGrid::write(os);
os << "\\end{" << name_ << '}';
if (open)
os.startOuterRow();
}

View File

@ -103,6 +103,7 @@ void InsetMathArray::write(WriteStream & os) const
if (os.fragile())
os << "\\protect";
os << "\\begin{" << name_ << '}';
bool open = os.startOuterRow();
char const v = verticalAlignment();
if (v == 't' || v == 'b')
@ -114,6 +115,8 @@ void InsetMathArray::write(WriteStream & os) const
if (os.fragile())
os << "\\protect";
os << "\\end{" << name_ << '}';
if (open)
os.startOuterRow();
// adding a \n here is bad if the array is the last item
// in an \eqnarray...
}

View File

@ -132,11 +132,14 @@ void InsetMathCases::write(WriteStream & os) const
MathEnsurer ensurer(os);
if (os.fragile())
os << "\\protect";
bool open = os.startOuterRow();
os << "\\begin{cases}\n";
InsetMathGrid::write(os);
if (os.fragile())
os << "\\protect";
os << "\\end{cases}";
if (open)
os.startOuterRow();
}

View File

@ -56,9 +56,12 @@ void InsetMathDiagram::write(WriteStream & os) const
{
MathEnsurer ensurer(os);
os << "\\Diagram";
bool open = os.startOuterRow();
os << '{';
InsetMathGrid::write(os);
os << "}\n";
if (open)
os.startOuterRow();
}

View File

@ -1266,9 +1266,16 @@ void InsetMathGrid::write(WriteStream & os,
emptyline = false;
}
}
for (col_type col = beg_col; col < lastcol;) {
for (col_type col = beg_col; col < end_col;) {
int nccols = 1;
idx_type const idx = index(row, col);
TexRow::RowEntry entry = os.texrow().mathEntry(id(),idx);
os.texrow().startMath(id(),idx);
if (col >= lastcol) {
++col;
continue;
}
os.pushRowEntry(entry);
if (cellinfo_[idx].multi_ == CELL_BEGIN_OF_MULTICOLUMN) {
size_t s = col + 1;
while (s < ncols() &&
@ -1286,6 +1293,7 @@ void InsetMathGrid::write(WriteStream & os,
os << '}';
os << eocString(col + nccols - 1, lastcol);
col += nccols;
os.popRowEntry();
}
eol = eolString(row, os.fragile(), os.latex(), last_eoln);
os << eol;

View File

@ -575,7 +575,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;
@ -590,7 +592,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());
}
@ -608,7 +612,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();
}
@ -928,15 +934,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:
@ -944,17 +953,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<unsigned int>((ncols() + 1)/2) << "}\n";
break;
case hullXXAlignAt:
os << "\n\\begin{" << hullName(type_) << '}'
os << "\n";
os.startOuterRow();
os << "\\begin{" << hullName(type_) << '}'
<< '{' << static_cast<unsigned int>((ncols() + 1)/2) << "}\n";
break;
@ -963,7 +978,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;
}
}
@ -983,10 +1000,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:
@ -996,11 +1015,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:
@ -1009,7 +1032,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;
}
}
@ -1367,7 +1392,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);
@ -2004,7 +2028,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());
@ -2046,8 +2072,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)
@ -2087,12 +2115,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()), "&", "&amp;"), "<", "&lt;"));
ms << ETag("alt");
@ -2102,9 +2132,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();
@ -2354,7 +2381,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();

View File

@ -250,7 +250,9 @@ bool InsetMathNest::idxLast(Cursor & cur) const
void InsetMathNest::dump() const
{
odocstringstream oss;
WriteStream os(oss);
TexRow texrow(false);
otexrowstream ots(oss,texrow);
WriteStream os(ots);
os << "---------------------------------------------\n";
write(os);
os << "\n";
@ -376,8 +378,11 @@ void InsetMathNest::write(WriteStream & os) const
ModeSpecifier specifier(os, currentMode(), lockedMode());
docstring const latex_name = name();
os << '\\' << latex_name;
for (size_t i = 0; i < nargs(); ++i)
for (size_t i = 0; i < nargs(); ++i) {
os.pushRowEntry(TexRow::mathEntry(id(),i));
os << '{' << cell(i) << '}';
os.popRowEntry();
}
if (nargs() == 0)
os.pendingSpace(true);
if (lock_ && !os.latex()) {
@ -398,22 +403,20 @@ void InsetMathNest::normalize(NormalStream & os) const
void InsetMathNest::latex(otexstream & os, OutputParams const & runparams) const
{
WriteStream wi(os.os(), runparams.moving_arg, true,
WriteStream wi(os, runparams.moving_arg, true,
runparams.dryrun ? WriteStream::wsDryrun : WriteStream::wsDefault,
runparams.encoding);
wi.canBreakLine(os.canBreakLine());
if (runparams.lastid != -1) {
wi.pushRowEntry(os.texrow().textEntry(runparams.lastid,
runparams.lastpos));
write(wi);
wi.popRowEntry();
} else
write(wi);
// Reset parbreak status after a math inset.
os.lastChar(0);
os.canBreakLine(wi.canBreakLine());
int lf = wi.line();
if (lf > 0 && runparams.lastid != -1) {
--lf;
os.texrow().newline();
os.texrow().start(runparams.lastid, runparams.lastpos);
}
os.texrow().newlines(lf);
}

View File

@ -104,6 +104,7 @@ void InsetMathSplit::write(WriteStream & ws) const
if (!numbered_ && name_ == "align")
suffix = from_ascii("*");
ws << "\\begin{" << name_ << suffix << '}';
bool open = ws.startOuterRow();
if (name_ != "split" && name_ != "align" && verticalAlignment() != 'c')
ws << '[' << verticalAlignment() << ']';
if (name_ == "alignedat")
@ -112,6 +113,8 @@ void InsetMathSplit::write(WriteStream & ws) const
if (ws.fragile())
ws << "\\protect";
ws << "\\end{" << name_ << suffix << "}\n";
if (open)
ws.startOuterRow();
}

View File

@ -107,8 +107,11 @@ void InsetMathSubstack::write(WriteStream & os) const
{
MathEnsurer ensurer(os);
os << "\\substack{";
bool open = os.startOuterRow();
InsetMathGrid::write(os);
os << "}\n";
if (open)
os.startOuterRow();
}

View File

@ -71,6 +71,7 @@ void InsetMathTabular::write(WriteStream & os) const
if (os.fragile())
os << "\\protect";
os << "\\begin{" << name_ << '}';
bool open = os.startOuterRow();
char const v = verticalAlignment();
if (v == 't' || v == 'b')
@ -82,6 +83,8 @@ void InsetMathTabular::write(WriteStream & os) const
if (os.fragile())
os << "\\protect";
os << "\\end{" << name_ << '}';
if (open)
os.startOuterRow();
// adding a \n here is bad if the tabular is the last item
// in an \eqnarray...
}

View File

@ -57,6 +57,7 @@ void InsetMathXYMatrix::write(WriteStream & os) const
{
MathEnsurer ensurer(os);
os << "\\xymatrix";
bool open = os.startOuterRow();
if (equal_spacing_) {
os << "@!";
switch (spacing_code_) {
@ -83,7 +84,10 @@ void InsetMathXYMatrix::write(WriteStream & os) const
}
os << '{';
InsetMathGrid::write(os);
os << "}\n";
os << "}";
if (open)
os.startOuterRow();
os << "\n";
}

View File

@ -200,7 +200,9 @@ int MacroData::write(odocstream & os, bool overwriteRedefinition) const
// output template
MathMacroTemplate const & tmpl =
static_cast<MathMacroTemplate const &>(*inset);
WriteStream wi(os, false, true, WriteStream::wsDefault);
TexRow texrow(false);
otexrowstream ots(os,texrow);
WriteStream wi(ots, false, true, WriteStream::wsDefault);
return tmpl.write(wi, overwriteRedefinition);
}

View File

@ -1386,6 +1386,7 @@ void write(MathData const & dat, WriteStream & wi)
extractStrings(ar);
wi.firstitem() = true;
for (MathData::const_iterator it = ar.begin(); it != ar.end(); ++it) {
// wi.startOuterRow();
(*it)->write(wi);
wi.firstitem() = false;
}

View File

@ -1168,7 +1168,9 @@ void MathMacroTemplate::read(Lexer & lex)
void MathMacroTemplate::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 << "FormulaMacro\n";
write(wi);
os << to_utf8(oss.str());

View File

@ -121,8 +121,8 @@ WriteStream & operator<<(WriteStream & ws, docstring const & s)
}
WriteStream::WriteStream(odocstream & os, bool fragile, bool latex, OutputType output,
Encoding const * encoding)
WriteStream::WriteStream(otexrowstream & os, bool fragile, bool latex,
OutputType output, Encoding const * encoding)
: os_(os), fragile_(fragile), firstitem_(false), latex_(latex),
output_(output), pendingspace_(false), pendingbrace_(false),
textmode_(false), locked_(0), ascii_(0), canbreakline_(true),
@ -130,7 +130,7 @@ WriteStream::WriteStream(odocstream & os, bool fragile, bool latex, OutputType o
{}
WriteStream::WriteStream(odocstream & os)
WriteStream::WriteStream(otexrowstream & os)
: os_(os), fragile_(false), firstitem_(false), latex_(false),
output_(wsDefault), pendingspace_(false), pendingbrace_(false),
textmode_(false), locked_(0), ascii_(0), canbreakline_(true),
@ -183,6 +183,29 @@ void WriteStream::asciiOnly(bool ascii)
}
void WriteStream::pushRowEntry(TexRow::RowEntry entry)
{
outer_row_entries_.push_back(entry);
}
void WriteStream::popRowEntry()
{
if (!outer_row_entries_.empty())
outer_row_entries_.pop_back();
}
bool WriteStream::startOuterRow()
{
size_t n = outer_row_entries_.size();
if (n > 0)
return texrow().start(outer_row_entries_[n - 1]);
else
return false;
}
WriteStream & operator<<(WriteStream & ws, MathAtom const & at)
{
at->write(ws);

View File

@ -17,6 +17,7 @@
#include "InsetMath.h"
// FIXME: Move to individual insets
#include "MetricsInfo.h"
#include "texstream.h"
namespace lyx {
@ -39,10 +40,10 @@ public:
wsPreview
};
///
WriteStream(odocstream & os, bool fragile, bool latex, OutputType output,
WriteStream(otexrowstream & os, bool fragile, bool latex, OutputType output,
Encoding const * encoding = 0);
///
explicit WriteStream(odocstream & os);
explicit WriteStream(otexrowstream & os);
///
~WriteStream();
///
@ -54,7 +55,9 @@ public:
///
OutputType output() const { return output_; }
///
odocstream & os() { return os_; }
otexrowstream & os() { return os_; }
///
TexRow & texrow() { return os_.texrow(); }
///
bool & firstitem() { return firstitem_; }
///
@ -85,9 +88,18 @@ public:
bool asciiOnly() const { return ascii_; }
/// LaTeX encoding
Encoding const * encoding() const { return encoding_; }
/// maintains a stack of texrow informations about outer math insets.
/// push an entry
void pushRowEntry(TexRow::RowEntry entry);
/// pop an entry
void popRowEntry();
/// TexRow::starts the innermost outer math inset
/// returns true if the outer row entry will appear at this line
bool startOuterRow();
private:
///
odocstream & os_;
otexrowstream & os_;
/// do we have to write \\protect sometimes
bool fragile_;
/// are we at the beginning of an MathData?
@ -112,6 +124,8 @@ private:
int line_;
///
Encoding const * encoding_;
///
std::vector<TexRow::RowEntry> outer_row_entries_;
};
///

View File

@ -877,7 +877,9 @@ bool isAlphaSymbol(MathAtom const & at)
docstring asString(MathData const & ar)
{
odocstringstream os;
WriteStream ws(os);
TexRow texrow(false);
otexrowstream ots(os,texrow);
WriteStream ws(ots);
ws << ar;
return os.str();
}
@ -894,7 +896,9 @@ void asArray(docstring const & str, MathData & ar, Parse::flags pf)
docstring asString(InsetMath const & inset)
{
odocstringstream os;
WriteStream ws(os);
TexRow texrow(false);
otexrowstream ots(os,texrow);
WriteStream ws(ots);
inset.write(ws);
return os.str();
}
@ -903,7 +907,9 @@ docstring asString(InsetMath const & inset)
docstring asString(MathAtom const & at)
{
odocstringstream os;
WriteStream ws(os);
TexRow texrow(false);
otexrowstream ots(os,texrow);
WriteStream ws(ots);
at->write(ws);
return os.str();
}