*
* \author Asger Alstrup Nielsen
* \author Jean-Marc Lasgouttes
- * \author Lars Gullik Bjønnes
- * \author Jürgen Spitzmüller
+ * \author Lars Gullik Bjønnes
+ * \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
#include "Dimension.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
+#include "Language.h"
+#include "LaTeXFeatures.h"
#include "Length.h"
#include "Lexer.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
+#include "output_xhtml.h"
#include "support/debug.h"
#include "support/docstream.h"
#include "support/gettext.h"
+#include "support/lassert.h"
#include "support/lstrings.h"
#include "frontends/Application.h"
InsetSpace::InsetSpace(InsetSpaceParams const & params)
- : params_(params)
+ : Inset(0), params_(params)
{}
}
-Length InsetSpace::length() const
+GlueLength InsetSpace::length() const
{
return params_.length;
}
-InsetSpace::~InsetSpace()
-{
- hideDialogs("space", this);
-}
-
-
docstring InsetSpace::toolTip(BufferView const &, int, int) const
{
docstring message;
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;
case InsetSpaceParams::QQUAD:
- message = _("QQuad Space");
+ message = _("Double Quad Space");
break;
case InsetSpaceParams::ENSPACE:
message = _("Enspace");
case InsetSpaceParams::NEGTHIN:
message = _("Negative Thin Space");
break;
+ case InsetSpaceParams::NEGMEDIUM:
+ message = _("Negative Medium Space");
+ break;
+ case InsetSpaceParams::NEGTHICK:
+ message = _("Negative Thick Space");
+ break;
case InsetSpaceParams::HFILL:
message = _("Horizontal Fill");
break;
message = _("Horizontal Fill (Down Brace)");
break;
case InsetSpaceParams::CUSTOM:
+ // FIXME unicode
message = support::bformat(_("Horizontal Space (%1$s)"),
- params_.length.asDocstring());
+ from_ascii(params_.length.asString()));
break;
case InsetSpaceParams::CUSTOM_PROTECTED:
+ // FIXME unicode
message = support::bformat(_("Protected Horizontal Space (%1$s)"),
- params_.length.asDocstring());
+ from_ascii(params_.length.asString()));
break;
}
return message;
void InsetSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
{
- switch (cmd.action) {
+ switch (cmd.action()) {
- case LFUN_INSET_MODIFY: {
+ case LFUN_INSET_MODIFY:
string2params(to_utf8(cmd.argument()), params_);
break;
- }
- case LFUN_MOUSE_RELEASE:
- if (!cur.selection() && cmd.button() == mouse_button::button1)
- cur.bv().showDialog("space", params2string(params()), this);
+ case LFUN_INSET_DIALOG_UPDATE:
+ cur.bv().updateDialog("space", params2string(params()));
break;
default:
bool InsetSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
FuncStatus & status) const
{
- switch (cmd.action) {
+ switch (cmd.action()) {
// we handle these
case LFUN_INSET_MODIFY:
if (cmd.getArg(0) == "space") {
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:
}
-void InsetSpace::edit(Cursor & cur, bool, EntryDirection)
-{
- cur.bv().showDialog("space", params2string(params()), this);
+namespace {
+int const arrow_size = 8;
}
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(' '));
dim.wid = int(0.5 * fm.width(char_type('M')));
break;
case InsetSpaceParams::CUSTOM:
- case InsetSpaceParams::CUSTOM_PROTECTED:
- dim.wid = max(4, abs(params_.length.inBP()));
+ case InsetSpaceParams::CUSTOM_PROTECTED: {
+ int const w =
+ params_.length.len().inPixels(mi.base.textwidth,
+ fm.width(char_type('M')));
+ int const minw = (w < 0) ? 3 * arrow_size : 4;
+ dim.wid = max(minw, abs(w));
break;
+ }
case InsetSpaceParams::HFILL:
case InsetSpaceParams::HFILL_PROTECTED:
case InsetSpaceParams::DOTFILL:
{
Dimension const dim = dimension(*pi.base.bv);
- if (isStretchableSpace()) {
+ if (isStretchableSpace() || params_.length.len().value() < 0) {
int const asc = theFontMetrics(pi.base.font).ascent('M');
int const desc = theFontMetrics(pi.base.font).descent('M');
// Pixel height divisible by 2 for prettier fill graphics:
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) {
pi.pain.line(xm + 1, y1 + 1 , xmr, y2, Color_special);
pi.pain.line(xmr, y2 , x3, y2, Color_special);
pi.pain.line(x3 + 1, y2 + 1 , x1, y0, Color_special);
+ } else if (params_.kind == InsetSpaceParams::CUSTOM) {
+ pi.pain.line(x0, y1 + 1 , x2 + 1, y2, Color_special);
+ pi.pain.line(x2 + 1, y2 + 1 , x0, y0, Color_special);
+ pi.pain.line(x1 + 1, y1 + 1 , x3, y2, Color_special);
+ pi.pain.line(x3, y2 + 1 , x1 + 1, y0, Color_special);
+ pi.pain.line(x2, y2 , x3, y2, Color_special);
+ } else if (params_.kind == InsetSpaceParams::CUSTOM_PROTECTED) {
+ pi.pain.line(x0, y1 + 1 , x2 + 1, y2, Color_latex);
+ pi.pain.line(x2 + 1, y2 + 1 , x0, y0, Color_latex);
+ pi.pain.line(x1 + 1, y1 + 1 , x3, y2, Color_latex);
+ pi.pain.line(x3, y2 + 1 , x1 + 1, y0, Color_latex);
+ pi.pain.line(x2, y2 , x3, y2, Color_latex);
}
return;
}
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 {
- if (params_.length.inBP() < 0) {
- // use another color for negative spaces
- pi.pain.lines(xp, yp, 4, Color_red);
- } else
- pi.pain.lines(xp, yp, 4, Color_special);
- }
+ else
+ pi.pain.lines(xp, yp, 4, Color_special);
}
case InsetSpaceParams::THIN:
os << "\\thinspace{}";
break;
+ case InsetSpaceParams::MEDIUM:
+ os << "\\medspace{}";
+ break;
+ case InsetSpaceParams::THICK:
+ os << "\\thickspace{}";
+ break;
case InsetSpaceParams::QUAD:
os << "\\quad{}";
break;
case InsetSpaceParams::NEGTHIN:
os << "\\negthinspace{}";
break;
+ case InsetSpaceParams::NEGMEDIUM:
+ os << "\\negmedspace{}";
+ break;
+ case InsetSpaceParams::NEGTHICK:
+ os << "\\negthickspace{}";
+ break;
case InsetSpaceParams::HFILL:
os << "\\hfill{}";
break;
break;
}
- if (!length.empty())
+ if (!length.len().empty())
os << "\n\\length " << length.asString();
}
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{}")
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}")
os << (runparams.free_spacing ? " " : "\\ ");
break;
case InsetSpaceParams::PROTECTED:
- os << (runparams.free_spacing ? ' ' : '~');
+ if (runparams.local_font &&
+ runparams.local_font->language()->lang() == "polutonikogreek")
+ // in babel's polutonikogreek, ~ is active
+ os << (runparams.free_spacing ? " " : "\\nobreakspace{}");
+ else
+ os << (runparams.free_spacing ? ' ' : '~');
break;
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;
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;
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:
}
-void InsetSpace::textString(odocstream & os) const
+docstring InsetSpace::xhtml(XHTMLStream & xs, OutputParams const &) const
+{
+ string output;
+ switch (params_.kind) {
+ case InsetSpaceParams::NORMAL:
+ output = " ";
+ break;
+ case InsetSpaceParams::ENSKIP:
+ case InsetSpaceParams::ENSPACE:
+ output =" ";
+ break;
+ case InsetSpaceParams::QQUAD:
+ output =" ";
+ case InsetSpaceParams::THICK:
+ case InsetSpaceParams::QUAD:
+ output =" ";
+ break;
+ case InsetSpaceParams::THIN:
+ output =" ";
+ break;
+ case InsetSpaceParams::PROTECTED:
+ case InsetSpaceParams::MEDIUM:
+ case InsetSpaceParams::NEGTHIN:
+ case InsetSpaceParams::NEGMEDIUM:
+ case InsetSpaceParams::NEGTHICK:
+ output =" ";
+ break;
+ case InsetSpaceParams::HFILL:
+ case InsetSpaceParams::HFILL_PROTECTED:
+ case InsetSpaceParams::DOTFILL:
+ case InsetSpaceParams::HRULEFILL:
+ case InsetSpaceParams::LEFTARROWFILL:
+ case InsetSpaceParams::RIGHTARROWFILL:
+ case InsetSpaceParams::UPBRACEFILL:
+ case InsetSpaceParams::DOWNBRACEFILL:
+ // FIXME XHTML
+ // Can we do anything with those in HTML?
+ break;
+ case InsetSpaceParams::CUSTOM:
+ case InsetSpaceParams::CUSTOM_PROTECTED:
+ // FIXME XHTML
+ // Probably we could do some sort of blank span?
+ break;
+ }
+ // don't escape the entities!
+ xs << XHTMLStream::NextRaw() << from_ascii(output);
+ return docstring();
+}
+
+
+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));
}
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
string InsetSpace::params2string(InsetSpaceParams const & params)
{
ostringstream data;
+ if (params.math)
+ data << "math";
data << "space" << ' ';
params.write(data);
return data.str();