X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Finsets%2FInsetSpace.cpp;h=a419a684648477620ed6dbccd0a6f846ebe5f9f1;hb=11e7cc23448610d17e998d3cc2ee6f284a330ba4;hp=761526a76dbf2d577652e2ac479189aae156d0aa;hpb=63c45ec226153a9f7f1314ac51e4c1f5a9de9fda;p=lyx.git diff --git a/src/insets/InsetSpace.cpp b/src/insets/InsetSpace.cpp index 761526a76d..a419a68464 100644 --- a/src/insets/InsetSpace.cpp +++ b/src/insets/InsetSpace.cpp @@ -5,8 +5,8 @@ * * \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. */ @@ -15,64 +15,236 @@ #include "InsetSpace.h" -#include "support/debug.h" +#include "BufferView.h" +#include "Cursor.h" #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" #include "frontends/FontMetrics.h" #include "frontends/Painter.h" -#include "support/docstream.h" - using namespace std; namespace lyx { -InsetSpace::InsetSpace() +InsetSpace::InsetSpace(InsetSpaceParams const & params) + : Inset(0), params_(params) {} -InsetSpace::InsetSpace(Kind k) - : kind_(k) -{} +InsetSpaceParams::Kind InsetSpace::kind() const +{ + return params_.kind; +} -InsetSpace::Kind InsetSpace::kind() const +GlueLength InsetSpace::length() const { - return kind_; + return params_.length; +} + + +docstring InsetSpace::toolTip(BufferView const &, int, int) const +{ + docstring message; + switch (params_.kind) { + case InsetSpaceParams::NORMAL: + message = _("Interword Space"); + break; + case InsetSpaceParams::PROTECTED: + message = _("Protected Space"); + break; + 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 = _(" Double Quad Space"); + break; + case InsetSpaceParams::ENSPACE: + message = _("Enspace"); + break; + case InsetSpaceParams::ENSKIP: + message = _("Enskip"); + break; + 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; + case InsetSpaceParams::HFILL_PROTECTED: + message = _("Protected Horizontal Fill"); + break; + case InsetSpaceParams::DOTFILL: + message = _("Horizontal Fill (Dots)"); + break; + case InsetSpaceParams::HRULEFILL: + message = _("Horizontal Fill (Rule)"); + break; + case InsetSpaceParams::LEFTARROWFILL: + message = _("Horizontal Fill (Left Arrow)"); + break; + case InsetSpaceParams::RIGHTARROWFILL: + message = _("Horizontal Fill (Right Arrow)"); + break; + case InsetSpaceParams::UPBRACEFILL: + message = _("Horizontal Fill (Up Brace)"); + break; + case InsetSpaceParams::DOWNBRACEFILL: + message = _("Horizontal Fill (Down Brace)"); + break; + case InsetSpaceParams::CUSTOM: + // FIXME unicode + message = support::bformat(_("Horizontal Space (%1$s)"), + from_ascii(params_.length.asString())); + break; + case InsetSpaceParams::CUSTOM_PROTECTED: + // FIXME unicode + message = support::bformat(_("Protected Horizontal Space (%1$s)"), + from_ascii(params_.length.asString())); + break; + } + return message; +} + + +void InsetSpace::doDispatch(Cursor & cur, FuncRequest & cmd) +{ + switch (cmd.action()) { + + case LFUN_INSET_MODIFY: + string2params(to_utf8(cmd.argument()), params_); + break; + + case LFUN_INSET_DIALOG_UPDATE: + cur.bv().updateDialog("space", params2string(params())); + break; + + default: + Inset::doDispatch(cur, cmd); + break; + } +} + + +bool InsetSpace::getStatus(Cursor & cur, FuncRequest const & cmd, + FuncStatus & status) const +{ + switch (cmd.action()) { + // we handle these + case LFUN_INSET_MODIFY: + if (cmd.getArg(0) == "space") { + InsetSpaceParams params; + 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: + return Inset::getStatus(cur, cmd, status); + } +} + + +namespace { +int const arrow_size = 8; } void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const { + if (isStretchableSpace()) { + // The metrics for this kinds are calculated externally in + // \c TextMetrics::computeRowMetrics. Those are dummy value: + dim = Dimension(10, 10, 10); + return; + } + frontend::FontMetrics const & fm = theFontMetrics(mi.base.font); dim.asc = fm.maxAscent(); dim.des = fm.maxDescent(); - switch (kind_) { - case THIN: - case NEGTHIN: - dim.wid = fm.width(char_type('M')) / 6; + switch (params_.kind) { + case InsetSpaceParams::THIN: + 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 PROTECTED: - case NORMAL: - dim.wid = fm.width(char_type(' ')); + case InsetSpaceParams::THICK: + case InsetSpaceParams::NEGTHICK: + dim.wid = fm.width(char_type('M')) / 2; break; - case QUAD: + case InsetSpaceParams::PROTECTED: + case InsetSpaceParams::NORMAL: + dim.wid = fm.width(char_type(' ')); + break; + case InsetSpaceParams::QUAD: dim.wid = fm.width(char_type('M')); break; - case QQUAD: + case InsetSpaceParams::QQUAD: dim.wid = 2 * fm.width(char_type('M')); break; - case ENSPACE: - case ENSKIP: + case InsetSpaceParams::ENSPACE: + case InsetSpaceParams::ENSKIP: dim.wid = int(0.5 * fm.width(char_type('M'))); break; + case InsetSpaceParams::CUSTOM: + 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: + case InsetSpaceParams::HRULEFILL: + case InsetSpaceParams::LEFTARROWFILL: + case InsetSpaceParams::RIGHTARROWFILL: + case InsetSpaceParams::UPBRACEFILL: + case InsetSpaceParams::DOWNBRACEFILL: + // shut up compiler + break; } - // Cache the inset dimension. + // Cache the inset dimension. setDimCache(mi, dim); } @@ -80,14 +252,100 @@ void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const void InsetSpace::draw(PainterInfo & pi, int x, int y) const { Dimension const dim = dimension(*pi.base.bv); + + 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: + int const oddheight = (asc ^ desc) & 1; + int const x0 = x + 1; + int const x1 = x + dim.wid - 2; + int const y0 = y + desc - 1; + int const y1 = y - asc + oddheight - 1; + int const y2 = (y0 + y1) / 2; + int xoffset = (y0 - y1) / 2; + + // Two tests for very narrow insets + if (xoffset > x1 - x0 + && (params_.kind == InsetSpaceParams::LEFTARROWFILL + || params_.kind == InsetSpaceParams::RIGHTARROWFILL)) + xoffset = x1 - x0; + if (xoffset * 6 > (x1 - x0) + && (params_.kind == InsetSpaceParams::UPBRACEFILL + || params_.kind == InsetSpaceParams::DOWNBRACEFILL)) + xoffset = (x1 - x0) / 6; + + int const x2 = x0 + xoffset; + int const x3 = x1 - xoffset; + int const xm = (x0 + x1) / 2; + int const xml = xm - xoffset; + int const xmr = xm + xoffset; + + 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, + 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, + frontend::Painter::line_onoffdash); + pi.pain.line(x1, y1, x1, y0, Color_latex); + } else if (params_.kind == InsetSpaceParams::DOTFILL) { + pi.pain.line(x0, y1, x0, y0, Color_special); + pi.pain.line(x0, y0, x1, y0, Color_special, + frontend::Painter::line_onoffdash); + pi.pain.line(x1, y1, x1, y0, Color_special); + } else if (params_.kind == InsetSpaceParams::HRULEFILL) { + pi.pain.line(x0, y1, x0, y0, Color_special); + pi.pain.line(x0, y0, x1, y0, Color_special); + pi.pain.line(x1, y1, x1, y0, Color_special); + } else if (params_.kind == InsetSpaceParams::LEFTARROWFILL) { + pi.pain.line(x2, y1 + 1 , x0 + 1, y2, Color_special); + pi.pain.line(x0 + 1, y2 + 1 , x2, y0, Color_special); + pi.pain.line(x0, y2 , x1, y2, Color_special); + } else if (params_.kind == InsetSpaceParams::RIGHTARROWFILL) { + pi.pain.line(x3 + 1, y1 + 1 , x1, y2, Color_special); + pi.pain.line(x1, y2 + 1 , x3 + 1, y0, Color_special); + pi.pain.line(x0, y2 , x1, y2, Color_special); + } else if (params_.kind == InsetSpaceParams::UPBRACEFILL) { + pi.pain.line(x0 + 1, y1 + 1 , x2, y2, Color_special); + pi.pain.line(x2, y2 , xml, y2, Color_special); + pi.pain.line(xml + 1, y2 + 1 , xm, y0, Color_special); + pi.pain.line(xm + 1, y0 , xmr, y2 + 1, Color_special); + pi.pain.line(xmr, y2 , x3, y2, Color_special); + pi.pain.line(x3 + 1, y2 , x1, y1 + 1, Color_special); + } else if (params_.kind == InsetSpaceParams::DOWNBRACEFILL) { + pi.pain.line(x0 + 1, y0 , x2, y2 + 1, Color_special); + pi.pain.line(x2, y2 , xml, y2, Color_special); + pi.pain.line(xml + 1, y2 , xm, y1 + 1, Color_special); + 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; + } + int const w = dim.wid; - int const h = theFontMetrics(pi.base.font) - .ascent('x'); + int const h = theFontMetrics(pi.base.font).ascent('x'); int xp[4], yp[4]; xp[0] = x; yp[0] = y - max(h / 4, 1); - if (kind_ == NORMAL || kind_ == PROTECTED) { + if (params_.kind == InsetSpaceParams::NORMAL || + params_.kind == InsetSpaceParams::PROTECTED) { xp[1] = x; yp[1] = y; xp[2] = x + w; yp[2] = y; } else { @@ -97,159 +355,444 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const xp[3] = x + w; yp[3] = y - max(h / 4, 1); - if (kind_ == PROTECTED || kind_ == ENSPACE || kind_ == NEGTHIN) + 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 pi.pain.lines(xp, yp, 4, Color_special); } -void InsetSpace::write(Buffer const &, ostream & os) const +void InsetSpaceParams::write(ostream & os) const { string command; - switch (kind_) { - case NORMAL: - command = "\\space{}"; + switch (kind) { + case InsetSpaceParams::NORMAL: + os << "\\space{}"; + break; + case InsetSpaceParams::PROTECTED: + os << "~"; + break; + 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::QQUAD: + os << "\\qquad{}"; + break; + case InsetSpaceParams::ENSPACE: + os << "\\enspace{}"; break; - case PROTECTED: - command = "~"; + case InsetSpaceParams::ENSKIP: + os << "\\enskip{}"; break; - case THIN: - command = "\\thinspace{}"; + case InsetSpaceParams::NEGTHIN: + os << "\\negthinspace{}"; break; - case QUAD: - command = "\\quad{}"; + case InsetSpaceParams::NEGMEDIUM: + os << "\\negmedspace{}"; break; - case QQUAD: - command = "\\qquad{}"; + case InsetSpaceParams::NEGTHICK: + os << "\\negthickspace{}"; break; - case ENSPACE: - command = "\\enspace{}"; + case InsetSpaceParams::HFILL: + os << "\\hfill{}"; break; - case ENSKIP: - command = "\\enskip{}"; + case InsetSpaceParams::HFILL_PROTECTED: + os << "\\hspace*{\\fill}"; break; - case NEGTHIN: - command = "\\negthinspace{}"; + case InsetSpaceParams::DOTFILL: + os << "\\dotfill{}"; + break; + case InsetSpaceParams::HRULEFILL: + os << "\\hrulefill{}"; + break; + case InsetSpaceParams::LEFTARROWFILL: + os << "\\leftarrowfill{}"; + break; + case InsetSpaceParams::RIGHTARROWFILL: + os << "\\rightarrowfill{}"; + break; + case InsetSpaceParams::UPBRACEFILL: + os << "\\upbracefill{}"; + break; + case InsetSpaceParams::DOWNBRACEFILL: + os << "\\downbracefill{}"; + break; + case InsetSpaceParams::CUSTOM: + os << "\\hspace{}"; + break; + case InsetSpaceParams::CUSTOM_PROTECTED: + os << "\\hspace*{}"; break; } - os << "\\InsetSpace " << command << "\n"; + + if (!length.len().empty()) + os << "\n\\length " << length.asString(); } -void InsetSpace::read(Buffer const &, Lexer & lex) +void InsetSpaceParams::read(Lexer & lex) { - lex.next(); - string const command = lex.getString(); + lex.setContext("InsetSpaceParams::read"); + string command; + lex >> command; + // The tests for math might be disabled after a file format change if (command == "\\space{}") - kind_ = NORMAL; + kind = InsetSpaceParams::NORMAL; else if (command == "~") - kind_ = PROTECTED; + kind = InsetSpaceParams::PROTECTED; else if (command == "\\thinspace{}") - kind_ = THIN; + kind = InsetSpaceParams::THIN; + else if (math && command == "\\medspace{}") + kind = InsetSpaceParams::MEDIUM; + else if (math && command == "\\thickspace{}") + kind = InsetSpaceParams::THICK; else if (command == "\\quad{}") - kind_ = QUAD; + kind = InsetSpaceParams::QUAD; else if (command == "\\qquad{}") - kind_ = QQUAD; + kind = InsetSpaceParams::QQUAD; else if (command == "\\enspace{}") - kind_ = ENSPACE; + kind = InsetSpaceParams::ENSPACE; else if (command == "\\enskip{}") - kind_ = ENSKIP; + kind = InsetSpaceParams::ENSKIP; else if (command == "\\negthinspace{}") - kind_ = NEGTHIN; + 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}") + kind = InsetSpaceParams::HFILL_PROTECTED; + else if (command == "\\dotfill{}") + kind = InsetSpaceParams::DOTFILL; + else if (command == "\\hrulefill{}") + kind = InsetSpaceParams::HRULEFILL; + else if (command == "\\hspace{}") + kind = InsetSpaceParams::CUSTOM; + else if (command == "\\leftarrowfill{}") + kind = InsetSpaceParams::LEFTARROWFILL; + else if (command == "\\rightarrowfill{}") + kind = InsetSpaceParams::RIGHTARROWFILL; + else if (command == "\\upbracefill{}") + kind = InsetSpaceParams::UPBRACEFILL; + else if (command == "\\downbracefill{}") + kind = InsetSpaceParams::DOWNBRACEFILL; + else if (command == "\\hspace*{}") + kind = InsetSpaceParams::CUSTOM_PROTECTED; else lex.printError("InsetSpace: Unknown kind: `$$Token'"); + + if (lex.checkFor("\\length")) + lex >> length; +} + + +void InsetSpace::write(ostream & os) const +{ + os << "space "; + params_.write(os); } -int InsetSpace::latex(Buffer const &, odocstream & os, - OutputParams const & runparams) const +void InsetSpace::read(Lexer & lex) { - switch (kind_) { - case NORMAL: + params_.read(lex); + lex >> "\\end_inset"; +} + + +int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const +{ + switch (params_.kind) { + case InsetSpaceParams::NORMAL: os << (runparams.free_spacing ? " " : "\\ "); break; - case PROTECTED: - os << (runparams.free_spacing ? ' ' : '~'); + case InsetSpaceParams::PROTECTED: + 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 THIN: + case InsetSpaceParams::THIN: os << (runparams.free_spacing ? " " : "\\,"); break; - case QUAD: + 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 QQUAD: + case InsetSpaceParams::QQUAD: os << (runparams.free_spacing ? " " : "\\qquad{}"); break; - case ENSPACE: + case InsetSpaceParams::ENSPACE: os << (runparams.free_spacing ? " " : "\\enspace{}"); break; - case ENSKIP: + case InsetSpaceParams::ENSKIP: os << (runparams.free_spacing ? " " : "\\enskip{}"); break; - case NEGTHIN: + 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::HFILL_PROTECTED: + os << (runparams.free_spacing ? " " : "\\hspace*{\\fill}"); + break; + case InsetSpaceParams::DOTFILL: + os << (runparams.free_spacing ? " " : "\\dotfill{}"); + break; + case InsetSpaceParams::HRULEFILL: + os << (runparams.free_spacing ? " " : "\\hrulefill{}"); + break; + case InsetSpaceParams::LEFTARROWFILL: + os << (runparams.free_spacing ? " " : "\\leftarrowfill{}"); + break; + case InsetSpaceParams::RIGHTARROWFILL: + os << (runparams.free_spacing ? " " : "\\rightarrowfill{}"); + break; + case InsetSpaceParams::UPBRACEFILL: + os << (runparams.free_spacing ? " " : "\\upbracefill{}"); + break; + case InsetSpaceParams::DOWNBRACEFILL: + os << (runparams.free_spacing ? " " : "\\downbracefill{}"); + break; + case InsetSpaceParams::CUSTOM: + if (runparams.free_spacing) + os << " "; + else + os << "\\hspace{" << from_ascii(params_.length.asLatexString()) << "}"; + break; + case InsetSpaceParams::CUSTOM_PROTECTED: + if (runparams.free_spacing) + os << " "; + else + os << "\\hspace*{" << from_ascii(params_.length.asLatexString()) << "}"; + break; } return 0; } -int InsetSpace::plaintext(Buffer const &, odocstream & os, - OutputParams const &) const +int InsetSpace::plaintext(odocstream & os, OutputParams const &) const { - os << ' '; - return 1; + switch (params_.kind) { + case InsetSpaceParams::HFILL: + case InsetSpaceParams::HFILL_PROTECTED: + os << " "; + return 5; + case InsetSpaceParams::DOTFILL: + os << "....."; + return 5; + case InsetSpaceParams::HRULEFILL: + os << "_____"; + return 5; + case InsetSpaceParams::LEFTARROWFILL: + os << "<----"; + return 5; + case InsetSpaceParams::RIGHTARROWFILL: + os << "---->"; + return 5; + case InsetSpaceParams::UPBRACEFILL: + os << "\\-v-/"; + return 5; + case InsetSpaceParams::DOWNBRACEFILL: + os << "/-^-\\"; + return 5; + default: + os << ' '; + return 1; + } } -int InsetSpace::docbook(Buffer const &, odocstream & os, - OutputParams const &) const +int InsetSpace::docbook(odocstream & os, OutputParams const &) const { - switch (kind_) { - case NORMAL: - case QUAD: - case QQUAD: - case ENSKIP: + switch (params_.kind) { + case InsetSpaceParams::NORMAL: + case InsetSpaceParams::QUAD: + case InsetSpaceParams::QQUAD: + case InsetSpaceParams::ENSKIP: os << " "; break; - case PROTECTED: - case ENSPACE: - case THIN: - case NEGTHIN: + 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: + case InsetSpaceParams::HFILL_PROTECTED: + os << '\n'; + case InsetSpaceParams::DOTFILL: + // FIXME + os << '\n'; + case InsetSpaceParams::HRULEFILL: + // FIXME + os << '\n'; + case InsetSpaceParams::LEFTARROWFILL: + case InsetSpaceParams::RIGHTARROWFILL: + case InsetSpaceParams::UPBRACEFILL: + case InsetSpaceParams::DOWNBRACEFILL: + case InsetSpaceParams::CUSTOM: + case InsetSpaceParams::CUSTOM_PROTECTED: + // FIXME + os << '\n'; } return 0; } -void InsetSpace::textString(Buffer const & buf, odocstream & os) const +docstring InsetSpace::xhtml(XHTMLStream & xs, OutputParams const &) const { - plaintext(buf, os, OutputParams(0)); + 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"); } -Inset * InsetSpace::clone() const +void InsetSpace::tocString(odocstream & os) const { - return new InsetSpace(kind_); + plaintext(os, OutputParams(0)); } -bool InsetSpace::isChar() const +bool InsetSpace::isStretchableSpace() const { - return true; + return params_.kind == InsetSpaceParams::HFILL + || params_.kind == InsetSpaceParams::HFILL_PROTECTED + || params_.kind == InsetSpaceParams::DOTFILL + || params_.kind == InsetSpaceParams::HRULEFILL + || params_.kind == InsetSpaceParams::LEFTARROWFILL + || params_.kind == InsetSpaceParams::RIGHTARROWFILL + || params_.kind == InsetSpaceParams::UPBRACEFILL + || params_.kind == InsetSpaceParams::DOWNBRACEFILL; } -bool InsetSpace::isLetter() const + +docstring InsetSpace::contextMenu(BufferView const &, int, int) const { - return false; + return from_ascii("context-space"); } -bool InsetSpace::isSpace() const + +void InsetSpace::string2params(string const & in, InsetSpaceParams & params) +{ + params = InsetSpaceParams(); + if (in.empty()) + return; + + istringstream data(in); + Lexer lex; + lex.setStream(data); + lex.setContext("InsetSpace::string2params"); + 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 + // than a full "space \type{}\n\\end_inset". + if (lex.isOK()) + params.read(lex); +} + + +string InsetSpace::params2string(InsetSpaceParams const & params) { - return true; + ostringstream data; + if (params.math) + data << "math"; + data << "space" << ' '; + params.write(data); + return data.str(); }