Fix bug #8464: stackrel with subscript.

The fix is basically mechanical, the additional code for fraction like insets
with three arguments was stolen from \unitfrac. As any math package,
stackrel.sty needs a buffer parameter to switch it off.
I also added the two stackrel flavours to the toolbar.
This commit is contained in:
Georg Baum 2012-12-28 19:51:28 +01:00
parent 8693f5a91e
commit 56ece75ad9
28 changed files with 218 additions and 34 deletions

View File

@ -11,6 +11,11 @@ adjustments are made to tex2lyx and bugs are fixed in lyx2lyx.
-----------------------
2012-12-28 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* Format incremented to 457
support for the LaTeX-package stackrel (fix bug 8464)
New buffer param \use_package stackrel
2012-12-28 Jürgen Spitzmüller <spitz@lyx.org>
* Format incremented to 456: Proper support for memoir \epigraph
\epigraph{text}{source} > begin_layout Epigraph, <source> as

View File

@ -978,6 +978,8 @@ dist_imagesmath_DATA = \
images/math/ssearrow.png \
images/math/sslash.png \
images/math/sswarrow.png \
images/math/stackrel.png \
images/math/stackrelthree.png \
images/math/star.png \
images/math/style.png \
images/math/sub.png \

View File

@ -343,6 +343,7 @@
\TestPackage{slashed}
\TestPackage{soul}
\TestPackage{splitidx}
\TestPackage{stackrel}
\TestPackage{stmaryrd}
\TestPackage{subfig}
\TestPackage{Sweave}

View File

@ -6580,6 +6580,36 @@ splitindex
converter programs.
\end_layout
\begin_layout Subsection
stackrel
\end_layout
\begin_layout Description
Found:
\begin_inset Info
type "package"
arg "stackrel"
\end_inset
\end_layout
\begin_layout Description
CTAN:
\family typewriter
macros/latex/contrib/oberdiek
\end_layout
\begin_layout Description
Notes: The package
\family sans
stackrel
\family default
is needed by LyX to be able to output formulas using the
\backslash
stackrel command with subscript.
\end_layout
\begin_layout Subsection
stmaryrd
\end_layout

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

View File

@ -495,6 +495,49 @@ def revert_use_stmaryrd(document):
i = j
def convert_use_stackrel(document):
"insert use_package stackrel"
i = find_token(document.header, "\\use_package", 0)
if i == -1:
document.warning("Malformed LyX document: Can't find \\use_package.")
return;
j = find_token(document.preamble, "\\usepackage{stackrel}", 0)
if j == -1:
document.header.insert(i + 1, "\\use_package stackrel 0")
else:
document.header.insert(i + 1, "\\use_package stackrel 2")
del document.preamble[j]
def revert_use_stackrel(document):
"remove use_package stackrel"
regexp = re.compile(r'(\\use_package\s+stackrel)')
i = find_re(document.header, regexp, 0)
value = "1" # default is auto
if i != -1:
value = get_value(document.header, "\\use_package" , i).split()[1]
del document.header[i]
if value == "2": # on
add_to_preamble(document, ["\\usepackage{stackrel}"])
elif value == "1": # auto
regcmd = re.compile(r'.*\\stackrel\s*\[')
i = 0
while True:
i = find_token(document.body, '\\begin_inset Formula', i)
if i == -1:
return
j = find_end_of_inset(document.body, i)
if j == -1:
document.warning("Malformed LyX document: Can't find end of Formula inset at line " + str(i))
i += 1
continue
code = "\n".join(document.body[i:j])
if regcmd.match(code):
add_to_preamble(document, ["\\usepackage{stackrel}"])
return
i = j
def convert_cite_engine_type(document):
"Determine the \\cite_engine_type from the citation engine."
i = find_token(document.header, "\\cite_engine", 0)
@ -3022,10 +3065,12 @@ convert = [
[453, [convert_use_stmaryrd]],
[454, [convert_overprint]],
[455, []],
[456, [convert_epigraph]]
[456, [convert_epigraph]],
[457, [convert_use_stackrel]]
]
revert = [
[456, [revert_use_stackrel]],
[455, [revert_epigraph]],
[454, [revert_frametitle]],
[453, [revert_overprint]],

View File

@ -435,6 +435,8 @@ ToolbarSet
Item "bcancel" "math-insert \bcancel"
Item "xcancel" "math-insert \xcancel"
Item "cancelto" "math-insert \cancelto"
Item "stackrel" "math-insert \stackrel"
Item "stackrelthree" "math-insert \stackrelthree"
End
Toolbar "latex_arrow" "Arrows"

View File

@ -454,6 +454,7 @@ vector<string> const & BufferParams::auto_packages()
packages.push_back("mathdots");
packages.push_back("mathtools");
packages.push_back("mhchem");
packages.push_back("stackrel");
packages.push_back("stmaryrd");
packages.push_back("undertilde");
}

