]> git.lyx.org Git - lyx.git/blob - src/mathed/math_draw.C
some small updates to Painter, and make the new painter the default.
[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 #ifdef USE_PAINTER
27 extern LyXFont mathed_get_font(short type, int size);
28 #else
29 extern void mathed_set_font(short type, int style);
30 #endif
31 extern int mathed_char_width(short type, int style, byte c);
32 extern int mathed_string_width(short type, int style, byte const* s, int ls);
33 extern int mathed_string_height(short, int, byte const*, int, int&, int&);
34 extern int mathed_char_height(short, int, byte, int&, int&);
35
36 #ifndef USE_PAINTER
37 GC canvasGC= 0, mathGC= 0, mathLineGC= 0, latexGC= 0, cursorGC= 0, mathFrameGC= 0;
38 #endif
39
40
41 #ifndef USE_PAINTER
42 unsigned long MathedInset::pm;
43 #endif
44
45 #ifdef USE_PAINTER
46 void
47 MathSpaceInset::draw(Painter & pain, int x, int y)
48
49
50 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
51
52 // Sadly, HP-UX CC can't handle that kind of initialization.
53
54    int xp[4];
55    int yp[4];
56    
57    xp[0] = ++x;            yp[0] = y - 3;
58    xp[1] = x;              yp[1] = y;
59    xp[2] = x + width - 2;  yp[2] = y;
60    xp[3] = x + width - 2;  yp[3] = y - 3;
61
62    pain.lines(xp, yp, 4, (space) ? LColor::latex : LColor::math);
63 }
64 #else
65 void
66 MathSpaceInset::Draw(int x, int y)
67
68
69 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
70
71 // Sadly, HP-UX CC can't handle that kind of initialization.
72
73    XPoint p[4];
74    p[0].x = ++x;        p[0].y = y-3;
75    p[1].x = x;          p[1].y = y;
76    p[2].x = x+width-2;  p[2].y = y;
77    p[3].x = x+width-2;  p[3].y = y-3;
78
79    XDrawLines(fl_display, pm,(space) ? latexGC: mathGC, p, 4, CoordModeOrigin);
80    XFlush(fl_display);
81 }
82 #endif
83
84
85 #ifdef USE_PAINTER
86 void 
87 MathParInset::draw(Painter & pain, int x, int y)
88 {
89    byte cx, cxp = 0;
90    int xp = 0, ls;
91    int asc = df_asc, des = 0;
92    bool limits = false;
93     
94    xo = x;  yo = y; 
95    if (!array || array->empty()) {
96        if (array) {
97            MathedXIter data(this);
98            data.GetPos(x, y);
99        }
100        pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
101       return;
102    }  
103    MathedXIter data(this);
104    data.GoBegin();
105    while (data.OK()) {
106       data.GetPos(x, y);
107       cx = data.GetChar();
108       if (cx >= ' ') {
109          byte * s = data.GetString(ls);
110           drawStr(pain, data.FCode(), size, x, y, s, ls);
111           mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
112           limits = false;
113       } else {
114           if (cx == 0) break;
115          if (MathIsInset(cx)) {
116             int yy = y;
117             MathedInset * p = data.GetInset();
118             if (cx == LM_TC_UP) {
119                if (limits) {
120                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;  
121                   yy -= (asc + p->Descent()+4);
122                } else
123                   yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
124             } else
125             if (cx == LM_TC_DOWN) {
126                if (limits) {
127                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
128                   yy += des + p->Ascent() + 2;
129                } else
130                  yy += des + p->Ascent()/2;
131             } else {
132                asc = p->Ascent();
133                des = p->Descent();
134             }
135             p->draw(pain, x, yy);
136             if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
137                limits = p->GetLimits();
138                if (limits) xp = p->Width();
139             }
140             data.Next();
141          } else 
142            if (cx == LM_TC_TAB) {
143                if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
144                        pain.rectangle(x, y - df_asc, df_width, df_asc,
145                                       LColor::mathline);
146                }
147               data.Next();
148               limits = false;
149            } else
150             if (cx == LM_TC_CR) {
151                 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { //  && objtype == LM_OT_MATRIX) {
152                         pain.rectangle(x, y - df_asc, df_width, df_asc,
153                                        LColor::mathline);
154                 }
155                 data.Next();
156                 limits = false;
157             }
158          else {  
159                  lyxerr << "GMathed Error: Unrecognized code[" << cx
160                         << "]" << endl;
161             break;
162          }
163       }
164       cxp = cx;
165    }
166    if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
167       data.GetPos(x, y);
168       pain.rectangle(x, y - df_asc, df_width, df_asc, LColor::mathline);
169    }
170 }
171 #else
172 void 
173 MathParInset::Draw(int x, int y)
174 {
175    byte cx, cxp= 0;
176    int xp= 0, ls;
177    int asc= df_asc, des= 0;
178    bool limits = false;
179     
180    xo = x;  yo = y; 
181    if (!array || array->empty()) {
182       mathed_set_font(LM_TC_VAR, 1);
183        if (array) {
184            MathedXIter data(this);
185            data.GetPos(x, y);
186        }
187       XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
188       XFlush(fl_display);
189       return;
190    }  
191    MathedXIter data(this);
192    data.GoBegin();
193    while (data.OK()) {
194       data.GetPos(x, y);
195       cx = data.GetChar();
196       if (cx >= ' ') {
197          byte *s = data.GetString(ls);
198           drawStr(data.FCode(), size, x, y, s, ls);
199           mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
200           limits = false;
201       } else {
202           if (cx == 0) break;
203          if (MathIsInset(cx)) {
204             int yy = y;
205             MathedInset *p = data.GetInset();
206             if (cx == LM_TC_UP) {
207                if (limits) {
208                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;  
209                   yy -= (asc + p->Descent()+4);
210                } else
211                   yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
212             } else
213             if (cx == LM_TC_DOWN) {
214                if (limits) {
215                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
216                   yy += des + p->Ascent() + 2;
217                } else
218                  yy += des + p->Ascent()/2;
219             } else {
220                asc = p->Ascent();
221                des = p->Descent();
222             }
223             p->Draw(x, yy);
224             if (cx!= LM_TC_UP && cx!= LM_TC_DOWN) {
225                limits = p->GetLimits();
226                if (limits) xp = p->Width();
227             }
228             data.Next();
229          } else 
230            if (cx == LM_TC_TAB) {
231                if ((cxp == cx || cxp == LM_TC_CR || data.IsFirst())) { // && objtype == L
232                    XDrawRectangle(fl_display, pm, mathLineGC,
233                                   x, y-df_asc, df_width, df_asc);
234                }
235            
236               XFlush(fl_display);
237               data.Next();
238               limits = false;
239            } else
240             if (cx == LM_TC_CR) {
241                 if (cxp == LM_TC_TAB || cxp == LM_TC_CR || data.IsFirst()) { //  && objtype == LM_OT_MATRIX) {
242                   XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
243                 }
244                 data.Next();
245                 limits = false;
246             }
247          else {  
248                  lyxerr << "GMathed Error: Unrecognized code[" << cx
249                         << "]" << endl;
250             break;
251          }
252       }
253       cxp = cx;
254    }
255    if (cxp == LM_TC_TAB || cxp == LM_TC_CR) { // && objtype == LM_OT_MATRIX) {
256       data.GetPos(x, y);
257       XDrawRectangle(fl_display, pm, mathLineGC, x, y-df_asc, df_width, df_asc);
258       XFlush(fl_display);
259    }
260 }
261 #endif
262
263
264 void 
265 MathParInset::Metrics()
266 {
267     byte cx, cxp= 0, *s;
268     int ls;
269     int asc= df_asc, des= 0;
270     int tb = 0, tab= 0;
271
272     bool limits = false;
273     
274     ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des); 
275     width = df_width;
276     descent = 0;
277     if (!array) return;
278     if (array->empty()) return;
279     
280     ascent = 0;
281     MathedXIter data(this);
282     data.GoBegin();
283     while (data.OK()) {
284         cx = data.GetChar();      
285         if (cx >= ' ') {
286             s = data.GetString(ls);
287             mathed_string_height(data.FCode(), size, s, ls, asc, des);
288             if (asc > ascent) ascent = asc;
289             if (des > descent) descent = des;
290             limits = false;
291             mathed_char_height(LM_TC_CONST, size, 'y', asc, des);
292         } else
293           if (MathIsInset(cx)) {
294               MathedInset *p = data.GetInset();
295               p->SetStyle(size);   
296               p->Metrics();
297               if (cx == LM_TC_UP) {
298                   asc += (limits) ? p->Height()+4: p->Ascent() + 
299                     ((p->Descent()>asc) ? p->Descent()-asc+4: 0);
300               } else
301                 if (cx == LM_TC_DOWN) {
302                     des += ((limits) ? p->Height()+4: p->Height()-p->Ascent()/2);
303                 } else {
304                     asc = p->Ascent();
305                     des = p->Descent();
306                 }
307               if (asc > ascent) ascent = asc;
308               if (des > descent) descent = des;
309               if (cx!= LM_TC_UP && cx!= LM_TC_DOWN)
310                 limits = p->GetLimits();
311               data.Next();
312           } else 
313           if (cx == LM_TC_TAB) {
314               int x, y;
315               data.GetIncPos(x, y);
316               if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
317                   if (ascent<df_asc) ascent = df_asc;
318                   tb = x;
319               }
320               data.setTab(x-tb, tab);
321               tb = x;
322               ++tab;
323               limits = false;                   
324               data.Next();
325           } else
326           if (cx == LM_TC_CR) {
327               if (tb>0) {
328                   int x, y;
329                   data.GetIncPos(x, y);
330                   if (data.IsFirst() || cxp == LM_TC_TAB || cxp == LM_TC_CR) {
331                       if (ascent<df_asc) ascent = df_asc;
332                       tb = x;
333                   } 
334                   data.setTab(x-tb, tab);
335               } else //if (GetColumns() == 1) 
336                     {
337                   int x, y;
338                   data.GetIncPos(x, y);
339                   data.setTab(x, tab);
340                   if (ascent<df_asc) ascent = df_asc;
341               } 
342               tb= tab= 0;
343               data.subMetrics(ascent, descent);
344               ascent = df_asc;   
345               descent = 0;
346               data.Next();
347           }      
348         else {
349                 lyxerr << "Mathed Error: Unrecognized code[" << cx
350                        << "]" << endl;
351             break;
352         }       
353         cxp = cx;
354     }
355     data.GetIncPos(width, ls);
356     
357     // No matter how simple is a matrix, it is NOT a subparagraph
358     if (isMatrix()) {
359         if (cxp == LM_TC_TAB) {
360             if (ascent<df_asc) ascent = df_asc;
361             data.setTab(0, tab);
362         } else {
363           data.setTab(width-tb, tab);
364         }
365     }
366           
367     data.subMetrics(ascent, descent);
368 }
369
370
371 #ifdef USE_PAINTER
372 void
373 MathSqrtInset::draw(Painter & pain, int x, int y)
374
375    MathParInset::draw(pain, x + hmax + 2, y); 
376    int h = ascent;
377    int d = descent;
378    int h2 = Height() / 2;
379    int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2; 
380    int xp[4], yp[4];
381    xp[0] = x + hmax + wbody; yp[0] = y - h;
382    xp[1] = x + hmax;         yp[1] = y - h;
383    xp[2] = x + w2;           yp[2] = y + d;
384    xp[3] = x;                yp[3] = y + d - h2;
385    pain.lines(xp, yp, 4, LColor::mathline);
386 }
387 #else
388 void
389 MathSqrtInset::Draw(int x, int y)
390
391    MathParInset::Draw(x+hmax+2, y); 
392    int h = ascent;
393    int d = descent;
394    int h2 = Height() / 2;
395    int w2 = (Height() > 4 * hmax) ? hmax : hmax / 2; 
396    XPoint p[4];
397    p[0].x = x + hmax + wbody; p[0].y = y - h;
398    p[1].x = x + hmax;    p[1].y = y - h;
399    p[2].x = x + w2;      p[2].y = y + d;
400    p[3].x = x;         p[3].y = y + d - h2;
401    XDrawLines(fl_display, pm, mathLineGC, p, 4, CoordModeOrigin);
402    XFlush(fl_display);
403 }
404 #endif
405
406
407 void
408 MathSqrtInset::Metrics()
409 {
410    MathParInset::Metrics();
411    ascent += 4;
412    descent += 2;
413    int a, b;
414    hmax = mathed_char_height(LM_TC_VAR, size, 'I', a, b);
415    if (hmax < 10) hmax = 10;
416    wbody = width + 4;
417    width += hmax + 4;
418 }
419
420
421 #ifdef USE_PAINTER
422 void
423 MathFracInset::draw(Painter & pain, int x, int y)
424
425     short idxp = idx;
426     short sizex = size;
427     
428     idx = 0;
429     if (size == LM_ST_DISPLAY) ++size;
430     MathParInset::draw(pain, x + (width - w0) / 2, y - des0);
431     den->draw(pain, x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
432     size = sizex;
433     if (objtype == LM_OT_FRAC)
434             pain.line(x + 2, y - dh, x + width - 4, y - dh, LColor::mathline);
435     idx = idxp;
436 }
437 #else
438 void
439 MathFracInset::Draw(int x, int y)
440
441     short idxp = idx;
442     short sizex = size;
443     
444     idx = 0;
445     if (size == LM_ST_DISPLAY) ++size;
446     MathParInset::Draw(x + (width - w0) / 2, y - des0);
447     den->Draw(x + (width - w1) / 2, y + den->Ascent() + 2 - dh);
448     size = sizex;
449     if (objtype == LM_OT_FRAC)
450       XDrawLine(fl_display, pm, mathLineGC,
451                 x + 2, y - dh, x + width - 4, y - dh);
452     XFlush(fl_display);
453     idx = idxp;
454 }
455 #endif
456
457
458 void
459 MathFracInset::Metrics()
460 {
461     if (!dh) {
462         int a, b;
463         dh = mathed_char_height(LM_TC_CONST, size, 'I', a, b)/2;
464     }
465     short idxp = idx;
466     short sizex = size; 
467     idx = 0;
468     if (size == LM_ST_DISPLAY) ++size; 
469     MathParInset::Metrics();
470     size = sizex;
471     w0 = width;
472     int as = Height() + 2 + dh;
473     des0 = Descent() + 2 + dh;
474     den->Metrics();  
475     w1 = den->Width();   
476     width = ((w0 > w1) ? w0: w1) + 12;
477     ascent = as; 
478     descent = den->Height()+ 2 - dh;
479     idx = idxp;
480 }
481
482
483 #ifdef USE_PAINTER
484 void
485 MathBigopInset::draw(Painter & pain, int x, int y)
486 {
487    int ls;
488    char c;
489    char const *s;
490    short t;
491    
492    if (sym < 256 || sym == LM_oint) {
493       ls = 1;
494       c = (sym == LM_oint) ? LM_int : sym;
495       s = &c;
496       t = LM_TC_BSYM;
497    } else {
498       s = name;
499       ls = strlen(name);
500       t = LM_TC_TEXTRM;
501    }
502    if (sym == LM_oint) {
503            pain.arc(x, y - 5 * width / 4, width, width, 0, 360*64,
504                     LColor::mathline);
505            ++x;
506    }
507    pain.text(x, y, s, ls, mathed_get_font(t, size));
508 }
509 #else
510 void
511 MathBigopInset::Draw(int x, int y)
512 {
513    int ls;
514    char c;
515    char const *s;
516    short t;
517    
518    if (sym<256 || sym == LM_oint) {
519       ls = 1;
520       c = (sym == LM_oint) ? LM_int: sym;
521       s = &c;
522       t = LM_TC_BSYM;
523    } else {
524       s = name;
525       ls = strlen(name);
526       t = LM_TC_TEXTRM;
527    }
528    mathed_set_font(t, size);
529    if (sym == LM_oint) {
530       XDrawArc(fl_display, pm, mathLineGC, x, y-5*width/4, width, width, 0, 23040);
531       XFlush(fl_display);
532       ++x;
533    }
534    XDrawString(fl_display, pm, mathGC, x, y, s, ls);
535    XFlush(fl_display);
536 }
537 #endif
538
539
540 #ifdef USE_PAINTER
541 void
542 MathBigopInset::Metrics()
543 {   
544         int ls;
545         char c;
546         char const *s;
547         short t;
548         
549         if (sym < 256 || sym == LM_oint) {
550                 ls = 1;
551                 c = (sym == LM_oint) ? LM_int: sym;
552                 s = &c;
553                 t = LM_TC_BSYM;
554         } else {
555                 s = name;
556                 ls = strlen(name);
557                 t = LM_TC_TEXTRM;
558         }
559         mathed_string_height(t, size,
560                              reinterpret_cast<const unsigned char*>(s),
561                              ls, ascent, descent);
562         width = mathed_string_width(t, size,
563                                     reinterpret_cast<const unsigned char*>(s),
564                                     ls);
565         if (sym == LM_oint) width += 2;
566 }
567 #else
568 void
569 MathBigopInset::Metrics()
570 {   
571    int ls;
572    char c;
573    char const *s;
574    short t;
575
576    if (sym<256 || sym == LM_oint) {
577       ls = 1;
578       c = (sym == LM_oint) ? LM_int: sym;
579       s = &c;
580       t = LM_TC_BSYM;
581    } else {
582       s = name;
583       ls = strlen(name);
584       t = LM_TC_TEXTRM;
585    }
586    mathed_set_font(t, size);
587    mathed_string_height(t, size, reinterpret_cast<const unsigned char*>(s), ls, ascent, descent);
588    width = mathed_string_width(t, size, reinterpret_cast<const unsigned char*>(s), ls);
589    if (sym == LM_oint) width += 2;
590 }
591 #endif
592