mirror of
https://git.lyx.org/repos/lyx.git
synced 2025-01-23 16:52:02 +00:00
699a6db9fa
These were all found by cppcheck. Even in constructors that are there "only because of std containers" the class should be initialized correctly. You can never know whether such an object does not get used, and then a nice crash caused by dereferencing a NULL-pointer is better than undefined behaviour.
295 lines
7.8 KiB
C++
295 lines
7.8 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/docstring.h"
|
|
#include "support/gettext.h"
|
|
#include "support/lassert.h"
|
|
#include "support/lstrings.h"
|
|
|
|
#include <ostream>
|
|
|
|
using namespace lyx::support;
|
|
|
|
using namespace std;
|
|
|
|
namespace lyx {
|
|
|
|
|
|
InsetMathDecoration::InsetMathDecoration(Buffer * buf, latexkeys const * key)
|
|
: InsetMathNest(buf, 1), key_(key), dh_(0), dy_(0), dw_(0)
|
|
{
|
|
// 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" && key_->name != "utilde";
|
|
}
|
|
|
|
|
|
bool InsetMathDecoration::isScriptable() const
|
|
{
|
|
return
|
|
key_->name == "overbrace" ||
|
|
key_->name == "underbrace";
|
|
}
|
|
|
|
|
|
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" ||
|
|
key_->name == "undertilde" ||
|
|
key_->name == "utilde";
|
|
}
|
|
|
|
|
|
InsetMath::mode_type InsetMathDecoration::currentMode() const
|
|
{
|
|
return key_->name == "underbar" ? TEXT_MODE : MATH_MODE;
|
|
}
|
|
|
|
|
|
void InsetMathDecoration::metrics(MetricsInfo & mi, Dimension & dim) const
|
|
{
|
|
bool really_change_font = currentMode() == TEXT_MODE
|
|
&& isMathFont(from_ascii(mi.base.fontname));
|
|
FontSetChanger dummy(mi.base, "textnormal", really_change_font);
|
|
|
|
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
|
|
{
|
|
bool really_change_font = currentMode() == TEXT_MODE
|
|
&& isMathFont(from_ascii(pi.base.fontname));
|
|
FontSetChanger dummy(pi.base, "textnormal", really_change_font);
|
|
|
|
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 << bformat(_("Decoration: %1$s"), key_->name);
|
|
}
|
|
|
|
|
|
namespace {
|
|
struct Attributes {
|
|
Attributes() {}
|
|
Attributes(bool o, string t)
|
|
: over(o), tag(t) {}
|
|
bool over;
|
|
string tag;
|
|
};
|
|
|
|
typedef map<string, Attributes> TranslationMap;
|
|
|
|
void buildTranslationMap(TranslationMap & 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["undertilde"] = Attributes(false, "∼");
|
|
t["utilde"] = Attributes(false, "∼");
|
|
t["vec"] = Attributes(true, "→");
|
|
t["widehat"] = Attributes(true, "^");
|
|
t["widetilde"] = Attributes(true, "∼");
|
|
}
|
|
|
|
TranslationMap const & translationMap() {
|
|
static TranslationMap t;
|
|
if (t.empty())
|
|
buildTranslationMap(t);
|
|
return t;
|
|
}
|
|
}
|
|
|
|
void InsetMathDecoration::mathmlize(MathStream & os) const
|
|
{
|
|
TranslationMap const & t = translationMap();
|
|
TranslationMap::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;
|
|
}
|
|
|
|
TranslationMap const & t = translationMap();
|
|
TranslationMap::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.addCSSSnippet("span.overbar{border-top: thin black solid;}");
|
|
} else if (name == "underbar" || name == "underline") {
|
|
features.addCSSSnippet("span.underbar{border-bottom: thin black solid;}");
|
|
} else {
|
|
features.addCSSSnippet(
|
|
"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;}");
|
|
}
|
|
} else {
|
|
if (!key_->requires.empty())
|
|
features.require(key_->requires);
|
|
}
|
|
InsetMathNest::validate(features);
|
|
}
|
|
|
|
} // namespace lyx
|