6047: Lyx 1.6.3 unable to typeset the third chemical equation of the
      file mhchem.lyx (package mhchem)
4043: mhchem support
5394: support for the mhchems's \ce command
The \ce and \cf insets are text mode environments that allow entering
spaces and mathmode commands. LyX leaves them alone and doesn't try to
be smart, i.e., the behaviour is exactly the same we had in the old days
with text-in-math mode environments, before the introduction of the
\ensuremath and \lyxmathsym macros. This means that in those environments
one has to know what he is doing, as LyX will not offer any protection.
The hack of enclosing \ce and \cf in a \text{} environment in order to
be able to enter spaces is no longer necessary.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@30338 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Enrico Forestieri 2009-07-03 00:05:58 +00:00
parent 7e2391c64c
commit 0a90c42b86
13 changed files with 88 additions and 29 deletions

View File

@ -99,6 +99,9 @@ texttt font textmode
textup font textmode
emph font textmode
noun font textmode
# ce and cf are provided by the mhchem package
ce font forcetext
cf font forcetext
# old-style font commands
bf oldfont none

View File

@ -405,7 +405,10 @@ int Cursor::currentMode()
LASSERT(!empty(), /**/);
for (int i = depth() - 1; i >= 0; --i) {
int res = operator[](i).inset().currentMode();
if (res != Inset::UNDECIDED_MODE)
bool locked_mode = operator[](i).inset().lockedMode();
// Also return UNDECIDED_MODE when the mode is locked,
// as in this case it is treated the same as TEXT_MODE
if (res != Inset::UNDECIDED_MODE || locked_mode)
return res;
}
return Inset::TEXT_MODE;

View File

