]> git.lyx.org Git - lyx.git/blob - src/mathed/InsetMathBox.cpp
Merge remote-tracking branch 'features/properpaint' into 2.3.2-staging
[lyx.git] / src / mathed / InsetMathBox.cpp
1 /**
2  * \file InsetMathBox.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  * \author Ling Li (InsetMathMakebox)
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetMathBox.h"
15
16 #include "LaTeXFeatures.h"
17 #include "MathData.h"
18 #include "MathStream.h"
19 #include "MathSupport.h"
20 #include "MetricsInfo.h"
21
22 #include "support/gettext.h"
23 #include "support/lstrings.h"
24
25 #include "frontends/Painter.h"
26
27 #include <algorithm>
28 #include <ostream>
29
30 using namespace lyx::support;
31
32 namespace lyx {
33
34 /////////////////////////////////////////////////////////////////////
35 //
36 // InsetMathBox
37 //
38 /////////////////////////////////////////////////////////////////////
39
40 InsetMathBox::InsetMathBox(Buffer * buf, docstring const & name)
41         : InsetMathNest(buf, 1), name_(name)
42 {}
43
44
45 void InsetMathBox::write(WriteStream & os) const
46 {
47         ModeSpecifier specifier(os, TEXT_MODE);
48         os << '\\' << name_ << '{' << cell(0) << '}';
49 }
50
51
52 void InsetMathBox::normalize(NormalStream & os) const
53 {
54         os << '[' << name_ << ' ';
55         //text_->write(buffer(), os);
56         os << "] ";
57 }
58
59
60 void InsetMathBox::mathmlize(MathStream & ms) const
61 {
62         // FIXME XHTML
63         // Need to do something special for tags here.
64         // Probably will have to involve deferring them, which
65         // means returning something from this routine.
66         SetMode textmode(ms, true);
67         ms << MTag("mstyle", "class='mathbox'")
68            << cell(0)
69            << ETag("mstyle");
70 }
71
72
73 void InsetMathBox::htmlize(HtmlStream & ms) const
74 {
75         SetHTMLMode textmode(ms, true);
76         ms << MTag("span", "class='mathbox'")
77            << cell(0)
78            << ETag("span");
79 }
80
81
82 void InsetMathBox::metrics(MetricsInfo & mi, Dimension & dim) const
83 {
84         Changer dummy = mi.base.changeFontSet("textnormal");
85         cell(0).metrics(mi, dim);
86 }
87
88
89 void InsetMathBox::draw(PainterInfo & pi, int x, int y) const
90 {
91         Changer dummy = pi.base.changeFontSet("textnormal");
92         cell(0).draw(pi, x, y);
93 }
94
95
96 void InsetMathBox::infoize(odocstream & os) const
97 {
98         os << bformat(_("Box: %1$s"), name_);
99 }
100
101
102 void InsetMathBox::validate(LaTeXFeatures & features) const
103 {
104         // FIXME XHTML
105         // It'd be better to be able to get this from an InsetLayout, but at present
106         // InsetLayouts do not seem really to work for things that aren't InsetTexts.
107         if (features.runparams().math_flavor == OutputParams::MathAsMathML)
108                 features.addCSSSnippet("mstyle.mathbox { font-style: normal; }");
109         else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
110                 features.addCSSSnippet("span.mathbox { font-style: normal; }");
111
112         if (name_ == "tag" || name_ == "tag*")
113                 features.require("amsmath");
114
115         InsetMathNest::validate(features);
116 }
117
118
119
120 /////////////////////////////////////////////////////////////////////
121 //
122 // InsetMathFBox
123 //
124 /////////////////////////////////////////////////////////////////////
125
126
127 InsetMathFBox::InsetMathFBox(Buffer * buf)
128         : InsetMathNest(buf, 1)
129 {}
130
131
132 void InsetMathFBox::metrics(MetricsInfo & mi, Dimension & dim) const
133 {
134         Changer dummy = mi.base.changeFontSet("textnormal");
135         cell(0).metrics(mi, dim);
136         // 1 pixel space, 1 frame, 1 space
137         dim.wid += 2 * 3;
138         dim.asc += 3;
139         dim.des += 3;
140 }
141
142
143 void InsetMathFBox::draw(PainterInfo & pi, int x, int y) const
144 {
145         Dimension const dim = dimension(*pi.base.bv);
146         pi.pain.rectangle(x + 1, y - dim.ascent() + 1,
147                 dim.width() - 2, dim.height() - 2, Color_foreground);
148         Changer dummy = pi.base.changeFontSet("textnormal");
149         cell(0).draw(pi, x + 3, y);
150 }
151
152
153 void InsetMathFBox::write(WriteStream & os) const
154 {
155         ModeSpecifier specifier(os, TEXT_MODE);
156         os << "\\fbox{" << cell(0) << '}';
157 }
158
159
160 void InsetMathFBox::normalize(NormalStream & os) const
161 {
162         os << "[fbox " << cell(0) << ']';
163 }
164
165
166 void InsetMathFBox::mathmlize(MathStream & ms) const
167 {
168         SetMode textmode(ms, true);
169         ms << MTag("mstyle", "class='fbox'")
170            << cell(0)
171            << ETag("mstyle");
172 }
173
174
175 void InsetMathFBox::htmlize(HtmlStream & ms) const
176 {
177         SetHTMLMode textmode(ms, true);
178         ms << MTag("span", "class='fbox'")
179            << cell(0)
180            << ETag("span");
181 }
182
183
184 void InsetMathFBox::infoize(odocstream & os) const
185 {
186         os << "FBox: ";
187 }
188
189
190 void InsetMathFBox::validate(LaTeXFeatures & features) const
191 {
192         // FIXME XHTML
193         // It'd be better to be able to get this from an InsetLayout, but at present
194         // InsetLayouts do not seem really to work for things that aren't InsetTexts.
195         if (features.runparams().math_flavor == OutputParams::MathAsMathML)
196                 features.addCSSSnippet(
197                         "mstyle.fbox { border: 1px solid black; font-style: normal; padding: 0.5ex; }");
198         else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
199                 features.addCSSSnippet(
200                         "span.fbox { border: 1px solid black; font-style: normal; padding: 0.5ex; }");
201
202         cell(0).validate(features);
203         InsetMathNest::validate(features);
204 }
205
206
207
208 /////////////////////////////////////////////////////////////////////
209 //
210 // InsetMathMakebox
211 //
212 /////////////////////////////////////////////////////////////////////
213
214
215 InsetMathMakebox::InsetMathMakebox(Buffer * buf, bool framebox)
216         : InsetMathNest(buf, 3), framebox_(framebox)
217 {}
218
219
220 void InsetMathMakebox::metrics(MetricsInfo & mi, Dimension & dim) const
221 {
222         Changer dummy = mi.base.changeFontSet("textnormal");
223
224         Dimension wdim;
225         static docstring bracket = from_ascii("[");
226         metricsStrRedBlack(mi, wdim, bracket);
227         int w = wdim.wid;
228
229         Dimension dim0;
230         Dimension dim1;
231         Dimension dim2;
232         cell(0).metrics(mi, dim0);
233         cell(1).metrics(mi, dim1);
234         cell(2).metrics(mi, dim2);
235
236         dim.wid = w + dim0.wid + w + w + dim1.wid + w + 2 + dim2.wid;
237         dim.asc = std::max(std::max(wdim.asc, dim0.asc), std::max(dim1.asc, dim2.asc));
238         dim.des = std::max(std::max(wdim.des, dim0.des), std::max(dim1.des, dim2.des));
239
240         if (framebox_) {
241                 dim.wid += 4;
242                 dim.asc += 3;
243                 dim.des += 2;
244         } else {
245                 dim.asc += 1;
246                 dim.des += 1;
247         }
248 }
249
250
251 void InsetMathMakebox::draw(PainterInfo & pi, int x, int y) const
252 {
253         Changer dummy = pi.base.changeFontSet("textnormal");
254         BufferView const & bv = *pi.base.bv;
255         int w = mathed_char_width(pi.base.font, '[');
256
257         if (framebox_) {
258                 Dimension const dim = dimension(*pi.base.bv);
259                 pi.pain.rectangle(x + 1, y - dim.ascent() + 1,
260                                   dim.width() - 2, dim.height() - 2, Color_foreground);
261                 x += 2;
262         }
263
264         drawStrBlack(pi, x, y, from_ascii("["));
265         x += w;
266         cell(0).draw(pi, x, y);
267         x += cell(0).dimension(bv).wid;
268         drawStrBlack(pi, x, y, from_ascii("]"));
269         x += w;
270
271         drawStrBlack(pi, x, y, from_ascii("["));
272         x += w;
273         cell(1).draw(pi, x, y);
274         x += cell(1).dimension(bv).wid;
275         drawStrBlack(pi, x, y, from_ascii("]"));
276         x += w + 2;
277
278         cell(2).draw(pi, x, y);
279 }
280
281
282 void InsetMathMakebox::write(WriteStream & os) const
283 {
284         ModeSpecifier specifier(os, TEXT_MODE);
285         os << (framebox_ ? "\\framebox" : "\\makebox");
286         if (!cell(0).empty() || !os.latex()) {
287                 os << '[' << cell(0) << ']';
288                 if (!cell(1).empty() || !os.latex())
289                         os << '[' << cell(1) << ']';
290         }
291         os << '{' << cell(2) << '}';
292 }
293
294
295 void InsetMathMakebox::normalize(NormalStream & os) const
296 {
297         os << (framebox_ ? "[framebox " : "[makebox ")
298            << cell(0) << ' ' << cell(1) << ' ' << cell(2) << ']';
299 }
300
301
302 void InsetMathMakebox::infoize(odocstream & os) const
303 {
304         os << (framebox_ ? "Framebox" : "Makebox")
305            << " (width: " << cell(0)
306            << " pos: " << cell(1) << ")";
307 }
308
309
310 void InsetMathMakebox::mathmlize(MathStream & ms) const
311 {
312         // FIXME We could do something with the other arguments.
313         std::string const cssclass = framebox_ ? "framebox" : "makebox";
314         SetMode textmode(ms, true);
315         ms << MTag("mstyle", "class='" + cssclass + "'")
316            << cell(2)
317            << ETag("mstyle");
318 }
319
320
321 void InsetMathMakebox::htmlize(HtmlStream & ms) const
322 {
323         // FIXME We could do something with the other arguments.
324         SetHTMLMode textmode(ms, true);
325         std::string const cssclass = framebox_ ? "framebox" : "makebox";
326         ms << MTag("span", "class='" + cssclass + "'")
327            << cell(2)
328            << ETag("span");
329 }
330
331
332 void InsetMathMakebox::validate(LaTeXFeatures & features) const
333 {
334         // FIXME XHTML
335         // It'd be better to be able to get this from an InsetLayout, but at present
336         // InsetLayouts do not seem really to work for things that aren't InsetTexts.
337         if (features.runparams().math_flavor == OutputParams::MathAsMathML)
338                 features.addCSSSnippet("mstyle.framebox { border: 1px solid black; }");
339         else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
340                 features.addCSSSnippet("span.framebox { border: 1px solid black; }");
341         InsetMathNest::validate(features);
342 }
343
344
345 /////////////////////////////////////////////////////////////////////
346 //
347 // InsetMathBoxed
348 //
349 /////////////////////////////////////////////////////////////////////
350
351 InsetMathBoxed::InsetMathBoxed(Buffer * buf)
352         : InsetMathNest(buf, 1)
353 {}
354
355
356 void InsetMathBoxed::metrics(MetricsInfo & mi, Dimension & dim) const
357 {
358         cell(0).metrics(mi, dim);
359         // 1 pixel space, 1 frame, 1 space
360         dim.wid += 2 * 3;
361         dim.asc += 3;
362         dim.des += 3;
363 }
364
365
366 void InsetMathBoxed::draw(PainterInfo & pi, int x, int y) const
367 {
368         Dimension const dim = dimension(*pi.base.bv);
369         pi.pain.rectangle(x + 1, y - dim.ascent() + 1,
370                 dim.width() - 2, dim.height() - 2, Color_foreground);
371         cell(0).draw(pi, x + 3, y);
372 }
373
374
375 void InsetMathBoxed::write(WriteStream & os) const
376 {
377         ModeSpecifier specifier(os, MATH_MODE);
378         os << "\\boxed{" << cell(0) << '}';
379 }
380
381
382 void InsetMathBoxed::normalize(NormalStream & os) const
383 {
384         os << "[boxed " << cell(0) << ']';
385 }
386
387
388 void InsetMathBoxed::infoize(odocstream & os) const
389 {
390         os << "Boxed: ";
391 }
392
393
394 void InsetMathBoxed::mathmlize(MathStream & ms) const
395 {
396         ms << MTag("mstyle", "class='boxed'")
397            << cell(0)
398            << ETag("mstyle");
399 }
400
401
402 void InsetMathBoxed::htmlize(HtmlStream & ms) const
403 {
404         ms << MTag("span", "class='boxed'")
405            << cell(0)
406                  << ETag("span");
407 }
408
409
410 void InsetMathBoxed::validate(LaTeXFeatures & features) const
411 {
412         features.require("amsmath");
413
414         // FIXME XHTML
415         // It'd be better to be able to get this from an InsetLayout, but at present
416         // InsetLayouts do not seem really to work for things that aren't InsetTexts.
417         if (features.runparams().math_flavor == OutputParams::MathAsMathML)
418                 features.addCSSSnippet("mstyle.boxed { border: 1px solid black; }");
419         else if (features.runparams().math_flavor == OutputParams::MathAsHTML)
420                 features.addCSSSnippet("span.boxed { border: 1px solid black; }");
421
422         InsetMathNest::validate(features);
423 }
424
425
426 } // namespace lyx