]> git.lyx.org Git - lyx.git/blob - src/mathed/MathSupport.cpp
Use master buffer's setting for math output type.
[lyx.git] / src / mathed / MathSupport.cpp
1 /**
2  * \file MathSupport.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "MathSupport.h"
15
16 #include "InsetMathFont.h"
17 #include "InsetMathSymbol.h"
18 #include "MathData.h"
19 #include "MathParser.h"
20 #include "MathStream.h"
21
22 #include "frontends/FontLoader.h"
23 #include "frontends/FontMetrics.h"
24 #include "frontends/Painter.h"
25
26 #include "support/debug.h"
27 #include "support/docstream.h"
28
29 #include <map>
30
31 using namespace std;
32
33 namespace lyx {
34
35 using frontend::Painter;
36
37
38 ///
39 class Matrix {
40 public:
41         ///
42         Matrix(int, double, double);
43         ///
44         void transform(double &, double &);
45 private:
46         ///
47         double m_[2][2];
48 };
49
50
51 Matrix::Matrix(int code, double x, double y)
52 {
53         double const cs = (code & 1) ? 0 : (1 - code);
54         double const sn = (code & 1) ? (2 - code) : 0;
55         m_[0][0] =  cs * x;
56         m_[0][1] =  sn * x;
57         m_[1][0] = -sn * y;
58         m_[1][1] =  cs * y;
59 }
60
61
62 void Matrix::transform(double & x, double & y)
63 {
64         double xx = m_[0][0] * x + m_[0][1] * y;
65         double yy = m_[1][0] * x + m_[1][1] * y;
66         x = xx;
67         y = yy;
68 }
69
70
71
72 namespace {
73
74 /*
75  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
76  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4 = square polyline
77  */
78
79
80 double const parenthHigh[] = {
81         2, 13,
82         0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
83         0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
84         0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
85         0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
86         0.9840, 0.9986,
87         0
88 };
89
90
91 double const parenth[] = {
92         2, 13,
93         0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
94         0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
95         0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
96         0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
97         0.9930, 0.9919,
98         0
99 };
100
101
102 double const brace[] = {
103         2, 21,
104         0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
105         0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
106         0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
107         0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
108         0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
109         0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
110         0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
111         0
112 };
113
114
115 double const arrow[] = {
116         4, 7,
117         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
118         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
119         0.9500, 0.7500,
120         3, 0.5000, 0.1500, 0.5000, 0.9500,
121         0
122 };
123
124
125 double const Arrow[] = {
126         4, 7,
127         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
128         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
129         0.9500, 0.7500,
130         3, 0.3500, 0.5000, 0.3500, 0.9500,
131         3, 0.6500, 0.5000, 0.6500, 0.9500,
132         0
133 };
134
135
136 double const udarrow[] = {
137         2, 3,
138         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
139         2, 3,
140         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
141         1, 0.5, 0.2,  0.5, 0.8,
142         0
143 };
144
145
146 double const Udarrow[] = {
147         2, 3,
148         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
149         2, 3,
150         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
151         1, 0.35, 0.2, 0.35, 0.8,
152         1, 0.65, 0.2, 0.65, 0.8,
153         0
154 };
155
156
157 double const brack[] = {
158         2, 4,
159         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
160         0
161 };
162
163
164 double const dbrack[] = {
165         2, 4,
166         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
167         2, 2,
168         0.50, 0.05,  0.50, 0.95,
169         0
170 };
171
172
173 double const corner[] = {
174         2, 3,
175         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
176         0
177 };
178
179
180 double const angle[] = {
181         2, 3,
182         1, 0,  0.05, 0.5,  1, 1,
183         0
184 };
185
186
187 double const slash[] = {
188         1, 0.95, 0.05, 0.05, 0.95,
189         0
190 };
191
192
193 double const hline[] = {
194         1, 0.00, 0.5, 1.0, 0.5,
195         0
196 };
197
198
199 double const ddot[] = {
200         1, 0.2, 0.5, 0.3, 0.5,
201         1, 0.7, 0.5, 0.8, 0.5,
202         0
203 };
204
205
206 double const dddot[] = {
207         1, 0.1,  0.5, 0.2,  0.5,
208         1, 0.45, 0.5, 0.55, 0.5,
209         1, 0.8,  0.5, 0.9,  0.5,
210         0
211 };
212
213
214 double const ddddot[] = {
215         1, 0.1,  0.5, 0.2,  0.5,
216         1, 0.45, 0.5, 0.55, 0.5,
217         1, 0.8,  0.5, 0.9,  0.5,
218         1, 1.15, 0.5, 1.25, 0.5,
219         0
220 };
221
222
223 double const hline3[] = {
224         1, 0.1,   0,  0.15,  0,
225         1, 0.475, 0,  0.525, 0,
226         1, 0.85,  0,  0.9,   0,
227         0
228 };
229
230
231 double const dline3[] = {
232         1, 0.1,   0.1,   0.15,  0.15,
233         1, 0.475, 0.475, 0.525, 0.525,
234         1, 0.85,  0.85,  0.9,   0.9,
235         0
236 };
237
238
239 double const hlinesmall[] = {
240         1, 0.4, 0.5, 0.6, 0.5,
241         0
242 };
243
244
245 double const ring[] = {
246         2, 5,
247         0.5, 0.8,  0.8, 0.5,  0.5, 0.2,  0.2, 0.5,  0.5, 0.8,
248         0
249 };
250
251
252 double const vert[] = {
253         1, 0.5, 0.05,  0.5, 0.95,
254         0
255 };
256
257
258 double const  Vert[] = {
259         1, 0.3, 0.05,  0.3, 0.95,
260         1, 0.7, 0.05,  0.7, 0.95,
261         0
262 };
263
264
265 double const tilde[] = {
266         2, 4,
267         0.00, 0.8,  0.25, 0.2,  0.75, 0.8,  1.00, 0.2,
268         0
269 };
270
271
272 struct deco_struct {
273         double const * data;
274         int angle;
275 };
276
277 struct named_deco_struct {
278         char const * name;
279         double const * data;
280         int angle;
281 };
282
283 named_deco_struct deco_table[] = {
284         // Decorations
285         {"widehat",             angle,    3 },
286         {"widetilde",           tilde,    0 },
287         {"underbar",            hline,    0 },
288         {"underline",           hline,    0 },
289         {"overline",            hline,    0 },
290         {"underbrace",          brace,    1 },
291         {"overbrace",           brace,    3 },
292         {"overleftarrow",       arrow,    1 },
293         {"overrightarrow",      arrow,    3 },
294         {"overleftrightarrow",  udarrow,  1 },
295         {"xleftarrow",          arrow,    1 },
296         {"xrightarrow",         arrow,    3 },
297         {"underleftarrow",      arrow,    1 },
298         {"underrightarrow",     arrow,    3 },
299         {"underleftrightarrow", udarrow,  1 },
300         {"undertilde",          tilde,    0 },
301         {"utilde",              tilde,    0 },
302
303         // Delimiters
304         {"(",              parenth,    0 },
305         {")",              parenth,    2 },
306         {"{",              brace,      0 },
307         {"}",              brace,      2 },
308         {"lbrace",         brace,      0 },
309         {"rbrace",         brace,      2 },
310         {"[",              brack,      0 },
311         {"]",              brack,      2 },
312         {"llbracket",      dbrack,     0 },
313         {"rrbracket",      dbrack,     2 },
314         {"|",              vert,       0 },
315         {"/",              slash,      0 },
316         {"slash",          slash,      0 },
317         {"vert",           vert,       0 },
318         {"Vert",           Vert,       0 },
319         {"'",              slash,      1 },
320         {"<",              angle,      0 },
321         {">",              angle,      2 },
322         {"\\",             slash,      1 },
323         {"backslash",      slash,      1 },
324         {"langle",         angle,      0 },
325         {"lceil",          corner,     0 },
326         {"lfloor",         corner,     1 },
327         {"rangle",         angle,      2 },
328         {"rceil",          corner,     3 },
329         {"rfloor",         corner,     2 },
330         {"downarrow",      arrow,      2 },
331         {"Downarrow",      Arrow,      2 },
332         {"uparrow",        arrow,      0 },
333         {"Uparrow",        Arrow,      0 },
334         {"updownarrow",    udarrow,    0 },
335         {"Updownarrow",    Udarrow,    0 },
336
337         // Accents
338         {"ddot",           ddot,       0 },
339         {"dddot",          dddot,      0 },
340         {"ddddot",         ddddot,     0 },
341         {"hat",            angle,      3 },
342         {"grave",          slash,      1 },
343         {"acute",          slash,      0 },
344         {"tilde",          tilde,      0 },
345         {"bar",            hline,      0 },
346         {"dot",            hlinesmall, 0 },
347         {"check",          angle,      1 },
348         {"breve",          parenth,    1 },
349         {"vec",            arrow,      3 },
350         {"mathring",       ring,       0 },
351
352         // Dots
353         {"dots",           hline3,     0 },
354         {"ldots",          hline3,     0 },
355         {"cdots",          hline3,     0 },
356         {"vdots",          hline3,     1 },
357         {"ddots",          dline3,     0 },
358         {"adots",          dline3,     1 },
359         {"iddots",         dline3,     1 },
360         {"dotsb",          hline3,     0 },
361         {"dotsc",          hline3,     0 },
362         {"dotsi",          hline3,     0 },
363         {"dotsm",          hline3,     0 },
364         {"dotso",          hline3,     0 }
365 };
366
367
368 map<docstring, deco_struct> deco_list;
369
370 // sort the table on startup
371 class init_deco_table {
372 public:
373         init_deco_table() {
374                 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
375                 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
376                         deco_struct d;
377                         d.data  = p->data;
378                         d.angle = p->angle;
379                         deco_list[from_ascii(p->name)] = d;
380                 }
381         }
382 };
383
384 static init_deco_table dummy;
385
386
387 deco_struct const * search_deco(docstring const & name)
388 {
389         map<docstring, deco_struct>::const_iterator p = deco_list.find(name);
390         return p == deco_list.end() ? 0 : &(p->second);
391 }
392
393
394 } // namespace anon
395
396
397 int mathed_char_width(FontInfo const & font, char_type c)
398 {
399         return theFontMetrics(font).width(c);
400 }
401
402
403 int mathed_char_kerning(FontInfo const & font, char_type c)
404 {
405         frontend::FontMetrics const & fm = theFontMetrics(font);
406         return fm.rbearing(c) - fm.width(c);
407 }
408
409
410 void mathed_string_dim(FontInfo const & font,
411                        docstring const & s,
412                        Dimension & dim)
413 {
414         frontend::FontMetrics const & fm = theFontMetrics(font);
415         dim.asc = 0;
416         dim.des = 0;
417         for (docstring::const_iterator it = s.begin();
418              it != s.end();
419              ++it) {
420                 dim.asc = max(dim.asc, fm.ascent(*it));
421                 dim.des = max(dim.des, fm.descent(*it));
422         }
423         dim.wid = fm.width(s);
424 }
425
426
427 int mathed_string_width(FontInfo const & font, docstring const & s)
428 {
429         return theFontMetrics(font).width(s);
430 }
431
432
433 void mathed_draw_deco(PainterInfo & pi, int x, int y, int w, int h,
434         docstring const & name)
435 {
436         if (name == ".") {
437                 pi.pain.line(x + w/2, y, x + w/2, y + h,
438                           Color_cursor, Painter::line_onoffdash);
439                 return;
440         }
441
442         deco_struct const * mds = search_deco(name);
443         if (!mds) {
444                 lyxerr << "Deco was not found. Programming error?" << endl;
445                 lyxerr << "name: '" << to_utf8(name) << "'" << endl;
446                 return;
447         }
448
449         int const n = (w < h) ? w : h;
450         int const r = mds->angle;
451         double const * d = mds->data;
452
453         if (h > 70 && (name == "(" || name == ")"))
454                 d = parenthHigh;
455
456         Matrix mt(r, w, h);
457         Matrix sqmt(r, n, n);
458
459         if (r > 0 && r < 3)
460                 y += h;
461
462         if (r >= 2)
463                 x += w;
464
465         for (int i = 0; d[i]; ) {
466                 int code = int(d[i++]);
467                 if (code & 1) {  // code == 1 || code == 3
468                         double xx = d[i++];
469                         double yy = d[i++];
470                         double x2 = d[i++];
471                         double y2 = d[i++];
472                         if (code == 3)
473                                 sqmt.transform(xx, yy);
474                         else
475                                 mt.transform(xx, yy);
476                         mt.transform(x2, y2);
477                         pi.pain.line(
478                                 int(x + xx + 0.5), int(y + yy + 0.5),
479                                 int(x + x2 + 0.5), int(y + y2 + 0.5),
480                                 pi.base.font.color());
481                 } else {
482                         int xp[32];
483                         int yp[32];
484                         int const n = int(d[i++]);
485                         for (int j = 0; j < n; ++j) {
486                                 double xx = d[i++];
487                                 double yy = d[i++];
488 //           lyxerr << ' ' << xx << ' ' << yy << ' ';
489                                 if (code == 4)
490                                         sqmt.transform(xx, yy);
491                                 else
492                                         mt.transform(xx, yy);
493                                 xp[j] = int(x + xx + 0.5);
494                                 yp[j] = int(y + yy + 0.5);
495                                 //  lyxerr << "P[" << j ' ' << xx << ' ' << yy << ' ' << x << ' ' << y << ']';
496                         }
497                         pi.pain.lines(xp, yp, n, pi.base.font.color());
498                 }
499         }
500 }
501
502
503 void metricsStrRedBlack(MetricsInfo & mi, Dimension & dim, docstring const & str)
504 {
505         FontInfo font = mi.base.font;
506         augmentFont(font, from_ascii("mathnormal"));
507         mathed_string_dim(font, str, dim);
508 }
509
510
511 void drawStrRed(PainterInfo & pi, int x, int y, docstring const & str)
512 {
513         FontInfo f = pi.base.font;
514         augmentFont(f, from_ascii("mathnormal"));
515         f.setColor(Color_latex);
516         pi.pain.text(x, y, str, f);
517 }
518
519
520 void drawStrBlack(PainterInfo & pi, int x, int y, docstring const & str)
521 {
522         FontInfo f = pi.base.font;
523         augmentFont(f, from_ascii("mathnormal"));
524         f.setColor(Color_foreground);
525         pi.pain.text(x, y, str, f);
526 }
527
528
529 void math_font_max_dim(FontInfo const & font, int & asc, int & des)
530 {
531         frontend::FontMetrics const & fm = theFontMetrics(font);
532         asc = fm.maxAscent();
533         des = fm.maxDescent();
534 }
535
536
537 struct fontinfo {
538         string cmd_;
539         FontFamily family_;
540         FontSeries series_;
541         FontShape  shape_;
542         ColorCode        color_;
543 };
544
545
546 FontFamily const inh_family = INHERIT_FAMILY;
547 FontSeries const inh_series = INHERIT_SERIES;
548 FontShape  const inh_shape  = INHERIT_SHAPE;
549
550
551 // mathnormal should be the first, otherwise the fallback further down
552 // does not work
553 fontinfo fontinfos[] = {
554         // math fonts
555         {"mathnormal",    ROMAN_FAMILY, MEDIUM_SERIES,
556                           ITALIC_SHAPE, Color_math},
557         {"mathbf",        inh_family, BOLD_SERIES,
558                           inh_shape, Color_math},
559         {"mathcal",       CMSY_FAMILY, inh_series,
560                           inh_shape, Color_math},
561         {"mathfrak",      EUFRAK_FAMILY, inh_series,
562                           inh_shape, Color_math},
563         {"mathrm",        ROMAN_FAMILY, inh_series,
564                           UP_SHAPE, Color_math},
565         {"mathsf",        SANS_FAMILY, inh_series,
566                           inh_shape, Color_math},
567         {"mathbb",        MSB_FAMILY, inh_series,
568                           inh_shape, Color_math},
569         {"mathtt",        TYPEWRITER_FAMILY, inh_series,
570                           inh_shape, Color_math},
571         {"mathit",        inh_family, inh_series,
572                           ITALIC_SHAPE, Color_math},
573         {"mathscr",       RSFS_FAMILY, inh_series,
574                   inh_shape, Color_math}, 
575         {"cmex",          CMEX_FAMILY, inh_series,
576                           inh_shape, Color_math},
577         {"cmm",           CMM_FAMILY, inh_series,
578                           inh_shape, Color_math},
579         {"cmr",           CMR_FAMILY, inh_series,
580                           inh_shape, Color_math},
581         {"cmsy",          CMSY_FAMILY, inh_series,
582                           inh_shape, Color_math},
583         {"eufrak",        EUFRAK_FAMILY, inh_series,
584                           inh_shape, Color_math},
585         {"msa",           MSA_FAMILY, inh_series,
586                           inh_shape, Color_math},
587         {"msb",           MSB_FAMILY, inh_series,
588                           inh_shape, Color_math},
589         {"stmry",         STMARY_FAMILY, inh_series,
590                           inh_shape, Color_math},
591         {"wasy",          WASY_FAMILY, inh_series,
592                           inh_shape, Color_math},
593         {"esint",         ESINT_FAMILY, inh_series,
594                           inh_shape, Color_math},
595
596         // Text fonts
597         {"text",          inh_family, inh_series,
598                           inh_shape, Color_foreground},
599         {"textbf",        inh_family, BOLD_SERIES,
600                           inh_shape, Color_foreground},
601         {"textit",        inh_family, inh_series,
602                           ITALIC_SHAPE, Color_foreground},
603         {"textmd",        inh_family, MEDIUM_SERIES,
604                           inh_shape, Color_foreground},
605         {"textnormal",    inh_family, inh_series,
606                           UP_SHAPE, Color_foreground},
607         {"textrm",        ROMAN_FAMILY,
608                           inh_series, UP_SHAPE,Color_foreground},
609         {"textsc",        inh_family, inh_series,
610                           SMALLCAPS_SHAPE, Color_foreground},
611         {"textsf",        SANS_FAMILY, inh_series,
612                           inh_shape, Color_foreground},
613         {"textsl",        inh_family, inh_series,
614                           SLANTED_SHAPE, Color_foreground},
615         {"texttt",        TYPEWRITER_FAMILY, inh_series,
616                           inh_shape, Color_foreground},
617         {"textup",        inh_family, inh_series,
618                           UP_SHAPE, Color_foreground},
619
620         // TIPA support
621         {"textipa",       inh_family, inh_series,
622                           inh_shape, Color_foreground},
623
624         // mhchem support
625         {"ce",            inh_family, inh_series,
626                           inh_shape, Color_foreground},
627         {"cf",            inh_family, inh_series,
628                           inh_shape, Color_foreground},
629
630         // LyX internal usage
631         {"lyxtex",        inh_family, inh_series,
632                           UP_SHAPE, Color_latex},
633         {"lyxsymbol",     SYMBOL_FAMILY, inh_series,
634                           inh_shape, Color_math},
635         {"lyxboldsymbol", SYMBOL_FAMILY, BOLD_SERIES,
636                           inh_shape, Color_math},
637         {"lyxblacktext",  ROMAN_FAMILY, MEDIUM_SERIES,
638                           UP_SHAPE, Color_foreground},
639         {"lyxnochange",   inh_family, inh_series,
640                           inh_shape, Color_foreground},
641         {"lyxfakebb",     TYPEWRITER_FAMILY, BOLD_SERIES,
642                           UP_SHAPE, Color_math},
643         {"lyxfakecal",    SANS_FAMILY, MEDIUM_SERIES,
644                           ITALIC_SHAPE, Color_math},
645         {"lyxfakefrak",   ROMAN_FAMILY, BOLD_SERIES,
646                           ITALIC_SHAPE, Color_math}
647 };
648
649
650 fontinfo * lookupFont(docstring const & name0)
651 {
652         //lyxerr << "searching font '" << name << "'" << endl;
653         int const n = sizeof(fontinfos) / sizeof(fontinfo);
654         string name = to_utf8(name0);
655         for (int i = 0; i < n; ++i)
656                 if (fontinfos[i].cmd_ == name) {
657                         //lyxerr << "found '" << i << "'" << endl;
658                         return fontinfos + i;
659                 }
660         return 0;
661 }
662
663
664 fontinfo * searchFont(docstring const & name)
665 {
666         fontinfo * f = lookupFont(name);
667         return f ? f : fontinfos;
668         // this should be mathnormal
669         //return searchFont("mathnormal");
670 }
671
672
673 bool isFontName(docstring const & name)
674 {
675         return lookupFont(name);
676 }
677
678
679 bool isMathFont(docstring const & name)
680 {
681         fontinfo * f = lookupFont(name);
682         return f && f->color_ == Color_math;
683 }
684
685
686 bool isTextFont(docstring const & name)
687 {
688         fontinfo * f = lookupFont(name);
689         return f && f->color_ == Color_foreground;
690 }
691
692
693 FontInfo getFont(docstring const & name)
694 {
695         FontInfo font;
696         augmentFont(font, name);
697         return font;
698 }
699
700
701 void fakeFont(docstring const & orig, docstring const & fake)
702 {
703         fontinfo * forig = searchFont(orig);
704         fontinfo * ffake = searchFont(fake);
705         if (forig && ffake) {
706                 forig->family_ = ffake->family_;
707                 forig->series_ = ffake->series_;
708                 forig->shape_  = ffake->shape_;
709                 forig->color_  = ffake->color_;
710         } else {
711                 lyxerr << "Can't fake font '" << to_utf8(orig) << "' with '"
712                        << to_utf8(fake) << "'" << endl;
713         }
714 }
715
716
717 void augmentFont(FontInfo & font, docstring const & name)
718 {
719         static bool initialized = false;
720         if (!initialized) {
721                 initialized = true;
722                 // fake fonts if necessary
723                 if (!theFontLoader().available(getFont(from_ascii("mathfrak"))))
724                         fakeFont(from_ascii("mathfrak"), from_ascii("lyxfakefrak"));
725                 if (!theFontLoader().available(getFont(from_ascii("mathcal"))))
726                         fakeFont(from_ascii("mathcal"), from_ascii("lyxfakecal"));
727         }
728         fontinfo * info = searchFont(name);
729         if (info->family_ != inh_family)
730                 font.setFamily(info->family_);
731         if (info->series_ != inh_series)
732                 font.setSeries(info->series_);
733         if (info->shape_ != inh_shape)
734                 font.setShape(info->shape_);
735         if (info->color_ != Color_none)
736                 font.setColor(info->color_);
737 }
738
739
740 bool isAlphaSymbol(MathAtom const & at)
741 {
742         if (at->asCharInset() ||
743             (at->asSymbolInset() &&
744              at->asSymbolInset()->isOrdAlpha()))
745                 return true;
746
747         if (at->asFontInset()) {
748                 MathData const & ar = at->asFontInset()->cell(0);
749                 for (size_t i = 0; i < ar.size(); ++i) {
750                         if (!(ar[i]->asCharInset() ||
751                               (ar[i]->asSymbolInset() &&
752                                ar[i]->asSymbolInset()->isOrdAlpha())))
753                                 return false;
754                 }
755                 return true;
756         }
757         return false;
758 }
759
760
761 docstring asString(MathData const & ar)
762 {
763         odocstringstream os;
764         WriteStream ws(os);
765         ws << ar;
766         return os.str();
767 }
768
769
770 void asArray(docstring const & str, MathData & ar, Parse::flags pf)
771 {
772         bool quiet = pf & Parse::QUIET;
773         if ((str.size() == 1 && quiet) || (!mathed_parse_cell(ar, str, pf) && quiet))
774                 mathed_parse_cell(ar, str, pf | Parse::VERBATIM);
775 }
776
777
778 docstring asString(InsetMath const & inset)
779 {
780         odocstringstream os;
781         WriteStream ws(os);
782         inset.write(ws);
783         return os.str();
784 }
785
786
787 docstring asString(MathAtom const & at)
788 {
789         odocstringstream os;
790         WriteStream ws(os);
791         at->write(ws);
792         return os.str();
793 }
794
795
796 } // namespace lyx