@ -744,6 +744,10 @@ string const LaTeXFeatures::getPackages() const
packages << "\\PassOptionsToPackage{normalem}{ulem}\n"
"\\usepackage{ulem}\n";
if (mustProvide("mhchem"))
packages << "\\PassOptionsToPackage{version=3}{mhchem}\n"
"\\usepackage{mhchem}\n";
if (mustProvide("nomencl")) {
// Make it work with the new and old version of the package,
// but don't use the compatibility option since it is

View File

@ -470,6 +470,8 @@ public:
enum mode_type {UNDECIDED_MODE, TEXT_MODE, MATH_MODE};
/// return text or mathmode if that is possible to determine
virtual mode_type currentMode() const { return UNDECIDED_MODE; }
/// returns whether changing mode during latex export is forbidden
virtual bool lockedMode() const { return false; }
/// returns whether this inset is allowed in other insets of given mode
virtual bool allowedIn(mode_type) const { return true; }
/**

View File

@ -44,6 +44,14 @@ InsetMath::mode_type InsetMathFont::currentMode() const
}
bool InsetMathFont::lockedMode() const
{
if (key_->extra == "forcetext")
return true;
return false;
}
void InsetMathFont::metrics(MetricsInfo & mi, Dimension & dim) const
{
FontSetChanger dummy(mi.base, key_->name);
@ -93,6 +101,8 @@ void InsetMathFont::validate(LaTeXFeatures & features) const
features.require("amstext");
if (key_->name == "textipa")
features.require("tipa");
if (key_->name == "ce" || key_->name == "cf")
features.require("mhchem");
}

View File

@ -31,6 +31,8 @@ public:
InsetMathFont const * asFontInset() const { return this; }
/// are we in math mode, text mode, or unsure?
mode_type currentMode() const;
/// do we allow changing mode during latex export?
bool lockedMode() const;
///
docstring name() const;
///

View File

@ -1259,7 +1259,7 @@ void InsetMathGrid::doDispatch(Cursor & cur, FuncRequest & cmd)
parseflg |= Parse::VERBATIM;
// fall through
case LFUN_PASTE: {
if (cur.currentMode() == TEXT_MODE)
if (cur.currentMode() <= TEXT_MODE)
parseflg |= Parse::TEXTMODE;
cur.message(_("Paste"));
cap::replaceSelection(cur);

View File

@ -340,7 +340,7 @@ MathData InsetMathNest::glue() const
void InsetMathNest::write(WriteStream & os) const
{
ModeSpecifier specifier(os, currentMode());
ModeSpecifier specifier(os, currentMode(), lockedMode());
docstring const latex_name = name();
os << '\\' << latex_name;
for (size_t i = 0; i < nargs(); ++i)
@ -525,7 +525,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
parseflg |= Parse::VERBATIM;
// fall through
case LFUN_PASTE: {
if (cur.currentMode() == TEXT_MODE)
if (cur.currentMode() <= TEXT_MODE)
parseflg |= Parse::TEXTMODE;
cur.recordUndoSelection();
cur.message(_("Paste"));
@ -890,37 +890,37 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
break;
case LFUN_FONT_BOLD:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
handleFont(cur, cmd.argument(), "textbf");
else
handleFont(cur, cmd.argument(), "mathbf");
break;
case LFUN_FONT_BOLDSYMBOL:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
handleFont(cur, cmd.argument(), "textbf");
else
handleFont(cur, cmd.argument(), "boldsymbol");
break;
case LFUN_FONT_SANS:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
handleFont(cur, cmd.argument(), "textsf");
else
handleFont(cur, cmd.argument(), "mathsf");
break;
case LFUN_FONT_EMPH:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
handleFont(cur, cmd.argument(), "emph");
else
handleFont(cur, cmd.argument(), "mathcal");
break;
case LFUN_FONT_ROMAN:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
handleFont(cur, cmd.argument(), "textrm");
else
handleFont(cur, cmd.argument(), "mathrm");
break;
case LFUN_FONT_TYPEWRITER:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
handleFont(cur, cmd.argument(), "texttt");
else
handleFont(cur, cmd.argument(), "mathtt");
@ -929,13 +929,13 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
handleFont(cur, cmd.argument(), "mathfrak");
break;
case LFUN_FONT_ITAL:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
handleFont(cur, cmd.argument(), "textit");
else
handleFont(cur, cmd.argument(), "mathit");
break;
case LFUN_FONT_NOUN:
if (currentMode() == TEXT_MODE)
if (currentMode() <= TEXT_MODE)
// FIXME: should be "noun"
handleFont(cur, cmd.argument(), "textsc");
else
@ -955,7 +955,7 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
docstring const save_selection = grabAndEraseSelection(cur);
selClearOrDel(cur);
//cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv())));
if (currentMode() == Inset::TEXT_MODE)
if (currentMode() <= Inset::TEXT_MODE)
cur.plainInsert(MathAtom(new InsetMathEnsureMath));
else
cur.plainInsert(MathAtom(new InsetMathBox(from_ascii("mbox"))));
@ -1472,7 +1472,7 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
// remove the '\\'
if (c == '\\') {
cur.backspace();
if (currentMode() == InsetMath::TEXT_MODE)
if (currentMode() <= InsetMath::TEXT_MODE)
cur.niceInsert(createInsetMath("textbackslash"));
else
cur.niceInsert(createInsetMath("backslash"));
@ -1585,14 +1585,14 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
selClearOrDel(cur);
if (c == '\n') {
if (currentMode() == InsetMath::TEXT_MODE)
if (currentMode() <= InsetMath::TEXT_MODE)
cur.insert(c);
return true;
}
if (c == ' ') {
if (currentMode() == InsetMath::TEXT_MODE) {
// insert spaces in text mode,
if (currentMode() <= InsetMath::TEXT_MODE) {
// insert spaces in text or undecided mode,
// but suppress direct insertion of two spaces in a row
// the still allows typing '<space>a<space>' and deleting the 'a', but
// it is better than nothing...
@ -1643,7 +1643,7 @@ bool InsetMathNest::interpretChar(Cursor & cur, char_type const c)
cur.niceInsert(createInsetMath("sim"));
return true;
}
if (!isAsciiOrMathAlpha(c)) {
if (currentMode() == InsetMath::MATH_MODE && !isAsciiOrMathAlpha(c)) {
MathAtom at = createInsetMath("text");
at.nucleus()->cell(0).push_back(MathAtom(new InsetMathChar(c)));
cur.niceInsert(at);

View File

@ -103,7 +103,7 @@ void InsetMathString::mathmlize(MathStream & os) const
void InsetMathString::write(WriteStream & os) const
{
if (!os.latex()) {
if (!os.latex() || os.lockedMode()) {
os << str_;
return;
}

View File

@ -276,7 +276,7 @@ bool ensureMath(WriteStream & os, bool needs_math_mode, bool macro)
}
bool ensureMode(WriteStream & os, InsetMath::mode_type mode)
int ensureMode(WriteStream & os, InsetMath::mode_type mode, bool locked)
{
bool textmode = mode == InsetMath::TEXT_MODE;
if (os.latex() && textmode && os.pendingBrace()) {
@ -285,9 +285,11 @@ bool ensureMode(WriteStream & os, InsetMath::mode_type mode)
os.pendingSpace(false);
os.textMode(true);
}
bool oldmode = os.textMode();
int oldmodes = os.textMode() ? 1 : 0;
os.textMode(textmode);
return oldmode;
oldmodes |= os.lockedMode() ? 2 : 0;
os.lockedMode(locked);
return oldmodes;
}

View File

@ -155,6 +155,12 @@ void WriteStream::textMode(bool textmode)
}
void WriteStream::lockedMode(bool locked)
{
locked_ = locked;
}
WriteStream & operator<<(WriteStream & ws, MathAtom const & at)
{
at->write(ws);

View File

@ -65,6 +65,10 @@ public:
void textMode(bool textmode);
/// tell whether we are in text mode or not when producing latex code
bool textMode() const { return textmode_; }
/// tell whether we are allowed to switch mode when producing latex code
void lockedMode(bool locked);
/// tell whether we are allowed to switch mode when producing latex code
bool lockedMode() const { return locked_; }
/// LaTeX encoding
Encoding const * encoding() const { return encoding_; }
private:
@ -84,6 +88,8 @@ private:
bool pendingbrace_;
/// are we in text mode when producing latex code?
bool textmode_;
/// are we allowed to switch mode when producing latex code?
bool locked_;
///
int line_;
///
@ -109,7 +115,7 @@ WriteStream & operator<<(WriteStream &, unsigned int);
bool ensureMath(WriteStream & os, bool needs_math_mode = true, bool macro = false);
/// ensure the requested mode, possibly by closing \ensuremath
bool ensureMode(WriteStream & os, InsetMath::mode_type mode);
int ensureMode(WriteStream & os, InsetMath::mode_type mode, bool locked);
/**
@ -169,12 +175,22 @@ private:
* environment works in a given mode. For example, \mbox works in text
* mode, but \boxed works in math mode. Note that no mode changing commands
* are needed, but we have to track the current mode, hence this class.
* This is only used when exporting to latex and helps determining whether
* the mode needs being temporarily switched when a command would not work
* in the current mode. As there are cases where this switching is to be
* avoided, the optional third parameter can be used to lock the mode.
*
* Example:
* Example 1:
*
* ModeSpecifier specifier(os, TEXT_MODE);
*
* Sets the current mode to text mode.
* Sets the current mode to text mode and allows mode switching.
*
* Example 2:
*
* ModeSpecifier specifier(os, TEXT_MODE, true);
*
* Sets the current mode to text mode and disallows mode switching.
*
* At the end of specifier's scope the mode is reset to its previous value.
*/
@ -182,15 +198,20 @@ class ModeSpecifier
{
public:
///
explicit ModeSpecifier(WriteStream & os, InsetMath::mode_type mode)
: os_(os), textmode_(ensureMode(os, mode)) {}
explicit ModeSpecifier(WriteStream & os, InsetMath::mode_type mode,
bool locked = false)
: os_(os), oldmodes_(ensureMode(os, mode, locked)) {}
///
~ModeSpecifier() { os_.textMode(textmode_); }
~ModeSpecifier()
{
os_.textMode(oldmodes_ & 1);
os_.lockedMode(oldmodes_ & 2);
}
private:
///
WriteStream & os_;
///
bool textmode_;
int oldmodes_;
};

View File

@ -591,6 +591,12 @@ fontinfo fontinfos[] = {
{"textipa", inh_family, inh_series,
inh_shape, Color_foreground},
// mhchem support
{"ce", inh_family, inh_series,
inh_shape, Color_foreground},
{"cf", inh_family, inh_series,
inh_shape, Color_foreground},
// LyX internal usage
{"lyxtex", inh_family, inh_series,
UP_SHAPE, Color_latex},