View File

@ -519,7 +519,7 @@ private:
typedef std::map<std::string, Package> PackageMap;
/** Whether and how to load packages like amsmath, esint, mhchem,
* mathdots and undertilde.
* mathdots, stackrel, stmaryrd and undertilde.
*/
PackageMap use_packages;

View File

@ -851,6 +851,10 @@ string const LaTeXFeatures::getPackages() const
params_.use_package("stmaryrd") != BufferParams::package_off)
packages << "\\usepackage{stmaryrd}\n";
if (mustProvide("stackrel") &&
params_.use_package("stackrel") != BufferParams::package_off)
packages << "\\usepackage{stackrel}\n";
if (mustProvide("undertilde") &&
params_.use_package("undertilde") != BufferParams::package_off)
packages << "\\usepackage{undertilde}\n";

View File

@ -156,6 +156,10 @@ char const * packages_gui[][4] =
N_("Use mhchem &package automatically"),
N_("Use mh&chem package"),
N_("The LaTeX package mhchem is only used if either the command \\ce or \\cf is inserted into formulas")},
{"stackrel",
N_("Use stackrel package automatically"),
N_("Use stackrel package"),
N_("The LaTeX package stackrel is only used if the command \\stackrel with subscript is inserted into formulas")},
{"stmaryrd",
N_("Use stmaryrd package automatically"),
N_("Use stmaryrd package"),

View File

@ -2099,6 +2099,7 @@ MathCompletionList::MathCompletionList(Cursor const & cur)
globals.push_back(from_ascii("\\root"));
globals.push_back(from_ascii("\\tabular"));
globals.push_back(from_ascii("\\stackrel"));
globals.push_back(from_ascii("\\stackrelthree"));
globals.push_back(from_ascii("\\binom"));
globals.push_back(from_ascii("\\choose"));
globals.push_back(from_ascii("\\brace"));

View File

@ -12,6 +12,7 @@
#include "InsetMathStackrel.h"
#include "Cursor.h"
#include "LaTeXFeatures.h"
#include "MathData.h"
#include "MathStream.h"
@ -20,7 +21,8 @@ using namespace std;
namespace lyx {
InsetMathStackrel::InsetMathStackrel(Buffer * buf) : InsetMathFracBase(buf)
InsetMathStackrel::InsetMathStackrel(Buffer * buf, bool sub)
: InsetMathFracBase(buf, sub ? 3 : 2)
{}
@ -30,6 +32,24 @@ Inset * InsetMathStackrel::clone() const
}
bool InsetMathStackrel::idxUpDown(Cursor & cur, bool up) const
{
if (up) {
if (cur.idx() == 0)
return false;
} else {
if (cur.idx() + 1 == nargs())
return false;
}
InsetMath::idx_type target = up ? cur.idx() - 1 : cur.idx() + 1;
if (cur.idx() == target)
return false;
cur.idx() = target;
cur.pos() = cell(target).x2pos(&cur.bv(), cur.x_target());
return true;
}
void InsetMathStackrel::metrics(MetricsInfo & mi, Dimension & dim) const
{
Dimension dim1;
@ -37,9 +57,17 @@ void InsetMathStackrel::metrics(MetricsInfo & mi, Dimension & dim) const
FracChanger dummy(mi.base);
Dimension dim0;
cell(0).metrics(mi, dim0);
dim.wid = max(dim0.width(), dim1.width()) + 4;
dim.asc = dim1.ascent() + dim0.height() + 4;
dim.des = dim1.descent();
if (nargs() > 2) {
Dimension dim2;
cell(2).metrics(mi, dim2);
dim.wid = max(max(dim0.width(), dim1.width()), dim2.width()) + 4;
dim.asc = dim1.ascent() + dim0.height() + 4;
dim.des = dim1.descent() + dim2.height() + dim2.descent() + 1;
} else {
dim.wid = max(dim0.width(), dim1.width()) + 4;
dim.asc = dim1.ascent() + dim0.height() + 4;
dim.des = dim1.descent();
}
metricsMarkers(dim);
}
@ -54,6 +82,11 @@ void InsetMathStackrel::draw(PainterInfo & pi, int x, int y) const
cell(1).draw(pi, m - dim1.width() / 2, y);
FracChanger dummy(pi.base);
cell(0).draw(pi, m - dim0.width() / 2, yo);
if (nargs() > 2) {
Dimension const & dim2 = cell(2).dimension(*pi.base.bv);
int y2 = y + dim1.descent() + dim2.ascent() + 1;
cell(2).draw(pi, m - dim2.width() / 2, y2);
}
drawMarkers(pi, x, y);
}
@ -61,40 +94,69 @@ void InsetMathStackrel::draw(PainterInfo & pi, int x, int y) const
void InsetMathStackrel::write(WriteStream & os) const
{
MathEnsurer ensurer(os);
os << "\\stackrel{" << cell(0) << "}{" << cell(1) << '}';
os << "\\stackrel";
if (nargs() > 2)
os << '[' << cell(2) << ']';
os << '{' << cell(0) << "}{" << cell(1) << '}';
}
void InsetMathStackrel::normalize(NormalStream & os) const
{
os << "[stackrel " << cell(0) << ' ' << cell(1) << ']';
os << "[stackrel " << cell(0) << ' ' << cell(1);
if (nargs() > 2)
os << ' ' << cell(2);
os << ']';
}
void InsetMathStackrel::mathmlize(MathStream & ms) const
{
ms << "<mover accent='false'>" << cell(1) << cell(0) << "</mover>";
if (nargs() > 2)
ms << "<munderover>" << cell(1) << cell(2) << cell(0) << "</munderover>";
else
ms << "<mover accent='false'>" << cell(1) << cell(0) << "</mover>";
}
void InsetMathStackrel::htmlize(HtmlStream & os) const
{
// at the moment, this is exactly the same as overset
os << MTag("span", "class='overset'")
<< MTag("span", "class='top'") << cell(0) << ETag("span")
<< MTag("span") << cell(1) << ETag("span")
<< ETag("span");
if (nargs() > 2) {
os << MTag("span", "class='underoverset'")
<< MTag("span", "class='top'") << cell(0) << ETag("span")
<< MTag("span") << cell(1) << ETag("span")
<< MTag("span", "class='bottom'") << cell(2) << ETag("span");
} else {
// at the moment, this is exactly the same as overset
os << MTag("span", "class='overset'")
<< MTag("span", "class='top'") << cell(0) << ETag("span")
<< MTag("span") << cell(1) << ETag("span");
}
os << ETag("span");
}
void InsetMathStackrel::validate(LaTeXFeatures & features) const
{
// from overset
if (features.runparams().math_flavor == OutputParams::MathAsHTML)
features.addCSSSnippet(
"span.overset{display: inline-block; vertical-align: bottom; text-align:center;}\n"
"span.overset span {display: block;}\n"
"span.top{font-size: 66%;}");
if (features.runparams().math_flavor == OutputParams::MathAsHTML) {
if (nargs() > 2) {
// FIXME: "vertical-align: middle" works only if the
// height of sub and super script is approximately equal.
features.addCSSSnippet(
"span.underoverset{display: inline-block; vertical-align: middle; text-align:center;}\n"
"span.underoverset span {display: block;}\n"
"span.bottom{font-size: 66%;}\n"
"span.top{font-size: 66%;}");
} else {
// from overset
features.addCSSSnippet(
"span.overset{display: inline-block; vertical-align: bottom; text-align:center;}\n"
"span.overset span {display: block;}\n"
"span.top{font-size: 66%;}");
}
}
if (nargs() > 2)
features.require("stackrel");
InsetMathNest::validate(features);
}

