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