X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fmathed%2FInsetMathSpace.cpp;h=f4c4d25f1ce117ab5fdbe58df7b9e7b0ea3109a2;hb=dc976c2b6f6e1f19ee4d884c12abafbdae9e5126;hp=4aa9ed58c1d025a70f8f1a5b8f9077ae4a47eb11;hpb=31713932b247802b5b59482f5157c8a4f7206825;p=lyx.git diff --git a/src/mathed/InsetMathSpace.cpp b/src/mathed/InsetMathSpace.cpp index 4aa9ed58c1..f4c4d25f1c 100644 --- a/src/mathed/InsetMathSpace.cpp +++ b/src/mathed/InsetMathSpace.cpp @@ -3,7 +3,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author André Pönitz + * \author André Pönitz * * Full author contact details are available in file CREDITS. */ @@ -12,63 +12,104 @@ #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 "MetricsInfo.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") +namespace { + +struct SpaceInfo { + string name; + int width; + InsetSpaceParams::Kind kind; + bool negative; + bool visible; + bool custom; + bool escape; ///< whether a backslash needs to be added for writing }; -int const nSpace = sizeof(latex_mathspace)/sizeof(char *); +SpaceInfo space_info[] = { + // name width kind negative visible custom escape + {"!", 6, InsetSpaceParams::NEGTHIN, true, true, false, true}, + {"negthinspace", 6, InsetSpaceParams::NEGTHIN, true, true, false, true}, + {"negmedspace", 8, InsetSpaceParams::NEGMEDIUM, true, true, false, true}, + {"negthickspace", 10, InsetSpaceParams::NEGTHICK, true, true, false, true}, + {",", 6, InsetSpaceParams::THIN, false, true, false, true}, + {"thinspace", 6, InsetSpaceParams::THIN, false, true, false, true}, + {":", 8, InsetSpaceParams::MEDIUM, false, true, false, true}, + {"medspace", 8, InsetSpaceParams::MEDIUM, false, true, false, true}, + {";", 10, InsetSpaceParams::THICK, false, true, false, true}, + {"thickspace", 10, InsetSpaceParams::THICK, false, true, false, true}, + {"enskip", 10, InsetSpaceParams::ENSKIP, false, true, false, true}, + {"enspace", 10, InsetSpaceParams::ENSPACE, false, true, false, true}, + {"quad", 20, InsetSpaceParams::QUAD, false, true, false, true}, + {"qquad", 40, InsetSpaceParams::QQUAD, false, true, false, true}, + {"lyxnegspace", -2, InsetSpaceParams::NEGTHIN, true, false, false, true}, + {"lyxposspace", 2, InsetSpaceParams::THIN, false, false, false, true}, + {"hfill", 80, InsetSpaceParams::HFILL, false, true, false, true}, + {"hspace*{\\fill}", 80, InsetSpaceParams::HFILL_PROTECTED, false, true, false, true}, + {"hspace*", 0, InsetSpaceParams::CUSTOM_PROTECTED,false, true, true, true}, + {"hspace", 0, InsetSpaceParams::CUSTOM, false, true, true, true}, + {" ", 10, InsetSpaceParams::NORMAL, false, true, false, true}, + {"~", 10, InsetSpaceParams::PROTECTED, false, true, false, false}, +}; -namespace { +int const nSpace = sizeof(space_info)/sizeof(SpaceInfo); +int const defaultSpace = 4; -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; - } +} // namespace + +InsetMathSpace::InsetMathSpace() + : space_(defaultSpace) +{ } -} // anon namespace -InsetMathSpace::InsetMathSpace(int sp) - : space_(sp) +InsetMathSpace::InsetMathSpace(string const & name, string const & length) + : space_(defaultSpace) { - dim_.asc = 4; - dim_.des = 0; - dim_.wid = spaceToWidth(space_); + for (int i = 0; i < nSpace; ++i) + if (space_info[i].name == name) { + space_ = i; + break; + } + if (space_info[space_].custom) { + length_ = Length(length); + if (length_.zero() || length_.empty()) { + length_.value(1.0); + length_.unit(Length::EM); + } + } } -InsetMathSpace::InsetMathSpace(docstring const & name) - : space_(1) +InsetMathSpace::InsetMathSpace(Length const & length, bool const prot) + : space_(defaultSpace), length_(length) { - dim_.asc = 4; - dim_.des = 0; for (int i = 0; i < nSpace; ++i) - if (latex_mathspace[i] == name) + if ((prot && space_info[i].name == "hspace*") + || (!prot && space_info[i].name == "hspace")) { space_ = i; - dim_.wid = spaceToWidth(space_); + break; + } } @@ -78,46 +119,62 @@ Inset * InsetMathSpace::clone() const } -void InsetMathSpace::metrics(MetricsInfo &, Dimension & dim) const +void InsetMathSpace::metrics(MetricsInfo & mi, Dimension & dim) const { - dim = dim_; + Changer dummy = mi.base.changeEnsureMath(); + dim.asc = 4; + dim.des = 0; + if (space_info[space_].custom) + dim.wid = abs(mi.base.inPixels(length_)); + else + dim.wid = space_info[space_].width; } void InsetMathSpace::draw(PainterInfo & pi, int x, int y) const { + Changer dummy = pi.base.changeEnsureMath(); // 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"); } @@ -138,21 +195,163 @@ void InsetMathSpace::octave(OctaveStream & os) const } +void InsetMathSpace::mathmlize(MathMLStream & ms) const +{ + SpaceInfo const & si = space_info[space_]; + if (si.negative || !si.visible) + return; + string l; + if (si.custom) + l = length_.asHTMLString(); + else if (si.kind != InsetSpaceParams::MEDIUM) { + stringstream ss; + ss << si.width; + l = ss.str() + "px"; + } + + std::string attr; + if (!l.empty()) + attr = "width=\"" + l + "\""; + + ms << CTag("mspace", attr); +} + + +void InsetMathSpace::htmlize(HtmlStream & ms) const +{ + SpaceInfo const & si = space_info[space_]; + switch (si.kind) { + case InsetSpaceParams::THIN: + ms << from_ascii(" "); + break; + case InsetSpaceParams::MEDIUM: + ms << from_ascii(" "); + break; + case InsetSpaceParams::THICK: + ms << from_ascii(" "); + break; + case InsetSpaceParams::ENSKIP: + case InsetSpaceParams::ENSPACE: + ms << from_ascii(" "); + break; + case InsetSpaceParams::QUAD: + ms << from_ascii(" "); + break; + case InsetSpaceParams::QQUAD: + ms << from_ascii("  "); + break; + 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(" ") << ETag("span"); + break; + } + case InsetSpaceParams::NORMAL: + case InsetSpaceParams::PROTECTED: + ms << from_ascii(" "); + break; + default: + break; + } +} + + void InsetMathSpace::normalize(NormalStream & os) const { os << "[space " << int(space_) << "] "; } -void InsetMathSpace::write(WriteStream & os) const +void InsetMathSpace::write(TeXMathStream & os) const { - if (space_ >= 0 && space_ < nSpace) { - bool brace = ensureMath(os); - os << '\\' << latex_mathspace[space_]; + // All kinds work in text and math mode, so simply suspend + // writing a possibly pending mode closing brace. + MathEnsurer ensurer(os, false); + if (space_info[space_].escape) + os << '\\'; + os << space_info[space_].name.c_str(); + if (space_info[space_].custom) + os << '{' << length_.asLatexString().c_str() << '}'; + else if (space_info[space_].escape && space_info[space_].name.length() > 1) os.pendingSpace(true); - os.pendingBrace(brace); +} + + +InsetSpaceParams InsetMathSpace::params() const +{ + InsetSpaceParams isp(true); + LASSERT(space_info[space_].visible, return isp); + isp.kind = space_info[space_].kind; + isp.length = GlueLength(length_); + return isp; +} + + +string InsetMathSpace::contextMenuName() const +{ + return "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: + 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)) { + Buffer * buf = buffer_; + cur.recordUndo(); + *this = *ar[0].nucleus()->asSpaceInset(); + buffer_ = buf; + break; + } + } + cur.undispatched(); + break; + + case LFUN_MOUSE_RELEASE: + if (cmd.button() == mouse_button::button1 && !cur.selection()) { + showInsetDialog(&cur.bv()); + break; + } + cur.undispatched(); + 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