]> git.lyx.org Git - lyx.git/blob - src/mathed/math_draw.C
Hopefully fix the problem with stateText() in lyxfont.C
[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 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, byte const* s, int ls);
31 extern int mathed_string_height(short, int, byte const*, int, 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) {
88                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;  
89                   yy -= (asc + p->Descent()+4);
90                } else
91                   yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
92             } else
93             if (cx == LM_TC_DOWN) {
94                if (limits) {
95                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
96                   yy += des + p->Ascent() + 2;
97                } else
98                  yy += des + p->Ascent()/2;
99             } else {
100                asc = p->Ascent();
101                des = p->Descent();
102             }
103             p->draw(pain, x, yy);
104             if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
105                limits = p->GetLimits();
106                if (limits) xp = p->Width();
107             }
108             data.Next();
109          } else 
110            if (cx == LM_TC_TAB) {
111                if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
112                        pain.rectangle(x, y - df_asc, df_width, df_asc,
113                                       LColor::mathline);
114                }
115               data.Next();
116               limits = false;
117            } else
118             if (cx == LM_TC_CR) {
119                 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { //  && objtype == LM_OT_MATRIX) {
120                         pain.rectangle(x, y - df_asc, df_width, df_asc,
121                                        LColor::mathline);
122                 }
123                 data.Next();
124                 limits = false;
125             }
126          else {  
127                  lyxerr << "GMathed Error: Unrecognized code[" << cx
128                         << "]" << endl;
129             break;
130          }
131       }
132       cxp = cx;
133    }
134    if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
135       data.GetPos(x, y);
136       pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
137    }
138 }
139
140
141 void 
142 MathParInset::Metrics()
143 {
144     byte cx, cxp= 0, *s;
145     int ls;
146     int asc= df_asc, des= 0;
147     int tb = 0, tab= 0;
148
149     bool limits = false;
150     
151     ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des); 
152     width = df_width;
153     descent = 0;
154     if (!array) return;
155     if (array->empty()) return;
156     
157     ascent = 0;
158     MathedXIter data(this);
159     data.GoBegin();
160     while (data.OK()) {
161         cx = data.GetChar();      
162         if (cx >= ' ') {
163             s = data.GetString(ls);
164             mathed_string_height(data.FCode(), size, s, ls, asc, des);
165             if (asc > ascent) ascent = asc;
166             if (des > descent) descent = des;
167             limits = false;
168             mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
169         } else
170           if (MathIsInset(cx)) {
171               MathedInset *p = data.GetInset();
172               p->SetStyle(size);   
173               p->Metrics();
174               if (cx == LM_TC_UP) {
175                   asc += (limits) ? p->Height()+4: p->Ascent() + 
176                     ((p->Descent()>asc) ? p->Descent()-asc+4: 0);
177               } else
178                 if (cx == LM_TC_DOWN) {
179                     des += ((limits) ? p->Height()+4: p->Height()-p->Ascent()/2);
180                 } else {
181                     asc = p->Ascent();
182                     des = p->Descent();
183                 }
184               if (asc > ascent) ascent = asc;
185               if (des > descent) descent = des;
186               if (cx!= LM_TC_UP && cx!= LM_TC_DOWN)
187                 limits = p->GetLimits();
188               data.Next();
189           } else 
190           if (cx == LM_TC_TAB) {
191               int x, y;
192               data.GetIncPos(x, y);
193               if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
194                   if (ascent<df_asc) ascent = df_asc;
195                   tb = x;
196               }
197               data.setTab(x-tb, tab);
198               tb = x;
199               ++tab;
200               limits = false;                   
201               data.Next();
202           } else
203           if (cx == LM_TC_CR) {
204               if (tb>0) {
205                   int x, y;
206                   data.GetIncPos(x, y);
207                   if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
208                       if (ascent<df_asc) ascent = df_asc;
209                       tb = x;
210                   } 
211                   data.setTab(x-tb, tab);
212               } else //if (GetColumns() == 1) 
213                     {
214                   int x, y;
215                   data.GetIncPos(x, y);
216                   data.setTab(x, tab);
217                   if (ascent<df_asc) ascent = df_asc;
218               } 
219               tb= tab= 0;
220               data.subMetrics(ascent, descent);
221               ascent = df_asc;   
222               descent = 0;
223               data.Next();
224           }      
225         else {
226                 lyxerr << "Mathed Error: Unrecognized code[" << cx
227                        << "]" << endl;
228             break;
229         }       
230         cxp = cx;
231     }
232     data.GetIncPos(width, ls);
233     
234     // No matter how simple is a matrix, it is NOT a subparagraph
235     if (isMatrix()) {
236         if (cxp == LM_TC_TAB) {
237             if (ascent<df_asc) ascent = df_asc;
238             data.setTab(0, tab);
239         } else {
240           data.setTab(width-tb, tab);
241         }
242     }
243           
244     data.subMetrics(ascent, descent);
245 }
246
247
248 void
249 MathSqrtInset::draw(Painter & pain, int x, int y)
250
251    MathParInset::draw(pain, x + hmax + 2, y); 
252    int h = ascent;
253    int d = descent;
254    int h2 = Height() / 2;
255    int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2; 
256    int xp[4], yp[4];
257    xp[0] = x + hmax + wbody; yp[0] = y - h;
258    xp[1] = x + hmax;         yp[1] = y - h;
259    xp[2] = x + w2;           yp[2] = y + d;
260    xp[3] = x;                yp[3] = y + d - h2;
261    pain.lines(xp, yp, 4, LColor::mathline);
262 }
263
264
265 void
266 MathSqrtInset::Metrics()
267 {
268    MathParInset::Metrics();
269    ascent += 4;
270    descent += 2;
271    int a, b;
272    hmax = mathed_char_height(LM_TC_VAR, size, 'I', a, b);
273    if (hmax < 10) hmax = 10;
274    wbody = width + 4;
275    width += hmax + 4;
276 }
277
278
279 void
280 MathFracInset::draw(Painter & pain, int x, int y)
281
282     short idxp = idx;
283     short sizex = size;
284     
285     idx = 0;
286     if (size == LM_ST_DISPLAY) ++size;
287     MathParInset::draw(pain, x + (width - w0) / 2, y - des0);
288     den->draw(pain, x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
289     size = sizex;
290     if (objtype == LM_OT_FRAC)
291             pain.line(x + 2, y - dh, x + width - 4, y - dh, LColor::mathline);
292     idx = idxp;
293 }
294
295
296 void
297 MathFracInset::Metrics()
298 {
299     if (!dh) {
300         int a, b;
301         dh = mathed_char_height(LM_TC_CONST, size, 'I', a, b)/2;
302     }
303     short idxp = idx;
304     short sizex = size; 
305     idx = 0;
306     if (size == LM_ST_DISPLAY) ++size; 
307     MathParInset::Metrics();
308     size = sizex;
309     w0 = width;
310     int as = Height() + 2 + dh;
311     des0 = Descent() + 2 + dh;
312     den->Metrics();  
313     w1 = den->Width();   
314     width = ((w0 > w1) ? w0: w1) + 12;
315     ascent = as; 
316     descent = den->Height()+ 2 - dh;
317     idx = idxp;
318 }
319
320
321 void
322 MathBigopInset::draw(Painter & pain, int x, int y)
323 {
324    int ls;
325    char c;
326    char const *s;
327    short t;
328    
329    if (sym < 256 || sym == LM_oint) {
330       ls = 1;
331       c = (sym == LM_oint) ? LM_int : sym;
332       s = &c;
333       t = LM_TC_BSYM;
334    } else {
335       s = name;
336       ls = strlen(name);
337       t = LM_TC_TEXTRM;
338    }
339    if (sym == LM_oint) {
340            pain.arc(x, y - 5 * width / 4, width, width, 0, 360*64,
341                     LColor::mathline);
342            ++x;
343    }
344    pain.text(x, y, s, ls, mathed_get_font(t, size));
345 }
346
347
348 void
349 MathBigopInset::Metrics()
350 {   
351         int ls;
352         char c;
353         char const *s;
354         short t;
355         
356         if (sym < 256 || sym == LM_oint) {
357                 ls = 1;
358                 c = (sym == LM_oint) ? LM_int: sym;
359                 s = &c;
360                 t = LM_TC_BSYM;
361         } else {
362                 s = name;
363                 ls = strlen(name);
364                 t = LM_TC_TEXTRM;
365         }
366         mathed_string_height(t, size,
367                              reinterpret_cast<const unsigned char*>(s),
368                              ls, ascent, descent);
369         width = mathed_string_width(t, size,
370                                     reinterpret_cast<const unsigned char*>(s),
371                                     ls);
372         if (sym == LM_oint) width += 2;
373 }