X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetSpace.cpp;h=ddb85b71ea6b4ca69d69a50f06383fc7400a4599;hb=d6a93143ec2146210d79f58cac42f9608da86100;hp=7ece382c4338e61e5a0b07609d26b5ba588ddee7;hpb=832d6cd7e1017b11058048a9dc6930ec08aee30c;p=lyx.git diff --git a/src/insets/InsetSpace.cpp b/src/insets/InsetSpace.cpp index 7ece382c43..ddb85b71ea 100644 --- a/src/insets/InsetSpace.cpp +++ b/src/insets/InsetSpace.cpp @@ -27,6 +27,7 @@ #include "MetricsInfo.h" #include "OutputParams.h" #include "output_xhtml.h" +#include "texstream.h" #include "support/debug.h" #include "support/docstream.h" @@ -70,6 +71,9 @@ docstring InsetSpace::toolTip(BufferView const &, int, int) const case InsetSpaceParams::PROTECTED: message = _("Protected Space"); break; + case InsetSpaceParams::VISIBLE: + message = _("Visible Space"); + break; case InsetSpaceParams::THIN: message = _("Thin Space"); break; @@ -143,10 +147,16 @@ void InsetSpace::doDispatch(Cursor & cur, FuncRequest & cmd) { switch (cmd.action()) { - case LFUN_INSET_MODIFY: + case LFUN_INSET_MODIFY: { cur.recordUndo(); - string2params(to_utf8(cmd.argument()), params_); + string arg = to_utf8(cmd.argument()); + if (arg == "space \\hspace{}") + arg += params_.length.len().empty() + ? " \\length 1" + string(stringFromUnit(Length::defaultUnit())) + : " \\length " + params_.length.asString(); + string2params(arg, params_); break; + } case LFUN_INSET_DIALOG_UPDATE: cur.bv().updateDialog("space", params2string(params())); @@ -169,8 +179,11 @@ bool InsetSpace::getStatus(Cursor & cur, FuncRequest const & cmd, InsetSpaceParams params; string2params(to_utf8(cmd.argument()), params); status.setOnOff(params_.kind == params.kind); - } - // fall through + status.setEnabled(true); + } else + status.setEnabled(false); + return true; + case LFUN_INSET_DIALOG_UPDATE: status.setEnabled(true); return true; @@ -187,49 +200,50 @@ 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); + if (isHfill()) { + // The width for hfills is calculated externally in + // TextMetrics::computeRowMetrics. The value of 5 is the + // minimal value when the hfill is not active. + dim = Dimension(5, 10, 10); return; } frontend::FontMetrics const & fm = theFontMetrics(mi.base.font); dim.asc = fm.maxAscent(); dim.des = fm.maxDescent(); + int const em = fm.em(); switch (params_.kind) { case InsetSpaceParams::THIN: case InsetSpaceParams::NEGTHIN: - dim.wid = fm.width(char_type('M')) / 6; + dim.wid = em / 6; break; case InsetSpaceParams::MEDIUM: case InsetSpaceParams::NEGMEDIUM: - dim.wid = fm.width(char_type('M')) / 4; + dim.wid = em / 4; break; case InsetSpaceParams::THICK: case InsetSpaceParams::NEGTHICK: - dim.wid = fm.width(char_type('M')) / 2; + dim.wid = em / 2; break; case InsetSpaceParams::PROTECTED: + case InsetSpaceParams::VISIBLE: case InsetSpaceParams::NORMAL: dim.wid = fm.width(char_type(' ')); break; case InsetSpaceParams::QUAD: - dim.wid = fm.width(char_type('M')); + dim.wid = em; break; case InsetSpaceParams::QQUAD: - dim.wid = 2 * fm.width(char_type('M')); + dim.wid = 2 * em; break; case InsetSpaceParams::ENSPACE: case InsetSpaceParams::ENSKIP: - dim.wid = int(0.5 * fm.width(char_type('M'))); + dim.wid = int(0.5 * em); 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 w = mi.base.inPixels(params_.length.len()); int const minw = (w < 0) ? 3 * arrow_size : 4; dim.wid = max(minw, abs(w)); break; @@ -245,8 +259,6 @@ void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const // shut up compiler break; } - // Cache the inset dimension. - setDimCache(mi, dim); } @@ -254,7 +266,7 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const { Dimension const dim = dimension(*pi.base.bv); - if (isStretchableSpace() || params_.length.len().value() < 0) { + if (isHfill() || 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: @@ -340,37 +352,40 @@ void InsetSpace::draw(PainterInfo & pi, int x, int y) const } int const w = dim.wid; - int const h = theFontMetrics(pi.base.font).ascent('x'); + int const h = theFontMetrics(pi.base.font).xHeight(); int xp[4], yp[4]; - xp[0] = x; + xp[0] = x + 1; yp[0] = y - max(h / 4, 1); if (params_.kind == InsetSpaceParams::NORMAL || - params_.kind == InsetSpaceParams::PROTECTED) { - xp[1] = x; yp[1] = y; - xp[2] = x + w; yp[2] = y; + params_.kind == InsetSpaceParams::PROTECTED || + params_.kind == InsetSpaceParams::VISIBLE) { + xp[1] = x + 1; yp[1] = y; + xp[2] = x + w - 2; yp[2] = y; } else { - xp[1] = x; yp[1] = y + max(h / 4, 1); - xp[2] = x + w; yp[2] = y + max(h / 4, 1); + xp[1] = x + 1; yp[1] = y + max(h / 4, 1); + xp[2] = x + w - 2; yp[2] = y + max(h / 4, 1); } - xp[3] = x + w; + xp[3] = x + w - 2; yp[3] = y - max(h / 4, 1); + Color col = Color_special; 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); + col = Color_latex; + else if (params_.kind == InsetSpaceParams::VISIBLE) + col = Color_foreground; + + pi.pain.lines(xp, yp, 4, col); } void InsetSpaceParams::write(ostream & os) const { - string command; switch (kind) { case InsetSpaceParams::NORMAL: os << "\\space{}"; @@ -378,6 +393,9 @@ void InsetSpaceParams::write(ostream & os) const case InsetSpaceParams::PROTECTED: os << "~"; break; + case InsetSpaceParams::VISIBLE: + os << "\\textvisiblespace{}"; + break; case InsetSpaceParams::THIN: os << "\\thinspace{}"; break; @@ -439,7 +457,7 @@ void InsetSpaceParams::write(ostream & os) const os << "\\hspace*{}"; break; } - + if (!length.len().empty()) os << "\n\\length " << length.asString(); } @@ -456,6 +474,8 @@ void InsetSpaceParams::read(Lexer & lex) kind = InsetSpaceParams::NORMAL; else if (command == "~") kind = InsetSpaceParams::PROTECTED; + else if (command == "\\textvisiblespace{}") + kind = InsetSpaceParams::VISIBLE; else if (command == "\\thinspace{}") kind = InsetSpaceParams::THIN; else if (math && command == "\\medspace{}") @@ -472,9 +492,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; @@ -518,7 +538,7 @@ void InsetSpace::read(Lexer & lex) } -int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const +void InsetSpace::latex(otexstream & os, OutputParams const & runparams) const { switch (params_.kind) { case InsetSpaceParams::NORMAL: @@ -532,6 +552,9 @@ int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const else os << (runparams.free_spacing ? ' ' : '~'); break; + case InsetSpaceParams::VISIBLE: + os << (runparams.free_spacing ? " " : "\\textvisiblespace{}"); + break; case InsetSpaceParams::THIN: os << (runparams.free_spacing ? " " : "\\,"); break; @@ -599,11 +622,11 @@ int InsetSpace::latex(odocstream & os, OutputParams const & runparams) const os << "\\hspace*{" << from_ascii(params_.length.asLatexString()) << "}"; break; } - return 0; } -int InsetSpace::plaintext(odocstream & os, OutputParams const &) const +int InsetSpace::plaintext(odocstringstream & os, + OutputParams const &, size_t) const { switch (params_.kind) { case InsetSpaceParams::HFILL: @@ -628,6 +651,45 @@ int InsetSpace::plaintext(odocstream & os, OutputParams const &) const case InsetSpaceParams::DOWNBRACEFILL: os << "/-^-\\"; return 5; + case InsetSpaceParams::VISIBLE: + os.put(0x2423); + return 1; + case InsetSpaceParams::ENSKIP: + os.put(0x2002); + return 1; + case InsetSpaceParams::ENSPACE: + os.put(0x2060); // WORD JOINER, makes the breakable en space unbreakable + os.put(0x2002); + os.put(0x2060); // WORD JOINER, makes the breakable en space unbreakable + return 3; + case InsetSpaceParams::QUAD: + os.put(0x2003); + return 1; + case InsetSpaceParams::QQUAD: + os.put(0x2003); + os.put(0x2003); + return 2; + case InsetSpaceParams::THIN: + os.put(0x202f); + return 1; + case InsetSpaceParams::MEDIUM: + os.put(0x200b); // ZERO WIDTH SPACE, makes the unbreakable medium space breakable + os.put(0x2005); + os.put(0x200b); // ZERO WIDTH SPACE, makes the unbreakable medium space breakable + return 1; + case InsetSpaceParams::THICK: + os.put(0x200b); // ZERO WIDTH SPACE, makes the unbreakable thick space breakable + os.put(0x2004); + os.put(0x200b); // ZERO WIDTH SPACE, makes the unbreakable thick space breakable + return 1; + case InsetSpaceParams::PROTECTED: + case InsetSpaceParams::CUSTOM_PROTECTED: + os.put(0x00a0); + return 1; + case InsetSpaceParams::NEGTHIN: + case InsetSpaceParams::NEGMEDIUM: + case InsetSpaceParams::NEGTHICK: + return 0; default: os << ' '; return 1; @@ -639,30 +701,53 @@ int InsetSpace::docbook(odocstream & os, OutputParams const &) const { switch (params_.kind) { case InsetSpaceParams::NORMAL: + os << " "; + break; case InsetSpaceParams::QUAD: + os << " "; + break; case InsetSpaceParams::QQUAD: + os << "  "; + break; case InsetSpaceParams::ENSKIP: - os << " "; + os << " "; break; case InsetSpaceParams::PROTECTED: + os << " "; + break; + case InsetSpaceParams::VISIBLE: + os << "␣"; + break; case InsetSpaceParams::ENSPACE: + os << "⁠ ⁠"; + break; case InsetSpaceParams::THIN: + os << " "; + break; case InsetSpaceParams::MEDIUM: + os << " "; + break; case InsetSpaceParams::THICK: + os << " "; + break; case InsetSpaceParams::NEGTHIN: case InsetSpaceParams::NEGMEDIUM: case InsetSpaceParams::NEGTHICK: + // FIXME os << " "; break; case InsetSpaceParams::HFILL: case InsetSpaceParams::HFILL_PROTECTED: os << '\n'; + break; case InsetSpaceParams::DOTFILL: // FIXME os << '\n'; + break; case InsetSpaceParams::HRULEFILL: // FIXME os << '\n'; + break; case InsetSpaceParams::LEFTARROWFILL: case InsetSpaceParams::RIGHTARROWFILL: case InsetSpaceParams::UPBRACEFILL: @@ -671,6 +756,7 @@ int InsetSpace::docbook(odocstream & os, OutputParams const &) const case InsetSpaceParams::CUSTOM_PROTECTED: // FIXME os << '\n'; + break; } return 0; } @@ -684,25 +770,36 @@ docstring InsetSpace::xhtml(XHTMLStream & xs, OutputParams const &) const output = " "; break; case InsetSpaceParams::ENSKIP: - case InsetSpaceParams::ENSPACE: output =" "; break; + case InsetSpaceParams::ENSPACE: + output ="⁠ ⁠"; + break; case InsetSpaceParams::QQUAD: - output =" "; + output ="  "; + break; case InsetSpaceParams::THICK: + output =" "; + break; case InsetSpaceParams::QUAD: output =" "; break; + case InsetSpaceParams::MEDIUM: + output =" "; + break; case InsetSpaceParams::THIN: output =" "; break; case InsetSpaceParams::PROTECTED: - case InsetSpaceParams::MEDIUM: case InsetSpaceParams::NEGTHIN: case InsetSpaceParams::NEGMEDIUM: case InsetSpaceParams::NEGTHICK: output =" "; break; + // no XHTML entity, only unicode code for space character exists + case InsetSpaceParams::VISIBLE: + output ="␣"; + break; case InsetSpaceParams::HFILL: case InsetSpaceParams::HFILL_PROTECTED: case InsetSpaceParams::DOTFILL: @@ -715,9 +812,13 @@ docstring InsetSpace::xhtml(XHTMLStream & xs, OutputParams const &) const // Can we do anything with those in HTML? break; case InsetSpaceParams::CUSTOM: + // FIXME XHTML + // Probably we could do some sort of blank span? + break; case InsetSpaceParams::CUSTOM_PROTECTED: // FIXME XHTML // Probably we could do some sort of blank span? + output =" "; break; } // don't escape the entities! @@ -729,18 +830,27 @@ docstring InsetSpace::xhtml(XHTMLStream & xs, OutputParams const &) const void InsetSpace::validate(LaTeXFeatures & features) const { if (params_.kind == InsetSpaceParams::NEGMEDIUM || - params_.kind == InsetSpaceParams::NEGTHICK) + params_.kind == InsetSpaceParams::NEGTHICK) features.require("amsmath"); } void InsetSpace::toString(odocstream & os) const { - plaintext(os, OutputParams(0)); + odocstringstream ods; + plaintext(ods, OutputParams(0)); + os << ods.str(); +} + + +void InsetSpace::forOutliner(docstring & os, size_t const, bool const) const +{ + // There's no need to be cute here. + os += " "; } -bool InsetSpace::isStretchableSpace() const +bool InsetSpace::isHfill() const { return params_.kind == InsetSpaceParams::HFILL || params_.kind == InsetSpaceParams::HFILL_PROTECTED @@ -753,9 +863,9 @@ bool InsetSpace::isStretchableSpace() const } -docstring InsetSpace::contextMenuName() const +string InsetSpace::contextMenuName() const { - return from_ascii("context-space"); + return "context-space"; } @@ -775,7 +885,8 @@ void InsetSpace::string2params(string const & in, InsetSpaceParams & params) params.math = true; else { params.math = false; - LASSERT(name == "space", /**/); + // we can try to read this even if the name is wrong + LATTEST(name == "space"); } // There are cases, such as when we are called via getStatus() from