This commit was manufactured by cvs2svn to create tag
[lyx.git] / src / mathed / math_draw.C
blobe826d0f54e8d8fd802292c169e468236290d633d
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  */
18 #include <config.h>
19 #include FORMS_H_LOCATION
20 #include "math_cursor.h"
21 #include "math_parser.h"
22 #include "debug.h"
24 extern void mathed_set_font(short type, int style);
25 extern int mathed_char_width(short type, int style, byte c);
26 extern int mathed_string_width(short type, int style, byte const* s, int ls);
27 extern int mathed_string_height(short, int, byte const*, int, int&, int&);
28 extern int mathed_char_height(short, int, byte, int&, int&);
29    
30 GC canvasGC=0, mathGC=0, mathLineGC=0, latexGC=0, cursorGC=0, mathFrameGC=0;
33 long unsigned int MathedInset::pm;
35 void
36 MathSpaceInset::Draw(int x, int y)
37
39 // XPoint p[4] = {{++x, y-3}, {x, y}, {x+width-2, y}, {x+width-2, y-3}};
41 // Sadly, HP-UX CC can't handle that kind of initialization.
43    XPoint p[4];
44    p[0].x = ++x;        p[0].y = y-3;
45    p[1].x = x;          p[1].y = y;
46    p[2].x = x+width-2;  p[2].y = y;
47    p[3].x = x+width-2;  p[3].y = y-3;
49    XDrawLines(fl_display,pm,(space) ? latexGC: mathGC,p,4,CoordModeOrigin);
50    XFlush(fl_display);
53 void 
54 MathParInset::Draw(int x, int y)
56    byte cx, cxp=0;
57    int xp=0, ls;
58    int asc=df_asc, des=0;
59    bool limits = false;
60     
61    xo = x;  yo = y; 
62    if (!array || array->Empty()) {
63       mathed_set_font(LM_TC_VAR, 1);
64        if (array) {
65            MathedXIter data(this);
66            data.GetPos(x, y);
67        }
68       XDrawRectangle(fl_display,pm,mathLineGC,x,y-df_asc, df_width, df_asc);
69       XFlush(fl_display);
70       return;
71    }  
72    MathedXIter data(this);
73    data.GoBegin();
74    while (data.OK()) {
75       data.GetPos(x, y);
76       cx = data.GetChar();
77       if (cx >= ' ') {
78          byte *s = data.GetString(ls);
79           drawStr(data.FCode(), size, x, y, s, ls);
80           mathed_char_height(data.FCode(), size, s[ls-1], asc, des);
81           limits = false;
82       } else {
83           if (cx==0) break;
84          if (MathIsInset(cx)) {
85             int yy = y;
86             MathedInset *p = data.GetInset();
87             if (cx==LM_TC_UP) {
88                if (limits) {
89                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;  
90                   yy -= (asc + p->Descent()+4);
91                } else
92                   yy -= (p->Descent()>asc) ? p->Descent()+4: asc;
93             } else
94             if (cx==LM_TC_DOWN) {
95                if (limits) {
96                   x -= (xp>p->Width()) ? p->Width()+(xp-p->Width())/2: xp;
97                   yy += des + p->Ascent() + 2;
98                } else
99                  yy += des + p->Ascent()/2;
100             } else {
101                asc = p->Ascent();
102                des = p->Descent();
103             }
104             p->Draw(x, yy);
105             if (cx!=LM_TC_UP && cx!=LM_TC_DOWN) {
106                limits = p->GetLimits();
107                if (limits) xp = p->Width();
108             }
109             data.Next();
110          } else 
111            if (cx==LM_TC_TAB) {
112                if ((cxp==cx || cxp==LM_TC_CR || data.IsFirst())) { // && objtype==L
113                    XDrawRectangle(fl_display,pm,mathLineGC,
114                                   x,y-df_asc, df_width, df_asc);
115                }
116            
117               XFlush(fl_display);
118               data.Next();
119               limits = false;
120            } else
121             if (cx==LM_TC_CR) {
122                 if (cxp==LM_TC_TAB || cxp==LM_TC_CR || data.IsFirst()) { //  && objtype==LM_OT_MATRIX) {
123                   XDrawRectangle(fl_display,pm,mathLineGC,x,y-df_asc, df_width, df_asc);
124                 }
125                 data.Next();
126                 limits = false;
127             }
128          else {  
129                  lyxerr << "GMathed Error: Unrecognized code[" << cx
130                         << "]" << endl;
131             break;
132          }
133       }
134       cxp = cx;
135    }
136    if (cxp==LM_TC_TAB || cxp==LM_TC_CR) { // && objtype==LM_OT_MATRIX) {
137       data.GetPos(x, y);
138       XDrawRectangle(fl_display,pm,mathLineGC,x,y-df_asc, df_width, df_asc);
139       XFlush(fl_display);
140    }
144 void 
145 MathParInset::Metrics()
147     byte cx, cxp=0, *s;
148     int ls;
149     int asc=df_asc, des=0;
150     int tb = 0, tab=0;
152     bool limits = false;
153     
154     ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des); 
155     width = df_width;
156     descent = 0;
157     if (!array) return;
158     if (array->Empty()) return;
159     
160     ascent = 0;
161     MathedXIter data(this);
162     data.GoBegin();
163     while (data.OK()) {
164         cx = data.GetChar();      
165         if (cx >= ' ') {
166             s = data.GetString(ls);
167             mathed_string_height(data.FCode(), size, s, ls, asc, des);
168             if (asc > ascent) ascent = asc;
169             if (des > descent) descent = des;
170             limits = false;
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           }      
227         else {
228                 lyxerr << "Mathed Error: Unrecognized code[" << cx
229                        << "]" << endl;
230             break;
231         }       
232         cxp = cx;
233     }
234     data.GetIncPos(width, ls);
235     
236     // No matter how simple is a matrix, it is NOT a subparagraph
237     if (isMatrix()) {
238         if (cxp==LM_TC_TAB) {
239             if (ascent<df_asc) ascent = df_asc;
240             data.setTab(0, tab);
241         } else {
242           data.setTab(width-tb, tab);
243         }
244     }
245           
246     data.subMetrics(ascent, descent);
250 void
251 MathSqrtInset::Draw(int x, int y)
253    MathParInset::Draw(x+hmax+2, y); 
254    int h=ascent, d=descent, h2=Height()/2, w2 = (Height()>4*hmax)?hmax:hmax/2; 
255    XPoint p[4];
256    p[0].x = x + hmax + wbody, p[0].y = y-h;
257    p[1].x = x+hmax,    p[1].y = y-h;
258    p[2].x = x+w2,      p[2].y = y+d;
259    p[3].x = x,         p[3].y = y+d-h2;
260    XDrawLines(fl_display, pm, mathLineGC,p, 4, CoordModeOrigin);
261    XFlush(fl_display);
264 void
265 MathSqrtInset::Metrics()
267    MathParInset::Metrics();
268    ascent += 4;
269    descent += 2;
270    int a, b;
271    hmax = mathed_char_height(LM_TC_VAR, size, 'I',a, b);
272    if (hmax<10) hmax = 10;
273    wbody = width + 4;
274    width += hmax + 4;
277 void
278 MathFracInset::Draw(int x, int y)
280     short idxp = idx;
281     short sizex = size;
282     
283     idx = 0;
284     if (size==LM_ST_DISPLAY) size++;
285     MathParInset::Draw(x+(width-w0)/2, y - des0);
286     den->Draw(x+(width-w1)/2, y + den->Ascent() + 2 - dh);
287     size = sizex;
288     if (objtype==LM_OT_FRAC)
289       XDrawLine(fl_display, pm, mathLineGC, x+2, y-dh, x+width-4, y - dh);
290     XFlush(fl_display);
291     idx = idxp;
294 void
295 MathFracInset::Metrics()
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;
319 void
320 MathBigopInset::Draw(int x, int y)
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    mathed_set_font(t, size);
338    if (sym==LM_oint) {
339       XDrawArc(fl_display, pm, mathLineGC, x,y-5*width/4,width,width,0,23040);
340       XFlush(fl_display);
341       x++;
342    }
343    XDrawString(fl_display, pm, mathGC, x, y, s, ls);
344    XFlush(fl_display);
347 void
348 MathBigopInset::Metrics()
349 {   
350    int ls;
351    char c;
352    char const *s;
353    short t;
355    if (sym<256 || sym==LM_oint) {
356       ls = 1;
357       c = (sym==LM_oint) ? LM_int: sym;
358       s = &c;
359       t = LM_TC_BSYM;
360    } else {
361       s = name;
362       ls = strlen(name);
363       t = LM_TC_TEXTRM;
364    }
365    mathed_set_font(t, size);
366    mathed_string_height(t, size, reinterpret_cast<const unsigned char*>(s), ls, ascent, descent);
367    width = mathed_string_width(t, size, reinterpret_cast<const unsigned char*>(s), ls);
368    if (sym==LM_oint) width += 2;