]> git.lyx.org Git - lyx.git/blob - src/mathed/math_support.C
make \newcommand{\bb}[1]{\mathbf{#1}} work for read/write/display.
[lyx.git] / src / mathed / math_support.C
1 #include <config.h>
2
3 #include <map>
4
5 #include "math_support.h"
6 #include "lyxfont.h"
7 #include "FontLoader.h"
8 #include "font.h"
9 #include "math_cursor.h"
10 #include "math_defs.h"
11 #include "math_inset.h"
12 #include "math_parser.h"
13 #include "Painter.h"
14 #include "debug.h"
15
16 using std::map;
17 using std::endl;
18 using std::max;
19
20
21 bool isBinaryOp(char c, MathTextCodes type)
22 {
23         return type < LM_TC_SYMB && strchr("+-<>=/*", c);
24 }
25
26
27 ///
28 class Matrix {
29 public:
30         ///
31         Matrix(int, double, double);
32         ///
33         void transform(double &, double &);
34 private:
35         ///
36         double m_[2][2];
37 };
38
39
40 Matrix::Matrix(int code, double x, double y)
41 {
42         double const cs = (code & 1) ? 0 : (1 - code);
43         double const sn = (code & 1) ? (2 - code) : 0;
44         m_[0][0] =  cs * x;
45         m_[0][1] =  sn * x;
46         m_[1][0] = -sn * y;
47         m_[1][1] =  cs * y;
48 }
49
50
51 void Matrix::transform(double & x, double & y)
52 {
53         double xx = m_[0][0] * x + m_[0][1] * y;
54         double yy = m_[1][0] * x + m_[1][1] * y;
55         x = xx;
56         y = yy;
57 }
58
59
60 namespace {
61
62 LyXFont * MathFonts = 0;
63 bool font_available[LM_FONT_END];
64 bool font_available_initialized[LM_FONT_END];
65
66 enum MathFont {
67         FONT_IT,
68         FONT_SYMBOL,
69         FONT_SYMBOLI,
70         FONT_BF,
71         FONT_TT,
72         FONT_RM,
73         FONT_SF,
74         FONT_CMR,
75         FONT_CMSY,
76         FONT_CMM,
77         FONT_CMEX,
78         FONT_MSA,
79         FONT_MSB,
80         FONT_EUFRAK,
81         FONT_FAKEBB,
82         FONT_FAKECAL,
83         FONT_FAKEFRAK,
84         FONT_NUM
85 };
86
87 void mathed_init_fonts()
88 {
89         MathFonts = new LyXFont[FONT_NUM];
90
91         MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
92
93         MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
94
95         MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
96         MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
97
98         MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
99
100         MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
101         MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
102         MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
103
104         MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
105         MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
106         MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
107         MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
108         MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
109         MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
110         MathFonts[FONT_EUFRAK].setFamily(LyXFont::EUFRAK_FAMILY);
111
112         MathFonts[FONT_FAKEBB].setFamily(LyXFont::TYPEWRITER_FAMILY);
113         MathFonts[FONT_FAKEBB].setSeries(LyXFont::BOLD_SERIES);
114
115         MathFonts[FONT_FAKECAL].setFamily(LyXFont::SANS_FAMILY);
116         MathFonts[FONT_FAKECAL].setShape(LyXFont::ITALIC_SHAPE);
117
118         MathFonts[FONT_FAKEFRAK].setFamily(LyXFont::SANS_FAMILY);
119         MathFonts[FONT_FAKEFRAK].setSeries(LyXFont::BOLD_SERIES);
120
121         for (int i = 0; i < LM_FONT_END; ++i)
122                 font_available_initialized[i] = false;
123 }
124
125
126 LyXFont const & whichFontBaseIntern(MathTextCodes type)
127 {
128         if (!MathFonts)
129                 mathed_init_fonts();
130
131         switch (type) {
132         case LM_TC_SYMB:        
133         case LM_TC_BOLDSYMB:    
134                 return MathFonts[FONT_SYMBOLI];
135
136         case LM_TC_VAR:
137         case LM_TC_IT:
138                 return MathFonts[FONT_IT];
139
140         case LM_TC_BF:
141                 return MathFonts[FONT_BF];
142
143         case LM_TC_BB:
144                 return MathFonts[FONT_MSB];
145
146         case LM_TC_CAL:
147                 return MathFonts[FONT_CMSY];
148
149         case LM_TC_TT:
150                 return MathFonts[FONT_TT];
151
152         case LM_TC_BOX:
153         case LM_TC_TEXTRM:
154         case LM_TC_CONST:
155         case LM_TC_TEX:
156         case LM_TC_RM:
157                 return MathFonts[FONT_RM];
158
159         case LM_TC_SF:
160                 return MathFonts[FONT_SF];
161
162         case LM_TC_CMR:
163                 return MathFonts[FONT_CMR];
164
165         case LM_TC_CMSY:
166                 return MathFonts[FONT_CMSY];
167
168         case LM_TC_CMM:
169                 return MathFonts[FONT_CMM];
170
171         case LM_TC_CMEX:
172                 return MathFonts[FONT_CMEX];
173
174         case LM_TC_MSA:
175                 return MathFonts[FONT_MSA];
176
177         case LM_TC_MSB:
178                 return MathFonts[FONT_MSB];
179
180         case LM_TC_EUFRAK:
181                 return MathFonts[FONT_EUFRAK];
182
183         default:
184                 break;
185         }
186         return MathFonts[1];
187 }
188
189
190 LyXFont const & whichFontBase(MathTextCodes type)
191 {
192         if (!MathFonts)
193                 mathed_init_fonts();
194
195         switch (type) {
196         case LM_TC_BB:
197                 if (math_font_available(LM_TC_MSB))
198                         return MathFonts[FONT_MSB];
199                 else
200                         return MathFonts[FONT_FAKEBB];
201
202         case LM_TC_CAL:
203                 if (math_font_available(LM_TC_CMSY))
204                         return MathFonts[FONT_CMSY];
205                 else
206                         return MathFonts[FONT_FAKECAL];
207
208         case LM_TC_EUFRAK:
209                 if (math_font_available(LM_TC_EUFRAK))
210                         return MathFonts[FONT_EUFRAK];
211                 else
212                         return MathFonts[FONT_FAKEFRAK];
213
214         default:
215                 break;
216         }
217         return whichFontBaseIntern(type);
218 }
219
220
221 LyXFont whichFont(MathTextCodes type, MathMetricsInfo const & size)
222 {
223         LyXFont f = whichFontBase(type);
224         // use actual size
225         f.setSize(size.font.size());
226
227         switch (size.style) {
228         case LM_ST_DISPLAY:
229                 if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
230                         f.incSize();
231                         f.incSize();
232                 }
233                 break;
234
235         case LM_ST_TEXT:
236                 break;
237
238         case LM_ST_SCRIPT:
239                 f.decSize();
240                 f.decSize();
241                 break;
242
243         case LM_ST_SCRIPTSCRIPT:
244                 f.decSize();
245                 f.decSize();
246                 f.decSize();
247                 break;
248
249         default:
250                 lyxerr << "Math Error: wrong font size: " << size.style << endl;
251                 break;
252         }
253
254         if (type != LM_TC_TEXTRM && type != LM_TC_BOX)
255                 f.setColor(LColor::math);
256
257         if (type == LM_TC_TEX)
258                 f.setColor(LColor::latex);
259
260         return f;
261 }
262
263 } // namespace
264
265
266 bool math_font_available(MathTextCodes type)
267 {
268         if (!font_available_initialized[type]) {
269                 font_available_initialized[type] = true;
270                 font_available[type] = fontloader.available(whichFontBaseIntern(type));
271         }
272         return font_available[type];
273 }
274
275
276 namespace {
277
278 /*
279  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
280  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
281  */
282
283
284 double const parenthHigh[] = {
285         2, 13,
286         0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
287         0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
288         0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
289         0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
290         0.9840, 0.9986,
291         0
292 };
293
294
295 double const parenth[] = {
296         2, 13,
297         0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
298         0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
299         0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
300         0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
301         0.9930, 0.9919,
302         0
303 };
304
305
306 double const brace[] = {
307         2, 21,
308         0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
309         0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
310         0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
311         0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
312         0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
313         0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
314         0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
315         0
316 };
317
318
319 double const arrow[] = {
320         4, 7,
321         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
322         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
323         0.9500, 0.7500,
324         3, 0.5000, 0.1500, 0.5000, 0.9500,
325         0
326 };
327
328
329 double const Arrow[] = {
330         4, 7,
331         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
332         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
333         0.9500, 0.7500,
334         3, 0.3500, 0.5000, 0.3500, 0.9500,
335         3, 0.6500, 0.5000, 0.6500, 0.9500,
336         0
337 };
338
339
340 double const udarrow[] = {
341         2, 3,
342         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
343         2, 3,
344         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
345         1, 0.5, 0.2,  0.5, 0.8,
346         0
347 };
348
349
350 double const Udarrow[] = {
351         2, 3,
352         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
353         2, 3,
354         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
355         1, 0.35, 0.2, 0.35, 0.8,
356         1, 0.65, 0.2, 0.65, 0.8,
357         0
358 };
359
360
361 double const brack[] = {
362         2, 4,
363         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
364         0
365 };
366
367
368 double const corner[] = {
369         2, 3,
370         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
371         0
372 };
373
374
375 double const angle[] = {
376         2, 3,
377         1, 0,  0.05, 0.5,  1, 1,
378         0
379 };
380
381
382 double const slash[] = {
383         1, 0.95, 0.05, 0.05, 0.95,
384         0
385 };
386
387
388 double const hline[] = {
389         1, 0.00, 0.5, 1.0, 0.5,
390         0
391 };
392
393
394 double const hline2[] = {
395         1, 0.1, 0.5,  0.3, 0.5,
396         1, 0.7, 0.5,  0.9, 0.5,
397         0
398 };
399
400
401 double const hline3[] = {
402         1, 0.1,   0,  0.15,  0,
403         1, 0.475, 0,  0.525, 0,
404         1, 0.85,  0,  0.9,   0,
405         0
406 };
407
408
409 double const dline3[] = {
410         1, 0.1,   0.1,   0.15,  0.15,
411         1, 0.475, 0.475, 0.525, 0.525,
412         1, 0.85,  0.85,  0.9,   0.9,
413         0
414 };
415
416
417 double const hlinesmall[] = {
418         1, 0.4, 0.5, 0.6, 0.5,
419         0
420 };
421
422
423 double const vert[] = {
424         1, 0.5, 0.05,  0.5, 0.95,
425         0
426 };
427
428
429 double const  Vert[] = {
430         1, 0.3, 0.05,  0.3, 0.95,
431         1, 0.7, 0.05,  0.7, 0.95,
432         0
433 };
434
435
436 double const tilde[] = {
437         2, 4,
438         0.05, 0.8,  0.25, 0.2,  0.75, 0.8,  0.95, 0.2,
439         0
440 };
441
442
443 struct deco_struct {
444         double const * data;
445         int angle;
446 };
447
448 struct named_deco_struct {
449         char const * name;
450         double const * data;
451         int angle;
452 };
453
454 named_deco_struct deco_table[] = {
455         // Decorations
456         {"widehat",        angle,      3 },
457         {"widetilde",      tilde,      0 },
458         {"underline",      hline,      0 },
459         {"overline",       hline,      0 },
460         {"underbrace",     brace,      1 },
461         {"overbrace",      brace,      3 },
462         {"overleftarrow",  arrow,      1 },
463         {"overrightarrow", arrow,      3 },
464         
465         // Delimiters
466         {"(",              parenth,    0 },
467         {")",              parenth,    2 },
468         {"{",              brace,      0 },
469         {"}",              brace,      2 },
470         {"[",              brack,      0 },
471         {"]",              brack,      2 },
472         {"|",              vert,       0 },
473         {"/",              slash,      0 },
474         {"Vert",           Vert,       0 },
475         {"'",              slash,      1 },
476         {"backslash",      slash,      1 },
477         {"langle",         angle,      0 },
478         {"lceil",          corner,     0 },
479         {"lfloor",         corner,     1 },
480         {"rangle",         angle,      2 },
481         {"rceil",          corner,     3 },
482         {"rfloor",         corner,     2 },
483         {"downarrow",      arrow,      2 },
484         {"Downarrow",      Arrow,      2 },
485         {"uparrow",        arrow,      0 },
486         {"Uparrow",        Arrow,      0 },
487         {"updownarrow",    udarrow,    0 },
488         {"Updownarrow",    Udarrow,    0 },     
489         
490         // Accents
491         {"ddot",           hline2,     0 },
492         {"hat",            angle,      3 },
493         {"grave",          slash,      1 },
494         {"acute",          slash,      0 },
495         {"tilde",          tilde,      0 },
496         {"bar",            hline,      0 },
497         {"dot",            hlinesmall, 0 },
498         {"check",          angle,      1 },
499         {"breve",          parenth,    1 },
500         {"vec",            arrow,      3 },
501         {"not",            slash,      0 },
502         
503         // Dots
504         {"ldots",          hline3,     0 },
505         {"cdots",          hline3,     0 },
506         {"vdots",          hline3,     1 },
507         {"ddots",          dline3,     0 }
508 };
509
510
511 map<string, deco_struct> deco_list;
512
513 // sort the table on startup
514 struct init_deco_table {
515         init_deco_table() {
516                 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
517                 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
518                         deco_struct d;
519                         d.data  = p->data;
520                         d.angle = p->angle;
521                         deco_list[p->name]= d;
522                 }
523         }
524 };
525
526 static init_deco_table dummy;
527
528
529 deco_struct const * search_deco(string const & name)
530 {
531         map<string, deco_struct>::const_iterator p = deco_list.find(name);
532         return (p == deco_list.end()) ? 0 : &(p->second);
533 }
534
535
536 } // namespace anon
537
538
539 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
540         unsigned char c, int & asc, int & des, int & wid)
541 {
542         LyXFont const font = whichFont(type, size);
543         des = lyxfont::descent(c, font);
544         asc = lyxfont::ascent(c, font);
545         wid = mathed_char_width(type, size, c);
546 }
547
548
549 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
550         unsigned char c, int & asc, int & des)
551 {
552         LyXFont const font = whichFont(type, size);
553         des = lyxfont::descent(c, font);
554         asc = lyxfont::ascent(c, font);
555         return asc + des;
556 }
557
558
559 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
560         unsigned char c)
561 {
562         int asc;
563         int des;
564         return mathed_char_height(type, size, c, asc, des);
565 }
566
567
568 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
569         unsigned char c)
570 {
571         LyXFont const font = whichFont(type, size);
572         return lyxfont::ascent(c, font);
573 }
574
575
576 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
577         unsigned char c)
578 {
579         LyXFont const font = whichFont(type, size);
580         return lyxfont::descent(c, font);
581 }
582
583
584 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
585         unsigned char c)
586 {
587         LyXFont const font = whichFont(type, size);
588         if (isBinaryOp(c, type))
589                 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
590         else
591                 return lyxfont::width(c, font);
592 }
593
594
595 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
596         string const & s, int & asc, int & des, int & wid)
597 {
598         mathed_string_height(type, size, s, asc, des);
599         wid = mathed_string_width(type, size, s);
600 }
601
602
603 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
604         string const & s, int & asc, int & des)
605 {
606         LyXFont const font = whichFont(type, size);
607         asc = des = 0;
608         for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
609                 des = max(des, lyxfont::descent(*it, font));
610                 asc = max(asc, lyxfont::ascent(*it, font));
611         }
612         return asc + des;
613 }
614
615
616 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
617         string const & s)
618 {
619         return lyxfont::width(s, whichFont(type, size));
620 }
621
622
623 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
624         string const & s)
625 {
626         LyXFont const font = whichFont(type, size);
627         int asc = 0;
628         for (string::const_iterator it = s.begin(); it != s.end(); ++it)
629                 asc = max(asc, lyxfont::ascent(*it, font));
630         return asc;
631 }
632
633
634 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
635         string const & s)
636 {
637         LyXFont const font = whichFont(type, size);
638         int des = 0;
639         for (string::const_iterator it = s.begin(); it != s.end(); ++it)
640                 des = max(des, lyxfont::descent(*it, font));
641         return des;
642 }
643
644
645
646 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
647         const string & name)
648 {
649         if (name == ".") {
650                 pain.line(x + w/2, y, x + w/2, y + h,
651                           LColor::mathcursor, Painter::line_onoffdash);
652                 return;
653         }       
654         
655         deco_struct const * mds = search_deco(name);
656         if (!mds) {
657                 lyxerr << "Deco was not found. Programming error?\n";
658                 lyxerr << "name: '" << name << "'\n";
659                 return;
660         }
661         
662         int const n = (w < h) ? w : h;
663         int const r = mds->angle;
664         double const * d = mds->data;
665         
666         if (h > 70 && (name == "(" || name == ")"))
667                 d = parenthHigh;
668         
669         Matrix mt(r, w, h);
670         Matrix sqmt(r, n, n);
671
672         if (r > 0 && r < 3)
673                 y += h;
674
675         if (r >= 2)
676                 x += w;
677
678         for (int i = 0; d[i]; ) {
679                 int code = int(d[i++]);
680                 if (code & 1) {  // code == 1 || code == 3
681                         double xx = d[i++];
682                         double yy = d[i++];
683                         double x2 = d[i++];
684                         double y2 = d[i++];
685                         if (code == 3)
686                                 sqmt.transform(xx, yy);
687                         else
688                                 mt.transform(xx, yy);
689                         mt.transform(x2, y2);
690                         pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
691                                         LColor::math);
692                 }       else {
693                         int xp[32];
694                         int yp[32];
695                         int const n = int(d[i++]);
696                         for (int j = 0; j < n; ++j) {
697                                 double xx = d[i++];
698                                 double yy = d[i++];
699 //           lyxerr << " " << xx << " " << yy << " ";
700                                 if (code == 4)
701                                         sqmt.transform(xx, yy);
702                                 else
703                                         mt.transform(xx, yy);
704                                 xp[j] = x + int(xx);
705                                 yp[j] = y + int(yy);
706                                 //  lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
707                         }
708                         pain.lines(xp, yp, n, LColor::math);
709                 }
710         }
711 }
712
713
714 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
715 {
716         if (mathcursor && mathcursor->isInside(p))
717                 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
718                         LColor::mathframe);
719 }
720
721
722 // In the future maybe we use a better fonts renderer
723 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
724         int x, int y, string const & s)
725 {
726         pain.text(x, y, s, whichFont(type, siz));
727 }
728
729
730 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
731         int x, int y, char c)
732 {
733         string s;
734         if (isBinaryOp(c, type))
735                 s += ' ';
736         s += c;
737         if (isBinaryOp(c, type))
738                 s += ' ';
739         drawStr(pain, type, siz, x, y, s);
740 }
741
742
743 // decrease math size for super- and subscripts
744 void smallerStyleScript(MathMetricsInfo & st)
745 {
746         switch (st.style) {
747                 case LM_ST_DISPLAY:
748                 case LM_ST_TEXT:    st.style = LM_ST_SCRIPT; break;
749                 default:            st.style = LM_ST_SCRIPTSCRIPT;
750         }
751 }
752
753
754 // decrease math size for fractions
755 void smallerStyleFrac(MathMetricsInfo & st)
756 {
757         switch (st.style) {
758                 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
759                 case LM_ST_TEXT:    st.style = LM_ST_SCRIPT; break;
760                 default:            st.style = LM_ST_SCRIPTSCRIPT;
761         }
762 }
763
764
765 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
766         int & asc, int & des)
767 {
768         LyXFont font = whichFont(code, siz);
769         asc = lyxfont::maxAscent(font);
770         des = lyxfont::maxDescent(font);
771 }
772
773
774 char const * latex_mathspace[] = {
775         "!", ",", ":", ";", "quad", "qquad"
776 };
777
778
779 char const * latex_mathstyle[] = {
780         "textstyle", "displaystyle", "scriptstyle", "scriptscriptstyle", 
781         "mathbf", "mathcal","mathrm","mathtt", "mathsf", "mathit",
782         "mathbb","mathfrak", "textrm", "mathnormal"
783 };
784
785
786 char const * math_font_name(MathTextCodes code)
787 {
788         static char const * theFontNames[] = {
789                 "mathrm",
790                 "mathcal",
791                 "mathfrak",
792                 "mathbf",
793                 "mathbb",
794                 "mathsf",
795                 "mathtt",
796                 "mathit",
797                 "textrm"
798         };
799
800         if (code >= LM_TC_RM && code <= LM_TC_TEXTRM) 
801                 return theFontNames[code - LM_TC_RM];
802         return 0;
803 }