]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/support.C
fix pullArg when pressing <Delete> at the end of an cell
[lyx.git] / src / mathed / support.C
index 8ef4aa4bc5c49be000f1018d4f055b3efce8c970..47f4736fcae19f4d3f20df71ee24080c0bc544a7 100644 (file)
@@ -6,9 +6,8 @@
 #include "lyxfont.h"
 #include "font.h"
 #include "math_defs.h"
+#include "math_parser.h"
 #include "Painter.h"
-#include "matriz.h"
-#include "symbol_def.h"
 #include "debug.h"
 #include "math_utils.h"
 
@@ -17,7 +16,229 @@ using std::lower_bound;
 using std::endl;
 using std::max;
 
-extern LyXFont WhichFont(short type, int size);
+
+bool MathIsInset(MathTextCodes x)
+{
+       return LM_TC_INSET == x;
+}
+
+
+bool MathIsAlphaFont(MathTextCodes x)
+{
+       return LM_TC_VAR <= x && x <= LM_TC_TEXTRM;
+}
+
+
+bool MathIsBOPS(MathTextCodes x)
+{
+       return MathLookupBOP(x) != LMB_NONE;
+}
+
+
+bool MathIsBinary(MathTextCodes x)
+{
+       return x == LM_TC_BOP || x == LM_TC_BOPS;
+}
+
+
+bool MathIsSymbol(MathTextCodes x)
+{
+       return x == LM_TC_SYMB || x == LM_TC_BOPS || x == LM_TC_BSYM;
+}
+     
+
+
+///
+class Matrix {
+public:
+       ///
+       typedef float matriz_data[2][2];
+       ///
+       Matrix();
+       ///
+       void rotate(int);
+       ///
+       void escalate(float, float);
+       ///
+       void transform(float, float, float &, float &);
+private:
+       ///
+       matriz_data m_;
+       ///
+       void multiply(matriz_data & a);
+};
+
+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)
+{
+       matriz_data s;
+       s[0][0] = x;
+       s[0][1] = 0;
+       s[1][0] = 0;
+       s[1][1] = y;
+       multiply(s);
+}
+
+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)
+{
+       x = m_[0][0] * xp + m_[0][1] * yp;
+       y = m_[1][0] * xp + m_[1][1] * yp;
+}
+
+
+namespace {
+
+LyXFont           * Math_Fonts = 0;
+
+void mathed_init_fonts()
+{
+       Math_Fonts = new LyXFont[8]; //DEC cxx cannot initialize all fonts
+       //at once (JMarc) rc
+
+       for (int i = 0 ; i < 8 ; ++i) {
+               Math_Fonts[i] = LyXFont(LyXFont::ALL_SANE);
+       }
+
+       Math_Fonts[0].setShape(LyXFont::ITALIC_SHAPE);
+
+       Math_Fonts[1].setFamily(LyXFont::SYMBOL_FAMILY);
+
+       Math_Fonts[2].setFamily(LyXFont::SYMBOL_FAMILY);
+       Math_Fonts[2].setShape(LyXFont::ITALIC_SHAPE);
+
+       Math_Fonts[3].setSeries(LyXFont::BOLD_SERIES);
+
+       Math_Fonts[4].setFamily(LyXFont::SANS_FAMILY);
+       Math_Fonts[4].setShape(LyXFont::ITALIC_SHAPE);
+
+       Math_Fonts[5].setFamily(LyXFont::TYPEWRITER_FAMILY);
+
+       Math_Fonts[6].setFamily(LyXFont::ROMAN_FAMILY);
+
+       Math_Fonts[7].setFamily(LyXFont::SANS_FAMILY);
+}
+
+} // namespace
+
+
+LyXFont WhichFont(MathTextCodes type, MathStyles size)
+{
+       LyXFont f;
+       
+       if (!Math_Fonts)
+               mathed_init_fonts();
+
+       switch (type) {
+       case LM_TC_SYMB:        
+               f = Math_Fonts[2];
+               break;
+
+       case LM_TC_BSYM:        
+               f = Math_Fonts[2];
+               break;
+
+       case LM_TC_VAR:
+       case LM_TC_IT:
+               f = Math_Fonts[0];
+               break;
+
+       case LM_TC_BF:
+               f = Math_Fonts[3];
+               break;
+
+       case LM_TC_SF:
+               f = Math_Fonts[7];
+               break;
+
+       case LM_TC_CAL:
+               f = Math_Fonts[4];
+               break;
+
+       case LM_TC_TT:
+               f = Math_Fonts[5];
+               break;
+
+       case LM_TC_SPECIAL: //f = Math_Fonts[0]; break;
+       case LM_TC_TEXTRM:
+       case LM_TC_TEX:
+       case LM_TC_RM:
+               f = Math_Fonts[6];
+               break;
+
+       default:
+               f = Math_Fonts[1];
+               break;
+       }
+
+       switch (size) {
+       case LM_ST_DISPLAY:
+               if (type == LM_TC_BSYM) {
+                       f.incSize();
+                       f.incSize();
+               }
+               break;
+
+       case LM_ST_TEXT:
+               break;
+
+       case LM_ST_SCRIPT:
+               f.decSize();
+               break;
+
+       case LM_ST_SCRIPTSCRIPT:
+               f.decSize();
+               f.decSize();
+               break;
+
+       default:
+               lyxerr << "Math Error: wrong font size: " << size << endl;
+               break;
+       }
+
+       if (type != LM_TC_TEXTRM)
+               f.setColor(LColor::math);
+
+       if (type == LM_TC_TEX)
+               f.setColor(LColor::latex);
+
+       return f;
+}
 
 char const * math_font_name[] = {
        "mathrm",
@@ -204,59 +425,65 @@ float const tilde[] = {
 };
 
 
+struct math_deco_struct {
+       int code;
+       float 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 }
+       { 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 }
 };
 
 
