]> git.lyx.org Git - lyx.git/blob - src/mathed/math_inset.C
c7336b45f45d6158c2ef50c3a77e5bb762540beb
[lyx.git] / src / mathed / math_inset.C
1 /*
2  *  File:        math_inset.C
3  *  Purpose:     Implementation of insets for mathed
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
5  *  Created:     January 1996
6  *  Description: 
7  *
8  *  Dependencies: Xlib, XForms
9  *
10  *  Copyright: (c) 1996, 1997 Alejandro Aguilar Sierra
11  *
12  *   Version: 0.8beta.
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
20 #ifdef __GNUG__
21 #pragma implementation "math_inset.h"
22 #endif
23
24 #include "math_iter.h"
25 #include "math_inset.h"
26 #include "symbol_def.h"
27
28
29 inline
30 char * strnew(char const * s)
31 {
32    char * s1 = new char[strlen(s)+1];
33    return strcpy(s1, s);
34 }
35
36
37 MathedInset::MathedInset(MathedInset * inset) 
38 {
39    if (inset) {
40       name = inset->GetName();
41       objtype = inset->GetType();
42       size = inset->GetStyle();
43       width = inset->Width();
44       ascent = inset->Ascent();
45       descent = inset->Descent();
46    } else {
47       objtype = LM_OT_UNDEF;
48       size = LM_ST_TEXT;
49       width = ascent = descent = 0;
50       name = 0;
51    }
52 }
53
54
55 MathFuncInset::MathFuncInset(char const * nm, short ot, short st):
56     MathedInset("", ot, st)
57 {
58    ln = 0;
59    lims = (GetType() == LM_OT_FUNCLIM);
60     if (GetType() == LM_OT_UNDEF) {
61         fname = strnew(nm);
62         SetName(fname);
63     } else {
64         fname = 0;
65         SetName(nm);
66     }
67 }
68
69 MathFuncInset * MathFuncInset::Clone()
70 {
71 #if 0
72    MathedInset *l = new MathFuncInset(name, GetType(), GetStyle());
73    return l;
74 #endif
75    return new MathFuncInset(name, GetType(), GetStyle());
76 }
77
78 MathSpaceInset::MathSpaceInset(int sp, short ot, short st):
79     MathedInset("", ot, st), space(sp)
80 {
81 }
82
83 MathSpaceInset * MathSpaceInset::Clone()
84 {
85 #if 0
86    MathedInset *l = new MathSpaceInset(space, GetType(), GetStyle());
87    return l;
88 #endif
89    return new MathSpaceInset(space, GetType(), GetStyle());
90 }
91
92 MathParInset::MathParInset(short st, char const * nm, short ot):
93    MathedInset(nm, ot, st)
94 {
95     array = 0;
96     ascent = 8;
97     width = 4;
98     descent = 0;
99     flag = 1;
100     if (objtype == LM_OT_SCRIPT)
101       flag |= LMPF_SCRIPT;
102 }
103
104 MathParInset::MathParInset(MathParInset * p): MathedInset(p)
105 {
106     flag = p->flag;
107     p->setArgumentIdx(0);
108     MathedIter it(p->GetData());
109     SetData(it.Copy());
110 }
111
112
113 MathParInset::~MathParInset()
114 {
115    if (array) {
116       MathedIter it(array);
117       it.Clear();
118       delete array;
119    }
120 }
121
122
123 MathParInset * MathParInset::Clone()
124 {
125 #if 0
126    MathParInset * p = new MathParInset(this);
127    return p;
128 #endif
129    return new MathParInset(this);
130 }
131
132
133 void MathParInset::SetData(LyxArrayBase * a)
134 {
135     array = a;
136    
137     // A standard paragraph shouldn't have any tabs nor CRs.
138     if (array) {
139         MathedIter it(array);
140         while (it.OK()) {
141             char c = it.GetChar();
142             if (c == LM_TC_TAB || c == LM_TC_CR) 
143               it.Delete();
144             else
145               it.Next();
146         }
147    }
148 }
149
150
151 MathSqrtInset::MathSqrtInset(short st): MathParInset(st, "sqrt", LM_OT_SQRT)
152 {    
153 }
154
155
156 MathSqrtInset * MathSqrtInset::Clone()
157 {   
158    MathSqrtInset * p = new MathSqrtInset(GetStyle());
159    MathedIter it(array);
160    p->SetData(it.Copy());
161    return p;
162 }
163
164
165 bool MathSqrtInset::Inside(int x, int y) 
166 {
167     return (x>= xo-hmax && x<= xo+width-hmax && y<= yo+descent && y>= yo-ascent);
168 }
169
170
171 MathDelimInset::MathDelimInset(int l, int r, short st): 
172   MathParInset(st, "", LM_OT_DELIM), left(l), right(r)
173 {
174 }
175
176 MathDelimInset * MathDelimInset::Clone()
177 {   
178    MathDelimInset * p = new MathDelimInset(left, right, GetStyle());
179    MathedIter it(array);
180    p->SetData(it.Copy());
181    return p;
182 }
183
184
185 MathDecorationInset::MathDecorationInset(int d, short st): 
186   MathParInset(st, "", LM_OT_DECO), deco(d)
187 {
188    upper = (deco!= LM_underline && deco!= LM_underbrace);
189 }
190
191 MathDecorationInset * MathDecorationInset::Clone()
192 {   
193    MathDecorationInset * p = new MathDecorationInset(deco, GetStyle());
194    MathedIter it(array);
195    p->SetData(it.Copy());
196    return p;
197 }
198
199 MathFracInset::MathFracInset(short ot): MathParInset(LM_ST_TEXT, "frac", ot)
200 {
201         
202     den = new MathParInset(LM_ST_TEXT); // this leaks
203     dh = 0;
204     idx = 0;
205     if (objtype == LM_OT_STACKREL) {
206         flag |= LMPF_SCRIPT;
207         SetName("stackrel");
208     }
209 }
210
211 MathFracInset::~MathFracInset()
212 {
213     delete den;
214 }
215
216 MathFracInset * MathFracInset::Clone()
217 {   
218     MathFracInset * p = new MathFracInset(GetType());
219     MathedIter itn(array);
220     MathedIter itd(den->GetData());
221     p->SetData(itn.Copy(), itd.Copy());
222     p->idx = idx;
223     p->dh = dh;
224    return p;
225 }
226
227 bool MathFracInset::setArgumentIdx(int i)
228 {
229    if (i == 0 || i == 1) {
230        idx = i;
231        return true;
232    } else 
233       return false;
234 }
235
236
237 void MathFracInset::SetStyle(short st)
238 {
239     MathParInset::SetStyle(st);
240     dh = 0;
241     den->SetStyle((size == LM_ST_DISPLAY) ? (short)LM_ST_TEXT: size);
242 }
243
244 void MathFracInset::SetData(LyxArrayBase * n, LyxArrayBase * d)
245 {
246    den->SetData(d);
247    MathParInset::SetData(n);
248 }
249
250 void MathFracInset::SetData(LyxArrayBase * d)
251 {
252    if (idx == 0)
253      MathParInset::SetData(d);
254    else {
255       den->SetData(d);
256    }
257 }
258
259 void MathFracInset::GetXY(int & x, int & y) const
260 {  
261    if (idx == 0)
262      MathParInset::GetXY(x, y);
263    else
264      den->GetXY(x, y);
265 }
266    
267 LyxArrayBase * MathFracInset::GetData()
268 {
269    if (idx == 0)
270      return array;
271    else
272      return den->GetData();
273 }
274
275
276 bool MathFracInset::Inside(int x, int y) 
277 {
278     int xx = xo - (width-w0)/2;
279     
280     return (x>= xx && x<= xx+width && y<= yo+descent && y>= yo-ascent);
281 }
282
283 void MathFracInset::SetFocus(int /*x*/, int y)
284 {  
285 //    lyxerr << "y " << y << " " << yo << " " << den->yo << " ";
286     idx = (y > yo) ? 1: 0;
287 }
288
289
290 MathMatrixInset::MathMatrixInset(int m, int n, short st): 
291    MathParInset(st, "array", LM_OT_MATRIX), nc(m)
292 {
293     ws = new int[nc]; 
294     v_align = 0;
295     h_align = new char[nc+1];
296     for (int i = 0; i < nc; i++) h_align[i] = 'c'; 
297     h_align[nc] = '\0';
298     nr = 0;
299     row = 0;
300     flag = 15;
301     if (n>0) {
302             row = new MathedRowSt(nc+1);
303         MathedXIter it(this);
304         for (int j = 1; j < n; j++) it.addRow();
305         nr = n;
306         if (nr == 1 && nc>1) {
307             for (int j = 0; j < nc - 1; j++) 
308               it.Insert('T', LM_TC_TAB);
309         }
310     } else if (n<0) {
311             row = new MathedRowSt(nc+1);
312         nr = 1;
313     }
314 }
315
316
317 MathMatrixInset::MathMatrixInset(MathMatrixInset * mt): 
318    MathParInset(mt->GetStyle(), mt->GetName(), mt->GetType())
319 {
320     nr = 0;
321     nc = mt->nc;
322     ws = new int[nc];
323     h_align = new char[nc+1];
324     strcpy(h_align, mt->GetAlign(&v_align));
325     MathedIter it;   
326     it.SetData(mt->GetData());
327     array = it.Copy();
328     if (mt->row != 0) {
329         MathedRowSt *r, *ro= 0, *mrow = mt->row;
330         mrow = mt->row;
331         while (mrow) {
332             r = new MathedRowSt(nc+1);
333             r->numbered = mrow->numbered;
334             if (mrow->label) 
335               r->label = strnew(mrow->label);
336             if (!ro) 
337               row = r;
338             else
339               ro->next = r;
340             mrow = mrow->next;
341             ro = r;
342             nr++;
343         } 
344     } else         
345       row = 0;
346     flag = mt->flag;
347 }
348
349
350 MathMatrixInset::~MathMatrixInset()
351 {
352     delete[] ws;
353     
354     MathedRowSt * r = row;
355     while (r) {
356         MathedRowSt * q = r->next;
357         delete r;
358         r = q;
359     }
360 }
361
362 MathMatrixInset * MathMatrixInset::Clone()
363 {   
364     MathMatrixInset * mt = new MathMatrixInset(this);
365     return mt;
366 }
367
368 void MathMatrixInset::SetAlign(char vv, char const* hh)
369 {
370    v_align = vv;
371    strncpy(h_align, hh, nc);
372 }
373
374
375 // Check the number of tabs and crs
376 void MathMatrixInset::SetData(LyxArrayBase * a)
377 {
378     if (!a) return;
379     MathedIter it(a);
380     int nn = nc-1;
381     nr = 1;
382     // count tabs per row
383     while (it.OK()) {
384         if (it.IsTab()) {
385             if (nn<0) { 
386                 it.Delete();
387                 continue;
388             } else {
389 //            it.Next();
390                 nn--;
391             }
392         }
393         if (it.IsCR()) {
394             while (nn>0) {
395                 it.Insert(' ', LM_TC_TAB);
396                 nn--;
397             }
398             nn = nc-1;
399             nr++;
400         }
401         it.Next();
402     }  
403     it.Reset();
404
405     // Automatically inserts tabs around bops
406     // DISABLED because it's very easy to insert tabs 
407     array = a;
408 }
409
410
411 void MathMatrixInset::Draw(int x, int baseline)
412 {
413     MathParInset::Draw(x, baseline);
414 }                
415
416 void MathMatrixInset::Metrics()
417 {
418     int i, /*cy,*/ hl, h= 0;
419     MathedRowSt *cprow= 0, *cxrow;
420
421     if (!row) {
422 //      lyxerr << " MIDA ";
423         MathedXIter it(this);
424         row = it.adjustVerticalSt();
425     } 
426     
427     // Clean the arrays      
428     cxrow = row;
429     while (cxrow) {   
430         for (i= 0; i<= nc; i++) cxrow->w[i] = 0;
431         cxrow = cxrow->next;
432     }
433     
434     // Basic metrics
435     MathParInset::Metrics();
436             
437     if (nc<= 1 && !row->next) {
438         row->asc = ascent;
439         row->desc = descent;
440     }
441     
442     // Vertical positions of each row
443     cxrow = row;     
444     while (cxrow) {
445         for (i= 0; i<nc; i++) {
446             if (cxrow == row || ws[i]<cxrow->w[i]) ws[i]= cxrow->w[i];
447             if (cxrow->next == 0 && ws[i] == 0) ws[i] = df_width;
448         }
449         
450         cxrow->y = (cxrow == row) ? cxrow->asc:
451                    cxrow->asc + cprow->desc + MATH_ROWSEP + cprow->y;
452         h += cxrow->asc + cxrow->desc + MATH_ROWSEP;    
453         cprow = cxrow;
454         cxrow = cxrow->next;
455     }
456     
457     hl = Descent();
458     h -= MATH_ROWSEP;
459
460     //  Compute vertical align
461     switch (v_align) {
462      case 't': ascent = row->y; break;
463      case 'b': ascent = h - hl; break;
464      default:  ascent = (row->next) ? h/2: h - hl; break;
465     }
466     descent = h - ascent + 2;
467     
468    
469    // Adjust local tabs
470     cxrow = row;
471     width = MATH_COLSEP;
472     while (cxrow) {   
473         int rg= MATH_COLSEP, ww, lf= 0, *w = cxrow->w;
474         for (i= 0; i<nc; i++) {
475             bool isvoid = false;
476             if (w[i]<= 0) {
477                 w[i] = df_width;
478                 isvoid = true;
479             }
480             switch (h_align[i]) {
481              case 'l': lf = 0; break;
482              case 'c': lf = (ws[i] - w[i])/2; 
483                        break;
484              case 'r': lf = ws[i] - w[i]; break;
485             }
486             ww = (isvoid) ? lf: lf + w[i];
487             w[i] = lf + rg;
488             rg = ws[i] - ww + MATH_COLSEP;
489             if (cxrow == row) width += ws[i] + MATH_COLSEP;
490         }
491         cxrow->y -= ascent;
492         cxrow = cxrow->next;
493     }
494 }
495
496 MathAccentInset::MathAccentInset(byte cx, MathedTextCodes f, int cd, short st): 
497   MathedInset("", LM_OT_ACCENT, st), c(cx), fn(f), code(cd)
498 {
499     inset = 0;
500 }
501
502 MathAccentInset::MathAccentInset(MathedInset *ins, int cd, short st):
503   MathedInset("", LM_OT_ACCENT, st), c(0), fn(LM_TC_MIN), code(cd), inset(ins)
504 {
505 }
506
507
508 MathAccentInset::~MathAccentInset()
509 {
510     if (inset)
511       delete inset;
512 }
513
514 MathAccentInset * MathAccentInset::Clone()
515 {   
516     MathAccentInset * p;
517     
518     if (inset) 
519       p = new MathAccentInset(inset->Clone(), code, GetStyle());
520     else
521       p = new MathAccentInset(c, fn, code, GetStyle());
522     
523     return p;
524 }
525
526
527 MathBigopInset::MathBigopInset(char const* nam, int id, short st): 
528   MathedInset(nam, LM_OT_BIGOP, st), sym(id)
529 {
530    lims = -1;
531 }
532
533 MathBigopInset * MathBigopInset::Clone()
534 {
535 #if 0
536    MathBigopInset* p = new MathBigopInset(name, sym, GetStyle());
537    return p;
538 #endif
539    return new MathBigopInset(name, sym, GetStyle());
540 }
541  
542 MathDotsInset::MathDotsInset(char const * nam, int id, short st):
543   MathedInset(nam, LM_OT_DOTS, st), code(id)
544 {
545 }
546
547 MathDotsInset * MathDotsInset::Clone()
548 {
549 #if 0
550    MathDotsInset* p = new MathDotsInset(name, code, GetStyle());
551    return p;
552 #endif
553    return new MathDotsInset(name, code, GetStyle());
554 }     
555