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