]> git.lyx.org Git - lyx.git/blob - src/mathed/math_support.C
fix build, thesaurus
[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         }
273         return font_available[type];
274 }
275
276
277 namespace {
278
279 /*
280  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
281  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
282  */
283
284
285 double const parenthHigh[] = {
286         2, 13,
287         0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
288         0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
289         0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
290         0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
291         0.9840, 0.9986,
292         0
293 };
294
295
296 double const parenth[] = {
297         2, 13,
298         0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
299         0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
300         0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
301         0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
302         0.9930, 0.9919,
303         0
304 };
305
306
307 double const brace[] = {
308         2, 21,
309         0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
310         0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
311         0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
312         0.0734, 0.4919, 0.0113, 0.5000, 0.0734, 0.5081,
313         0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
314         0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
315         0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
316         0
317 };
318
319
320 double const arrow[] = {
321         4, 7,
322         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
323         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
324         0.9500, 0.7500,
325         3, 0.5000, 0.1500, 0.5000, 0.9500,
326         0
327 };
328
329
330 double const Arrow[] = {
331         4, 7,
332         0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
333         0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
334         0.9500, 0.7500,
335         3, 0.3500, 0.5000, 0.3500, 0.9500,
336         3, 0.6500, 0.5000, 0.6500, 0.9500,
337         0
338 };
339
340
341 double const udarrow[] = {
342         2, 3,
343         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
344         2, 3,
345         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
346         1, 0.5, 0.2,  0.5, 0.8,
347         0
348 };
349
350
351 double const Udarrow[] = {
352         2, 3,
353         0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
354         2, 3,
355         0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
356         1, 0.35, 0.2, 0.35, 0.8,
357         1, 0.65, 0.2, 0.65, 0.8,
358         0
359 };
360
361
362 double const brack[] = {
363         2, 4,
364         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
365         0
366 };
367
368
369 double const corner[] = {
370         2, 3,
371         0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
372         0
373 };
374
375
376 double const angle[] = {
377         2, 3,
378         1, 0,  0.05, 0.5,  1, 1,
379         0
380 };
381
382
383 double const slash[] = {
384         1, 0.95, 0.05, 0.05, 0.95,
385         0
386 };
387
388
389 double const hline[] = {
390         1, 0.00, 0.5, 1.0, 0.5,
391         0
392 };
393
394
395 double const hline2[] = {
396         1, 0.1, 0.5,  0.3, 0.5,
397         1, 0.7, 0.5,  0.9, 0.5,
398         0
399 };
400
401
402 double const hline3[] = {
403         1, 0.1,   0,  0.15,  0,
404         1, 0.475, 0,  0.525, 0,
405         1, 0.85,  0,  0.9,   0,
406         0
407 };
408
409
410 double const dline3[] = {
411         1, 0.1,   0.1,   0.15,  0.15,
412         1, 0.475, 0.475, 0.525, 0.525,
413         1, 0.85,  0.85,  0.9,   0.9,
414         0
415 };
416
417
418 double const hlinesmall[] = {
419         1, 0.4, 0.5, 0.6, 0.5,
420         0
421 };
422
423
424 double const vert[] = {
425         1, 0.5, 0.05,  0.5, 0.95,
426         0
427 };
428
429
430 double const  Vert[] = {
431         1, 0.3, 0.05,  0.3, 0.95,
432         1, 0.7, 0.05,  0.7, 0.95,
433         0
434 };
435
436
437 double const tilde[] = {
438         2, 4,
439         0.05, 0.8,  0.25, 0.2,  0.75, 0.8,  0.95, 0.2,
440         0
441 };
442
443
444 struct deco_struct {
445         double const * data;
446         int angle;
447 };
448
449 struct named_deco_struct {
450         char const * name;
451         double const * data;
452         int angle;
453 };
454
455 named_deco_struct deco_table[] = {
456         // Decorations
457         {"widehat",        angle,      3 },
458         {"widetilde",      tilde,      0 },
459         {"underbar",       hline,      0 },
460         {"underline",      hline,      0 },
461         {"overline",       hline,      0 },
462         {"underbrace",     brace,      1 },
463         {"overbrace",      brace,      3 },
464         {"overleftarrow",  arrow,      1 },
465         {"overrightarrow", arrow,      3 },
466         
467         // Delimiters
468         {"(",              parenth,    0 },
469         {")",              parenth,    2 },
470         {"{",              brace,      0 },
471         {"}",              brace,      2 },
472         {"[",              brack,      0 },
473         {"]",              brack,      2 },
474         {"|",              vert,       0 },
475         {"/",              slash,      0 },
476         {"Vert",           Vert,       0 },
477         {"'",              slash,      1 },
478         {"backslash",      slash,      1 },
479         {"langle",         angle,      0 },
480         {"lceil",          corner,     0 },
481         {"lfloor",         corner,     1 },
482         {"rangle",         angle,      2 },
483         {"rceil",          corner,     3 },
484         {"rfloor",         corner,     2 },
485         {"downarrow",      arrow,      2 },
486         {"Downarrow",      Arrow,      2 },
487         {"uparrow",        arrow,      0 },
488         {"Uparrow",        Arrow,      0 },
489         {"updownarrow",    udarrow,    0 },
490         {"Updownarrow",    Udarrow,    0 },     
491         
492         // Accents
493         {"ddot",           hline2,     0 },
494         {"hat",            angle,      3 },
495         {"grave",          slash,      1 },
496         {"acute",          slash,      0 },
497         {"tilde",          tilde,      0 },
498         {"bar",            hline,      0 },
499         {"dot",            hlinesmall, 0 },
500         {"check",          angle,      1 },
501         {"breve",          parenth,    1 },
502         {"vec",            arrow,      3 },
503         {"not",            slash,      0 },
504         
505         // Dots
506         {"ldots",          hline3,     0 },
507         {"cdots",          hline3,     0 },
508         {"vdots",          hline3,     1 },
509         {"ddots",          dline3,     0 }
510 };
511
512
513 map<string, deco_struct> deco_list;
514
515 // sort the table on startup
516 struct init_deco_table {
517         init_deco_table() {
518                 unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
519                 for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
520                         deco_struct d;
521                         d.data  = p->data;
522                         d.angle = p->angle;
523                         deco_list[p->name]= d;
524                 }
525         }
526 };
527
528 static init_deco_table dummy;
529
530
531 deco_struct const * search_deco(string const & name)
532 {
533         map<string, deco_struct>::const_iterator p = deco_list.find(name);
534         return (p == deco_list.end()) ? 0 : &(p->second);
535 }
536
537
538 } // namespace anon
539
540
541 void mathed_char_dim(MathTextCodes type, MathMetricsInfo const & size,
542         unsigned char c, int & asc, int & des, int & wid)
543 {
544         LyXFont const font = whichFont(type, size);
545         des = lyxfont::descent(c, font);
546         asc = lyxfont::ascent(c, font);
547         wid = mathed_char_width(type, size, c);
548 }
549
550
551 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
552         unsigned char c, int & asc, int & des)
553 {
554         LyXFont const font = whichFont(type, size);
555         des = lyxfont::descent(c, font);
556         asc = lyxfont::ascent(c, font);
557         return asc + des;
558 }
559
560
561 int mathed_char_height(MathTextCodes type, MathMetricsInfo const & size,
562         unsigned char c)
563 {
564         int asc;
565         int des;
566         return mathed_char_height(type, size, c, asc, des);
567 }
568
569
570 int mathed_char_ascent(MathTextCodes type, MathMetricsInfo const & size,
571         unsigned char c)
572 {
573         LyXFont const font = whichFont(type, size);
574         return lyxfont::ascent(c, font);
575 }
576
577
578 int mathed_char_descent(MathTextCodes type, MathMetricsInfo const & size,
579         unsigned char c)
580 {
581         LyXFont const font = whichFont(type, size);
582         return lyxfont::descent(c, font);
583 }
584
585
586 int mathed_char_width(MathTextCodes type, MathMetricsInfo const & size,
587         unsigned char c)
588 {
589         LyXFont const font = whichFont(type, size);
590         if (isBinaryOp(c, type))
591                 return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
592         else
593                 return lyxfont::width(c, font);
594 }
595
596
597 void mathed_string_dim(MathTextCodes type, MathMetricsInfo const & size,
598         string const & s, int & asc, int & des, int & wid)
599 {
600         mathed_string_height(type, size, s, asc, des);
601         wid = mathed_string_width(type, size, s);
602 }
603
604
605 int mathed_string_height(MathTextCodes type, MathMetricsInfo const & size,
606         string const & s, int & asc, int & des)
607 {
608         LyXFont const font = whichFont(type, size);
609         asc = des = 0;
610         for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
611                 des = max(des, lyxfont::descent(*it, font));
612                 asc = max(asc, lyxfont::ascent(*it, font));
613         }
614         return asc + des;
615 }
616
617
618 int mathed_string_width(MathTextCodes type, MathMetricsInfo const & size,
619         string const & s)
620 {
621         return lyxfont::width(s, whichFont(type, size));
622 }
623
624
625 int mathed_string_ascent(MathTextCodes type, MathMetricsInfo const & size,
626         string const & s)
627 {
628         LyXFont const font = whichFont(type, size);
629         int asc = 0;
630         for (string::const_iterator it = s.begin(); it != s.end(); ++it)
631                 asc = max(asc, lyxfont::ascent(*it, font));
632         return asc;
633 }
634
635
636 int mathed_string_descent(MathTextCodes type, MathMetricsInfo const & size,
637         string const & s)
638 {
639         LyXFont const font = whichFont(type, size);
640         int des = 0;
641         for (string::const_iterator it = s.begin(); it != s.end(); ++it)
642                 des = max(des, lyxfont::descent(*it, font));
643         return des;
644 }
645
646
647
648 void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
649         const string & name)
650 {
651         if (name == ".") {
652                 pain.line(x + w/2, y, x + w/2, y + h,
653                           LColor::mathcursor, Painter::line_onoffdash);
654                 return;
655         }       
656         
657         deco_struct const * mds = search_deco(name);
658         if (!mds) {
659                 lyxerr << "Deco was not found. Programming error?\n";
660                 lyxerr << "name: '" << name << "'\n";
661                 return;
662         }
663         
664         int const n = (w < h) ? w : h;
665         int const r = mds->angle;
666         double const * d = mds->data;
667         
668         if (h > 70 && (name == "(" || name == ")"))
669                 d = parenthHigh;
670         
671         Matrix mt(r, w, h);
672         Matrix sqmt(r, n, n);
673
674         if (r > 0 && r < 3)
675                 y += h;
676
677         if (r >= 2)
678                 x += w;
679
680         for (int i = 0; d[i]; ) {
681                 int code = int(d[i++]);
682                 if (code & 1) {  // code == 1 || code == 3
683                         double xx = d[i++];
684                         double yy = d[i++];
685                         double x2 = d[i++];
686                         double y2 = d[i++];
687                         if (code == 3)
688                                 sqmt.transform(xx, yy);
689                         else
690                                 mt.transform(xx, yy);
691                         mt.transform(x2, y2);
692                         pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
693                                         LColor::math);
694                 }       else {
695                         int xp[32];
696                         int yp[32];
697                         int const n = int(d[i++]);
698                         for (int j = 0; j < n; ++j) {
699                                 double xx = d[i++];
700                                 double yy = d[i++];
701 //           lyxerr << " " << xx << " " << yy << " ";
702                                 if (code == 4)
703                                         sqmt.transform(xx, yy);
704                                 else
705                                         mt.transform(xx, yy);
706                                 xp[j] = x + int(xx);
707                                 yp[j] = y + int(yy);
708                                 //  lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
709                         }
710                         pain.lines(xp, yp, n, LColor::math);
711                 }
712         }
713 }
714
715
716 void mathed_draw_framebox(Painter & pain, int x, int y, MathInset const * p)
717 {
718         if (mathcursor && mathcursor->isInside(p))
719                 pain.rectangle(x, y - p->ascent(), p->width(), p->height(),
720                         LColor::mathframe);
721 }
722
723
724 // In the future maybe we use a better fonts renderer
725 void drawStr(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
726         int x, int y, string const & s)
727 {
728         pain.text(x, y, s, whichFont(type, siz));
729 }
730
731
732 void drawChar(Painter & pain, MathTextCodes type, MathMetricsInfo const & siz,
733         int x, int y, char c)
734 {
735         string s;
736         if (isBinaryOp(c, type))
737                 s += ' ';
738         s += c;
739         if (isBinaryOp(c, type))
740                 s += ' ';
741         drawStr(pain, type, siz, x, y, s);
742 }
743
744
745 // decrease math size for super- and subscripts
746 void smallerStyleScript(MathMetricsInfo & st)
747 {
748         switch (st.style) {
749                 case LM_ST_DISPLAY:
750                 case LM_ST_TEXT:    st.style = LM_ST_SCRIPT; break;
751                 default:            st.style = LM_ST_SCRIPTSCRIPT;
752         }
753 }
754
755
756 // decrease math size for fractions
757 void smallerStyleFrac(MathMetricsInfo & st)
758 {
759         switch (st.style) {
760                 case LM_ST_DISPLAY: st.style = LM_ST_TEXT; break;
761                 case LM_ST_TEXT:    st.style = LM_ST_SCRIPT; break;
762                 default:            st.style = LM_ST_SCRIPTSCRIPT;
763         }
764 }
765
766
767 void math_font_max_dim(MathTextCodes code, MathMetricsInfo const & siz,
768         int & asc, int & des)
769 {
770         LyXFont font = whichFont(code, siz);
771         asc = lyxfont::maxAscent(font);
772         des = lyxfont::maxDescent(font);
773 }
774
775
776 char const * latex_mathspace[] = {
777         "!", ",", ":", ";", "quad", "qquad"
778 };
779
780
781 char const * latex_mathstyle[] = {
782         "textstyle", "displaystyle", "scriptstyle", "scriptscriptstyle" 
783 };
784
785 kb_action latex_mathfontcmds[] = {
786         LFUN_BOLD, LFUN_EMPH, LFUN_ROMAN, LFUN_CODE, LFUN_SANS,
787         LFUN_ITAL, LFUN_NOUN, LFUN_FRAK, LFUN_FREE, LFUN_DEFAULT
788 };
789
790
791 char const * math_font_name(MathTextCodes code)
792 {
793         static char const * theFontNames[] = {
794                 "mathrm",
795                 "mathcal",
796                 "mathfrak",
797                 "mathbf",
798                 "mathbb",
799                 "mathsf",
800                 "mathtt",
801                 "mathit",
802                 "textrm"
803         };
804
805         if (code >= LM_TC_RM && code <= LM_TC_TEXTRM) 
806                 return theFontNames[code - LM_TC_RM];
807         return 0;
808 }