]> git.lyx.org Git - lyx.git/blob - src/mathed/InsetMathSpace.cpp
Fix functions that used functions but did not defined it
[lyx.git] / src / mathed / InsetMathSpace.cpp
1 /**
2  * \file InsetMathSpace.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "InsetMathSpace.h"
14 #include "MathData.h"
15 #include "MathFactory.h"
16 #include "MathStream.h"
17 #include "MathSupport.h"
18
19 #include "BufferView.h"
20 #include "Cursor.h"
21 #include "FuncRequest.h"
22 #include "FuncStatus.h"
23 #include "LaTeXFeatures.h"
24 #include "MetricsInfo.h"
25
26 #include "insets/InsetSpace.h"
27
28 #include "frontends/Application.h"
29 #include "frontends/Painter.h"
30
31 #include "support/lassert.h"
32
33 using namespace std;
34
35 namespace lyx {
36
37 namespace {
38
39 struct SpaceInfo {
40         string name;
41         int width;
42         InsetSpaceParams::Kind kind;
43         bool negative;
44         bool visible;
45         bool custom;
46         bool escape; ///< whether a backslash needs to be added for writing
47 };
48
49 SpaceInfo space_info[] = {
50         // name           width kind                            negative visible custom escape
51         {"!",                6, InsetSpaceParams::NEGTHIN,         true,  true,  false, true},
52         {"negthinspace",     6, InsetSpaceParams::NEGTHIN,         true,  true,  false, true},
53         {"negmedspace",      8, InsetSpaceParams::NEGMEDIUM,       true,  true,  false, true},
54         {"negthickspace",   10, InsetSpaceParams::NEGTHICK,        true,  true,  false, true},
55         {",",                6, InsetSpaceParams::THIN,            false, true,  false, true},
56         {"thinspace",        6, InsetSpaceParams::THIN,            false, true,  false, true},
57         {":",                8, InsetSpaceParams::MEDIUM,          false, true,  false, true},
58         {"medspace",         8, InsetSpaceParams::MEDIUM,          false, true,  false, true},
59         {";",               10, InsetSpaceParams::THICK,           false, true,  false, true},
60         {"thickspace",      10, InsetSpaceParams::THICK,           false, true,  false, true},
61         {"enskip",          10, InsetSpaceParams::ENSKIP,          false, true,  false, true},
62         {"enspace",         10, InsetSpaceParams::ENSPACE,         false, true,  false, true},
63         {"quad",            20, InsetSpaceParams::QUAD,            false, true,  false, true},
64         {"qquad",           40, InsetSpaceParams::QQUAD,           false, true,  false, true},
65         {"lyxnegspace",     -2, InsetSpaceParams::NEGTHIN,         true,  false, false, true},
66         {"lyxposspace",      2, InsetSpaceParams::THIN,            false, false, false, true},
67         {"hfill",           80, InsetSpaceParams::HFILL,           false, true,  false, true},
68         {"hspace*{\\fill}", 80, InsetSpaceParams::HFILL_PROTECTED, false, true,  false, true},
69         {"hspace*",          0, InsetSpaceParams::CUSTOM_PROTECTED,false, true,  true,  true},
70         {"hspace",           0, InsetSpaceParams::CUSTOM,          false, true,  true,  true},
71         {" ",               10, InsetSpaceParams::NORMAL,          false, true,  false, true},
72         {"~",               10, InsetSpaceParams::PROTECTED,       false, true,  false, false},
73 };
74
75 int const nSpace = sizeof(space_info)/sizeof(SpaceInfo);
76 int const defaultSpace = 4;
77
78 } // namespace
79
80 InsetMathSpace::InsetMathSpace(Buffer * buf)
81         : InsetMath(buf), space_(defaultSpace)
82 {
83 }
84
85
86 InsetMathSpace::InsetMathSpace(Buffer * buf, string const & name, string const & length)
87         : InsetMath(buf), space_(defaultSpace)
88 {
89         for (int i = 0; i < nSpace; ++i)
90                 if (space_info[i].name == name) {
91                         space_ = i;
92                         break;
93                 }
94         if (space_info[space_].custom) {
95                 length_ = Length(length);
96                 if (length_.zero() || length_.empty()) {
97                         length_.value(1.0);
98                         length_.unit(Length::EM);
99                 }
100         }
101 }
102
103
104 InsetMathSpace::InsetMathSpace(Buffer * buf, Length const & length, bool const prot)
105         : InsetMath(buf), space_(defaultSpace), length_(length)
106 {
107         for (int i = 0; i < nSpace; ++i)
108                 if ((prot && space_info[i].name == "hspace*")
109                         || (!prot && space_info[i].name == "hspace")) {
110                         space_ = i;
111                         break;
112                 }
113 }
114
115
116 Inset * InsetMathSpace::clone() const
117 {
118         return new InsetMathSpace(*this);
119 }
120
121
122 void InsetMathSpace::metrics(MetricsInfo & mi, Dimension & dim) const
123 {
124         Changer dummy = mi.base.changeEnsureMath();
125         dim.asc = 4;
126         dim.des = 0;
127         if (space_info[space_].custom)
128                 dim.wid = abs(mi.base.inPixels(length_));
129         else
130                 dim.wid = space_info[space_].width;
131 }
132
133
134 void InsetMathSpace::draw(PainterInfo & pi, int x, int y) const
135 {
136         Changer dummy = pi.base.changeEnsureMath();
137         // Sadly, HP-UX CC can't handle that kind of initialization.
138         // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
139         if (!space_info[space_].visible)
140                 return;
141
142         Dimension const dim = dimension(*pi.base.bv);
143         int xp[4];
144         int yp[4];
145         int w = dim.wid;
146
147         xp[0] = ++x;        yp[0] = y - 3;
148         xp[1] = x;          yp[1] = y;
149         xp[2] = x + w - 2;  yp[2] = y;
150         xp[3] = x + w - 2;  yp[3] = y - 3;
151
152         pi.pain.lines(xp, yp, 4,
153                         space_info[space_].custom ?
154                         Color_special :
155                         (isNegative() ? Color_latex : Color_math));
156 }
157
158
159 void InsetMathSpace::incSpace()
160 {
161         int const oldwidth = space_info[space_].width;
162         do
163                 space_ = (space_ + 1) % nSpace;
164         while ((space_info[space_].width == oldwidth && !space_info[space_].custom) ||
165                !space_info[space_].visible);
166         if (space_info[space_].custom && (length_.zero() || length_.empty())) {
167                 length_.value(1.0);
168                 length_.unit(Length::EM);
169         }
170 }
171
172
173 void InsetMathSpace::validate(LaTeXFeatures & features) const
174 {
175         if (space_info[space_].name == "negmedspace" ||
176             space_info[space_].name == "negthickspace")
177                 features.require("amsmath");
178 }
179
180
181 void InsetMathSpace::maple(MapleStream & os) const
182 {
183         os << ' ';
184 }
185
186 void InsetMathSpace::mathematica(MathematicaStream & os) const
187 {
188         os << ' ';
189 }
190
191
192 void InsetMathSpace::octave(OctaveStream & os) const
193 {
194         os << ' ';
195 }
196
197
198 void InsetMathSpace::mathmlize(MathMLStream & ms) const
199 {
200         SpaceInfo const & si = space_info[space_];
201         if (si.negative || !si.visible)
202                 return;
203         string l;
204         if (si.custom)
205                 l = length_.asHTMLString();
206         else if (si.kind != InsetSpaceParams::MEDIUM)
207                 l = to_string(si.width) + "px";
208
209         std::string attr;
210         if (!l.empty())
211                 attr = "width=\"" + l + "\"";
212
213         ms << CTag("mspace", attr);
214 }
215
216
217 void InsetMathSpace::htmlize(HtmlStream & ms) const
218 {
219         SpaceInfo const & si = space_info[space_];
220         switch (si.kind) {
221         case InsetSpaceParams::THIN:
222                 ms << from_ascii("&#x202F;"); // HTML: &thinsp;
223                 break;
224         case InsetSpaceParams::MEDIUM:
225                 ms << from_ascii("&#160;");
226                 break;
227         case InsetSpaceParams::THICK:
228                 ms << from_ascii("&#x2003;"); // HTML: &emsp;
229                 break;
230         case InsetSpaceParams::ENSKIP:
231         case InsetSpaceParams::ENSPACE:
232                 ms << from_ascii("&#x2002;"); // HTML: &ensp;
233                 break;
234         case InsetSpaceParams::QUAD:
235                 ms << from_ascii("&#x2003;"); // HTML: &emsp;
236                 break;
237         case InsetSpaceParams::QQUAD:
238                 ms << from_ascii("&#x2003;&#x2003;"); // HTML: &emsp;&emsp;
239                 break;
240         case InsetSpaceParams::HFILL:
241         case InsetSpaceParams::HFILL_PROTECTED:
242                 // FIXME: is there a useful HTML entity?
243                 break;
244         case InsetSpaceParams::CUSTOM:
245         case InsetSpaceParams::CUSTOM_PROTECTED: {
246                 string l = length_.asHTMLString();
247                 ms << MTag("span", "width='" + l + "'")
248                    << from_ascii("&#160;") << ETag("span");
249                 break;
250         }
251         case InsetSpaceParams::NORMAL:
252         case InsetSpaceParams::PROTECTED:
253                 ms << from_ascii("&#160;");
254                 break;
255         default:
256                 break;
257         }
258 }
259
260
261 void InsetMathSpace::normalize(NormalStream & os) const
262 {
263         os << "[space " << int(space_) << "] ";
264 }
265
266
267 void InsetMathSpace::write(TeXMathStream & os) const
268 {
269         // All kinds work in text and math mode, so simply suspend
270         // writing a possibly pending mode closing brace.
271         MathEnsurer ensurer(os, false);
272         if (space_info[space_].escape)
273                 os << '\\';
274         os << space_info[space_].name.c_str();
275         if (space_info[space_].custom)
276                 os << '{' << length_.asLatexString().c_str() << '}';
277         else if (space_info[space_].escape && space_info[space_].name.length() > 1)
278                 os.pendingSpace(true);
279 }
280
281
282 InsetSpaceParams InsetMathSpace::params() const
283 {
284         InsetSpaceParams isp(true);
285         LASSERT(space_info[space_].visible, return isp);
286         isp.kind = space_info[space_].kind;
287         isp.length = GlueLength(length_);
288         return isp;
289 }
290
291
292 string InsetMathSpace::contextMenuName() const
293 {
294         return "context-mathspace";
295 }
296
297
298 bool InsetMathSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
299                                FuncStatus & status) const
300 {
301         switch (cmd.action()) {
302         // we handle these
303         case LFUN_INSET_MODIFY:
304         case LFUN_INSET_DIALOG_UPDATE:
305         case LFUN_MOUSE_RELEASE:
306                 status.setEnabled(true);
307                 return true;
308         default:
309                 bool retval = InsetMath::getStatus(cur, cmd, status);
310                 return retval;
311         }
312 }
313
314
315 void InsetMathSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
316 {
317         switch (cmd.action()) {
318         case LFUN_INSET_MODIFY:
319                 if (cmd.getArg(0) == "mathspace") {
320                         MathData ar(buffer_);
321                         if (createInsetMath_fromDialogStr(cmd.argument(), ar)) {
322                                 Buffer * buf = buffer_;
323                                 cur.recordUndo();
324                                 *this = *ar[0].nucleus()->asSpaceInset();
325                                 buffer_ = buf;
326                                 break;
327                         }
328                 }
329                 cur.undispatched();
330                 break;
331
332         case LFUN_MOUSE_RELEASE:
333                 if (cmd.button() == mouse_button::button1 && !cur.selection()) {
334                         showInsetDialog(&cur.bv());
335                         break;
336                 }
337                 cur.undispatched();
338                 break;
339
340         default:
341                 InsetMath::doDispatch(cur, cmd);
342                 break;
343         }
344 }
345
346
347 bool InsetMathSpace::isNegative() const
348 {
349         if (space_info[space_].custom)
350                 return length_.value() < 0;
351         return space_info[space_].negative;
352 }
353
354 } // namespace lyx