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