]> git.lyx.org Git - lyx.git/blob - src/mathed/math_draw.C
Fixed a bug in InsetFormula drawing.
[lyx.git] / src / mathed / math_draw.C
1 /*
2  *  File:        math_draw.C
3  *  Purpose:     Interaction and drawing for mathed
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
5  *  Created:     January 1996
6  *  Description: Math drawing and interaction for a WYSIWYG math editor.
7  *
8  *  Dependencies: Xlib, XForms
9  *
10  *  Copyright: 1996, Alejandro Aguilar Sierra
11  *
12  *   Version: 0.8beta, Mathed & Lyx project.
13  *
14  *   You are free to use and modify this code under the terms of
15  *   the GNU General Public Licence version 2 or later.
16  */
17
18 #include <config.h>
19 #include FORMS_H_LOCATION
20 #include "math_cursor.h"
21 #include "math_parser.h"
22 #include "debug.h"
23 #include "lyxfont.h"
24 #include "Painter.h"
25
26 using std::endl;
27
28 extern LyXFont const mathed_get_font(short type, int size);
29 extern int mathed_char_width(short type, int style, byte c);
30 extern int mathed_string_width(short type, int style, string const &);
31 extern int mathed_string_height(short, int, string const &, int &, int &);
32 extern int mathed_char_height(short, int, byte, int &, int &);
33
34 void
35 MathSpaceInset::draw(Painter & pain, int x, int y)
36
37
38 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
39
40 // Sadly, HP-UX CC can't handle that kind of initialization.
41
42    int xp[4];
43    int yp[4];
44    
45    xp[0] = ++x;            yp[0] = y - 3;
46    xp[1] = x;              yp[1] = y;
47    xp[2] = x + width - 2;  yp[2] = y;
48    xp[3] = x + width - 2;  yp[3] = y - 3;
49
50    pain.lines(xp, yp, 4, (space) ? LColor::latex : LColor::math);
51 }
52
53
54 void 
55 MathParInset::draw(Painter & pain, int x, int y)
56 {
57    byte cx, cxp = 0;
58    int xp = 0, ls;
59    int asc = df_asc, des = 0;
60    bool limits = false;
61     
62    xo = x;  yo = y; 
63    if (!array || array->empty()) {
64        if (array) {
65            MathedXIter data(this);
66            data.GetPos(x, y);
67        }
68        pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
69       return;
70    }  
71    MathedXIter data(this);
72    data.GoBegin();
73    while (data.OK()) {
74       data.GetPos(x, y);
75       cx = data.GetChar();
76       if (cx >= ' ') {
77          byte * s = data.GetString(ls);
78           drawStr(pain, data.FCode(), size, x, y, s, ls);
79           mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
80           limits = false;
81       } else {
82           if (cx == 0) break;
83          if (MathIsInset(cx)) {
84             int yy = y;
85             MathedInset * p = data.GetInset();
86             if (cx == LM_TC_UP) {
87                if (limits) {              x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;  
88                   yy -= (asc + p->Descent()+4);
89                } else
90                   yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
91             } else
92             if (cx == LM_TC_DOWN) {
93                if (limits) {
94                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
95                   yy += des + p->Ascent() + 2;
96                } else
97                  yy += des + p->Ascent()/2;
98             } else {
99                asc = p->Ascent();
100                des = p->Descent();
101             }
102             p->draw(pain, x, yy);
103             if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
104                limits = p->GetLimits();
105                if (limits) xp = p->Width();
106             }
107             data.Next();
108          } else 
109            if (cx == LM_TC_TAB) {
110                if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
111                        pain.rectangle(x, y - df_asc, df_width, df_asc,
112                                       LColor::mathline);
113                }
114               data.Next();
115               limits = false;
116            } else
117             if (cx == LM_TC_CR) {
118                 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { //  && objtype == LM_OT_MATRIX) {
119                         pain.rectangle(x, y - df_asc, df_width, df_asc,
120                                        LColor::mathline);
121                 }
122                 data.Next();
123                 limits = false;
124             }
125          else {  
126                  lyxerr << "GMathed Error: Unrecognized code[" << cx
127                         << "]" << endl;
128             break;
129          }
130       }
131       cxp = cx;
132    }
133    if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
134       data.GetPos(x, y);
135       pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
136    }
137 }
138
139
140 void 
141 MathParInset::Metrics()
142 {
143     byte cx;
144     byte cxp = 0;
145     int ls;
146     int asc = df_asc;
147     int des = 0;
148     int tb = 0;
149     int tab = 0;
150
151     bool limits = false;
152     
153     ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des); 
154     width = df_width;
155     descent = 0;
156     if (!array) return;
157     if (array->empty()) return;
158     
159     ascent = 0;
160     MathedXIter data(this);
161     data.GoBegin();
162     while (data.OK()) {
163         cx = data.GetChar();      
164         if (cx >= ' ') {
165             string s = data.GetString();
166             mathed_string_height(data.FCode(), size, s, asc, des);
167             if (asc > ascent) ascent = asc;
168             if (des > descent) descent = des;
169             limits = false;
170             mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
171         } else
172           if (MathIsInset(cx)) {
173               MathedInset * p = data.GetInset();
174               p->SetStyle(size);   
175               p->Metrics();
176               if (cx == LM_TC_UP) {
177                   asc += (limits) ? p->Height() + 4: p->Ascent() + 
178                     ((p->Descent()>asc) ? p->Descent() - asc + 4: 0);
179               } else
180                 if (cx == LM_TC_DOWN) {
181                     des += ((limits) ? p->Height() + 4: p->Height() - p->Ascent() / 2);
182                 } else {
183                     asc = p->Ascent();
184                     des = p->Descent();
185                 }
186               if (asc > ascent) ascent = asc;
187               if (des > descent) descent = des;
188               if (cx!= LM_TC_UP && cx!= LM_TC_DOWN)
189                 limits = p->GetLimits();
190               data.Next();
191           } else 
192           if (cx == LM_TC_TAB) {
193               int x, y;
194               data.GetIncPos(x, y);
195               if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
196                   if (ascent<df_asc) ascent = df_asc;
197                   tb = x;
198               }
199               data.setTab(x-tb, tab);
200               tb = x;
201               ++tab;
202               limits = false;                   
203               data.Next();
204           } else
205           if (cx == LM_TC_CR) {
206               if (tb > 0) {
207                   int x, y;
208                   data.GetIncPos(x, y);
209                   if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
210                       if (ascent<df_asc) ascent = df_asc;
211                       tb = x;
212                   } 
213                   data.setTab(x - tb, tab);
214               } else //if (GetColumns() == 1) 
215                     {
216                   int x, y;
217                   data.GetIncPos(x, y);
218                   data.setTab(x, tab);
219                   if (ascent<df_asc) ascent = df_asc;
220               } 
221               tb = tab = 0;
222               data.subMetrics(ascent, descent);
223               ascent = df_asc;   
224               descent = 0;
225               data.Next();
226           } else {
227                 lyxerr << "Mathed Error: Unrecognized code[" << cx
228                        << "]" << endl;
229             break;
230         }       
231         cxp = cx;
232     }
233     data.GetIncPos(width, ls);
234     
235     // No matter how simple is a matrix, it is NOT a subparagraph
236     if (isMatrix()) {
237         if (cxp == LM_TC_TAB) {
238             if (ascent<df_asc) ascent = df_asc;
239             data.setTab(0, tab);
240         } else {
241           data.setTab(width - tb, tab);
242         }
243     }
244           
245     data.subMetrics(ascent, descent);
246 }
247
248
249 void
250 MathSqrtInset::draw(Painter & pain, int x, int y)
251
252    MathParInset::draw(pain, x + hmax + 2, y); 
253    int h = ascent;
254    int d = descent;
255    int h2 = Height() / 2;
256    int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2; 
257    int xp[4], yp[4];
258    xp[0] = x + hmax + wbody; yp[0] = y - h;
259    xp[1] = x + hmax;         yp[1] = y - h;
260    xp[2] = x + w2;           yp[2] = y + d;
261    xp[3] = x;                yp[3] = y + d - h2;
262    pain.lines(xp, yp, 4, LColor::mathline);
263 }
264
265
266 void
267 MathSqrtInset::Metrics()
268 {
269    MathParInset::Metrics();
270    ascent += 4;
271    descent += 2;
272    int a, b;
273    hmax = mathed_char_height(LM_TC_VAR, size, 'I', a, b);
274    if (hmax < 10) hmax = 10;
275    wbody = width + 4;
276    width += hmax + 4;
277 }
278
279
280 void
281 MathFracInset::draw(Painter & pain, int x, int y)
282
283     short idxp = idx;
284     short sizex = size;
285     
286     idx = 0;
287     if (size == LM_ST_DISPLAY) ++size;
288     MathParInset::draw(pain, x + (width - w0) / 2, y - des0);
289     den->draw(pain, x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
290     size = sizex;
291     if (objtype == LM_OT_FRAC)
292             pain.line(x + 2, y - dh, x + width - 4, y - dh, LColor::mathline);
293     idx = idxp;
294 }
295
296
297 void
298 MathFracInset::Metrics()
299 {
300     if (!dh) {
301         int a, b;
302         dh = mathed_char_height(LM_TC_CONST, size, 'I', a, b)/2;
303     }
304     short idxp = idx;
305     short sizex = size; 
306     idx = 0;
307     if (size == LM_ST_DISPLAY) ++size; 
308     MathParInset::Metrics();
309     size = sizex;
310     w0 = width;
311     int as = Height() + 2 + dh;
312     des0 = Descent() + 2 + dh;
313     den->Metrics();  
314     w1 = den->Width();   
315     width = ((w0 > w1) ? w0: w1) + 12;
316     ascent = as; 
317     descent = den->Height()+ 2 - dh;
318     idx = idxp;
319 }
320
321
322 void
323 MathBigopInset::draw(Painter & pain, int x, int y)
324 {
325    string s;
326    short t;
327    
328    if (sym < 256 || sym == LM_oint) {
329       s += (sym == LM_oint) ? LM_int : sym;
330       t = LM_TC_BSYM;
331    } else {
332       s = name;
333       t = LM_TC_TEXTRM;
334    }
335    if (sym == LM_oint) {
336            pain.arc(x, y - 5 * width / 4, width, width, 0, 360*64,
337                     LColor::mathline);
338            ++x;
339    }
340    pain.text(x, y, s, mathed_get_font(t, size));
341 }
342
343
344 void
345 MathBigopInset::Metrics()
346 {   
347         char c;
348         string s;
349         short t;
350         
351         if (sym < 256 || sym == LM_oint) {
352                 c = (sym == LM_oint) ? LM_int: sym;
353                 s += c;
354                 t = LM_TC_BSYM;
355         } else {
356                 s = name;
357                 t = LM_TC_TEXTRM;
358         }
359         mathed_string_height(t, size, s, ascent, descent);
360         width = mathed_string_width(t, size, s);
361         if (sym == LM_oint) width += 2;
362 }