2 * \file InsetMathSpace.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
13 #include "InsetMathSpace.h"
15 #include "MathFactory.h"
16 #include "MathStream.h"
17 #include "MathSupport.h"
19 #include "BufferView.h"
21 #include "FuncRequest.h"
22 #include "FuncStatus.h"
23 #include "LaTeXFeatures.h"
25 #include "insets/InsetSpace.h"
27 #include "frontends/Application.h"
28 #include "frontends/Painter.h"
30 #include "support/lassert.h"
41 InsetSpaceParams::Kind kind;
47 SpaceInfo space_info[] = {
48 // name width kind negative visible custom
49 {"!", 6, InsetSpaceParams::NEGTHIN, true, true, false},
50 {"negthinspace", 6, InsetSpaceParams::NEGTHIN, true, true, false},
51 {"negmedspace", 8, InsetSpaceParams::NEGMEDIUM, true, true, false},
52 {"negthickspace", 10, InsetSpaceParams::NEGTHICK, true, true, false},
53 {",", 6, InsetSpaceParams::THIN, false, true, false},
54 {"thinspace", 6, InsetSpaceParams::THIN, false, true, false},
55 {":", 8, InsetSpaceParams::MEDIUM, false, true, false},
56 {"medspace", 8, InsetSpaceParams::MEDIUM, false, true, false},
57 {";", 10, InsetSpaceParams::THICK, false, true, false},
58 {"thickspace", 10, InsetSpaceParams::THICK, false, true, false},
59 {"enskip", 10, InsetSpaceParams::ENSKIP, false, true, false},
60 {"enspace", 10, InsetSpaceParams::ENSPACE, false, true, false},
61 {"quad", 20, InsetSpaceParams::QUAD, false, true, false},
62 {"qquad", 40, InsetSpaceParams::QQUAD, false, true, false},
63 {"lyxnegspace", -2, InsetSpaceParams::NEGTHIN, true, false, false},
64 {"lyxposspace", 2, InsetSpaceParams::THIN, false, false, false},
65 {"hfill", 80, InsetSpaceParams::HFILL, false, true, false},
66 {"hspace*{\\fill}", 80, InsetSpaceParams::HFILL_PROTECTED, false, true, false},
67 {"hspace*", 0, InsetSpaceParams::CUSTOM_PROTECTED, false, true, true},
68 {"hspace", 0, InsetSpaceParams::CUSTOM, false, true, true},
71 int const nSpace = sizeof(space_info)/sizeof(SpaceInfo);
72 int const defaultSpace = 4;
76 InsetMathSpace::InsetMathSpace()
77 : space_(defaultSpace)
82 InsetMathSpace::InsetMathSpace(string const & name, string const & length)
83 : space_(defaultSpace)
85 for (int i = 0; i < nSpace; ++i)
86 if (space_info[i].name == name) {
90 if (space_info[space_].custom) {
91 length_ = Length(length);
92 if (length_.zero() || length_.empty()) {
94 length_.unit(Length::EM);
100 InsetMathSpace::InsetMathSpace(Length const & length, bool const prot)
101 : space_(defaultSpace), length_(length)
103 for (int i = 0; i < nSpace; ++i)
104 if ((prot && space_info[i].name == "hspace*")
105 || (!prot && space_info[i].name == "hspace")) {
112 Inset * InsetMathSpace::clone() const
114 return new InsetMathSpace(*this);
118 void InsetMathSpace::metrics(MetricsInfo & mi, Dimension & dim) const
122 if (space_info[space_].custom)
123 dim.wid = abs(length_.inPixels(
125 mathed_char_width(mi.base.font, 'M')));
127 dim.wid = space_info[space_].width;
131 void InsetMathSpace::draw(PainterInfo & pi, int x, int y) const
133 // Sadly, HP-UX CC can't handle that kind of initialization.
134 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
135 if (!space_info[space_].visible)
138 Dimension const dim = dimension(*pi.base.bv);
143 xp[0] = ++x; yp[0] = y - 3;
144 xp[1] = x; yp[1] = y;
145 xp[2] = x + w - 2; yp[2] = y;
146 xp[3] = x + w - 2; yp[3] = y - 3;
148 pi.pain.lines(xp, yp, 4,
149 space_info[space_].custom ?
151 (isNegative() ? Color_latex : Color_math));
155 void InsetMathSpace::incSpace()
157 int const oldwidth = space_info[space_].width;
159 space_ = (space_ + 1) % nSpace;
160 while ((space_info[space_].width == oldwidth && !space_info[space_].custom) ||
161 !space_info[space_].visible);
162 if (space_info[space_].custom && (length_.zero() || length_.empty())) {
164 length_.unit(Length::EM);
169 void InsetMathSpace::validate(LaTeXFeatures & features) const
171 if (space_info[space_].name == "negmedspace" ||
172 space_info[space_].name == "negthickspace")
173 features.require("amsmath");
177 void InsetMathSpace::maple(MapleStream & os) const
182 void InsetMathSpace::mathematica(MathematicaStream & os) const
188 void InsetMathSpace::octave(OctaveStream & os) const
194 void InsetMathSpace::mathmlize(MathStream & ms) const
196 SpaceInfo const & si = space_info[space_];
197 if (si.negative || !si.visible)
201 l = length_.asHTMLString();
202 else if (si.kind != InsetSpaceParams::MEDIUM) {
210 ms << " width=\"" << from_ascii(l) << "\"";
215 void InsetMathSpace::htmlize(HtmlStream & ms) const
217 SpaceInfo const & si = space_info[space_];
219 case InsetSpaceParams::THIN:
220 ms << from_ascii(" ");
222 case InsetSpaceParams::MEDIUM:
223 ms << from_ascii(" ");
225 case InsetSpaceParams::THICK:
226 ms << from_ascii(" ");
228 case InsetSpaceParams::ENSKIP:
229 case InsetSpaceParams::ENSPACE:
230 ms << from_ascii(" ");
232 case InsetSpaceParams::QUAD:
233 ms << from_ascii(" ");
235 case InsetSpaceParams::QQUAD:
236 ms << from_ascii("  ");
238 case InsetSpaceParams::HFILL:
239 case InsetSpaceParams::HFILL_PROTECTED:
240 // FIXME: is there a useful HTML entity?
242 case InsetSpaceParams::CUSTOM:
243 case InsetSpaceParams::CUSTOM_PROTECTED: {
244 string l = length_.asHTMLString();
245 ms << MTag("span", "width='" + l + "'")
246 << from_ascii(" ") << ETag("span");
255 void InsetMathSpace::normalize(NormalStream & os) const
257 os << "[space " << int(space_) << "] ";
261 void InsetMathSpace::write(WriteStream & os) const
263 // no MathEnsurer - all kinds work in text and math mode
264 os << '\\' << space_info[space_].name.c_str();
265 if (space_info[space_].custom)
266 os << '{' << length_.asLatexString().c_str() << '}';
268 os.pendingSpace(true);
272 InsetSpaceParams InsetMathSpace::params() const
274 LASSERT(space_info[space_].visible, /**/);
275 InsetSpaceParams isp(true);
276 isp.kind = space_info[space_].kind;
277 isp.length = GlueLength(length_);
282 docstring InsetMathSpace::contextMenuName() const
284 return from_ascii("context-mathspace");
288 bool InsetMathSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
289 FuncStatus & status) const
291 switch (cmd.action()) {
293 case LFUN_INSET_MODIFY:
294 case LFUN_INSET_DIALOG_UPDATE:
295 case LFUN_MOUSE_RELEASE:
296 case LFUN_MOUSE_PRESS:
297 case LFUN_MOUSE_MOTION:
298 status.setEnabled(true);
301 bool retval = InsetMath::getStatus(cur, cmd, status);
307 void InsetMathSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
309 switch (cmd.action()) {
310 case LFUN_INSET_MODIFY:
311 if (cmd.getArg(0) == "mathspace") {
313 if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
315 *this = *ar[0].nucleus()->asSpaceInset();
322 case LFUN_MOUSE_RELEASE:
323 if (cmd.button() == mouse_button::button1) {
324 showInsetDialog(&cur.bv());
330 case LFUN_MOUSE_PRESS:
331 case LFUN_MOUSE_MOTION:
332 // eat other mouse commands
336 InsetMath::doDispatch(cur, cmd);
342 bool InsetMathSpace::isNegative() const
344 if (space_info[space_].custom)
345 return length_.value() < 0;
346 return space_info[space_].negative;