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