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