@@ -294,8 +521,17 @@ 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);
+       des = lyxfont::descent(c, font);
+       asc = lyxfont::ascent(c, font);
+       wid = mathed_char_width(type, size, c);
+}
 
-int mathed_char_height(short type, int size, byte c, int & asc, int & des)
+int mathed_char_height(MathTextCodes type, MathStyles size, unsigned char c,
+       int & asc, int & des)
 {
        LyXFont const font = WhichFont(type, size);
        des = lyxfont::descent(c, font);
@@ -304,7 +540,7 @@ int mathed_char_height(short type, int size, byte c, int & asc, int & des)
 }
 
 
-int mathed_char_width(short type, int size, byte c)
+int mathed_char_width(MathTextCodes type, MathStyles size, unsigned char c)
 {
        if (MathIsBinary(type)) {
                string s;
@@ -315,7 +551,14 @@ int mathed_char_width(short type, int size, byte c)
 }
 
 
-int mathed_string_height(short type, int size, string const & s,
+void mathed_string_dim(MathTextCodes type, MathStyles size, string const & s,
+                        int & asc, int & des, int & wid)
+{
+       mathed_string_height(type, size, s, asc, des);
+       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);
@@ -328,7 +571,7 @@ int mathed_string_height(short type, int size, string const & s,
 }
 
 
-int mathed_string_width(short type, int size, string const & s)
+int mathed_string_width(MathTextCodes type, MathStyles size, string const & s)
 {
        string st;
        if (MathIsBinary(type))
@@ -341,49 +584,38 @@ int mathed_string_width(short type, int size, string const & s)
        else
                st = s;
        
-       LyXFont const f = WhichFont(type, size);
-       return lyxfont::width(st, f);
+       return lyxfont::width(st, WhichFont(type, size));
 }
 
 
-LyXFont mathed_get_font(short type, int size)
+namespace {
+
+math_deco_struct const * search_deco(int code)
 {
-       LyXFont f = WhichFont(type, size);
-       if (type == LM_TC_TEX) {
-               f.setLatex(LyXFont::ON);
-       }
-       return f;
+       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)
 {
-       Matriz mt;
-       Matriz sqmt;
+       Matrix mt;
+       Matrix sqmt;
        float xx;
        float yy;
        float x2;
        float y2;
        int i = 0;
        
-#if USE_EXCEPTIONS
-       math_deco_struct mds;
-       try {
-               mds = search_deco(code);
-       }
-       catch (deco_not_found) {
-               // Should this ever happen?
-               lyxerr << "Deco was not found. Programming error?" << endl;
-               return;
-       }
-       
-       int const r = mds.angle;
-       float const * d = mds.data;
-       
-       if (h > 70 && (mds.code == int('(')
-                      || mds.code == int(')')))
-               d = parenthHigh;
-#else
        math_deco_struct const * mds = search_deco(code);
        if (!mds) {
                // Should this ever happen?
@@ -391,21 +623,18 @@ void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
                return;
        }
        
-       
        int const r = mds->angle;
        float const * d = mds->data;
        
-       if (h > 70 && (mds->code == int('(')
-                      || mds->code == int(')')))
+       if (h > 70 && (mds->code == int('(') || mds->code == int(')')))
                d = parenthHigh;
-#endif
        
-       mt.rota(r);
-       mt.escala(w, h);
+       mt.rotate(r);
+       mt.escalate(w, h);
        
        int const n = (w < h) ? w : h;
-       sqmt.rota(r);
-       sqmt.escala(n, n);
+       sqmt.rotate(r);
+       sqmt.escalate(n, n);
        if (r > 0 && r < 3) y += h;   
        if (r >= 2) x += w;   
        do {
@@ -418,10 +647,10 @@ void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
                        xx = d[i++]; yy = d[i++];
                        x2 = d[i++]; y2 = d[i++];
                        if (code == 3) 
-                               sqmt.transf(xx, yy, xx, yy);
+                               sqmt.transform(xx, yy, xx, yy);
                        else
-                               mt.transf(xx, yy, xx, yy);
-                       mt.transf(x2, y2, x2, y2);
+                               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);
@@ -437,9 +666,9 @@ void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
                                xx = d[i++]; yy = d[i++];
 //          lyxerr << " " << xx << " " << yy << " ";
                                if (code == 4) 
-                                       sqmt.transf(xx, yy, xx, yy);
+                                       sqmt.transform(xx, yy, xx, yy);
                                else
-                                       mt.transf(xx, yy, xx, yy);
+                                       mt.transform(xx, yy, xx, yy);
                                xp[j] = x + int(xx);
                                yp[j] = y + int(yy);
                                //  lyxerr << "P[" << j " " << xx << " " << yy << " " << x << " " << y << "]";
@@ -451,147 +680,71 @@ void mathed_draw_deco(Painter & pain, int x, int y, int w, int h, int code)
 }
 
 
-#define USE_EXCEPTIONS 0
-#if USE_EXCEPTIONS
-struct deco_not_found {};
-
-
-math_deco_struct const & search_deco(int code)
-{
-       math_deco_struct const * res =
-               lower_bound(math_deco_table,
-                           math_deco_table + math_deco_table_size,
-                           code, math_deco_compare());
-       if (res != math_deco_table + math_deco_table_size &&
-           res->code == code)
-               return *res;
-       throw deco_not_found();
-}
-
-#else
-
 
-math_deco_struct const * search_deco(int code)
+// In a near future maybe we use a better fonts renderer
+void drawStr(Painter & pain, MathTextCodes type, MathStyles siz,
+       int x, int y, string const & s)
 {
-       math_deco_struct search_elem = { code, 0, 0 };
+       string st;
+       if (MathIsBinary(type))
+               for (string::const_iterator it = s.begin();
+                    it != s.end(); ++it) {
+                       st += ' ';
+                       st += *it;
+                       st += ' ';
+               }
+       else
+               st = s;
        
-       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;
-}
-#endif
-
-
-bool MathIsInset(short x)
-{
-       return LM_TC_INSET <= x && x <= LM_TC_ACTIVE_INSET;
-}
-
-
-bool MathIsFont(short x)
-{
-       return LM_TC_CONST <= x && x <= LM_TC_BSYM;
+       pain.text(x, y, st, WhichFont(type, siz));
 }
 
-
-bool MathIsAlphaFont(short x)
-{
-       return LM_TC_VAR <= x && x <= LM_TC_TEXTRM;
-}
-
-
-bool MathIsActive(short x)
-{
-       return LM_TC_INSET < x && x <= LM_TC_ACTIVE_INSET;
-}
-
-
-bool MathIsUp(short x)
-{
-       return x == LM_TC_UP;
-}
-
-
-bool MathIsDown(short x)
-{
-       return x == LM_TC_DOWN;
-}
-
-
-bool MathIsScript(short x)
-{
-       return x == LM_TC_DOWN || x == LM_TC_UP;
-}
-
-
-bool MathIsBOPS(short x)
-{
-       return MathedLookupBOP(x) > LMB_NONE;
-}
-
-
-bool MathIsBinary(short x)
+void drawChar(Painter & pain, MathTextCodes type, MathStyles siz, int x, int y, char c)
 {
-       return x == LM_TC_BOP || x == LM_TC_BOPS;
-}
-
-
-bool MathIsSymbol(short x)
-{
-       return LM_TC_SYMB <= x && x <= LM_TC_BSYM;
-}
-     
-
-bool is_eqn_type(short int type)
-{
-       return type >= LM_OT_MIN && type < LM_OT_MATRIX;
-}
-
-
-bool is_matrix_type(short int type)
-{
-       return type == LM_OT_MATRIX;
+       string s;
+       s += c;
+       drawStr(pain, type, siz, x, y, s);
 }
 
-
-bool is_multiline(short int type)
+// decrease math size for super- and subscripts
+MathStyles smallerStyleScript(MathStyles st)
 {
-       return type >= LM_OT_MPAR && type < LM_OT_MATRIX;
-}
-
-
-bool is_ams(short int type)
-{
-       return type > LM_OT_MPARN && type < LM_OT_MATRIX;
+       switch (st) {
+               case LM_ST_DISPLAY:
+               case LM_ST_TEXT:    st = LM_ST_SCRIPT; break;
+               default:            st = LM_ST_SCRIPTSCRIPT;
+       }
+       return st;
 }
 
-
-bool is_singlely_numbered(short int type)
+// decrease math size for fractions
+MathStyles smallerStyleFrac(MathStyles st)
 {
-       return type == LM_OT_PARN || type == LM_OT_MULTLINEN;
+       switch (st) {
+               case LM_ST_DISPLAY: st = LM_ST_TEXT; break;
+               case LM_ST_TEXT:    st = LM_ST_SCRIPT; break;
+               default:            st = LM_ST_SCRIPTSCRIPT;
+       }
+       return st;
 }
 
-
-bool is_multi_numbered(short int type)
+bool MathIsRelOp(unsigned char c, MathTextCodes f)
 {
-       return type == LM_OT_MPARN || type == LM_OT_ALIGNN
-               || type == LM_OT_ALIGNATN;
+       if (f == LM_TC_BOP && (c == '=' || c == '<' || c == '>'))
+               return true;
+#ifndef WITH_WARNINGS
+#warning implement me properly
+#endif
+       if (f == LM_TC_SYMB && (c == LM_leq || c == LM_geq))
+               return true;
+       return false;
 }
 
 
-bool is_numbered(short int type)
+void math_font_max_dim(MathTextCodes code, MathStyles siz, int & asc, int & des)
 {
-       return is_singlely_numbered(type) || is_multi_numbered(type);
+       LyXFont font = WhichFont(code, siz);
+       asc = lyxfont::maxAscent(font);
+       des = lyxfont::maxDescent(font);
 }
 
-
-bool is_multicolumn(short int type)
-{
-       return type == LM_OT_ALIGN || type == LM_OT_ALIGNN
-               || type == LM_OT_ALIGNAT || type == LM_OT_ALIGNATN;
-}