Fix bug 5393

http://bugzilla.lyx.org/show_bug.cgi?id=5393


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@27044 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Enrico Forestieri 2008-10-23 00:48:06 +00:00
parent bcf3db2dd5
commit 7d4ec3f944
10 changed files with 267 additions and 18 deletions

View File

@ -462,6 +462,7 @@ src_mathed_header_files = Split('''
InsetMathScript.h
InsetMathSize.h
InsetMathSpace.h
InsetMathSpecialChar.h
InsetMathSplit.h
InsetMathSqrt.h
InsetMathStackrel.h
@ -533,6 +534,7 @@ src_mathed_files = Split('''
InsetMathScript.cpp
InsetMathSize.cpp
InsetMathSpace.cpp
InsetMathSpecialChar.cpp
InsetMathSplit.cpp
InsetMathSqrt.cpp
InsetMathStackrel.cpp

View File

@ -865,14 +865,6 @@ gcd lyxblacktext 0 0 funclim x
deg lyxblacktext 0 0 func x
bmod lyxblacktext 0 0 func x
{ mathrm 0 0 special x
} mathrm 0 0 special x
$ mathrm 0 0 special x
% mathrm 0 0 special x
& mathrm 0 0 special x
## don't remove the space from the beginning of the next line
# mathrm 0 0 special x
#
@ -912,7 +904,6 @@ endif
iffont msb
\def\Join{\ltimes\kern-18.5mu\rtimes}
endif
\def\mathcircumflex{\mbox{\^{}}}{\^}
# Fixme: latin-1 chars in text file
\def\AA{\AA}{Å}
\def\O{\O}{Ø}

View File

@ -361,6 +361,7 @@ SOURCEFILESMATHED = \
mathed/InsetMathScript.cpp \
mathed/InsetMathSize.cpp \
mathed/InsetMathSpace.cpp \
mathed/InsetMathSpecialChar.cpp \
mathed/InsetMathSplit.cpp \
mathed/InsetMathSqrt.cpp \
mathed/InsetMathStackrel.cpp \
@ -425,6 +426,7 @@ HEADERFILESMATHED = \
mathed/InsetMathScript.h \
mathed/InsetMathSize.h \
mathed/InsetMathSpace.h \
mathed/InsetMathSpecialChar.h \
mathed/InsetMathSplit.h \
mathed/InsetMathSqrt.h \
mathed/InsetMathStackrel.h \

View File

@ -66,6 +66,7 @@ class InsetMathNest;
class InsetMathScript;
class InsetMathString;
class InsetMathSpace;
class InsetMathSpecialChar;
class InsetMathSymbol;
class InsetMathUnknown;
@ -142,6 +143,7 @@ public:
virtual InsetMathUnknown * asUnknownInset() { return 0; }
virtual InsetMathUnknown const * asUnknownInset() const { return 0; }
virtual InsetMathRef * asRefInset() { return 0; }
virtual InsetMathSpecialChar const * asSpecialCharInset() const { return 0; }
/// identifies things that can get scripts
virtual bool isScriptable() const { return false; }

View File

@ -1435,6 +1435,9 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type c)
cur.niceInsert(createInsetMath("textbackslash"));
else
cur.niceInsert(createInsetMath("backslash"));
} else if (c == '^' && currentMode() == InsetMath::MATH_MODE) {
cur.backspace();
cur.niceInsert(createInsetMath("mathcircumflex"));
} else if (c == '{') {
cur.backspace();
cur.niceInsert(MathAtom(new InsetMathBrace));
@ -1564,7 +1567,7 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type c)
return cur.pos() != cur.lastpos();
}
// These shouldn't work in text mode:
// These should be treated differently when not in text mode:
if (currentMode() != InsetMath::TEXT_MODE) {
if (c == '_') {
script(cur, false, save_selection);
@ -1578,10 +1581,19 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type c)
cur.niceInsert(createInsetMath("sim"));
return true;
}
} else {
if (c == '^') {
cur.niceInsert(createInsetMath("textasciicircum"));
return true;
}
if (c == '~') {
cur.niceInsert(createInsetMath("textasciitilde"));
return true;
}
}
if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' ||
c == '%' || c == '_' || c == '^') {
c == '%' || c == '_') {
cur.niceInsert(createInsetMath(docstring(1, c)));
return true;
}

