diff --git a/lib/symbols b/lib/symbols
index 66b8be98be..e32f50dfc9 100644
--- a/lib/symbols
+++ b/lib/symbols
@@ -128,13 +128,19 @@ vref ref none
lyxnegspace space none
lyxposspace space none
! space none
+negthinspace space none
negmedspace space none
negthickspace space none
, space none
+thinspace space none
: space none
+medspace space none
; space none
+thickspace space none
+enskip space none
quad space none
qquad space none
+hspace space none
# styles
displaystyle style 0
diff --git a/lib/ui/stdcontext.inc b/lib/ui/stdcontext.inc
index 3559143a42..102a059863 100644
--- a/lib/ui/stdcontext.inc
+++ b/lib/ui/stdcontext.inc
@@ -190,6 +190,24 @@ Menuset
Item "Settings...|S" "next-inset-toggle"
End
+#
+# InsetMathSpace context menu
+#
+ Menu "context-mathspace"
+ Item "Thin Space|T" "next-inset-modify mathspace \thinspace{}"
+ Item "Medium Space|M" "next-inset-modify mathspace \medspace{}"
+ Item "Thick Space|h" "next-inset-modify mathspace \thickspace{}"
+ Item "Negative Thin Space|N" "next-inset-modify mathspace \negthinspace{}"
+ Item "Negative Medium Space|u" "next-inset-modify mathspace \negmedspace{}"
+ Item "Negative Thick Space|i" "next-inset-modify mathspace \negthickspace{}"
+ Item "Half Quad Space (Enskip)|k" "next-inset-modify mathspace \enskip{}"
+ Item "Quad Space|Q" "next-inset-modify mathspace \quad{}"
+ Item "Double Quad Space|u" "next-inset-modify mathspace \qquad{}"
+ Item "Custom Length|C" "command-sequence next-inset-modify mathspace \hspace{} \length 1in; next-inset-toggle"
+ Separator
+ Item "Settings...|S" "next-inset-toggle"
+ End
+
#
# InsetVSpace context menu
#
diff --git a/src/factory.cpp b/src/factory.cpp
index 01e8c72652..0caddc872e 100644
--- a/src/factory.cpp
+++ b/src/factory.cpp
@@ -330,12 +330,17 @@ Inset * createInsetHelper(Buffer & buf, FuncRequest const & cmd)
break;
}
InsetSpaceParams isp;
+ // The tests for isp.math might be disabled after a file format change
if (name == "normal")
isp.kind = InsetSpaceParams::NORMAL;
else if (name == "protected")
isp.kind = InsetSpaceParams::PROTECTED;
else if (name == "thin")
isp.kind = InsetSpaceParams::THIN;
+ else if (isp.math && name == "med")
+ isp.kind = InsetSpaceParams::MEDIUM;
+ else if (isp.math && name == "thick")
+ isp.kind = InsetSpaceParams::THICK;
else if (name == "quad")
isp.kind = InsetSpaceParams::QUAD;
else if (name == "qquad")
@@ -346,6 +351,10 @@ 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")
+ isp.kind = InsetSpaceParams::NEGMEDIUM;
+ else if (isp.math && name == "negthickspace")
+ isp.kind = InsetSpaceParams::NEGTHICK;
else if (name == "hfill")
isp.kind = InsetSpaceParams::HFILL;
else if (name == "hfill*")
diff --git a/src/frontends/qt4/GuiHSpace.cpp b/src/frontends/qt4/GuiHSpace.cpp
index 984cd1a1e0..1967c2431d 100644
--- a/src/frontends/qt4/GuiHSpace.cpp
+++ b/src/frontends/qt4/GuiHSpace.cpp
@@ -35,9 +35,10 @@ using namespace std;
namespace lyx {
namespace frontend {
-GuiHSpace::GuiHSpace(GuiView & lv)
- : GuiDialog(lv, "space", qt_("Horizontal Space Settings"))
+GuiHSpace::GuiHSpace(GuiView & lv, bool math)
+ : GuiDialog(lv, math ? "mathspace" : "space", qt_("Horizontal Space Settings"))
{
+ params_.math = math;
setupUi(this);
connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
@@ -86,8 +87,23 @@ void GuiHSpace::change_adaptor()
}
+void GuiHSpace::setMath(bool custom)
+{
+ valueLE->setEnabled(custom);
+ unitCO->setEnabled(custom);
+ fillPatternCO->setEnabled(false);
+ keepCB->setToolTip(qt_("Insert the spacing even after a line break"));
+ keepCB->setEnabled(false);
+}
+
+
void GuiHSpace::enableWidgets(int selection)
{
+ if (params_.math) {
+ setMath(selection == 9);
+ changed();
+ return;
+ }
valueLE->setEnabled(selection == 7);
unitCO->setEnabled(selection == 7);
fillPatternCO->setEnabled(selection == 6);
@@ -120,6 +136,33 @@ static void setWidgetsFromHSpace(InsetSpaceParams const & params,
QCheckBox * keep,
QComboBox * fillPattern)
{
+ spacing->clear();
+ if (params.math) {
+ spacing->addItem(qt_("Thin space"));
+ spacing->addItem(qt_("Medium space"));
+ spacing->addItem(qt_("Thick space"));
+ spacing->addItem(qt_("Negative thin space"));
+ spacing->addItem(qt_("Negative medium space"));
+ spacing->addItem(qt_("Negative thick space"));
+ spacing->addItem(qt_("Half Quad (0.5 em)"));
+ spacing->addItem(qt_("Quad (1 em)"));
+ spacing->addItem(qt_("Double Quad (2 em)"));
+ spacing->addItem(qt_("Custom"));
+ keep->setEnabled(false);
+ fillPattern->setEnabled(false);
+ } else {
+ spacing->addItem(qt_("Inter-word space"));
+ spacing->addItem(qt_("Thin space"));
+ spacing->addItem(qt_("Negative thin space"));
+ spacing->addItem(qt_("Half Quad (0.5 em)"));
+ spacing->addItem(qt_("Quad (1 em)"));
+ spacing->addItem(qt_("Double Quad (2 em)"));
+ spacing->addItem(qt_("Horizontal Fill"));
+ spacing->addItem(qt_("Custom"));
+ keep->setEnabled(true);
+ fillPattern->setEnabled(true);
+ }
+
int item = 0;
int pattern = 0;
bool protect = false;
@@ -129,64 +172,76 @@ static void setWidgetsFromHSpace(InsetSpaceParams const & params,
break;
case InsetSpaceParams::PROTECTED:
item = 0;
- protect = true;
+ protect = !params.math;
break;
case InsetSpaceParams::THIN:
+ item = params.math ? 0 : 1;
+ break;
+ case InsetSpaceParams::MEDIUM:
item = 1;
break;
+ case InsetSpaceParams::THICK:
+ item = params.math ? 2 : 1;
+ break;
case InsetSpaceParams::NEGTHIN:
- item = 2;
+ item = params.math ? 3 : 2;
+ break;
+ case InsetSpaceParams::NEGMEDIUM:
+ item = params.math ? 4 : 2;
+ break;
+ case InsetSpaceParams::NEGTHICK:
+ item = params.math ? 5 : 2;
break;
case InsetSpaceParams::ENSKIP:
- item = 3;
+ item = params.math ? 6 : 3;
break;
case InsetSpaceParams::ENSPACE:
- item = 3;
- protect = true;
+ item = params.math ? 6 : 3;
+ protect = !params.math;
break;
case InsetSpaceParams::QUAD:
- item = 4;
+ item = params.math ? 7 : 4;
break;
case InsetSpaceParams::QQUAD:
- item = 5;
+ item = params.math ? 8 : 5;
break;
case InsetSpaceParams::HFILL:
- item = 6;
+ item = params.math ? 3 : 6;
break;
case InsetSpaceParams::HFILL_PROTECTED:
- item = 6;
- protect = true;
+ item = params.math ? 3 : 6;
+ protect = !params.math;
break;
case InsetSpaceParams::DOTFILL:
- item = 6;
+ item = params.math ? 3 : 6;
pattern = 1;
break;
case InsetSpaceParams::HRULEFILL:
- item = 6;
+ item = params.math ? 3 : 6;
pattern = 2;
break;
case InsetSpaceParams::LEFTARROWFILL:
- item = 6;
+ item = params.math ? 3 : 6;
pattern = 3;
break;
case InsetSpaceParams::RIGHTARROWFILL:
- item = 6;
+ item = params.math ? 3 : 6;
pattern = 4;
break;
case InsetSpaceParams::UPBRACEFILL:
- item = 6;
+ item = params.math ? 3 : 6;
pattern = 5;
break;
case InsetSpaceParams::DOWNBRACEFILL:
- item = 6;
+ item = params.math ? 3 : 6;
pattern = 6;
break;
case InsetSpaceParams::CUSTOM:
- item = 7;
+ item = params.math ? 9 : 7;
break;
case InsetSpaceParams::CUSTOM_PROTECTED:
- item = 7;
- protect = true;
+ item = params.math ? 9 : 7;
+ protect = !params.math;
break;
}
spacing->setCurrentIndex(item);
@@ -195,7 +250,7 @@ static void setWidgetsFromHSpace(InsetSpaceParams const & params,
Length::UNIT default_unit =
(lyxrc.default_papersize > 3) ? Length::CM : Length::IN;
- if (item == 7)
+ if (item == (params.math ? 9 : 7))
lengthToWidgets(value, unit, params.length, default_unit);
else
lengthToWidgets(value, unit, "", default_unit);
@@ -203,9 +258,28 @@ static void setWidgetsFromHSpace(InsetSpaceParams const & params,
static InsetSpaceParams setHSpaceFromWidgets(int spacing,
- QLineEdit * value, LengthCombo * unit, bool keep, int fill)
+ QLineEdit * value, LengthCombo * unit, bool keep, int fill, bool math)
{
- InsetSpaceParams params;
+ InsetSpaceParams params(math);
+ if (math) {
+ switch (spacing) {
+ 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 = Length(widgetsToLength(value, unit));
+ break;
+ }
+ return params;
+ }
+
switch (spacing) {
case 0:
if (keep)
@@ -265,7 +339,7 @@ void GuiHSpace::applyView()
{
params_ = setHSpaceFromWidgets(spacingCO->currentIndex(),
valueLE, unitCO, keepCB->isChecked(),
- fillPatternCO->currentIndex());
+ fillPatternCO->currentIndex(), params_.math);
}
@@ -279,7 +353,11 @@ void GuiHSpace::updateContents()
bool GuiHSpace::initialiseParams(string const & data)
{
+ bool const math = params_.math;
InsetSpace::string2params(data, params_);
+ params_.math = math;
+ if (params_.math)
+ setMath(params_.kind == InsetSpaceParams::CUSTOM);
setButtonsValid(true);
return true;
}
@@ -287,7 +365,7 @@ bool GuiHSpace::initialiseParams(string const & data)
void GuiHSpace::clearParams()
{
- params_ = InsetSpaceParams();
+ params_ = InsetSpaceParams(params_.math);
}
@@ -299,11 +377,15 @@ void GuiHSpace::dispatchParams()
bool GuiHSpace::isValid()
{
- return spacingCO->currentIndex() != 7 || !valueLE->text().isEmpty();
+ return spacingCO->currentIndex() != (params_.math ? 9 : 7)
+ || !valueLE->text().isEmpty();
}
-Dialog * createGuiHSpace(GuiView & lv) { return new GuiHSpace(lv); }
+Dialog * createGuiMathHSpace(GuiView & lv) { return new GuiHSpace(lv, true); }
+
+
+Dialog * createGuiTextHSpace(GuiView & lv) { return new GuiHSpace(lv, false); }
} // namespace frontend
diff --git a/src/frontends/qt4/GuiHSpace.h b/src/frontends/qt4/GuiHSpace.h
index 582afc932b..5b0bdece3b 100644
--- a/src/frontends/qt4/GuiHSpace.h
+++ b/src/frontends/qt4/GuiHSpace.h
@@ -24,7 +24,7 @@ class GuiHSpace : public GuiDialog, public Ui::HSpaceUi
Q_OBJECT
public:
- GuiHSpace(GuiView & lv);
+ GuiHSpace(GuiView & lv, bool math);
private Q_SLOTS:
///
@@ -35,6 +35,8 @@ private Q_SLOTS:
void patternChanged();
private:
+ ///
+ void setMath(bool custom);
/// Apply from dialog
void applyView();
/// Update the dialog
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index db1289fe1d..483f7a0f53 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -2068,8 +2068,9 @@ bool GuiView::dispatch(FuncRequest const & cmd)
Inset * inset = getOpenInset(name);
if (inset) {
// put cursor in front of inset.
- if (!view()->setCursorFromInset(inset))
+ if (!view()->setCursorFromInset(inset)) {
LASSERT(false, break);
+ }
// useful if we are called from a dialog.
view()->cursor().beginUndoGroup();
@@ -2289,7 +2290,7 @@ char const * const dialognames[] = {
"aboutlyx", "bibitem", "bibtex", "box", "branch", "changes", "character",
"citation", "document", "errorlist", "ert", "external", "file",
"findreplace", "float", "graphics", "include", "index", "info", "nomenclature", "label", "log",
-"mathdelimiter", "mathmatrix", "note", "paragraph", "prefs", "print",
+"mathdelimiter", "mathmatrix", "mathspace", "note", "paragraph", "prefs", "print",
"ref", "sendto", "space", "spellchecker", "symbols", "tabular", "tabularcreate",
#ifdef HAVE_LIBAIKSAURUS
@@ -2470,12 +2471,12 @@ Dialog * createGuiERT(GuiView & lv);
Dialog * createGuiExternal(GuiView & lv);
Dialog * createGuiFloat(GuiView & lv);
Dialog * createGuiGraphics(GuiView & lv);
-Dialog * createGuiHSpace(GuiView & lv);
Dialog * createGuiInclude(GuiView & lv);
Dialog * createGuiInfo(GuiView & lv);
Dialog * createGuiLabel(GuiView & lv);
Dialog * createGuiListings(GuiView & lv);
Dialog * createGuiLog(GuiView & lv);
+Dialog * createGuiMathHSpace(GuiView & lv);
Dialog * createGuiMathMatrix(GuiView & lv);
Dialog * createGuiNomenclature(GuiView & lv);
Dialog * createGuiNote(GuiView & lv);
@@ -2492,6 +2493,7 @@ Dialog * createGuiSymbols(GuiView & lv);
Dialog * createGuiTabularCreate(GuiView & lv);
Dialog * createGuiTabular(GuiView & lv);
Dialog * createGuiTexInfo(GuiView & lv);
+Dialog * createGuiTextHSpace(GuiView & lv);
Dialog * createGuiToc(GuiView & lv);
Dialog * createGuiThesaurus(GuiView & lv);
Dialog * createGuiHyperlink(GuiView & lv);
@@ -2552,6 +2554,8 @@ Dialog * GuiView::build(string const & name)
return createGuiViewSource(*this);
if (name == "mathdelimiter")
return createGuiDelimiter(*this);
+ if (name == "mathspace")
+ return createGuiMathHSpace(*this);
if (name == "mathmatrix")
return createGuiMathMatrix(*this);
if (name == "note")
@@ -2567,7 +2571,7 @@ Dialog * GuiView::build(string const & name)
if (name == "sendto")
return createGuiSendTo(*this);
if (name == "space")
- return createGuiHSpace(*this);
+ return createGuiTextHSpace(*this);
if (name == "spellchecker")
return createGuiSpellchecker(*this);
if (name == "symbols")
diff --git a/src/frontends/qt4/ui/HSpaceUi.ui b/src/frontends/qt4/ui/HSpaceUi.ui
index 613dfa20e9..5d6a7b5b8f 100644
--- a/src/frontends/qt4/ui/HSpaceUi.ui
+++ b/src/frontends/qt4/ui/HSpaceUi.ui
@@ -79,46 +79,6 @@
Supported spacing types
- -
-
- Inter-word space
-
-
- -
-
- Thin space
-
-
- -
-
- Negative thin space
-
-
- -
-
- Half Quad (0.5 em)
-
-
- -
-
- Quad (1 em)
-
-
- -
-
- Double Quad (2 em)
-
-
- -
-
- Horizontal Fill
-
-
- -
-
- Custom
-
-
-
diff --git a/src/insets/InsetSpace.cpp b/src/insets/InsetSpace.cpp
index d5c6619c19..c4827d28ce 100644
--- a/src/insets/InsetSpace.cpp
+++ b/src/insets/InsetSpace.cpp
@@ -20,6 +20,7 @@
#include "Dimension.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
+#include "LaTeXFeatures.h"
#include "Length.h"
#include "Lexer.h"
#include "MetricsInfo.h"
@@ -28,6 +29,7 @@
#include "support/debug.h"
#include "support/docstream.h"
#include "support/gettext.h"
+#include "support/lassert.h"
#include "support/lstrings.h"
#include "frontends/Application.h"
@@ -75,6 +77,12 @@ docstring InsetSpace::toolTip(BufferView const &, int, int) const
case InsetSpaceParams::THIN:
message = _("Thin Space");
break;
+ case InsetSpaceParams::MEDIUM:
+ message = _("Medium Space");
+ break;
+ case InsetSpaceParams::THICK:
+ message = _("Thick Space");
+ break;
case InsetSpaceParams::QUAD:
message = _("Quad Space");
break;
@@ -90,6 +98,12 @@ docstring InsetSpace::toolTip(BufferView const &, int, int) const
case InsetSpaceParams::NEGTHIN:
message = _("Negative Thin Space");
break;
+ case InsetSpaceParams::NEGMEDIUM:
+ message = _("Negative Mwedium Space");
+ break;
+ case InsetSpaceParams::NEGTHICK:
+ message = _("Negative Thick Space");
+ break;
case InsetSpaceParams::HFILL:
message = _("Horizontal Fill");
break;
@@ -131,10 +145,13 @@ void InsetSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
{
switch (cmd.action) {
- case LFUN_INSET_MODIFY: {
+ case LFUN_INSET_MODIFY:
string2params(to_utf8(cmd.argument()), params_);
break;
- }
+
+ case LFUN_INSET_DIALOG_UPDATE:
+ cur.bv().updateDialog("space", params2string(params()));
+ break;
case LFUN_MOUSE_RELEASE:
if (!cur.selection() && cmd.button() == mouse_button::button1)
@@ -159,6 +176,8 @@ bool InsetSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
string2params(to_utf8(cmd.argument()), params);
status.setOnOff(params_.kind == params.kind);
}
+ // fall through
+ case LFUN_INSET_DIALOG_UPDATE:
status.setEnabled(true);
return true;
default:
@@ -196,6 +215,14 @@ void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const
case InsetSpaceParams::NEGTHIN:
dim.wid = fm.width(char_type('M')) / 6;
break;
+ case InsetSpaceParams::MEDIUM:
+ case InsetSpaceParams::NEGMEDIUM:
+ dim.wid = fm.width(char_type('M')) / 4;
+ break;
+ case InsetSpaceParams::THICK:
+ case InsetSpaceParams::NEGTHICK:
+ dim.wid = fm.width(char_type('M')) / 2;
+ break;
case InsetSpaceParams::PROTECTED:
case InsetSpaceParams::NORMAL:
dim.wid = fm.width(char_type(' '));
@@ -269,12 +296,12 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const
if (params_.kind == InsetSpaceParams::HFILL) {
pi.pain.line(x0, y1, x0, y0, Color_added_space);
- pi.pain.line(x0, y2 , x1, y2, Color_added_space,
+ pi.pain.line(x0, y2, x1, y2, Color_added_space,
frontend::Painter::line_onoffdash);
pi.pain.line(x1, y1, x1, y0, Color_added_space);
} else if (params_.kind == InsetSpaceParams::HFILL_PROTECTED) {
pi.pain.line(x0, y1, x0, y0, Color_latex);
- pi.pain.line(x0, y2 , x1, y2, Color_latex,
+ pi.pain.line(x0, y2, x1, y2, Color_latex,
frontend::Painter::line_onoffdash);
pi.pain.line(x1, y1, x1, y0, Color_latex);
} else if (params_.kind == InsetSpaceParams::DOTFILL) {
@@ -344,6 +371,8 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const
if (params_.kind == InsetSpaceParams::PROTECTED ||
params_.kind == InsetSpaceParams::ENSPACE ||
params_.kind == InsetSpaceParams::NEGTHIN ||
+ params_.kind == InsetSpaceParams::NEGMEDIUM ||
+ params_.kind == InsetSpaceParams::NEGTHICK ||
params_.kind == InsetSpaceParams::CUSTOM_PROTECTED)
pi.pain.lines(xp, yp, 4, Color_latex);
else
@@ -364,6 +393,12 @@ void InsetSpaceParams::write(ostream & os) const
case InsetSpaceParams::THIN:
os << "\\thinspace{}";
break;
+ case InsetSpaceParams::MEDIUM:
+ os << "\\medspace{}";
+ break;
+ case InsetSpaceParams::THICK:
+ os << "\\thickspace{}";
+ break;
case InsetSpaceParams::QUAD:
os << "\\quad{}";
break;
@@ -379,6 +414,12 @@ void InsetSpaceParams::write(ostream & os) const
case InsetSpaceParams::NEGTHIN:
os << "\\negthinspace{}";
break;
+ case InsetSpaceParams::NEGMEDIUM:
+ os << "\\negmedspace{}";
+ break;
+ case InsetSpaceParams::NEGTHICK:
+ os << "\\negthickspace{}";
+ break;
case InsetSpaceParams::HFILL:
os << "\\hfill{}";
break;
@@ -422,12 +463,17 @@ void InsetSpaceParams::read(Lexer & lex)
string command;
lex >> command;
+ // The tests for math might be disabled after a file format change
if (command == "\\space{}")
kind = InsetSpaceParams::NORMAL;
else if (command == "~")
kind = InsetSpaceParams::PROTECTED;
else if (command == "\\thinspace{}")
kind = InsetSpaceParams::THIN;
+ else if (math && command == "\\medspace{}")
+ kind = InsetSpaceParams::MEDIUM;
+ else if (math && command == "\\thickspace{}")
+ kind = InsetSpaceParams::THICK;
else if (command == "\\quad{}")
kind = InsetSpaceParams::QUAD;
else if (command == "\\qquad{}")
@@ -438,6 +484,10 @@ void InsetSpaceParams::read(Lexer & lex)
kind = InsetSpaceParams::ENSKIP;
else if (command == "\\negthinspace{}")
kind = InsetSpaceParams::NEGTHIN;
+ else if (math && command == "\\negmedspace{}")
+ kind = InsetSpaceParams::NEGMEDIUM;
+ else if (math && command == "\\negthickspace{}")
+ kind = InsetSpaceParams::NEGTHICK;
else if (command == "\\hfill{}")
kind = InsetSpaceParams::HFILL;
else if (command == "\\hspace*{\\fill}")
@@ -492,6 +542,12 @@ int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const
case InsetSpaceParams::THIN:
os << (runparams.free_spacing ? " " : "\\,");
break;
+ case InsetSpaceParams::MEDIUM:
+ os << (runparams.free_spacing ? " " : "\\:");
+ break;
+ case InsetSpaceParams::THICK:
+ os << (runparams.free_spacing ? " " : "\\;");
+ break;
case InsetSpaceParams::QUAD:
os << (runparams.free_spacing ? " " : "\\quad{}");
break;
@@ -507,6 +563,12 @@ int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const
case InsetSpaceParams::NEGTHIN:
os << (runparams.free_spacing ? " " : "\\negthinspace{}");
break;
+ case InsetSpaceParams::NEGMEDIUM:
+ os << (runparams.free_spacing ? " " : "\\negmedspace{}");
+ break;
+ case InsetSpaceParams::NEGTHICK:
+ os << (runparams.free_spacing ? " " : "\\negthickspace{}");
+ break;
case InsetSpaceParams::HFILL:
os << (runparams.free_spacing ? " " : "\\hfill{}");
break;
@@ -592,7 +654,11 @@ int InsetSpace::docbook(odocstream & os, OutputParams const &) const
case InsetSpaceParams::PROTECTED:
case InsetSpaceParams::ENSPACE:
case InsetSpaceParams::THIN:
+ case InsetSpaceParams::MEDIUM:
+ case InsetSpaceParams::THICK:
case InsetSpaceParams::NEGTHIN:
+ case InsetSpaceParams::NEGMEDIUM:
+ case InsetSpaceParams::NEGTHICK:
os << " ";
break;
case InsetSpaceParams::HFILL:
@@ -617,6 +683,14 @@ int InsetSpace::docbook(odocstream & os, OutputParams const &) const
}
+void InsetSpace::validate(LaTeXFeatures & features) const
+{
+ if (params_.kind == InsetSpaceParams::NEGMEDIUM ||
+ params_.kind == InsetSpaceParams::NEGTHICK)
+ features.require("amsmath");
+}
+
+
void InsetSpace::tocString(odocstream & os) const
{
plaintext(os, OutputParams(0));
@@ -652,7 +726,14 @@ void InsetSpace::string2params(string const & in, InsetSpaceParams & params)
Lexer lex;
lex.setStream(data);
lex.setContext("InsetSpace::string2params");
- lex >> "space";
+ lex.next();
+ string const name = lex.getString();
+ if (name == "mathspace")
+ params.math = true;
+ else {
+ params.math = false;
+ LASSERT(name == "space", /**/);
+ }
// There are cases, such as when we are called via getStatus() from
// Dialog::canApply(), where we are just called with "space" rather
@@ -665,6 +746,8 @@ void InsetSpace::string2params(string const & in, InsetSpaceParams & params)
string InsetSpace::params2string(InsetSpaceParams const & params)
{
ostringstream data;
+ if (params.math)
+ data << "math";
data << "space" << ' ';
params.write(data);
return data.str();
diff --git a/src/insets/InsetSpace.h b/src/insets/InsetSpace.h
index 8363645698..777456a7d9 100644
--- a/src/insets/InsetSpace.h
+++ b/src/insets/InsetSpace.h
@@ -33,16 +33,24 @@ public:
PROTECTED,
/// Thin space ('\,')
THIN,
+ /// Medium space ('\:')
+ MEDIUM,
+ /// Thick space ('\;')
+ THICK,
/// \quad (1em)
QUAD,
/// \qquad (2em)
QQUAD,
- /// \enspace (0.5em unbreakable)
+ /// \enskip (0.5em unbreakable)
ENSPACE,
/// \enspace (0.5em breakable)
ENSKIP,
/// Negative thin space ('\negthinspace')
NEGTHIN,
+ /// Negative medium space ('\negmedspace')
+ NEGMEDIUM,
+ /// Negative thick space ('\negthickspace')
+ NEGTHICK,
/// rubber length
HFILL,
/// \hspace*{\fill}
@@ -65,7 +73,7 @@ public:
CUSTOM_PROTECTED
};
///
- InsetSpaceParams() : kind(NORMAL), length(Length()) {}
+ InsetSpaceParams(bool m = false) : kind(NORMAL), math(m) {}
///
void write(std::ostream & os) const;
///
@@ -74,6 +82,11 @@ public:
Kind kind;
///
Length length;
+ /**
+ * Whether these params are to be used in mathed.
+ * This determines the set of valid kinds.
+ */
+ bool math;
};
@@ -99,7 +112,6 @@ public:
///
Length length() const;
-private:
///
docstring toolTip(BufferView const & bv, int x, int y) const;
///
@@ -116,6 +128,8 @@ private:
int plaintext(odocstream &, OutputParams const &) const;
///
int docbook(odocstream &, OutputParams const &) const;
+ ///
+ void validate(LaTeXFeatures & features) const;
/// the string that is passed to the TOC
void tocString(odocstream &) const;
///
@@ -137,13 +151,16 @@ private:
bool isSpace() const { return true; }
///
docstring contextMenu(BufferView const & bv, int x, int y) const;
+protected:
///
Inset * clone() const { return new InsetSpace(*this); }
///
void doDispatch(Cursor & cur, FuncRequest & cmd);
+public:
///
bool getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus &) const;
+private:
///
InsetSpaceParams params_;
};
diff --git a/src/mathed/InsetMathNest.cpp b/src/mathed/InsetMathNest.cpp
index ef2d659d8d..11531f6614 100644
--- a/src/mathed/InsetMathNest.cpp
+++ b/src/mathed/InsetMathNest.cpp
@@ -840,7 +840,6 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
break;
//case LFUN_SERVER_GET_XY:
- // sprintf(dispatch_buffer, "%d %d",);
// break;
case LFUN_SERVER_SET_XY: {
@@ -1055,15 +1054,15 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
case LFUN_SPACE_INSERT:
cur.recordUndoSelection();
- cur.insert(MathAtom(new InsetMathSpace(from_ascii(","))));
+ cur.insert(MathAtom(new InsetMathSpace));
break;
case LFUN_MATH_SPACE:
cur.recordUndoSelection();
if (cmd.argument().empty())
- cur.insert(MathAtom(new InsetMathSpace(from_ascii(","))));
+ cur.insert(MathAtom(new InsetMathSpace));
else
- cur.insert(MathAtom(new InsetMathSpace(cmd.argument())));
+ cur.insert(MathAtom(new InsetMathSpace(to_utf8(cmd.argument()), "")));
break;
case LFUN_ERT_INSERT:
@@ -1131,6 +1130,9 @@ void InsetMathNest::doDispatch(Cursor & cur, FuncRequest & cmd)
if (name == "ref") {
InsetMathRef tmp(name);
data = tmp.createDialogStr(to_utf8(name));
+ } else if (name == "mathspace") {
+ InsetMathSpace tmp;
+ data = tmp.createDialogStr();
}
cur.bv().showDialog(to_utf8(name), data);
break;
@@ -1274,7 +1276,7 @@ bool InsetMathNest::getStatus(Cursor & cur, FuncRequest const & cmd,
// getStatus is not called with a valid reference and the
// dialog would not be applyable.
string const name = cmd.getArg(0);
- flag.setEnabled(name == "ref");
+ flag.setEnabled(name == "ref" || name == "mathspace");
break;
}
diff --git a/src/mathed/InsetMathSpace.cpp b/src/mathed/InsetMathSpace.cpp
index 6a0aae0ede..f3c05358cf 100644
--- a/src/mathed/InsetMathSpace.cpp
+++ b/src/mathed/InsetMathSpace.cpp
@@ -12,63 +12,101 @@
#include "InsetMathSpace.h"
#include "MathData.h"
+#include "MathFactory.h"
#include "MathStream.h"
+#include "MathSupport.h"
+#include "BufferView.h"
+#include "Cursor.h"
+#include "FuncRequest.h"
+#include "FuncStatus.h"
#include "LaTeXFeatures.h"
+#include "insets/InsetSpace.h"
+
+#include "frontends/Application.h"
#include "frontends/Painter.h"
+#include "support/lassert.h"
+
using namespace std;
namespace lyx {
-char const * latex_mathspace[] = {
- "!", "negmedspace", "negthickspace", // negative space
- ",", ":", ";", "quad", "qquad", // positive space
- "lyxnegspace", "lyxposspace" // LyX special ("unvisible space")
-};
-
-int const nSpace = sizeof(latex_mathspace)/sizeof(char *);
-
namespace {
-int spaceToWidth(int space)
-{
- switch (space) {
- case 0: return 6;
- case 1: return 8;
- case 2: return 10;
- case 3: return 6;
- case 4: return 8;
- case 5: return 10;
- case 6: return 20;
- case 7: return 40;
- case 8: return -2;
- case 9: return 2;
- default: return 6;
- }
-}
+struct SpaceInfo {
+ string name;
+ int width;
+ InsetSpaceParams::Kind kind;
+ bool negative;
+ bool visible;
+ bool custom;
+};
+
+SpaceInfo space_info[] = {
+ // name width kind negative visible custom
+ {"!", 6, InsetSpaceParams::NEGTHIN, true, true, false},
+ {"negthinspace", 6, InsetSpaceParams::NEGTHIN, true, true, false},
+ {"negmedspace", 8, InsetSpaceParams::NEGMEDIUM, true, true, false},
+ {"negthickspace", 10, InsetSpaceParams::NEGTHICK, true, true, false},
+ {",", 6, InsetSpaceParams::THIN, false, true, false},
+ {"thinspace", 6, InsetSpaceParams::THIN, false, true, false},
+ {":", 8, InsetSpaceParams::MEDIUM, false, true, false},
+ {"medspace", 8, InsetSpaceParams::MEDIUM, false, true, false},
+ {";", 10, InsetSpaceParams::THICK, false, true, false},
+ {"thickspace", 10, InsetSpaceParams::THICK, false, true, false},
+ {"enskip", 10, InsetSpaceParams::ENSKIP, 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},
+ {"hspace", 0, InsetSpaceParams::CUSTOM, false, true, true},
+};
+
+int const nSpace = sizeof(space_info)/sizeof(SpaceInfo);
+int const defaultSpace = 4;
} // anon namespace
-InsetMathSpace::InsetMathSpace(int sp)
- : space_(sp)
+InsetMathSpace::InsetMathSpace()
+ : space_(defaultSpace)
{
- dim_.asc = 4;
- dim_.des = 0;
- dim_.wid = spaceToWidth(space_);
}
-InsetMathSpace::InsetMathSpace(docstring const & name)
- : space_(1)
+InsetMathSpace::InsetMathSpace(string const & name, string const & length)
+ : space_(defaultSpace)
{
- dim_.asc = 4;
- dim_.des = 0;
for (int i = 0; i < nSpace; ++i)
- if (latex_mathspace[i] == name)
+ if (space_info[i].name == name) {
space_ = i;
- dim_.wid = spaceToWidth(space_);
+ break;
+ }
+ if (space_info[space_].custom) {
+ length_ = Length(length);
+ if (length_.zero() || length_.empty()) {
+ length_.value(1.0);
+ length_.unit(Length::EM);
+ }
+ }
+}
+
+
+InsetMathSpace::InsetMathSpace(Length const & length)
+ : space_(defaultSpace), length_(length)
+{
+ for (int i = 0; i < nSpace; ++i)
+ if (space_info[i].name == "hspace") {
+ space_ = i;
+ break;
+ }
+}
+
+
+InsetMathSpace::~InsetMathSpace()
+{
+ hideDialogs("mathspace", this);
}
@@ -78,9 +116,16 @@ Inset * InsetMathSpace::clone() const
}
-void InsetMathSpace::metrics(MetricsInfo &, Dimension & dim) const
+void InsetMathSpace::metrics(MetricsInfo & mi, Dimension & dim) const
{
- dim = dim_;
+ dim.asc = 4;
+ dim.des = 0;
+ if (space_info[space_].custom)
+ dim.wid = abs(length_.inPixels(
+ mi.base.textwidth,
+ mathed_char_width(mi.base.font, 'M')));
+ else
+ dim.wid = space_info[space_].width;
}
@@ -88,36 +133,45 @@ void InsetMathSpace::draw(PainterInfo & pi, int x, int y) const
{
// Sadly, HP-UX CC can't handle that kind of initialization.
// XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
- if (space_ >= nSpace - 2)
+ if (!space_info[space_].visible)
return;
+ Dimension const dim = dimension(*pi.base.bv);
int xp[4];
int yp[4];
- int w = dim_.wid;
+ int w = dim.wid;
xp[0] = ++x; yp[0] = y - 3;
xp[1] = x; yp[1] = y;
xp[2] = x + w - 2; yp[2] = y;
xp[3] = x + w - 2; yp[3] = y - 3;
- pi.pain.lines(xp, yp, 4, (space_ < 3) ? Color_latex : Color_math);
+ pi.pain.lines(xp, yp, 4,
+ space_info[space_].custom ?
+ Color_special :
+ (isNegative() ? Color_latex : Color_math));
}
void InsetMathSpace::incSpace()
{
- space_ = (space_ + 1) % (nSpace - 2);
- dim_.wid = spaceToWidth(space_);
+ int const oldwidth = space_info[space_].width;
+ do
+ space_ = (space_ + 1) % nSpace;
+ while ((space_info[space_].width == oldwidth && !space_info[space_].custom) ||
+ !space_info[space_].visible);
+ if (space_info[space_].custom && (length_.zero() || length_.empty())) {
+ length_.value(1.0);
+ length_.unit(Length::EM);
+ }
}
void InsetMathSpace::validate(LaTeXFeatures & features) const
{
- if (space_ >= 0 && space_< nSpace) {
- if ((latex_mathspace[space_] == string("negmedspace"))
- || (latex_mathspace[space_] == string("negthickspace")))
- features.require("amsmath");
- }
+ if (space_info[space_].name == "negmedspace" ||
+ space_info[space_].name == "negthickspace")
+ features.require("amsmath");
}
@@ -146,12 +200,94 @@ void InsetMathSpace::normalize(NormalStream & os) const
void InsetMathSpace::write(WriteStream & os) const
{
- if (space_ >= 0 && space_ < nSpace) {
- MathEnsurer ensurer(os);
- os << '\\' << latex_mathspace[space_];
+ // no MathEnsurer - all kinds work in text and math mode
+ os << '\\' << space_info[space_].name.c_str();
+ if (space_info[space_].custom)
+ os << '{' << length_.asLatexString().c_str() << '}';
+ else
os.pendingSpace(true);
+}
+
+
+string const InsetMathSpace::createDialogStr() const
+{
+ LASSERT(space_info[space_].visible, /**/);
+ InsetSpaceParams isp(true);
+ isp.kind = space_info[space_].kind;
+ isp.length = length_;
+ return InsetSpace::params2string(isp);
+}
+
+
+docstring InsetMathSpace::contextMenu(BufferView const &, int, int) const
+{
+ return from_ascii("context-mathspace");
+}
+
+
+bool InsetMathSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
+ FuncStatus & status) const
+{
+ switch (cmd.action) {
+ // we handle these
+ case LFUN_INSET_MODIFY:
+ case LFUN_INSET_DIALOG_UPDATE:
+ case LFUN_MOUSE_RELEASE:
+ case LFUN_MOUSE_PRESS:
+ case LFUN_MOUSE_MOTION:
+ status.setEnabled(true);
+ return true;
+ default:
+ bool retval = InsetMath::getStatus(cur, cmd, status);
+ return retval;
}
}
+void InsetMathSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
+{
+ switch (cmd.action) {
+ case LFUN_INSET_MODIFY:
+ if (cmd.getArg(0) == "mathspace") {
+ MathData ar;
+ if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
+ *this = *ar[0].nucleus()->asSpaceInset();
+ break;
+ }
+ }
+ cur.undispatched();
+ break;
+
+ case LFUN_INSET_DIALOG_UPDATE:
+ cur.bv().updateDialog("mathspace", createDialogStr());
+ break;
+
+ case LFUN_MOUSE_RELEASE:
+ if (cmd.button() == mouse_button::button1) {
+ string const data = createDialogStr();
+ cur.bv().showDialog("mathspace", data, this);
+ break;
+ }
+ cur.undispatched();
+ break;
+
+ case LFUN_MOUSE_PRESS:
+ case LFUN_MOUSE_MOTION:
+ // eat other mouse commands
+ break;
+
+ default:
+ InsetMath::doDispatch(cur, cmd);
+ break;
+ }
+}
+
+
+bool InsetMathSpace::isNegative() const
+{
+ if (space_info[space_].custom)
+ return length_.value() < 0;
+ return space_info[space_].negative;
+}
+
} // namespace lyx
diff --git a/src/mathed/InsetMathSpace.h b/src/mathed/InsetMathSpace.h
index eb89e8c50c..15b79d2b58 100644
--- a/src/mathed/InsetMathSpace.h
+++ b/src/mathed/InsetMathSpace.h
@@ -13,6 +13,7 @@
#define MATH_SPACEINSET_H
#include "InsetMath.h"
+#include "Length.h"
namespace lyx {
@@ -22,9 +23,13 @@ namespace lyx {
class InsetMathSpace : public InsetMath {
public:
///
- explicit InsetMathSpace(int sp);
+ explicit InsetMathSpace();
///
- explicit InsetMathSpace(docstring const & name);
+ explicit InsetMathSpace(std::string const & name, std::string const & length);
+ ///
+ explicit InsetMathSpace(Length const & length);
+ ///
+ ~InsetMathSpace();
///
InsetMathSpace const * asSpaceInset() const { return this; }
///
@@ -48,12 +53,25 @@ public:
void octave(OctaveStream &) const;
///
void write(WriteStream & os) const;
+ /// generate something that will be understood by the Dialogs.
+ std::string const createDialogStr() const;
+ ///
+ EDITABLE editable() const { return IS_EDITABLE; }
+ ///
+ docstring contextMenu(BufferView const &, int, int) const;
+ ///
+ bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;
+protected:
+ ///
+ virtual void doDispatch(Cursor & cur, FuncRequest & cmd);
private:
virtual Inset * clone() const;
///
- int space_;
+ bool isNegative() const;
///
- Dimension dim_;
+ int space_;
+ /// amount of space for \\hspace
+ Length length_;
};
diff --git a/src/mathed/MathFactory.cpp b/src/mathed/MathFactory.cpp
index d12ac0aa56..943c7e8ff6 100644
--- a/src/mathed/MathFactory.cpp
+++ b/src/mathed/MathFactory.cpp
@@ -52,6 +52,7 @@
#include "MathSupport.h"
#include "insets/InsetCommand.h"
+#include "insets/InsetSpace.h"
#include "support/debug.h"
#include "support/docstream.h"
@@ -61,7 +62,9 @@
#include "frontends/FontLoader.h"
+#include "Encoding.h"
#include "LyX.h" // use_gui
+#include "OutputParams.h"
using namespace std;
using namespace lyx::support;
@@ -317,7 +320,7 @@ MathAtom createInsetMath(docstring const & s)
if (inset == "decoration")
return MathAtom(new InsetMathDecoration(l));
if (inset == "space")
- return MathAtom(new InsetMathSpace(l->name));
+ return MathAtom(new InsetMathSpace(to_ascii(l->name), ""));
if (inset == "dots")
return MathAtom(new InsetMathDots(l));
if (inset == "mbox")
@@ -477,13 +480,28 @@ bool createInsetMath_fromDialogStr(docstring const & str, MathData & ar)
docstring name;
docstring body = split(str, name, ' ');
- if (name != "ref" )
+ if (name == "ref") {
+ InsetCommandParams icp(REF_CODE);
+ // FIXME UNICODE
+ InsetCommand::string2params("ref", to_utf8(str), icp);
+ mathed_parse_cell(ar, icp.getCommand());
+ } else if (name == "mathspace") {
+ InsetSpaceParams isp(true);
+ InsetSpace::string2params(to_utf8(str), isp);
+ InsetSpace is(isp);
+ odocstringstream os;
+ Encoding const * const ascii = encodings.fromLyXName("ascii");
+ OutputParams op(ascii);
+ is.latex(os, op);
+ mathed_parse_cell(ar, os.str());
+ if (ar.size() == 2) {
+ // remove "{}"
+ if (ar[1].nucleus()->asBraceInset())
+ ar.pop_back();
+ }
+ } else
return false;
- InsetCommandParams icp(REF_CODE);
- // FIXME UNICODE
- InsetCommand::string2params("ref", to_utf8(str), icp);
- mathed_parse_cell(ar, icp.getCommand());
if (ar.size() != 1)
return false;
diff --git a/src/mathed/MathParser.cpp b/src/mathed/MathParser.cpp
index 3cb58f42b7..3845bbc8a3 100644
--- a/src/mathed/MathParser.cpp
+++ b/src/mathed/MathParser.cpp
@@ -54,6 +54,7 @@ following hack as starting point to write some macros:
#include "InsetMathRef.h"
#include "InsetMathRoot.h"
#include "InsetMathScript.h"
+#include "InsetMathSpace.h"
#include "InsetMathSplit.h"
#include "InsetMathSqrt.h"
#include "InsetMathTabular.h"
@@ -671,7 +672,7 @@ docstring Parser::parse_verbatim_option()
putback();
res += '{' + parse_verbatim_item() + '}';
} else
- res += t.asString();
+ res += t.asInput();
}
}
return res;
@@ -690,7 +691,7 @@ docstring Parser::parse_verbatim_item()
res += '{' + parse_verbatim_item() + '}';
}
else
- res += t.asString();
+ res += t.asInput();
}
}
return res;
@@ -1594,6 +1595,22 @@ 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() != '*') {
+ 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)));
+ else {
+ // Since the Length class cannot use length variables
+ // we must not create an InsetMathSpace.
+ cell->push_back(MathAtom(new MathMacro(name)));
+ MathData ar;
+ mathed_parse_cell(ar, '{' + arg + '}');
+ cell->append(ar);
+ }
+ }
+
#if 0
else if (t.cs() == "infer") {
MathData ar;