]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/support.C
use stream-like syntax for LaTeX output
[lyx.git] / src / mathed / support.C
index d751a766322f9ca5bdddb172681105d45f3de863..9cb0cd114e5775116baad1b792ea3ce3d434954a 100644 (file)
 #include <config.h>
 
-#include <algorithm>
+#include <map>
 
 #include "mathed/support.h"
 #include "lyxfont.h"
+#include "FontLoader.h"
 #include "font.h"
 #include "math_defs.h"
 #include "math_parser.h"
 #include "Painter.h"
 #include "debug.h"
 
-using std::sort;
-using std::lower_bound;
+using std::map;
 using std::endl;
 using std::max;
 
 
-bool MathIsAlphaFont(MathTextCodes x)
+bool isBinaryOp(char c, MathTextCodes type)
 {
-       return LM_TC_VAR <= x && x <= LM_TC_TEXTRM;
+       return type < LM_TC_SYMB && strchr("+-<>=/*", c);
 }
 
 
-bool MathIsBinary(MathTextCodes x)
-{
-       return x == LM_TC_BOP;
-}
-
-
-bool MathIsSymbol(MathTextCodes x)
-{
-       return x == LM_TC_SYMB || x == LM_TC_BSYM;
-}
-     
-
-
 ///
 class Matrix {
 public:
        ///
-       typedef float matriz_data[2][2];
-       ///
-       Matrix();
-       ///
-       void rotate(int);
+       Matrix(int, double, double);
        ///
-       void escalate(float, float);
-       ///
-       void transform(float, float, float &, float &);
+       void transform(double &, double &);
 private:
        ///
-       matriz_data m_;
-       ///
-       void multiply(matriz_data & a);
+       double m_[2][2];
 };
 
-Matrix::Matrix()
-{
-       m_[0][0] = 1;
-       m_[0][1] = 0;
-       m_[1][0] = 0;
-       m_[1][1] = 1;
-}
-
-void Matrix::rotate(int code)
-{
-       matriz_data r;
-       r[0][0] = 1;
-       r[0][1] = 0;
-       r[1][0] = 0;
-       r[1][1] = 1;
-       float const cs = (code & 1) ? 0 : (1 - code);
-       float const sn = (code & 1) ? (2 - code) : 0;
-       r[0][0] = cs;
-       r[0][1] = sn;
-       r[1][0] = -r[0][1];
-       r[1][1] = r[0][0];
-       multiply(r);
-}
 
-void Matrix::escalate(float x, float y)
+Matrix::Matrix(int code, double x, double y)
 {
-       matriz_data s;
-       s[0][0] = x;
-       s[0][1] = 0;
-       s[1][0] = 0;
-       s[1][1] = y;
-       multiply(s);
+       double const cs = (code & 1) ? 0 : (1 - code);
+       double const sn = (code & 1) ? (2 - code) : 0;
+       m_[0][0] =  cs * x;
+       m_[0][1] =  sn * x;
+       m_[1][0] = -sn * y;
+       m_[1][1] =  cs * y;
 }
 
-void Matrix::multiply(matriz_data & a)
-{
-       matriz_data c;
-       c[0][0] = a[0][0] * m_[0][0] + a[0][1] * m_[1][0];
-       c[1][0] = a[1][0] * m_[0][0] + a[1][1] * m_[1][0];
-       c[0][1] = a[0][0] * m_[0][1] + a[0][1] * m_[1][1];
-       c[1][1] = a[1][0] * m_[0][1] + a[1][1] * m_[1][1];
-       m_[0][0] = c[0][0];     
-       m_[0][1] = c[0][1];     
-       m_[1][0] = c[1][0];     
-       m_[1][1] = c[1][1];     
-}
 