View File

@ -0,0 +1,148 @@
/**
* \file InsetMathSpecialChar.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Enrico Forestieri
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetMathSpecialChar.h"
#include "MathSupport.h"
#include "MathStream.h"
#include "MetricsInfo.h"
#include "Dimension.h"
#include "LaTeXFeatures.h"
#include "TextPainter.h"
#include "frontends/FontMetrics.h"
#include "support/lassert.h"
namespace lyx {
InsetMathSpecialChar::InsetMathSpecialChar(docstring name)
: name_(name), kerning_(0)
{
if (name.size() != 1) {
if (name == from_ascii("textasciicircum")
|| name == from_ascii("mathcircumflex"))
char_ = '^';
else if (name == from_ascii("textasciitilde"))
char_ = '~';
else if (name == from_ascii("textbackslash"))
char_ = '\\';
else
LASSERT(false, /**/);
} else
char_ = name.at(0);
}
Inset * InsetMathSpecialChar::clone() const
{
return new InsetMathSpecialChar(*this);
}
void InsetMathSpecialChar::metrics(MetricsInfo & mi, Dimension & dim) const
{
if (mi.base.fontname == "mathnormal") {
ShapeChanger dummy(mi.base.font, UP_SHAPE);
dim = theFontMetrics(mi.base.font).dimension(char_);
} else {
frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
dim = fm.dimension(char_);
kerning_ = fm.rbearing(char_) - dim.wid;
}
}
void InsetMathSpecialChar::draw(PainterInfo & pi, int x, int y) const
{
if (pi.base.fontname == "mathnormal") {
ShapeChanger dummy(pi.base.font, UP_SHAPE);
pi.draw(x, y, char_);
} else {
pi.draw(x, y, char_);
}
}
void InsetMathSpecialChar::metricsT(TextMetricsInfo const &, Dimension & dim) const
{
dim.wid = 1;
dim.asc = 1;
dim.des = 0;
}
void InsetMathSpecialChar::drawT(TextPainter & pain, int x, int y) const
{
pain.draw(x, y, char_);
}
void InsetMathSpecialChar::write(WriteStream & os) const
{
os << '\\' << name_;
if (name_.size() != 1)
os.pendingSpace(true);
}
void InsetMathSpecialChar::validate(LaTeXFeatures & features) const
{
if (name_ == "mathcircumflex")
features.require("mathcircumflex");
}
void InsetMathSpecialChar::normalize(NormalStream & os) const
{
os << "[char ";
os.os().put(char_);
os << " mathalpha]";
}
void InsetMathSpecialChar::maple(MapleStream & os) const
{
os.os().put(char_);
}
void InsetMathSpecialChar::mathematica(MathematicaStream & os) const
{
os.os().put(char_);
}
void InsetMathSpecialChar::octave(OctaveStream & os) const
{
os.os().put(char_);
}
void InsetMathSpecialChar::mathmlize(MathStream & ms) const
{
switch (char_) {
case '&':
ms << "&amp;";
break;
default:
ms.os().put(char_);
break;
}
}
} // namespace lyx

View File

