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