]> git.lyx.org Git - features.git/blob - src/mathed/math_draw.C
Initial revision
[features.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
23 extern void mathed_set_font(short type, int style);
24 extern int mathed_char_width(short type, int style, byte c);
25 extern int mathed_string_width(short type, int style, byte const* s, int ls);
26 extern int mathed_string_height(short, int, byte const*, int, int&, int&);
27 extern int mathed_char_height(short, int, byte, int&, int&);
28    
29 GC canvasGC=0, mathGC=0, mathLineGC=0, latexGC=0, cursorGC=0, mathFrameGC=0;
30
31
32 long unsigned int MathedInset::pm;
33
34 void
35 MathSpaceInset::Draw(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    XPoint p[4];
43    p[0].x = ++x;        p[0].y = y-3;
44    p[1].x = x;          p[1].y = y;
45    p[2].x = x+width-2;  p[2].y = y;
46    p[3].x = x+width-2;  p[3].y = y-3;
47
48    XDrawLines(fl_display,pm,(space) ? latexGC: mathGC,p,4,CoordModeOrigin);
49    XFlush(fl_display);
50 }
51
52 void 
53 MathParInset::Draw(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       mathed_set_font(LM_TC_VAR, 1);
63        if (array) {
64            MathedXIter data(this);
65            data.GetPos(x, y);
66        }
67       XDrawRectangle(fl_display,pm,mathLineGC,x,y-df_asc, df_width, df_asc);
68       XFlush(fl_display);
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(data.FCode(), size, x, y, s, ls);
79           mathed_char_height(data.FCode(), size, s[ls-1], 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(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                    XDrawRectangle(fl_display,pm,mathLineGC,
113                                   x,y-df_asc, df_width, df_asc);
114                }
115            
116               XFlush(fl_display);
117               data.Next();
118               limits = false;
119            } else
120             if (cx==LM_TC_CR) {
121                 if (cxp==LM_TC_TAB || cxp==LM_TC_CR || data.IsFirst()) { //  && objtype==LM_OT_MATRIX) {
122                   XDrawRectangle(fl_display,pm,mathLineGC,x,y-df_asc, df_width, df_asc);
123                 }
124                 data.Next();
125                 limits = false;
126             }
127          else {  
128             fprintf(stderr, "GMathed Error: Unrecognized code[%d]\n", cx);
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       XDrawRectangle(fl_display,pm,mathLineGC,x,y-df_asc, df_width, df_asc);
137       XFlush(fl_display);
138    }
139 }
140
141
142 void 
143 MathParInset::Metrics()
144 {
145     byte cx, cxp=0, *s;
146     int ls;
147     int asc=df_asc, des=0;
148     int tb = 0, tab=0;
149
150     bool limits = false;
151     
152     ascent = df_asc;//mathed_char_height(LM_TC_VAR, size, 'I', asc, des); 
153     width = df_width;
154     descent = 0;
155     if (!array) return;
156     if (array->Empty()) return;
157     
158     ascent = 0;
159     MathedXIter data(this);
160     data.GoBegin();
161     while (data.OK()) {
162         cx = data.GetChar();      
163         if (cx >= ' ') {
164             s = data.GetString(ls);
165             mathed_string_height(data.FCode(), size, s, ls, asc, des);
166             if (asc > ascent) ascent = asc;
167             if (des > descent) descent = des;
168             limits = false;
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             fprintf(stderr, "Mathed Error: Unrecognized code[%d]\n", cx);
227             break;
228         }       
229         cxp = cx;
230     }
231     data.GetIncPos(width, ls);
232     
233     // No matter how simple is a matrix, it is NOT a subparagraph
234     if (isMatrix()) {
235         if (cxp==LM_TC_TAB) {
236             if (ascent<df_asc) ascent = df_asc;
237             data.setTab(0, tab);
238         } else {
239           data.setTab(width-tb, tab);
240         }
241     }
242           
243     data.subMetrics(ascent, descent);
244 }
245
246
247 void
248 MathSqrtInset::Draw(int x, int y)
249
250    MathParInset::Draw(x+hmax+2, y); 
251    int h=ascent, d=descent, h2=Height()/2, w2 = (Height()>4*hmax)?hmax:hmax/2; 
252    XPoint p[4];
253    p[0].x = x + hmax + wbody, p[0].y = y-h;
254    p[1].x = x+hmax,    p[1].y = y-h;
255    p[2].x = x+w2,      p[2].y = y+d;
256    p[3].x = x,         p[3].y = y+d-h2;
257    XDrawLines(fl_display, pm, mathLineGC,p, 4, CoordModeOrigin);
258    XFlush(fl_display);
259 }
260
261 void
262 MathSqrtInset::Metrics()
263 {
264    MathParInset::Metrics();
265    ascent += 4;
266    descent += 2;
267    int a, b;
268    hmax = mathed_char_height(LM_TC_VAR, size, 'I',a, b);
269    if (hmax<10) hmax = 10;
270    wbody = width + 4;
271    width += hmax + 4;
272 }
273
274 void
275 MathFracInset::Draw(int x, int y)
276
277     short idxp = idx;
278     short sizex = size;
279     
280     idx = 0;
281     if (size==LM_ST_DISPLAY) size++;
282     MathParInset::Draw(x+(width-w0)/2, y - des0);
283     den->Draw(x+(width-w1)/2, y + den->Ascent() + 2 - dh);
284     size = sizex;
285     if (objtype==LM_OT_FRAC)
286       XDrawLine(fl_display, pm, mathLineGC, x+2, y-dh, x+width-4, y - dh);
287     XFlush(fl_display);
288     idx = idxp;
289 }
290
291 void
292 MathFracInset::Metrics()
293 {
294     if (!dh) {
295         int a, b;
296         dh = mathed_char_height(LM_TC_CONST, size, 'I', a, b)/2;
297     }
298     short idxp = idx;
299     short sizex = size; 
300     idx = 0;
301     if (size==LM_ST_DISPLAY) size++; 
302     MathParInset::Metrics();
303     size = sizex;
304     w0 = width;
305     int as = Height() + 2 + dh;
306     des0 = Descent() + 2 + dh;
307     den->Metrics();  
308     w1 = den->Width();   
309     width = ((w0 > w1) ? w0: w1) + 12;
310     ascent = as; 
311     descent = den->Height()+ 2 - dh;
312     idx = idxp;
313 }
314
315
316 void
317 MathBigopInset::Draw(int x, int y)
318 {
319    int ls;
320    char c;
321    char const *s;
322    short t;
323    
324    if (sym<256 || sym==LM_oint) {
325       ls = 1;
326       c = (sym==LM_oint) ? LM_int: sym;
327       s = &c;
328       t = LM_TC_BSYM;
329    } else {
330       s = name;
331       ls = strlen(name);
332       t = LM_TC_TEXTRM;
333    }
334    mathed_set_font(t, size);
335    if (sym==LM_oint) {
336       XDrawArc(fl_display, pm, mathLineGC, x,y-5*width/4,width,width,0,23040);
337       XFlush(fl_display);
338       x++;
339    }
340    XDrawString(fl_display, pm, mathGC, x, y, s, ls);
341    XFlush(fl_display);
342 }
343
344 void
345 MathBigopInset::Metrics()
346 {   
347    int ls;
348    char c;
349    char const *s;
350    short t;
351
352    if (sym<256 || sym==LM_oint) {
353       ls = 1;
354       c = (sym==LM_oint) ? LM_int: sym;
355       s = &c;
356       t = LM_TC_BSYM;
357    } else {
358       s = name;
359       ls = strlen(name);
360       t = LM_TC_TEXTRM;
361    }
362    mathed_set_font(t, size);
363    mathed_string_height(t, size, (unsigned char const *)s, ls, ascent, descent);
364    width = mathed_string_width(t, size, (unsigned char const *)s, ls);
365    if (sym==LM_oint) width += 2;
366 }
367