-void Matrix::transform(float xp, float yp, float & x, float & y)
+void Matrix::transform(double & x, double & y)
 {
-       x = m_[0][0] * xp + m_[0][1] * yp;
-       y = m_[1][0] * xp + m_[1][1] * yp;
+       double xx = m_[0][0] * x + m_[0][1] * y;
+       double yy = m_[1][0] * x + m_[1][1] * y;
+       x = xx;
+       y = yy;
 }
 
 
 namespace {
 
-LyXFont           * Math_Fonts = 0;
+LyXFont * MathFonts = 0;
+bool font_available[LM_FONT_END];
+bool font_available_initialized[LM_FONT_END];
+
+enum MathFont {
+       FONT_IT,
+       FONT_SYMBOL,
+       FONT_SYMBOLI,
+       FONT_BF,
+       FONT_BB,
+       FONT_CAL,
+       FONT_TT,
+       FONT_RM,
+       FONT_SF,
+       FONT_CMR,
+       FONT_CMSY,
+       FONT_CMM,
+       FONT_CMEX,
+       FONT_MSA,
+       FONT_MSB,
+       FONT_NUM
+};
 
 void mathed_init_fonts()
 {
-       Math_Fonts = new LyXFont[8]; //DEC cxx cannot initialize all fonts
+       MathFonts = new LyXFont[FONT_NUM]; //DEC cxx cannot initialize all fonts
        //at once (JMarc) rc
 
-       for (int i = 0 ; i < 8 ; ++i) {
-               Math_Fonts[i] = LyXFont(LyXFont::ALL_SANE);
+       for (int i = 0 ; i < FONT_NUM ; ++i) {
+               MathFonts[i] = LyXFont(LyXFont::ALL_SANE);
        }
 
-       Math_Fonts[0].setShape(LyXFont::ITALIC_SHAPE);
+       MathFonts[FONT_IT].setShape(LyXFont::ITALIC_SHAPE);
 
-       Math_Fonts[1].setFamily(LyXFont::SYMBOL_FAMILY);
+       MathFonts[FONT_SYMBOL].setFamily(LyXFont::SYMBOL_FAMILY);
 
-       Math_Fonts[2].setFamily(LyXFont::SYMBOL_FAMILY);
-       Math_Fonts[2].setShape(LyXFont::ITALIC_SHAPE);
+       MathFonts[FONT_SYMBOLI].setFamily(LyXFont::SYMBOL_FAMILY);
+       MathFonts[FONT_SYMBOLI].setShape(LyXFont::ITALIC_SHAPE);
 
-       Math_Fonts[3].setSeries(LyXFont::BOLD_SERIES);
+       MathFonts[FONT_BF].setSeries(LyXFont::BOLD_SERIES);
 
-       Math_Fonts[4].setFamily(LyXFont::SANS_FAMILY);
-       Math_Fonts[4].setShape(LyXFont::ITALIC_SHAPE);
+       MathFonts[FONT_BB].setSeries(LyXFont::BOLD_SERIES);
+       MathFonts[FONT_BB].setFamily(LyXFont::TYPEWRITER_FAMILY);
 
-       Math_Fonts[5].setFamily(LyXFont::TYPEWRITER_FAMILY);
+       MathFonts[FONT_CAL].setFamily(LyXFont::SANS_FAMILY);
+       MathFonts[FONT_CAL].setShape(LyXFont::ITALIC_SHAPE);
 
-       Math_Fonts[6].setFamily(LyXFont::ROMAN_FAMILY);
+       MathFonts[FONT_TT].setFamily(LyXFont::TYPEWRITER_FAMILY);
 
-       Math_Fonts[7].setFamily(LyXFont::SANS_FAMILY);
-}
+       MathFonts[FONT_RM].setFamily(LyXFont::ROMAN_FAMILY);
 
-} // namespace
+       MathFonts[FONT_SF].setFamily(LyXFont::SANS_FAMILY);
+
+       MathFonts[FONT_CMR].setFamily(LyXFont::CMR_FAMILY);
+       MathFonts[FONT_CMSY].setFamily(LyXFont::CMSY_FAMILY);
+       MathFonts[FONT_CMM].setFamily(LyXFont::CMM_FAMILY);
+       MathFonts[FONT_CMEX].setFamily(LyXFont::CMEX_FAMILY);
+       MathFonts[FONT_MSA].setFamily(LyXFont::MSA_FAMILY);
+       MathFonts[FONT_MSB].setFamily(LyXFont::MSB_FAMILY);
+
+       for (int i = 0; i < LM_FONT_END; ++i)
+               font_available_initialized[i] = false;
+}
 
 
-LyXFont WhichFont(MathTextCodes type, MathStyles size)
+LyXFont const & whichFontBase(MathTextCodes type)
 {
-       LyXFont f;
-       
-       if (!Math_Fonts)
+       if (!MathFonts)
                mathed_init_fonts();
 
        switch (type) {
        case LM_TC_SYMB:        
-       case LM_TC_BSYM:        
-               f = Math_Fonts[2];
-               break;
+       case LM_TC_BOLDSYMB:    
+               return MathFonts[FONT_SYMBOLI];
 
        case LM_TC_VAR:
        case LM_TC_IT:
-               f = Math_Fonts[0];
-               break;
+               return MathFonts[FONT_IT];
 
        case LM_TC_BF:
-               f = Math_Fonts[3];
-               break;
+               return MathFonts[FONT_BF];
 
-       case LM_TC_SF:
-               f = Math_Fonts[7];
-               break;
+       case LM_TC_BB:
+               if (math_font_available(LM_TC_MSB))
+                       return MathFonts[FONT_MSB];
+               else
+                       return MathFonts[FONT_BB];
 
        case LM_TC_CAL:
-               f = Math_Fonts[4];
-               break;
+               if (math_font_available(LM_TC_CMSY))
+                       return MathFonts[FONT_CMSY];
+               else
+                       return MathFonts[FONT_CAL];
 
        case LM_TC_TT:
-               f = Math_Fonts[5];
-               break;
+               return MathFonts[FONT_TT];
 
-       case LM_TC_SPECIAL: //f = Math_Fonts[0]; break;
        case LM_TC_TEXTRM:
+       case LM_TC_CONST:
        case LM_TC_TEX:
        case LM_TC_RM:
-               f = Math_Fonts[6];
-               break;
+               return MathFonts[FONT_RM];
+
+       case LM_TC_SF:
+               return MathFonts[FONT_SF];
+
+       case LM_TC_CMR:
+               return MathFonts[FONT_CMR];
+
+       case LM_TC_CMSY:
+               return MathFonts[FONT_CMSY];
+
+       case LM_TC_CMM:
+               return MathFonts[FONT_CMM];
+
+       case LM_TC_CMEX:
+               return MathFonts[FONT_CMEX];
+
+       case LM_TC_MSA:
+               return MathFonts[FONT_MSA];
+
+       case LM_TC_MSB:
+               return MathFonts[FONT_MSB];
 
        default:
-               f = Math_Fonts[1];
                break;
        }
+       return MathFonts[1];
+}
+
+
+LyXFont whichFont(MathTextCodes type, MathStyles size)
+{
+       LyXFont f = whichFontBase(type);
 
        switch (size) {
        case LM_ST_DISPLAY:
-               if (type == LM_TC_BSYM) {
+               if (type == LM_TC_BOLDSYMB || type == LM_TC_CMEX) {
                        f.incSize();
                        f.incSize();
                }
@@ -226,49 +228,52 @@ LyXFont WhichFont(MathTextCodes type, MathStyles size)
        return f;
 }
 
-char const * math_font_name[] = {
-       "mathrm",
-       "mathcal",
-       "mathbf",
-       "mathsf",
-       "mathtt",
-       "mathit",
-       "textrm"
-};
+} // namespace
+
+
+bool math_font_available(MathTextCodes type)
+{
+       if (!font_available_initialized[type]) {
+               font_available_initialized[type] = true;
+               font_available[type] =
+                       fontloader.available(whichFontBase(type));
+       }
+       return font_available[type];
+}
 
 
 namespace {
 
-/* 
+/*
  * Internal struct of a drawing: code n x1 y1 ... xn yn, where code is:
  * 0 = end, 1 = line, 2 = polyline, 3 = square line, 4= square polyline
  */
 
 
-float const parenthHigh[] = {
-       2.0, 13.0,
+double const parenthHigh[] = {
+       2, 13,
        0.9840, 0.0014, 0.7143, 0.0323, 0.4603, 0.0772,
        0.2540, 0.1278, 0.1746, 0.1966, 0.0952, 0.3300,
        0.0950, 0.5000, 0.0952, 0.6700, 0.1746, 0.8034,
        0.2540, 0.8722, 0.4603, 0.9228, 0.7143, 0.9677,
        0.9840, 0.9986,
-       0.0 
+       0
 };
 
 
-float const parenth[] = {
-       2.0, 13.0,
+double const parenth[] = {
+       2, 13,
        0.9930, 0.0071, 0.7324, 0.0578, 0.5141, 0.1126,
        0.3380, 0.1714, 0.2183, 0.2333, 0.0634, 0.3621,
        0.0141, 0.5000, 0.0563, 0.6369, 0.2113, 0.7647,
        0.3310, 0.8276, 0.5070, 0.8864, 0.7254, 0.9412,
        0.9930, 0.9919,
-       0.0   
+       0
 };
 
 
-float const brace[] = {
-       2.0, 21.0,
+double const brace[] = {
+       2, 21,
        0.9492, 0.0020, 0.9379, 0.0020, 0.7458, 0.0243,
        0.5819, 0.0527, 0.4859, 0.0892, 0.4463, 0.1278,
        0.4463, 0.3732, 0.4011, 0.4199, 0.2712, 0.4615,
@@ -276,245 +281,244 @@ float const brace[] = {
        0.2712, 0.5385, 0.4011, 0.5801, 0.4463, 0.6268,
        0.4463, 0.8722, 0.4859, 0.9108, 0.5819, 0.9473,
        0.7458, 0.9757, 0.9379, 0.9980, 0.9492, 0.9980,
-       0.0
+       0
 };
 
 
-// Is this correct? (Lgb)
-float const arrow[] = {
+double const arrow[] = {
        4, 7,
        0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
        0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
        0.9500, 0.7500,
        3, 0.5000, 0.1500, 0.5000, 0.9500,
-       0.0 
+       0
 };
 
 
-// Is this correct? (Lgb)
-float const Arrow[] = {
+double const Arrow[] = {
        4, 7,
        0.0150, 0.7500, 0.2000, 0.6000, 0.3500, 0.3500,
        0.5000, 0.0500, 0.6500, 0.3500, 0.8000, 0.6000,
        0.9500, 0.7500,
        3, 0.3500, 0.5000, 0.3500, 0.9500,
        3, 0.6500, 0.5000, 0.6500, 0.9500,
-       0.0
+       0
 };
 
 
-float const udarrow[] = {
+double const udarrow[] = {
        2, 3,
        0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
        2, 3,
-       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,  
+       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
        1, 0.5, 0.2,  0.5, 0.8,
-       0.0 
+       0
 };
 
 
-float const Udarrow[] = {
+double const Udarrow[] = {
        2, 3,
        0.015, 0.25,  0.5, 0.05, 0.95, 0.25,
        2, 3,
-       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,  
+       0.015, 0.75,  0.5, 0.95, 0.95, 0.75,
        1, 0.35, 0.2, 0.35, 0.8,
        1, 0.65, 0.2, 0.65, 0.8,
-       0.0 
+       0
 };
 
 
-float const brack[] = {
-       2.0, 4,
+double const brack[] = {
+       2, 4,
        0.95, 0.05,  0.05, 0.05,  0.05, 0.95,  0.95, 0.95,
-       0.0
+       0
 };
 
 
-float const corner[] = {
-       2.0, 3,
+double const corner[] = {
+       2, 3,
        0.95, 0.05,  0.05, 0.05,  0.05, 0.95,
-       0.0
+       0
 };
 
 
-float const angle[] = {
-       2.0, 3,
+double const angle[] = {
+       2, 3,
        1, 0,  0.05, 0.5,  1, 1,
-       0.0
+       0
 };
 
 
-float const slash[] = {
-       1, 0.95, 0.05,  0.05, 0.95, 
-       0.0
+double const slash[] = {
+       1, 0.95, 0.05, 0.05, 0.95,
+       0
 };
 
 
-float const hline[] = {
-       1, 0.05, 0.5,  0.95, 0.5, 
-       0.0
+double const hline[] = {
+       1, 0.00, 0.5, 1.0, 0.5,
+       0
 };
 
 
-float const hline2[] = {
-   1, 0.1, 0.5,  0.3, 0.5,
-   1, 0.7, 0.5,  0.9, 0.5,
-   0.0
-}; 
+double const hline2[] = {
+       1, 0.1, 0.5,  0.3, 0.5,
+       1, 0.7, 0.5,  0.9, 0.5,
+       0
+};
 
 
-float const hline3[] = {
-       1, 0.1, 0,  0.15, 0,
+double const hline3[] = {
+       1, 0.1,   0,  0.15,  0,
        1, 0.475, 0,  0.525, 0,
-       1, 0.85, 0,  0.9, 0,  
-       0.0
+       1, 0.85,  0,  0.9,   0,
+       0
 };
 
 
-float const dline3[] = {
-       1, 0.1, 0.1,  0.15, 0.15,
-       1, 0.475, 0.475,  0.525, 0.525,
-       1, 0.85, 0.85,  0.9, 0.9,
-       0.0
-};     
+double const dline3[] = {
+       1, 0.1,   0.1,   0.15,  0.15,
+       1, 0.475, 0.475, 0.525, 0.525,
+       1, 0.85,  0.85,  0.9,   0.9,
+       0
+};
 
 
-float const hlinesmall[] = {
-       1, 0.4, 0.5,  0.6, 0.5, 
-       0.0
+double const hlinesmall[] = {
+       1, 0.4, 0.5, 0.6, 0.5,
+       0
 };
 
 
-float const vert[] = {
-       1, 0.5, 0.05,  0.5, 0.95, 
-       0.0
+double const vert[] = {
+       1, 0.5, 0.05,  0.5, 0.95,
+       0
 };
 
 
-float const  Vert[] = {
-       1, 0.3, 0.05,  0.3, 0.95, 
+double const  Vert[] = {
+       1, 0.3, 0.05,  0.3, 0.95,
        1, 0.7, 0.05,  0.7, 0.95,
-       0.0
+       0
 };
 
 
-float const tilde[] = {
-       2.0, 4,
+double const tilde[] = {
+       2, 4,
        0.05, 0.8,  0.25, 0.2,  0.75, 0.8,  0.95, 0.2,
-       0.0
+       0
 };
 
 
-struct math_deco_struct {
-       int code;
-       float const * data;
+struct deco_struct {
+       double const * data;
        int angle;
 };
 
-math_deco_struct math_deco_table[] = {   
-       // Decorations
-       { LM_widehat,       &angle[0],      3 },
-       { LM_widetilde,     &tilde[0],      0 },
-       { LM_underline,     &hline[0],      0 },
-       { LM_overline,      &hline[0],      0 },
-       { LM_underbrace,    &brace[0],      1 },
-       { LM_overbrace,     &brace[0],      3 },
-       { LM_overleftarrow, &arrow[0],      1 },
-       { LM_overightarrow, &arrow[0],      3 },
-                                           
-       // Delimiters                       
-       { '(',              &parenth[0],    0 },
-       { ')',              &parenth[0],    2 },
-       { '{',              &brace[0],      0 },
-       { '}',              &brace[0],      2 },
-       { '[',              &brack[0],      0 },
-       { ']',              &brack[0],      2 },
-       { '|',              &vert[0],       0 },
-       { '/',              &slash[0],      0 },
-       { LM_Vert,          &Vert[0],       0 },
-       { LM_backslash,     &slash[0],      1 },
-       { LM_langle,        &angle[0],      0 },
-       { LM_lceil,         &corner[0],     0 }, 
-       { LM_lfloor,        &corner[0],     1 },  
-       { LM_rangle,        &angle[0],      2 }, 
-       { LM_rceil,         &corner[0],     3 }, 
-       { LM_rfloor,        &corner[0],     2 },
-       { LM_downarrow,     &arrow[0],      2 },
-       { LM_Downarrow,     &Arrow[0],      2 }, 
-       { LM_uparrow,       &arrow[0],      0 },
-       { LM_Uparrow,       &Arrow[0],      0 },
-       { LM_updownarrow,   &udarrow[0],    0 },
-       { LM_Updownarrow,   &Udarrow[0],    0 },         
-                                           
-       // Accents                          
-       { LM_ddot,          &hline2[0],     0 },
-       { LM_hat,           &angle[0],      3 },
-       { LM_grave,         &slash[0],      1 },
-       { LM_acute,         &slash[0],      0 },
-       { LM_tilde,         &tilde[0],      0 },
-       { LM_bar,           &hline[0],      0 },
-       { LM_dot,           &hlinesmall[0], 0 },
-       { LM_check,         &angle[0],      1 },
-       { LM_breve,         &parenth[0],    1 },
-       { LM_vec,           &arrow[0],      3 },
-       { LM_not,           &slash[0],      0 },  
-                                           
-       // Dots                             
-       { LM_ldots,         &hline3[0],     0 }, 
-       { LM_cdots,         &hline3[0],     0 },
-       { LM_vdots,         &hline3[0],     1 },
-       { LM_ddots,         &dline3[0],     0 }
+struct named_deco_struct {
+       char const * name;
+       double const * data;
+       int angle;
 };
 
-
-struct math_deco_compare {
-       /// for use by sort and lower_bound
-       inline
-       int operator()(math_deco_struct const & a,
-                      math_deco_struct const & b) const {
-               return a.code < b.code;
-       }
+named_deco_struct deco_table[] = {
+       // Decorations
+       {"widehat",        angle,      3 },
+       {"widetilde",      tilde,      0 },
+       {"underline",      hline,      0 },
+       {"overline",       hline,      0 },
+       {"underbrace",     brace,      1 },
+       {"overbrace",      brace,      3 },
+       {"overleftarrow",  arrow,      1 },
+       {"overrightarrow", arrow,      3 },
+       
+       // Delimiters
+       {"(",              parenth,    0 },
+       {")",              parenth,    2 },
+       {"{",              brace,      0 },
+       {"}",              brace,      2 },
+       {"[",              brack,      0 },
+       {"]",              brack,      2 },
+       {"|",              vert,       0 },
+       {"/",              slash,      0 },
+       {"Vert",           Vert,       0 },
+       {"'",              slash,      1 },
+       {"backslash",      slash,      1 },
+       {"langle",         angle,      0 },
+       {"lceil",          corner,     0 },
+       {"lfloor",         corner,     1 },
+       {"rangle",         angle,      2 },
+       {"rceil",          corner,     3 },
+       {"rfloor",         corner,     2 },
+       {"downarrow",      arrow,      2 },
+       {"Downarrow",      Arrow,      2 },
+       {"uparrow",        arrow,      0 },
+       {"Uparrow",        Arrow,      0 },
+       {"updownarrow",    udarrow,    0 },
+       {"Updownarrow",    Udarrow,    0 },     
+       
+       // Accents
+       {"ddot",           hline2,     0 },
+       {"hat",            angle,      3 },
+       {"grave",          slash,      1 },
+       {"acute",          slash,      0 },
+       {"tilde",          tilde,      0 },
+       {"bar",            hline,      0 },
+       {"dot",            hlinesmall, 0 },
+       {"check",          angle,      1 },
+       {"breve",          parenth,    1 },
+       {"vec",            arrow,      3 },
+       {"not",            slash,      0 },
+       
+       // Dots
+       {"ldots",          hline3,     0 },
+       {"cdots",          hline3,     0 },
+       {"vdots",          hline3,     1 },
+       {"ddots",          dline3,     0 }
 };
 
 
-int const math_deco_table_size =
-sizeof(math_deco_table) /sizeof(math_deco_struct);
+map<string, deco_struct> deco_list;
 
-
-class init_deco_table {
-public:
+// sort the table on startup
+struct init_deco_table {
        init_deco_table() {
-               if (!init) {
-                       sort(math_deco_table,
-                            math_deco_table + math_deco_table_size,
-                            math_deco_compare());
-                       init_deco_table::init = true;
+               unsigned const n = sizeof(deco_table) / sizeof(deco_table[0]);
+               for (named_deco_struct * p = deco_table; p != deco_table + n; ++p) {
+                       deco_struct d;
+                       d.data  = p->data;
+                       d.angle = p->angle;
+                       deco_list[p->name]= d;
                }
        }
-private:
-       static bool init;
 };
 
+static init_deco_table dummy;
+
+
+deco_struct const * search_deco(string const & name)
+{
+       map<string, deco_struct>::const_iterator p = deco_list.find(name);
+       return (p == deco_list.end()) ? 0 : &(p->second);
+}
 
-bool init_deco_table::init = false;
-static init_deco_table idt;
 
 } // namespace anon
 
+
 void mathed_char_dim(MathTextCodes type, MathStyles size, unsigned char c,
        int & asc, int & des, int & wid)
 {
-       LyXFont const font = WhichFont(type, size);
+       LyXFont const font = whichFont(type, size);
        des = lyxfont::descent(c, font);
        asc = lyxfont::ascent(c, font);
        wid = mathed_char_width(type, size, c);
 }
 
+
 int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
        int & asc, int & des)
 {
-       LyXFont const font = WhichFont(type, size);
+       LyXFont const font = whichFont(type, size);
        des = lyxfont::descent(c, font);
        asc = lyxfont::ascent(c, font);
        return asc + des;
@@ -528,28 +532,28 @@ int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c)
        return mathed_char_height(type, size, c, asc, des);
 }
 
+
 int mathed_char_ascent(MathTextCodes type, MathStyles size, unsigned char c)
 {
-       LyXFont const font = WhichFont(type, size);
+       LyXFont const font = whichFont(type, size);
        return lyxfont::ascent(c, font);
 }
 
+
 int mathed_char_descent(MathTextCodes type, MathStyles size, unsigned char c)
 {
-       LyXFont const font = WhichFont(type, size);
+       LyXFont const font = whichFont(type, size);
        return lyxfont::descent(c, font);
 }
 
 
-
 int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
 {
-       if (MathIsBinary(type)) {
-               string s;
-               s += c;
-               return mathed_string_width(type, size, s);
-       } else
-               return lyxfont::width(c, WhichFont(type, size));
+       LyXFont const font = whichFont(type, size);
+       if (isBinaryOp(c, type))
+               return lyxfont::width(c, font) + 2 * lyxfont::width(' ', font);
+       else
+               return lyxfont::width(c, font);
 }
 
 
@@ -560,10 +564,11 @@ void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
        wid = mathed_string_width(type, size, s);
 }
 
+
 int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
                         int & asc, int & des)
 {
-       LyXFont const font = WhichFont(type, size);
+       LyXFont const font = whichFont(type, size);
        asc = des = 0;
        for (string::const_iterator it = s.begin(); it != s.end(); ++it) {
                des = max(des, lyxfont::descent(*it, font));
@@ -575,139 +580,99 @@ int mathed_string_height(MathTextCodes type, MathStyles size, string const & s,
 
 int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
 {
-       string st;
-       if (MathIsBinary(type))
-               for (string::const_iterator it = s.begin();
-                    it != s.end(); ++it) {
-                       st += ' ';
-                       st += *it;
-                       st += ' ';
-               }
-       else
-               st = s;
-       
-       return lyxfont::width(st, WhichFont(type, size));
+       return lyxfont::width(s, whichFont(type, size));
 }
 
 
-namespace {
-
-math_deco_struct const * search_deco(int code)
+void mathed_draw_deco(Painter & pain, int x, int y, int w, int h,
+       const string & name)
 {
-       math_deco_struct search_elem = { code, 0, 0 };
-       
-       math_deco_struct const * res =
-               lower_bound(math_deco_table,
-                           math_deco_table + math_deco_table_size,
-                           search_elem, math_deco_compare());
-       if (res != math_deco_table + math_deco_table_size &&
-           res->code == code)
-               return res;
-       return 0;
-}
-
-}
-
-void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
-{
-       Matrix mt;
-       Matrix sqmt;
-       float xx;
-       float yy;
-       float x2;
-       float y2;
-       int i = 0;
+       if (name == ".") {
+               pain.line(x + w/2, y, x + w/2, y + h,
+                         LColor::mathcursor, Painter::line_onoffdash);
+               return;
+       }       
        
-       math_deco_struct const * mds = search_deco(code);
+       deco_struct const * mds = search_deco(name);
        if (!mds) {
-               // Should this ever happen?
-               lyxerr << "Deco was not found. Programming error?" << endl;
+               lyxerr << "Deco was not found. Programming error?\n";
+               lyxerr << "name: '" << name << "'\n";
                return;
        }
        
+       int const n = (w < h) ? w : h;
        int const r = mds->angle;
-       float const * d = mds->data;
+       double const * d = mds->data;
        
-       if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
+       if (h > 70 && (name == "(" || name == ")"))
                d = parenthHigh;
        
-       mt.rotate(r);
-       mt.escalate(w, h);
-       
-       int const n = (w < h) ? w : h;
-       sqmt.rotate(r);
-       sqmt.escalate(n, n);
-       if (r > 0 && r < 3) y += h;   
-       if (r >= 2) x += w;   
-       do {
-               code = int(d[i++]);
-               switch (code) {
-               case 0: break;
-               case 1: 
-               case 3:
-               {
-                       xx = d[i++]; yy = d[i++];
-                       x2 = d[i++]; y2 = d[i++];
-                       if (code == 3) 
-                               sqmt.transform(xx, yy, xx, yy);
+       Matrix mt(r, w, h);
+       Matrix sqmt(r, n, n);
+
+       if (r > 0 && r < 3)
+               y += h;
+
+       if (r >= 2)
+               x += w;
+
+       for (int i = 0; d[i]; ) {
+               int code = int(d[i++]);
+               if (code & 1) {  // code == 1 || code == 3
+                       double xx = d[i++];
+                       double yy = d[i++];
+                       double x2 = d[i++];
+                       double y2 = d[i++];
+                       if (code == 3)
+                               sqmt.transform(xx, yy);
                        else
-                               mt.transform(xx, yy, xx, yy);
-                       mt.transform(x2, y2, x2, y2);
-                       pain.line(x + int(xx), y + int(yy),
-                                 x + int(x2), y + int(y2),
-                                 LColor::mathline);
-                       break;
-               }        
-               case 2: 
-               case 4:
-               {
+                               mt.transform(xx, yy);
+                       mt.transform(x2, y2);
+                       pain.line(x + int(xx), y + int(yy), x + int(x2), y + int(y2),
+                                       LColor::mathline);
+               }       else {
                        int xp[32];
                        int yp[32];
                        int const n = int(d[i++]);
                        for (int j = 0; j < n; ++j) {
-                               xx = d[i++]; yy = d[i++];
+                               double xx = d[i++];
+                               double yy = d[i++];
 //          lyxerr << " " << xx << " " << yy << " ";
-                               if (code == 4) 
-                                       sqmt.transform(xx, yy, xx, yy);
+                               if (code == 4)
+                                       sqmt.transform(xx, yy);
                                else
-                                       mt.transform(xx, yy, xx, yy);
+                                       mt.transform(xx, yy);
                                xp[j] = x + int(xx);
                                yp[j] = y + int(yy);
                                //  lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
                        }
                        pain.lines(xp, yp, n, LColor::mathline);
                }
-               }
-       } while (code);
+       }
 }
 
 
-
-// In a near future maybe we use a better fonts renderer
+// In the future maybe we use a better fonts renderer
 void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
        int x, int y, string const & s)
 {
-       string st;
-       if (MathIsBinary(type))
-               for (string::const_iterator it = s.begin();
-                    it != s.end(); ++it) {
-                       st += ' ';
-                       st += *it;
-                       st += ' ';
-               }
-       else
-               st = s;
-       
-       pain.text(x, y, st, WhichFont(type, siz));
+       pain.text(x, y, s, whichFont(type, siz));
 }
 
-void drawChar(Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
+
+void drawChar
+       (Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
 {
        string s;
+       if (isBinaryOp(c, type))
+               s += ' ';
        s += c;
+       if (isBinaryOp(c, type))
+               s += ' ';
        drawStr(pain, type, siz, x, y, s);
 }
 
+
 // decrease math size for super- and subscripts
 MathStyles smallerStyleScript(MathStyles st)
 {
@@ -719,6 +684,7 @@ MathStyles smallerStyleScript(MathStyles st)
        return st;
 }
 
+
 // decrease math size for fractions
 MathStyles smallerStyleFrac(MathStyles st)
 {
@@ -733,11 +699,12 @@ MathStyles smallerStyleFrac(MathStyles st)
 
 void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
 {
-       LyXFont font = WhichFont(code, siz);
+       LyXFont font = whichFont(code, siz);
        asc = lyxfont::maxAscent(font);
        des = lyxfont::maxDescent(font);
 }
 
+
 char const * latex_mathspace[] = {
        "!", ",", ":", ";", "quad", "qquad"
 };