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