InsetSpace support for

- \negmedspace and \negthickspace outside of math
- \enspace, \hspace*, \hspace*{\fill} and \hfill inside math
(fileformat change)

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@39557 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Uwe Stöhr 2011-08-29 14:07:30 +00:00
parent 6a0ab44ca7
commit f5a03ab601
12 changed files with 216 additions and 182 deletions

View File

@ -11,6 +11,12 @@ adjustments are made to tex2lyx and bugs are fixed in lyx2lyx.
-----------------------
2011-08-30 Uwe Stöhr <uwestoehr@web.de>
* Format incremented to 416 (r3xxxx)
support for \negmedspace and \negthinspace outside of math
support for \hfill, \enspace and \hspace* in math
No new InsetSpace parameters
2011-07-30 Uwe Stöhr <uwestoehr@web.de>
* Format incremented to 415 (r39464)
support for the LaTeX-package undertilde (fix bug 6622)

View File

@ -78,7 +78,6 @@ def convert_undertilde(document):
def revert_undertilde(document):
" Load undertilde if used in the document "
undertilde = find_token(document.header, "\\use_undertilde" , 0)
if undertilde == -1:
document.warning("No \\use_undertilde line. Assuming auto.")
@ -118,16 +117,63 @@ def revert_undertilde(document):
i = j
def revert_negative_space(document):
"Revert InsetSpace negmedspace and negthickspace into its TeX-code counterpart"
i = 0
j = 0
reverted = False
while True:
i = find_token(document.body, "\\begin_inset space \\negmedspace{}", i)
if i == -1:
j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
if j == -1:
# load amsmath in the preamble if not already loaded if we are at the end of checking
if reverted == True:
i = find_token(document.header, "\\use_amsmath 2", 0)
if i == -1:
add_to_preamble(document, ["\\@ifundefined{negthickspace}{\\usepackage{amsmath}}"])
return
if i == -1:
return
end = find_end_of_inset(document.body, i)
subst = put_cmd_in_ert("\\negmedspace{}")
document.body[i:end + 1] = subst
j = find_token(document.body, "\\begin_inset space \\negthickspace{}", j)
if j == -1:
return
end = find_end_of_inset(document.body, j)
subst = put_cmd_in_ert("\\negthickspace{}")
document.body[j:end + 1] = subst
reverted = True
def revert_math_spaces(document):
"Revert formulas with protected custom space and protected hfills to TeX-code"
i = 0
while True:
i = find_token(document.body, "\\begin_inset Formula", i)
if i == -1:
return
j = document.body[i].find("\\hspace*")
if j != -1:
end = find_end_of_inset(document.body, i)
subst = put_cmd_in_ert(document.body[i][21:])
document.body[i:end + 1] = subst
i = i + 1
##
# Conversion hub
#
supported_versions = ["2.1.0","2.1"]
convert = [[414, []],
[415, [convert_undertilde]]
[415, [convert_undertilde]],
[416, []]
]
revert = [[414, [revert_undertilde]],
revert = [[415, [revert_negative_space,revert_math_spaces]],
[414, [revert_undertilde]],
[413, [revert_visible_space]]
]

View File

@ -160,8 +160,11 @@ medspace space none
; space none
thickspace space none
enskip space none
enspace space none
quad space none
qquad space none
hfill space none
hspace* space none
hspace space none
# styles

View File

@ -128,7 +128,7 @@ namespace {
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
int const LYX_FORMAT = 415; //uwestoehr : support for package undertilde (bug 6622)
int const LYX_FORMAT = 416; //uwestoehr : support for horizontal spaces (bug 7728)
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;

View File

@ -476,8 +476,8 @@ void LyXAction::init()
* \li Action: Inserts one of horizontal space insets.
* \li Syntax: space-insert <NAME> [<LEN>]
* \li Params: <NAME>: normal, protected, visible, thin, quad, qquad, enspace,
enskip, negthinspace, hfill, hfill*, dotfill, hrulefill, hspace,
hspace* \n
enskip, negthinspace, negmedspace, negthickspace, hfill,
hfill*, dotfill, hrulefill, hspace, hspace* \n
<LEN>: length for custom spaces (hspace, hspace* for protected)
* \li Origin: JSpitzm, 20 May 2003, Mar 17 2008
* \endvar

View File

@ -400,9 +400,9 @@ Inset * createInsetHelper(Buffer * buf, FuncRequest const & cmd)
isp.kind = InsetSpaceParams::ENSKIP;
else if (name == "negthinspace")
isp.kind = InsetSpaceParams::NEGTHIN;
else if (isp.math && name == "negmedspace")
else if (name == "negmedspace")
isp.kind = InsetSpaceParams::NEGMEDIUM;
else if (isp.math && name == "negthickspace")
else if (name == "negthickspace")
isp.kind = InsetSpaceParams::NEGTHICK;
else if (name == "hfill")
isp.kind = InsetSpaceParams::HFILL;

View File

@ -42,26 +42,29 @@ GuiHSpace::GuiHSpace(bool math_mode, QWidget * parent)
spacingCO->clear();
if (math_mode_) {
spacingCO->addItem(qt_("Thin Space"));
spacingCO->addItem(qt_("Medium Space"));
spacingCO->addItem(qt_("Thick Space"));
spacingCO->addItem(qt_("Negative Thin Space"));
spacingCO->addItem(qt_("Negative Medium Space"));
spacingCO->addItem(qt_("Negative Thick Space"));
spacingCO->addItem(qt_("Half Quad (0.5 em)"));
spacingCO->addItem(qt_("Quad (1 em)"));
spacingCO->addItem(qt_("Double Quad (2 em)"));
spacingCO->addItem(qt_("Custom"));
spacingCO->addItem(qt_("Thin Space"), toqstr("thinspace"));
spacingCO->addItem(qt_("Medium Space"), toqstr("medspace"));
spacingCO->addItem(qt_("Thick Space"), toqstr("thickspace"));
spacingCO->addItem(qt_("Negative Thin Space"), toqstr("negthinspace"));
spacingCO->addItem(qt_("Negative Medium Space"), toqstr("negmedspace"));
spacingCO->addItem(qt_("Negative Thick Space"), toqstr("negthickspace"));
spacingCO->addItem(qt_("Half Quad (0.5 em)"), toqstr("halfquad"));
spacingCO->addItem(qt_("Quad (1 em)"), toqstr("quad"));
spacingCO->addItem(qt_("Double Quad (2 em)"), toqstr("qquad"));
spacingCO->addItem(qt_("Horizontal Fill"), toqstr("hfill"));
spacingCO->addItem(qt_("Custom"), toqstr("custom"));
} else {
spacingCO->addItem(qt_("Interword Space"));
spacingCO->addItem(qt_("Thin Space"));
spacingCO->addItem(qt_("Negative Thin Space"));
spacingCO->addItem(qt_("Half Quad (0.5 em)"));
spacingCO->addItem(qt_("Quad (1 em)"));
spacingCO->addItem(qt_("Double Quad (2 em)"));
spacingCO->addItem(qt_("Horizontal Fill"));
spacingCO->addItem(qt_("Custom"));
spacingCO->addItem(qt_("Visible Space"));
spacingCO->addItem(qt_("Interword Space"), toqstr("normal"));
spacingCO->addItem(qt_("Thin Space"), toqstr("thinspace"));
spacingCO->addItem(qt_("Negative Thin Space"), toqstr("negthinspace"));
spacingCO->addItem(qt_("Negative Medium Space"), toqstr("negmedspace"));
spacingCO->addItem(qt_("Negative Thick Space"), toqstr("negthickspace"));
spacingCO->addItem(qt_("Half Quad (0.5 em)"), toqstr("halfquad"));
spacingCO->addItem(qt_("Quad (1 em)"), toqstr("quad"));
spacingCO->addItem(qt_("Double Quad (2 em)"), toqstr("qquad"));
spacingCO->addItem(qt_("Horizontal Fill"), toqstr("hfill"));
spacingCO->addItem(qt_("Custom"), toqstr("custom"));
spacingCO->addItem(qt_("Visible Space"), toqstr("visible"));
}
connect(spacingCO, SIGNAL(highlighted(QString)),
@ -96,21 +99,14 @@ void GuiHSpace::changedSlot()
void GuiHSpace::enableWidgets()
{
int const selection = spacingCO->currentIndex();
bool const custom = (math_mode_ && selection == 9) ||
(!math_mode_ && selection == 7);
QString const selection = spacingCO->itemData(spacingCO->currentIndex()).toString();
bool const custom = selection == "custom";
valueLE->setEnabled(custom);
unitCO->setEnabled(custom);
if (math_mode_) {
fillPatternCO->setEnabled(false);
keepCB->setEnabled(false);
return;
}
fillPatternCO->setEnabled(selection == 6);
bool const no_pattern = fillPatternCO->currentIndex() == 0;
fillPatternCO->setEnabled(!math_mode_ && selection == "hfill");
bool const no_pattern = fillPatternCO->currentIndex() == 0 || math_mode_;
bool const enable_keep =
selection == 0 || selection == 3 ||
(selection == 6 && no_pattern) || custom;
selection == "normal" || selection == "halfquad" || (selection == "hfill" && no_pattern) || custom;
keepCB->setEnabled(enable_keep);
}
@ -121,97 +117,95 @@ void GuiHSpace::paramsToDialog(Inset const * inset)
? static_cast<InsetMathSpace const *>(inset)->params()
: static_cast<InsetSpace const *>(inset)->params();
int item = 0;
QString item;
int pattern = 0;
bool protect = false;
switch (params.kind) {
case InsetSpaceParams::NORMAL:
item = 0;
item = "normal";
break;
case InsetSpaceParams::PROTECTED:
item = 0;
protect = !params.math;
item = "normal";
protect = true;
break;
case InsetSpaceParams::VISIBLE:
item = 8;
item = "visible";
protect = true;
break;
case InsetSpaceParams::THIN:
item = params.math ? 0 : 1;
item = "thinspace";
break;
case InsetSpaceParams::MEDIUM:
item = 1;
item = "medspace";
break;
case InsetSpaceParams::THICK:
item = params.math ? 2 : 1;
item = "thickspace";
break;
case InsetSpaceParams::NEGTHIN:
item = params.math ? 3 : 2;
item = "negthinspace";
break;
case InsetSpaceParams::NEGMEDIUM:
item = params.math ? 4 : 2;
item = "negmedspace";
break;
case InsetSpaceParams::NEGTHICK:
item = params.math ? 5 : 2;
item = "negthickspace";
break;
case InsetSpaceParams::ENSKIP:
item = params.math ? 6 : 3;
item = "halfquad";
break;
case InsetSpaceParams::ENSPACE:
item = params.math ? 6 : 3;
protect = !params.math;
item = "halfquad";
protect = true;
break;
case InsetSpaceParams::QUAD:
item = params.math ? 7 : 4;
item = "quad";
break;
case InsetSpaceParams::QQUAD:
item = params.math ? 8 : 5;
item = "qquad";
break;
case InsetSpaceParams::HFILL:
item = params.math ? 3 : 6;
item = "hfill";
break;
case InsetSpaceParams::HFILL_PROTECTED:
item = params.math ? 3 : 6;
protect = !params.math;
item = "hfill";
protect = true;
break;
case InsetSpaceParams::DOTFILL:
item = params.math ? 3 : 6;
item = "hfill";
pattern = 1;
break;
case InsetSpaceParams::HRULEFILL:
item = params.math ? 3 : 6;
item = "hfill";
pattern = 2;
break;
case InsetSpaceParams::LEFTARROWFILL:
item = params.math ? 3 : 6;
item = "hfill";
pattern = 3;
break;
case InsetSpaceParams::RIGHTARROWFILL:
item = params.math ? 3 : 6;
item = "hfill";
pattern = 4;
break;
case InsetSpaceParams::UPBRACEFILL:
item = params.math ? 3 : 6;
item = "hfill";
pattern = 5;
break;
case InsetSpaceParams::DOWNBRACEFILL:
item = params.math ? 3 : 6;
item = "hfill";
pattern = 6;
break;
case InsetSpaceParams::CUSTOM:
item = params.math ? 9 : 7;
item = "custom";
break;
case InsetSpaceParams::CUSTOM_PROTECTED:
item = params.math ? 9 : 7;
protect = !params.math;
item = "custom";
protect = true;
break;
}
spacingCO->setCurrentIndex(item);
spacingCO->setCurrentIndex(spacingCO->findData(item));
fillPatternCO->setCurrentIndex(pattern);
keepCB->setChecked(protect);
if (math_mode_) {
keepCB->setToolTip(qt_("Insert the spacing even after a line break"));
} else if (item == 3) {
if (item == "halfquad") {
keepCB->setToolTip(qt_("Insert the spacing even after a line break.\n"
"Note that a protected Half Quad will be turned into\n"
"a vertical space if used at the beginning of a paragraph!"));
@ -219,7 +213,7 @@ void GuiHSpace::paramsToDialog(Inset const * inset)
keepCB->setToolTip(qt_("Insert the spacing even after a line break"));
}
Length::UNIT const default_unit = Length::defaultUnit();
if (item == (params.math ? 9 : 7)) {
if (item == "custom") {
string length = params.length.asString();
lengthToWidgets(valueLE, unitCO, length, default_unit);
} else
@ -229,61 +223,37 @@ void GuiHSpace::paramsToDialog(Inset const * inset)
}
docstring GuiHSpace::dialogToMathParams() const
{
InsetSpaceParams params(true);
switch (spacingCO->currentIndex()) {
case 0: params.kind = InsetSpaceParams::THIN; break;
case 1: params.kind = InsetSpaceParams::MEDIUM; break;
case 2: params.kind = InsetSpaceParams::THICK; break;
case 3: params.kind = InsetSpaceParams::NEGTHIN; break;
case 4: params.kind = InsetSpaceParams::NEGMEDIUM; break;
case 5: params.kind = InsetSpaceParams::NEGTHICK; break;
case 6: params.kind = InsetSpaceParams::ENSKIP; break;
case 7: params.kind = InsetSpaceParams::QUAD; break;
case 8: params.kind = InsetSpaceParams::QQUAD; break;
case 9:
params.kind = InsetSpaceParams::CUSTOM;
params.length = GlueLength(widgetsToLength(valueLE, unitCO));
break;
}
return from_ascii(InsetSpace::params2string(params));
}
docstring GuiHSpace::dialogToParams() const
{
if (math_mode_)
return dialogToMathParams();
InsetSpaceParams params = math_mode_ ?
InsetSpaceParams(true) : InsetSpaceParams(false);
InsetSpaceParams params(false);
QString const item =
spacingCO->itemData(spacingCO->currentIndex()).toString();
switch (spacingCO->currentIndex()) {
case 0:
if (keepCB->isChecked())
params.kind = InsetSpaceParams::PROTECTED;
else
params.kind = InsetSpaceParams::NORMAL;
break;
case 1:
if (item == "normal")
params.kind = keepCB->isChecked() ?
InsetSpaceParams::PROTECTED : InsetSpaceParams::NORMAL;
else if (item == "thinspace")
params.kind = InsetSpaceParams::THIN;
break;
case 2:
else if (item == "medspace")
params.kind = InsetSpaceParams::MEDIUM;
else if (item == "thickspace")
params.kind = InsetSpaceParams::THICK;
else if (item == "negthinspace")
params.kind = InsetSpaceParams::NEGTHIN;
break;
case 3:
if (keepCB->isChecked())
params.kind = InsetSpaceParams::ENSPACE;
else
params.kind = InsetSpaceParams::ENSKIP;
break;
case 4:
else if (item == "negmedspace")
params.kind = InsetSpaceParams::NEGMEDIUM;
else if (item == "negthickspace")
params.kind = InsetSpaceParams::NEGTHICK;
else if (item == "halfquad")
params.kind = keepCB->isChecked() ?
InsetSpaceParams::ENSPACE : InsetSpaceParams::ENSKIP;
else if (item == "quad")
params.kind = InsetSpaceParams::QUAD;
break;
case 5:
else if (item == "qquad")
params.kind = InsetSpaceParams::QQUAD;
break;
case 6:
else if (item == "hfill") {
switch (fillPatternCO->currentIndex()) {
case 1:
params.kind = InsetSpaceParams::DOTFILL;
@ -310,18 +280,13 @@ docstring GuiHSpace::dialogToParams() const
params.kind = InsetSpaceParams::HFILL;
break;
}
break;
case 7:
if (keepCB->isChecked())
params.kind = InsetSpaceParams::CUSTOM_PROTECTED;
else
params.kind = InsetSpaceParams::CUSTOM;
} else if (item == "custom") {
params.kind = keepCB->isChecked() ?
InsetSpaceParams::CUSTOM_PROTECTED : InsetSpaceParams::CUSTOM;
params.length = GlueLength(widgetsToLength(valueLE, unitCO));
break;
case 8:
} else if (item == "visible")
params.kind = InsetSpaceParams::VISIBLE;
break;
}
return from_ascii(InsetSpace::params2string(params));
}
@ -330,7 +295,7 @@ bool GuiHSpace::checkWidgets() const
{
if (!InsetParamsWidget::checkWidgets())
return false;
return spacingCO->currentIndex() != (math_mode_ ? 9 : 7)
return spacingCO->itemData(spacingCO->currentIndex()).toString() != "custom"
|| !valueLE->text().isEmpty();
}

View File

@ -34,15 +34,13 @@ private Q_SLOTS:
private:
/// \name InsetParamsWidget inherited methods
//@{
InsetCode insetCode() const { return SPACE_CODE; }
InsetCode insetCode() const { return math_mode_ ? MATH_SPACE_CODE : SPACE_CODE; }
FuncCode creationCode() const { return LFUN_INSET_INSERT; }
void paramsToDialog(Inset const *);
docstring dialogToParams() const;
bool checkWidgets() const;
//@}
///
docstring dialogToMathParams() const;
///
bool const math_mode_;
};

View File

@ -488,9 +488,9 @@ void InsetSpaceParams::read(Lexer & lex)
kind = InsetSpaceParams::ENSKIP;
else if (command == "\\negthinspace{}")
kind = InsetSpaceParams::NEGTHIN;
else if (math && command == "\\negmedspace{}")
else if (command == "\\negmedspace{}")
kind = InsetSpaceParams::NEGMEDIUM;
else if (math && command == "\\negthickspace{}")
else if (command == "\\negthickspace{}")
kind = InsetSpaceParams::NEGTHICK;
else if (command == "\\hfill{}")
kind = InsetSpaceParams::HFILL;

View File

@ -57,10 +57,14 @@ SpaceInfo space_info[] = {
{";", 10, InsetSpaceParams::THICK, false, true, false},
{"thickspace", 10, InsetSpaceParams::THICK, false, true, false},
{"enskip", 10, InsetSpaceParams::ENSKIP, false, true, false},
{"enspace", 10, InsetSpaceParams::ENSPACE, false, true, false},
{"quad", 20, InsetSpaceParams::QUAD, false, true, false},
{"qquad", 40, InsetSpaceParams::QQUAD, false, true, false},
{"lyxnegspace", -2, InsetSpaceParams::NEGTHIN, true, false, false},
{"lyxposspace", 2, InsetSpaceParams::THIN, false, false, false},
{"hfill", 80, InsetSpaceParams::HFILL, false, true, false},
{"hspace*{\\fill}", 80, InsetSpaceParams::HFILL_PROTECTED, false, true, false},
{"hspace*", 0, InsetSpaceParams::CUSTOM_PROTECTED, false, true, true},
{"hspace", 0, InsetSpaceParams::CUSTOM, false, true, true},
};
@ -93,11 +97,12 @@ InsetMathSpace::InsetMathSpace(string const & name, string const & length)
}
InsetMathSpace::InsetMathSpace(Length const & length)
InsetMathSpace::InsetMathSpace(Length const & length, bool const prot)
: space_(defaultSpace), length_(length)
{
for (int i = 0; i < nSpace; ++i)
if (space_info[i].name == "hspace") {
if ((prot && space_info[i].name == "hspace*")
|| (!prot && space_info[i].name == "hspace")) {
space_ = i;
break;
}
@ -221,6 +226,7 @@ void InsetMathSpace::htmlize(HtmlStream & ms) const
ms << from_ascii("&emsp;");
break;
case InsetSpaceParams::ENSKIP:
case InsetSpaceParams::ENSPACE:
ms << from_ascii("&ensp;");
break;
case InsetSpaceParams::QUAD:
@ -229,7 +235,12 @@ void InsetMathSpace::htmlize(HtmlStream & ms) const
case InsetSpaceParams::QQUAD:
ms << from_ascii("&emsp;&emsp;");
break;
case InsetSpaceParams::CUSTOM: {
case InsetSpaceParams::HFILL:
case InsetSpaceParams::HFILL_PROTECTED:
// FIXME: is there a useful HTML entity?
break;
case InsetSpaceParams::CUSTOM:
case InsetSpaceParams::CUSTOM_PROTECTED: {
string l = length_.asHTMLString();
ms << MTag("span", "width='" + l + "'")
<< from_ascii("&nbsp;") << ETag("span");

View File

@ -28,7 +28,7 @@ public:
///
explicit InsetMathSpace(std::string const & name, std::string const & length);
///
explicit InsetMathSpace(Length const & length);
explicit InsetMathSpace(Length const & length, bool const prot = false);
///
InsetMathSpace const * asSpaceInset() const { return this; }
///

View File

@ -1751,12 +1751,17 @@ bool Parser::parse1(InsetMathGrid & grid, unsigned flags,
parse(cell->back().nucleus()->cell(0), FLAG_ITEM, InsetMath::TEXT_MODE);
}
else if (t.cs() == "hspace" && nextToken().character() != '*') {
else if (t.cs() == "hspace") {
bool const prot = nextToken().character() == '*';
if (prot)
getToken();
docstring const name = t.cs();
docstring const arg = parse_verbatim_item();
Length length;
if (isValidLength(to_utf8(arg), &length))
cell->push_back(MathAtom(new InsetMathSpace(length)));
if (prot && arg == "\\fill")
cell->push_back(MathAtom(new InsetMathSpace("hspace*{\\fill}", "")));
else if (isValidLength(to_utf8(arg), &length))
cell->push_back(MathAtom(new InsetMathSpace(length, prot)));
else {
// Since the Length class cannot use length variables
// we must not create an InsetMathSpace.