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