mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-16 16:18:22 +00:00
a0043da05f
I'm not happy about having what is basically the same enum in BufferParams.h and OutputParams.h, but I don't see how to unify them without either (a) including BufferParams.h in OutputParams.h, which is ugly or (b) creating some new file just containing this enum, which seems like overkill. Any other ideas? git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@33967 a592a061-630c-0410-9148-cb99ea01b6c8
295 lines
7.6 KiB
C++
295 lines
7.6 KiB
C++
/**
|
|
* \file InsetMathDecoration.cpp
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author Alejandro Aguilar Sierra
|
|
* \author André Pönitz
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "InsetMathDecoration.h"
|
|
|
|
#include "MathData.h"
|
|
#include "MathParser.h"
|
|
#include "MathSupport.h"
|
|
#include "MathStream.h"
|
|
#include "MetricsInfo.h"
|
|
|
|
#include "LaTeXFeatures.h"
|
|
|
|
#include "support/debug.h"
|
|
#include "support/lassert.h"
|
|
|
|
#include <ostream>
|
|
|
|
using namespace std;
|
|
|
|
namespace lyx {
|
|
|
|
|
|
InsetMathDecoration::InsetMathDecoration(Buffer * buf, latexkeys const * key)
|
|
: InsetMathNest(buf, 1), key_(key)
|
|
{
|
|
// lyxerr << " creating deco " << key->name << endl;
|
|
}
|
|
|
|
|
|
Inset * InsetMathDecoration::clone() const
|
|
{
|
|
return new InsetMathDecoration(*this);
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::upper() const
|
|
{
|
|
return key_->name.substr(0, 5) != "under";
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::isScriptable() const
|
|
{
|
|
return
|
|
key_->name == "overbrace" ||
|
|
key_->name == "underbrace" ||
|
|
key_->name == "overleftarrow" ||
|
|
key_->name == "overrightarrow" ||
|
|
key_->name == "overleftrightarrow" ||
|
|
key_->name == "underleftarrow" ||
|
|
key_->name == "underrightarrow" ||
|
|
key_->name == "underleftrightarrow";
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::protect() const
|
|
{
|
|
return
|
|
key_->name == "overbrace" ||
|
|
key_->name == "underbrace" ||
|
|
key_->name == "overleftarrow" ||
|
|
key_->name == "overrightarrow" ||
|
|
key_->name == "overleftrightarrow" ||
|
|
key_->name == "underleftarrow" ||
|
|
key_->name == "underrightarrow" ||
|
|
key_->name == "underleftrightarrow";
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::wide() const
|
|
{
|
|
return
|
|
key_->name == "overline" ||
|
|
key_->name == "underline" ||
|
|
key_->name == "overbrace" ||
|
|
key_->name == "underbrace" ||
|
|
key_->name == "overleftarrow" ||
|
|
key_->name == "overrightarrow" ||
|
|
key_->name == "overleftrightarrow" ||
|
|
key_->name == "widehat" ||
|
|
key_->name == "widetilde" ||
|
|
key_->name == "underleftarrow" ||
|
|
key_->name == "underrightarrow" ||
|
|
key_->name == "underleftrightarrow";
|
|
}
|
|
|
|
|
|
InsetMath::mode_type InsetMathDecoration::currentMode() const
|
|
{
|
|
return key_->name == "underbar" ? TEXT_MODE : MATH_MODE;
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
|
|
{
|
|
FontSetChanger dummy(mi.base, currentMode() == TEXT_MODE ?
|
|
"textnormal" : "mathnormal");
|
|
|
|
cell(0).metrics(mi, dim);
|
|
|
|
dh_ = 6; //mathed_char_height(LM_TC_VAR, mi, 'I', ascent_, descent_);
|
|
dw_ = 6; //mathed_char_width(LM_TC_VAR, mi, 'x');
|
|
|
|
if (upper()) {
|
|
dy_ = -dim.asc - dh_;
|
|
dim.asc += dh_ + 1;
|
|
} else {
|
|
dy_ = dim.des + 1;
|
|
dim.des += dh_ + 2;
|
|
}
|
|
|
|
metricsMarkers(dim);
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::draw(PainterInfo & pi, int x, int y) const
|
|
{
|
|
FontSetChanger dummy(pi.base, currentMode() == TEXT_MODE ?
|
|
"textnormal" : "mathnormal");
|
|
|
|
cell(0).draw(pi, x + 1, y);
|
|
Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
|
|
if (wide())
|
|
mathed_draw_deco(pi, x + 1, y + dy_, dim0.wid, dh_, key_->name);
|
|
else
|
|
mathed_draw_deco(pi, x + 1 + (dim0.wid - dw_) / 2,
|
|
y + dy_, dw_, dh_, key_->name);
|
|
drawMarkers(pi, x, y);
|
|
setPosCache(pi, x, y);
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::write(WriteStream & os) const
|
|
{
|
|
MathEnsurer ensurer(os);
|
|
if (os.fragile() && protect())
|
|
os << "\\protect";
|
|
os << '\\' << key_->name << '{';
|
|
ModeSpecifier specifier(os, currentMode());
|
|
os << cell(0) << '}';
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::normalize(NormalStream & os) const
|
|
{
|
|
os << "[deco " << key_->name << ' ' << cell(0) << ']';
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::infoize(odocstream & os) const
|
|
{
|
|
os << "Deco: " << key_->name;
|
|
}
|
|
|
|
|
|
namespace {
|
|
struct Attributes {
|
|
Attributes() {}
|
|
Attributes(bool o, string t)
|
|
: over(o), tag(t) {}
|
|
bool over;
|
|
string tag;
|
|
};
|
|
|
|
typedef map<string, Attributes> Translator;
|
|
|
|
void buildTranslator(Translator & t) {
|
|
// the decorations we need to support are listed in lib/symbols
|
|
t["acute"] = Attributes(true, "´");
|
|
t["bar"] = Attributes(true, "‾");
|
|
t["breve"] = Attributes(true, "˘");
|
|
t["check"] = Attributes(true, "ˇ");
|
|
t["ddddot"] = Attributes(true, "⃜");
|
|
t["dddot"] = Attributes(true, "⃛");
|
|
t["ddot"] = Attributes(true, "¨");
|
|
t["dot"] = Attributes(true, "˙");
|
|
t["grave"] = Attributes(true, "`");
|
|
t["hat"] = Attributes(true, "ˆ");
|
|
t["mathring"] = Attributes(true, "˚");
|
|
t["overbrace"] = Attributes(true, "⏞");
|
|
t["overleftarrow"] = Attributes(true, "⟵");
|
|
t["overleftrightarrow"] = Attributes(true, "⟷");
|
|
t["overline"] = Attributes(true, "¯");
|
|
t["overrightarrow"] = Attributes(true, "⟶");
|
|
t["tilde"] = Attributes(true, "˜");
|
|
t["underbar"] = Attributes(false, "_");
|
|
t["underbrace"] = Attributes(false, "⏟");
|
|
t["underleftarrow"] = Attributes(false, "⟵");
|
|
t["underleftrightarrow"] = Attributes(false, "⟷");
|
|
// this is the macron, again, but it works
|
|
t["underline"] = Attributes(false, "¯");
|
|
t["underrightarrow"] = Attributes(false, "⟶");
|
|
t["vec"] = Attributes(true, "→");
|
|
t["widehat"] = Attributes(true, "^");
|
|
t["widetilde"] = Attributes(true, "∼");
|
|
}
|
|
|
|
Translator const & translator() {
|
|
static Translator t;
|
|
if (t.empty())
|
|
buildTranslator(t);
|
|
return t;
|
|
}
|
|
}
|
|
|
|
void InsetMathDecoration::mathmlize(MathStream & os) const
|
|
{
|
|
Translator const & t = translator();
|
|
Translator::const_iterator cur = t.find(to_utf8(key_->name));
|
|
LASSERT(cur != t.end(), return);
|
|
char const * const outag = cur->second.over ? "mover" : "munder";
|
|
os << MTag(outag)
|
|
<< MTag("mrow") << cell(0) << ETag("mrow")
|
|
<< from_ascii("<mo stretchy=\"true\">" + cur->second.tag + "</mo>")
|
|
<< ETag(outag);
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::htmlize(HtmlStream & os) const
|
|
{
|
|
string const name = to_utf8(key_->name);
|
|
if (name == "bar") {
|
|
os << MTag("span", "class='overbar'") << cell(0) << ETag("span");
|
|
return;
|
|
}
|
|
|
|
if (name == "underbar" || name == "underline") {
|
|
os << MTag("span", "class='underbar'") << cell(0) << ETag("span");
|
|
return;
|
|
}
|
|
|
|
Translator const & t = translator();
|
|
Translator::const_iterator cur = t.find(name);
|
|
LASSERT(cur != t.end(), return);
|
|
|
|
bool symontop = cur->second.over;
|
|
string const symclass = symontop ? "symontop" : "symonbot";
|
|
os << MTag("span", "class='symbolpair " + symclass + "'")
|
|
<< '\n';
|
|
|
|
if (symontop)
|
|
os << MTag("span", "class='symbol'") << from_ascii(cur->second.tag);
|
|
else
|
|
os << MTag("span", "class='base'") << cell(0);
|
|
os << ETag("span") << '\n';
|
|
if (symontop)
|
|
os << MTag("span", "class='base'") << cell(0);
|
|
else
|
|
os << MTag("span", "class='symbol'") << from_ascii(cur->second.tag);
|
|
os << ETag("span") << '\n' << ETag("span") << '\n';
|
|
}
|
|
|
|
|
|
// ideas borrowed from the eLyXer code
|
|
void InsetMathDecoration::validate(LaTeXFeatures & features) const
|
|
{
|
|
if (features.runparams().math_flavor == OutputParams::MathAsHTML) {
|
|
string const name = to_utf8(key_->name);
|
|
if (name == "bar") {
|
|
features.addPreambleSnippet("<style type=\"text/css\">\n"
|
|
"span.overbar{border-top: thin black solid;}\n"
|
|
"</style>");
|
|
} else if (name == "underbar" || name == "underline") {
|
|
features.addPreambleSnippet("<style type=\"text/css\">\n"
|
|
"span.underbar{border-bottom: thin black solid;}\n"
|
|
"</style>");
|
|
} else {
|
|
features.addPreambleSnippet("<style type=\"text/css\">\n"
|
|
"span.symbolpair{display: inline-block; text-align:center;}\n"
|
|
"span.symontop{vertical-align: top;}\n"
|
|
"span.symonbot{vertical-align: bottom;}\n"
|
|
"span.symbolpair span{display: block;}\n"
|
|
"span.symbol{height: 0.5ex;}\n"
|
|
"</style>");
|
|
}
|
|
} else {
|
|
if (!key_->requires.empty())
|
|
features.require(to_utf8(key_->requires));
|
|
}
|
|
InsetMathNest::validate(features);
|
|
}
|
|
|
|
} // namespace lyx
|