Fix html export of \ne (second part of bug #9372)

The fix consists of two parts: The needed infrastructure to assign HTML
entities to global math macros, and the actual fix for \ne and \neq.
This commit is contained in:
Georg Baum 2014-12-29 21:13:42 +01:00
parent a88e6e1ea5
commit cc87f81002
9 changed files with 195 additions and 126 deletions

View File

@ -1124,8 +1124,8 @@ pod lyxblacktext 0 0 func x amsmath
# pre-defined macros # pre-defined macros
# #
\def\neq{\not=} \def\neq{\not=} mathrel ≠
\def\ne{\not=} \def\ne{\not=} mathrel ≠
\def\notin{\not\in} \def\notin{\not\in}
\def\slash{/} \def\slash{/}

View File

@ -1636,9 +1636,8 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
} }
// do not finish macro for known * commands // do not finish macro for known * commands
MathWordList const & mwl = mathedWordList();
bool star_macro = c == '*' bool star_macro = c == '*'
&& (mwl.find(name.substr(1) + "*") != mwl.end() && (in_word_set(name.substr(1) + '*')
|| cur.buffer()->getMacro(name.substr(1) + "*", cur, true)); || cur.buffer()->getMacro(name.substr(1) + "*", cur, true));
if (isAlphaASCII(c) || star_macro) { if (isAlphaASCII(c) || star_macro) {
cur.activeMacro()->setName(name + docstring(1, c)); cur.activeMacro()->setName(name + docstring(1, c));
@ -2197,8 +2196,11 @@ MathCompletionList::MathCompletionList(Cursor const & cur)
MathWordList::const_iterator it2; MathWordList::const_iterator it2;
//lyxerr << "Globals completion commands: "; //lyxerr << "Globals completion commands: ";
for (it2 = words.begin(); it2 != words.end(); ++it2) { for (it2 = words.begin(); it2 != words.end(); ++it2) {
globals.push_back("\\" + (*it2).first); if (it2->second.inset != "macro") {
//lyxerr << "\\" + (*it2).first << " "; // macros are already read from MacroTable::globalMacros()
globals.push_back('\\' + it2->first);
//lyxerr << '\\' + it2->first << ' ';
}
} }
//lyxerr << std::endl; //lyxerr << std::endl;
sort(globals.begin(), globals.end()); sort(globals.begin(), globals.end());

View File

@ -186,20 +186,11 @@ void InsetMathSymbol::mathematica(MathematicaStream & os) const
} }
// FIXME This will likely need some work.
char const * MathMLtype(docstring const & s)
{
if (s == "mathord")
return "mi";
return "mo";
}
void InsetMathSymbol::mathmlize(MathStream & os) const void InsetMathSymbol::mathmlize(MathStream & os) const
{ {
// FIXME We may need to do more interesting things // FIXME We may need to do more interesting things
// with MathMLtype. // with MathMLtype.
char const * type = MathMLtype(sym_->extra); char const * type = sym_->MathMLtype();
os << '<' << type << "> "; os << '<' << type << "> ";
if (sym_->xmlname == "x") if (sym_->xmlname == "x")
// unknown so far // unknown so far
@ -214,7 +205,7 @@ void InsetMathSymbol::htmlize(HtmlStream & os, bool spacing) const
{ {
// FIXME We may need to do more interesting things // FIXME We may need to do more interesting things
// with MathMLtype. // with MathMLtype.
char const * type = MathMLtype(sym_->extra); char const * type = sym_->MathMLtype();
bool op = (std::string(type) == "mo"); bool op = (std::string(type) == "mo");
if (sym_->xmlname == "x") if (sym_->xmlname == "x")

View File

@ -14,6 +14,7 @@
#include "MacroTable.h" #include "MacroTable.h"
#include "MathMacroTemplate.h" #include "MathMacroTemplate.h"
#include "MathMacroArgument.h" #include "MathMacroArgument.h"
#include "MathParser.h"
#include "MathStream.h" #include "MathStream.h"
#include "MathSupport.h" #include "MathSupport.h"
#include "InsetMathNest.h" #include "InsetMathNest.h"
@ -41,13 +42,13 @@ namespace lyx {
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
MacroData::MacroData(Buffer * buf) MacroData::MacroData(Buffer * buf)
: buffer_(buf), queried_(true), numargs_(0), optionals_(0), lockCount_(0), : buffer_(buf), queried_(true), numargs_(0), sym_(0), optionals_(0),
redefinition_(false), type_(MacroTypeNewcommand) lockCount_(0), redefinition_(false), type_(MacroTypeNewcommand)
{} {}
MacroData::MacroData(Buffer * buf, DocIterator const & pos) MacroData::MacroData(Buffer * buf, DocIterator const & pos)
: buffer_(buf), pos_(pos), queried_(false), numargs_(0), : buffer_(buf), pos_(pos), queried_(false), numargs_(0), sym_(0),
optionals_(0), lockCount_(0), redefinition_(false), optionals_(0), lockCount_(0), redefinition_(false),
type_(MacroTypeNewcommand) type_(MacroTypeNewcommand)
{ {
@ -55,8 +56,8 @@ MacroData::MacroData(Buffer * buf, DocIterator const & pos)
MacroData::MacroData(Buffer * buf, MathMacroTemplate const & macro) MacroData::MacroData(Buffer * buf, MathMacroTemplate const & macro)
: buffer_(buf), queried_(false), numargs_(0), optionals_(0), lockCount_(0), : buffer_(buf), queried_(false), numargs_(0), sym_(0), optionals_(0),
redefinition_(false), type_(MacroTypeNewcommand) lockCount_(0), redefinition_(false), type_(MacroTypeNewcommand)
{ {
queryData(macro); queryData(macro);
} }
@ -110,6 +111,14 @@ vector<docstring> const & MacroData::defaults() const
} }
string const MacroData::requires() const
{
if (sym_)
return to_utf8(sym_->requires);
return string();
}
void MacroData::unlock() const void MacroData::unlock() const
{ {
--lockCount_; --lockCount_;
@ -210,12 +219,11 @@ MacroTable::insert(docstring const & name, MacroData const & data)
MacroTable::iterator MacroTable::iterator
MacroTable::insert(Buffer * buf, docstring const & def, string const & requires) MacroTable::insert(Buffer * buf, docstring const & def)
{ {
//lyxerr << "MacroTable::insert, def: " << to_utf8(def) << endl; //lyxerr << "MacroTable::insert, def: " << to_utf8(def) << endl;
MathMacroTemplate mac(buf, def); MathMacroTemplate mac(buf, def);
MacroData data(buf, mac); MacroData data(buf, mac);
data.requires() = requires;
return insert(mac.name(), data); return insert(mac.name(), data);
} }

View File

@ -27,6 +27,7 @@ class Buffer;
class MathData; class MathData;
class MathMacroTemplate; class MathMacroTemplate;
class Paragraph; class Paragraph;
class latexkeys;
enum MacroType { enum MacroType {
MacroTypeNewcommand, MacroTypeNewcommand,
@ -59,9 +60,9 @@ public:
/// ///
std::vector<docstring> const & defaults() const; std::vector<docstring> const & defaults() const;
/// ///
std::string const & requires() const { return requires_; } std::string const requires() const;
/// ///
std::string & requires() { return requires_; } void setSymbol(latexkeys const * sym) { sym_ = sym; }
/// lock while being drawn to avoid recursions /// lock while being drawn to avoid recursions
int lock() const { return ++lockCount_; } int lock() const { return ++lockCount_; }
@ -86,7 +87,7 @@ public:
return definition_ == x.definition_ return definition_ == x.definition_
&& numargs_ == x.numargs_ && numargs_ == x.numargs_
&& display_ == x.display_ && display_ == x.display_
&& requires_ == x.requires_ && sym_ == x.sym_
&& optionals_ == x.optionals_ && optionals_ == x.optionals_
&& defaults_ == x.defaults_; && defaults_ == x.defaults_;
} }
@ -118,7 +119,7 @@ private:
/// ///
mutable docstring display_; mutable docstring display_;
/// ///
std::string requires_; latexkeys const * sym_;
/// ///
mutable size_t optionals_; mutable size_t optionals_;
/// ///
@ -149,7 +150,7 @@ class MacroTable : public std::map<docstring, MacroData>
{ {
public: public:
/// Parse full "\\def..." or "\\newcommand..." or ... /// Parse full "\\def..." or "\\newcommand..." or ...
iterator insert(Buffer * buf, docstring const & definition, std::string const &); iterator insert(Buffer * buf, docstring const & definition);
/// Insert pre-digested macro definition /// Insert pre-digested macro definition
iterator insert(docstring const & name, MacroData const & data); iterator insert(docstring const & name, MacroData const & data);
/// ///

View File

@ -175,18 +175,50 @@ void initSymbols()
// special case of pre-defined macros // special case of pre-defined macros
if (line.size() > 8 && line.substr(0, 5) == "\\def\\") { if (line.size() > 8 && line.substr(0, 5) == "\\def\\") {
//lyxerr << "macro definition: '" << line << '\'' << endl; //lyxerr << "macro definition: '" << line << '\'' << endl;
// syntax: Either
// \def\macroname{definition}
// or
// \def\macroname{definition} requires
// or
// \def\macroname{definition} extra xmlname requires
istringstream is(line); istringstream is(line);
string macro; string macro;
string requires; string requires;
string extra;
string xmlname;
is >> macro >> requires; is >> macro >> requires;
if ((is >> xmlname)) {
extra = requires;
if (!(is >> requires))
requires = "";
} else
xmlname = "";
MacroTable::iterator it = MacroTable::globalMacros().insert( MacroTable::iterator it = MacroTable::globalMacros().insert(
0, from_utf8(macro), requires); 0, from_utf8(macro));
if (!extra.empty() || !xmlname.empty() || !requires.empty()) {
MathWordList::iterator wit = theMathWordList.find(it->first);
if (wit != theMathWordList.end())
LYXERR(Debug::MATHED, "readSymbols: inset "
<< to_utf8(it->first) << " already exists.");
else {
latexkeys tmp;
tmp.inset = from_ascii("macro");
tmp.name = it->first;
tmp.extra = from_utf8(extra);
tmp.xmlname = from_utf8(xmlname);
tmp.requires = from_utf8(requires);
theMathWordList[it->first] = tmp;
wit = theMathWordList.find(it->first);
it->second.setSymbol(&(wit->second));
}
}
// If you change the following output, please adjust // If you change the following output, please adjust
// development/tools/generate_symbols_images.py. // development/tools/generate_symbols_images.py.
LYXERR(Debug::MATHED, "read symbol '" << to_utf8(it->first) LYXERR(Debug::MATHED, "read symbol '" << to_utf8(it->first)
<< " inset: macro" << " inset: macro"
<< " draw: 0" << " draw: 0"
<< " extra: " << " extra: " << extra
<< " xml: " << xmlname
<< " requires: " << requires << '\''); << " requires: " << requires << '\'');
continue; continue;
} }
@ -270,6 +302,7 @@ void initSymbols()
<< " inset: " << to_utf8(tmp.inset) << " inset: " << to_utf8(tmp.inset)
<< " draw: " << int(tmp.draw.empty() ? 0 : tmp.draw[0]) << " draw: " << int(tmp.draw.empty() ? 0 : tmp.draw[0])
<< " extra: " << to_utf8(tmp.extra) << " extra: " << to_utf8(tmp.extra)
<< " xml: " << to_utf8(tmp.xmlname)
<< " requires: " << to_utf8(tmp.requires) << '\''); << " requires: " << to_utf8(tmp.requires) << '\'');
} }
docstring tmp = from_ascii("cmm"); docstring tmp = from_ascii("cmm");
@ -354,7 +387,11 @@ int ensureMode(WriteStream & os, InsetMath::mode_type mode,
latexkeys const * in_word_set(docstring const & str) latexkeys const * in_word_set(docstring const & str)
{ {
MathWordList::iterator it = theMathWordList.find(str); MathWordList::iterator it = theMathWordList.find(str);
return it != theMathWordList.end() ? &(it->second) : 0; if (it == theMathWordList.end())
return 0;
if (it->second.inset == "macro")
return 0;
return &(it->second);
} }

View File

@ -288,7 +288,6 @@ void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
dim.asc += 1 + namedim.height() + 1; dim.asc += 1 + namedim.height() + 1;
dim.des += 2; dim.des += 2;
} }
} }
} }
@ -794,6 +793,17 @@ void MathMacro::maple(MapleStream & os) const
void MathMacro::mathmlize(MathStream & os) const void MathMacro::mathmlize(MathStream & os) const
{ {
MathWordList const & words = mathedWordList();
MathWordList::const_iterator it = words.find(name());
if (it != words.end()) {
docstring const xmlname = it->second.xmlname;
if (!xmlname.empty()) {
char const * type = it->second.MathMLtype();
os << '<' << type << "> " << xmlname << " /<"
<< type << '>';
return;
}
}
MathData const & data = expanded_.cell(0); MathData const & data = expanded_.cell(0);
if (data.empty()) { if (data.empty()) {
// this means that we do not recognize the macro // this means that we do not recognize the macro
@ -805,6 +815,15 @@ void MathMacro::mathmlize(MathStream & os) const
void MathMacro::htmlize(HtmlStream & os) const void MathMacro::htmlize(HtmlStream & os) const
{ {
MathWordList const & words = mathedWordList();
MathWordList::const_iterator it = words.find(name());
if (it != words.end()) {
docstring const xmlname = it->second.xmlname;
if (!xmlname.empty()) {
os << ' ' << xmlname << ' ';
return;
}
}
MathData const & data = expanded_.cell(0); MathData const & data = expanded_.cell(0);
if (data.empty()) { if (data.empty()) {
// this means that we do not recognize the macro // this means that we do not recognize the macro

View File

@ -2155,6 +2155,15 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
} // anonymous namespace } // anonymous namespace
// FIXME This will likely need some work.
char const * latexkeys::MathMLtype() const
{
if (extra == "mathord")
return "mi";
return "mo";
}
bool mathed_parse_cell(MathData & ar, docstring const & str, Parse::flags f) bool mathed_parse_cell(MathData & ar, docstring const & str, Parse::flags f)
{ {
return Parser(str, f, ar.buffer()).parse(ar, 0, f & Parse::TEXTMODE ? return Parser(str, f, ar.buffer()).parse(ar, 0, f & Parse::TEXTMODE ?

View File

@ -30,6 +30,8 @@ class Lexer;
/// ///
class latexkeys { class latexkeys {
public: public:
///
char const * MathMLtype() const;
/// name of the macro or primitive /// name of the macro or primitive
docstring name; docstring name;
/// name of a inset that handles that macro /// name of a inset that handles that macro