@ -0,0 +1,69 @@
// -*- C++ -*-
/**
* \file InsetMathSpecialChar.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Enrico Forestieri
*
* Full author contact details are available in file CREDITS.
*/
#ifndef MATH_SPECIALCHARINSET_H
#define MATH_SPECIALCHARINSET_H
#include "InsetMath.h"
namespace lyx {
/// The special character inset.
class InsetMathSpecialChar : public InsetMath {
public:
///
explicit InsetMathSpecialChar(docstring name);
///
void setBuffer(Buffer &) {}
///
void metrics(MetricsInfo & mi, Dimension & dim) const;
///
void draw(PainterInfo & pi, int x, int y) const;
///
void metricsT(TextMetricsInfo const & mi, Dimension & dim) const;
///
void drawT(TextPainter &, int x, int y) const;
///
int kerning(BufferView const *) const { return kerning_; }
///
void write(WriteStream & os) const;
///
void validate(LaTeXFeatures & features) const;
///
void normalize(NormalStream & ns) const;
///
void octave(OctaveStream & os) const;
///
void maple(MapleStream &) const;
///
void mathematica(MathematicaStream &) const;
///
void mathmlize(MathStream & ms) const;
/// identifies SpecialChar insets
InsetMathSpecialChar const * asSpecialCharInset() const { return this; }
///
docstring name() const { return name_; }
///
char_type getChar() const { return char_; }
private:
virtual Inset * clone() const;
/// the latex name
docstring name_;
/// the displayed character
char_type char_;
/// cached kerning for superscript
mutable int kerning_;
};
} // namespace lyx
#endif

View File

@ -32,6 +32,7 @@
#include "InsetMathRoot.h"
#include "InsetMathSize.h"
#include "InsetMathSpace.h"
#include "InsetMathSpecialChar.h"
#include "InsetMathSplit.h"
#include "InsetMathSqrt.h"
#include "InsetMathStackrel.h"
@ -218,6 +219,20 @@ void initSymbols()
}
bool isSpecialChar(docstring name)
{
if (name.size() != 1) {
string const s = to_ascii(name);
return s == "textasciicircum" || s == "mathcircumflex" ||
s == "textasciitilde" || s == "textbackslash";
} else {
char_type const c = name.at(0);
return c == '{' || c == '}' || c == '&' || c == '$' ||
c == '#' || c == '%' || c == '_';
}
}
} // namespace anon
MathWordList const & mathedWordList()
@ -446,6 +461,8 @@ MathAtom createInsetMath(docstring const & s)
return MathAtom(new InsetMathPhantom(InsetMathPhantom::vphantom));
if (s == "ensuremath")
return MathAtom(new InsetMathEnsureMath);
if (isSpecialChar(s))
return MathAtom(new InsetMathSpecialChar(s));
return MathAtom(new MathMacro(s));
}

View File

@ -518,8 +518,8 @@ void MathMacro::validate(LaTeXFeatures & features) const
if (!requires_.empty())
features.require(requires_);
if (name() == "binom" || name() == "mathcircumflex")
features.require(to_utf8(name()));
if (name() == "binom")
features.require("binom");
// validate the cells and the definition
if (displayMode() == DISPLAY_NORMAL) {

View File

@ -100,11 +100,16 @@ bool stared(docstring const & s)
}
docstring escapeSpecialChars(docstring const & str)
docstring escapeSpecialChars(docstring const & str, bool textmode)
{
docstring const backslash = textmode ? from_ascii("\\textbackslash ")
: from_ascii("\\backslash ");
docstring const caret = textmode ? from_ascii("\\textasciicircum ")
: from_ascii("\\mathcircumflex ");
return subst(subst(subst(subst(subst(subst(subst(subst(subst(str,
from_ascii("\\"), from_ascii("\\backslash ")),
from_ascii("^"), from_ascii("\\mathcircumflex ")),
from_ascii("\\"), backslash),
from_ascii("^"), caret),
from_ascii("_"), from_ascii("\\_")),
from_ascii("$"), from_ascii("\\$")),
from_ascii("#"), from_ascii("\\#")),
@ -540,8 +545,9 @@ void Parser::tokenize(istream & is)
void Parser::tokenize(docstring const & buffer)
{
idocstringstream is(mode_ & Parse::VERBATIM ?
escapeSpecialChars(buffer) : buffer, ios::in | ios::binary);
idocstringstream is(mode_ & Parse::VERBATIM
? escapeSpecialChars(buffer, mode_ & Parse::TEXTMODE)
: buffer, ios::in | ios::binary);
char_type c;
while (is.get(c)) {