View File

@ -20,7 +20,9 @@ namespace lyx {
class InsetMathStackrel : public InsetMathFracBase {
public:
///
InsetMathStackrel(Buffer * buf);
InsetMathStackrel(Buffer * buf, bool sub);
///
bool idxUpDown(Cursor &, bool up) const;
///
void metrics(MetricsInfo & mi, Dimension & dim) const;
///

View File

@ -453,7 +453,10 @@ MathAtom createInsetMath(docstring const & s, Buffer * buf)
if (s == "tabular")
return MathAtom(new InsetMathTabular(buf, s, 1, 1));
if (s == "stackrel")
return MathAtom(new InsetMathStackrel(buf));
return MathAtom(new InsetMathStackrel(buf, false));
// This string value is only for math toolbar use, no LaTeX name
if (s == "stackrelthree")
return MathAtom(new InsetMathStackrel(buf, true));
if (s == "binom")
return MathAtom(new InsetMathBinom(buf, InsetMathBinom::BINOM));
if (s == "dbinom")

View File

@ -59,6 +59,7 @@ following hack as starting point to write some macros:
#include "InsetMathSpace.h"
#include "InsetMathSplit.h"
#include "InsetMathSqrt.h"
#include "InsetMathStackrel.h"
#include "InsetMathString.h"
#include "InsetMathTabular.h"
#include "MathMacroTemplate.h"
@ -1441,6 +1442,17 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
}
else if (t.cs() == "stackrel") {
// Here allowed formats are \stackrel[subscript]{superscript}{operator}
MathData ar;
parse(ar, FLAG_OPTION, mode);
cell->push_back(MathAtom(new InsetMathStackrel(buf, !ar.empty())));
if (!ar.empty())
cell->back().nucleus()->cell(2) = ar;
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, mode);
parse(cell->back().nucleus()->cell(1), FLAG_ITEM, mode);
}
else if (t.cs() == "xrightarrow" || t.cs() == "xleftarrow") {
cell->push_back(createInsetMath(t.cs(), buf));
parse(cell->back().nucleus()->cell(1), FLAG_OPTION, mode);

View File

@ -517,6 +517,7 @@ Preamble::Preamble() : one_language(true), title_layout_found(false)
h_use_packages["mhchem"] = "0";
h_use_packages["mathdots"] = "0";
h_use_packages["mathtools"] = "0";
h_use_packages["stackrel"] = "0";
h_use_packages["stmaryrd"] = "0";
h_use_packages["undertilde"] = "0";
}
@ -703,8 +704,8 @@ void Preamble::handle_package(Parser &p, string const & name,
else if (name == "amsmath" || name == "amssymb" ||
name == "esint" || name == "mhchem" || name == "mathdots" ||
name == "mathtools" || name == "stmaryrd" ||
name == "undertilde")
name == "mathtools" || name == "stackrel" ||
name == "stmaryrd" || name == "undertilde")
h_use_packages[name] = "2";
else if (name == "babel") {

View File

@ -97,6 +97,7 @@ Format LaTeX feature LyX feature
455 beamer frametitle command \begin_layout FrameTitle
\frametitle<overlay>[short}{long}
456 memoir: \epigraph{text}{source} layout Epigraph, InsetArgument
457 automatic stackrel loading \use_package stackrel
General

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass article
@ -46,6 +46,7 @@
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine basic

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass article
@ -44,6 +44,7 @@
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine natbib

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass article
@ -46,6 +46,7 @@
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine basic

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass article
@ -70,6 +70,7 @@
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine basic

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass article
@ -50,6 +50,7 @@
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine natbib

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass amsart
@ -42,6 +42,7 @@ theorems-ams
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine basic

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass article
@ -75,6 +75,7 @@ logicalmkup
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine basic

View File

@ -1,5 +1,5 @@
#LyX file created by tex2lyx 2.1.0dev
\lyxformat 456
\lyxformat 457
\begin_document
\begin_header
\textclass article
@ -46,6 +46,7 @@
\use_package mathdots 0
\use_package mathtools 0
\use_package mhchem 0
\use_package stackrel 0
\use_package stmaryrd 0
\use_package undertilde 0
\cite_engine basic

View File

@ -30,8 +30,8 @@ extern char const * const lyx_version_info;
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
#define LYX_FORMAT_LYX 456 // spitz: proper support for memoir epigraph
#define LYX_FORMAT_TEX2LYX 456 // spitz: proper support for memoir epigraph
#define LYX_FORMAT_LYX 457 // gb: automatic stackrel package loading
#define LYX_FORMAT_TEX2LYX 457 // gb: automatic stackrel package loading
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
#ifndef _MSC_VER