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