]> git.lyx.org Git - lyx.git/blob - src/mathed/InsetMathFrac.cpp
Fix bug 5802 (http://bugzilla.lyx.org/show_bug.cgi?id=5802)
[lyx.git] / src / mathed / InsetMathFrac.cpp
1 /**
2  * \file InsetMathFracBase.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author André Pönitz
8  * \author Uwe Stöhr
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "InsetMathFrac.h"
16
17 #include "Cursor.h"
18 #include "LaTeXFeatures.h"
19 #include "MathData.h"
20 #include "MathStream.h"
21 #include "MathSupport.h"
22 #include "MetricsInfo.h"
23 #include "TextPainter.h"
24
25 #include "frontends/Painter.h"
26
27 using namespace std;
28
29 namespace lyx {
30
31 /////////////////////////////////////////////////////////////////////
32 //
33 // InsetMathFracBase
34 //
35 /////////////////////////////////////////////////////////////////////
36
37
38 InsetMathFracBase::InsetMathFracBase(idx_type ncells)
39         : InsetMathNest(ncells)
40 {}
41
42
43 bool InsetMathFracBase::idxUpDown(Cursor & cur, bool up) const
44 {
45         InsetMath::idx_type target = !up; // up ? 0 : 1, since upper cell has idx 0
46         if (cur.idx() == target)
47                 return false;
48         cur.idx() = target;
49         cur.pos() = cell(target).x2pos(&cur.bv(), cur.x_target());
50         return true;
51 }
52
53
54
55 /////////////////////////////////////////////////////////////////////
56 //
57 // InsetMathFrac
58 //
59 /////////////////////////////////////////////////////////////////////
60
61
62 InsetMathFrac::InsetMathFrac(Kind kind, InsetMath::idx_type ncells)
63         : InsetMathFracBase(ncells), kind_(kind)
64 {}
65
66
67 Inset * InsetMathFrac::clone() const
68 {
69         return new InsetMathFrac(*this);
70 }
71
72
73 InsetMathFrac * InsetMathFrac::asFracInset()
74 {
75         return kind_ == ATOP ? 0 : this;
76 }
77
78
79 InsetMathFrac const * InsetMathFrac::asFracInset() const
80 {
81         return kind_ == ATOP ? 0 : this;
82 }
83
84
85 bool InsetMathFrac::idxForward(Cursor & cur) const
86 {
87         InsetMath::idx_type target = 0;
88         if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) {
89                 if (nargs() == 3)
90                         target = 0;
91                 else if (nargs() == 2)
92                         target = 1;
93         } else
94                 return false;
95         if (cur.idx() == target)
96                 return false;
97         cur.idx() = target;
98         cur.pos() = cell(target).x2pos(&cur.bv(), cur.x_target());
99         return true;
100 }
101
102
103 bool InsetMathFrac::idxBackward(Cursor & cur) const
104 {
105         InsetMath::idx_type target = 0;
106         if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) {
107                 if (nargs() == 3)
108                         target = 2;
109                 else if (nargs() == 2)
110                         target = 0;
111         } else
112                 return false;
113         if (cur.idx() == target)
114                 return false;
115         cur.idx() = target;
116         cur.pos() = cell(target).x2pos(&cur.bv(), cur.x_target());
117         return true;
118 }
119
120
121 void InsetMathFrac::metrics(MetricsInfo & mi, Dimension & dim) const
122 {
123         Dimension dim0, dim1, dim2;
124
125         if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) {
126                 if (nargs() == 1) {
127                         ShapeChanger dummy2(mi.base.font, UP_SHAPE);
128                         cell(0).metrics(mi, dim0);
129                         dim.wid = dim0.width()+ 3;
130                         dim.asc = dim0.asc;
131                         dim.des = dim0.des;
132                 } else if (nargs() == 2) {
133                         cell(0).metrics(mi, dim0);
134                         ShapeChanger dummy2(mi.base.font, UP_SHAPE);
135                         cell(1).metrics(mi, dim1);
136                         dim.wid = dim0.width() + dim1.wid + 5;
137                         dim.asc = max(dim0.asc, dim1.asc);
138                         dim.des = max(dim0.des, dim1.des);
139                 } else {
140                         cell(2).metrics(mi, dim2);
141                         ShapeChanger dummy2(mi.base.font, UP_SHAPE);
142                         FracChanger dummy(mi.base);
143                         cell(0).metrics(mi, dim0);
144                         cell(1).metrics(mi, dim1);
145                         dim.wid = dim0.width() + dim1.wid + dim2.wid + 10;
146                         dim.asc = max(dim2.asc, dim0.height() + 5);
147                         dim.des = max(dim2.des, dim1.height() - 5);
148                 }
149         } else {
150                 FracChanger dummy(mi.base);
151                 cell(0).metrics(mi, dim0);
152                 cell(1).metrics(mi, dim1);
153                 if (nargs() == 3)
154                         cell(2).metrics(mi, dim2);
155
156                 if (kind_ == NICEFRAC) {
157                         dim.wid = dim0.width() + dim1.wid + 5;
158                         dim.asc = dim0.height() + 5;
159                         dim.des = dim1.height() - 5;
160                 } else if (kind_ == UNITFRAC) {
161                         ShapeChanger dummy2(mi.base.font, UP_SHAPE);
162                         dim.wid = dim0.width() + dim1.wid + 5;
163                         dim.asc = dim0.height() + 5;
164                         dim.des = dim1.height() - 5;
165                 } else {
166                         dim.wid = max(dim0.width(), dim1.wid) + 2;
167                         dim.asc = dim0.height() + 2 + 5;
168                         dim.des = dim1.height() + 2 - 5;
169                 }
170         }
171         metricsMarkers(dim);
172 }
173
174
175 void InsetMathFrac::draw(PainterInfo & pi, int x, int y) const
176 {
177         setPosCache(pi, x, y);
178         Dimension const dim = dimension(*pi.base.bv);
179         Dimension const dim0 = cell(0).dimension(*pi.base.bv);
180         int m = x + dim.wid / 2;
181         if (kind_ == UNIT || (kind_ == UNITFRAC && nargs() == 3)) {
182                 if (nargs() == 1) {
183                         ShapeChanger dummy2(pi.base.font, UP_SHAPE);
184                         cell(0).draw(pi, x + 1, y);
185                 } else if (nargs() == 2) {
186                         cell(0).draw(pi, x + 1, y);
187                         ShapeChanger dummy2(pi.base.font, UP_SHAPE);
188                         cell(1).draw(pi, x + dim0.width() + 5, y);
189                 } else {
190                         cell(2).draw(pi, x + 1, y);
191                         ShapeChanger dummy2(pi.base.font, UP_SHAPE);
192                         FracChanger dummy(pi.base);
193                         Dimension const dim1 = cell(1).dimension(*pi.base.bv);
194                         Dimension const dim2 = cell(2).dimension(*pi.base.bv);
195                         int xx = x + dim2.wid + 5;
196                         cell(0).draw(pi, xx + 2, 
197                                          y - dim0.des - 5);
198                         cell(1).draw(pi, xx  + dim0.width() + 5, 
199                                          y + dim1.asc / 2);
200                 }
201         } else {
202                 FracChanger dummy(pi.base);
203                 Dimension const dim1 = cell(1).dimension(*pi.base.bv);
204                 if (kind_ == NICEFRAC) {
205                         cell(0).draw(pi, x + 2,
206                                         y - dim0.des - 5);
207                         cell(1).draw(pi, x + dim0.width() + 5,
208                                         y + dim1.asc / 2);
209                 } else if (kind_ == UNITFRAC) {
210                         ShapeChanger dummy2(pi.base.font, UP_SHAPE);
211                         cell(0).draw(pi, x + 2,
212                                         y - dim0.des - 5);
213                         cell(1).draw(pi, x + dim0.width() + 5,
214                                         y + dim1.asc / 2);
215                 } else {
216                         // Classical fraction
217                         cell(0).draw(pi, m - dim0.width() / 2,
218                                         y - dim0.des - 2 - 5);
219                         cell(1).draw(pi, m - dim1.wid / 2,
220                                         y + dim1.asc  + 2 - 5);
221                 }
222         }
223         if (kind_ == NICEFRAC || kind_ == UNITFRAC) {
224                 // Diag line:
225                 int xx = x;
226                 if (nargs() == 3)
227                         xx += cell(2).dimension(*pi.base.bv).wid + 5;
228
229                 pi.pain.line(xx + dim0.wid,
230                                 y + dim.des - 2,
231                                 xx + dim0.wid + 5,
232                                 y - dim.asc + 2, Color_math);
233         }
234         if (kind_ == FRAC || kind_ == OVER)
235                 pi.pain.line(x + 1, y - 5,
236                                 x + dim.wid - 2, y - 5, Color_math);
237         drawMarkers(pi, x, y);
238 }
239
240
241 void InsetMathFrac::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
242 {
243         Dimension dim0, dim1;
244         cell(0).metricsT(mi, dim0);
245         cell(1).metricsT(mi, dim1);
246         dim.wid = max(dim0.width(), dim1.wid);
247         dim.asc = dim0.height() + 1;
248         dim.des = dim1.height();
249 }
250
251
252 void InsetMathFrac::drawT(TextPainter & /*pain*/, int /*x*/, int /*y*/) const
253 {
254         // FIXME: BROKEN!
255         /*
256         Dimension dim;
257         int m = x + dim.width() / 2;
258         cell(0).drawT(pain, m - dim0.width() / 2, y - dim0.des - 1);
259         cell(1).drawT(pain, m - dim1.wid / 2, y + dim1.asc);
260         // ASCII art: ignore niceties
261         if (kind_ == FRAC || kind_ == OVER || kind_ == NICEFRAC || kind_ == UNITFRAC)
262                 pain.horizontalLine(x, y, dim.width());
263         */
264 }
265
266
267 void InsetMathFrac::write(WriteStream & os) const
268 {
269         MathEnsurer ensurer(os);
270         switch (kind_) {
271         case ATOP:
272                 os << '{' << cell(0) << "\\atop " << cell(1) << '}';
273                 break;
274         case OVER:
275                 // \\over is only for compatibility, normalize this to \\frac
276                 os << "\\frac{" << cell(0) << "}{" << cell(1) << '}';
277                 break;
278         case FRAC:
279         case NICEFRAC:
280         case UNITFRAC:
281                 if (nargs() == 2)
282                         InsetMathNest::write(os);
283                 else
284                         os << "\\unitfrac[" << cell(2) << "]{" << cell(0) << "}{" << cell(1) << '}';
285                 break;
286         case UNIT:
287                 if (nargs() == 2)
288                         os << "\\unit[" << cell(0) << "]{" << cell(1) << '}';
289                 else
290                         os << "\\unit{" << cell(0) << '}';
291                 break;
292         }
293 }
294
295
296 docstring InsetMathFrac::name() const
297 {
298         switch (kind_) {
299         case FRAC:
300                 return from_ascii("frac");
301         case OVER:
302                 return from_ascii("over");
303         case NICEFRAC:
304                 return from_ascii("nicefrac");
305         case UNITFRAC:
306                 return from_ascii("unitfrac");
307         case UNIT:
308                 return from_ascii("unit");
309         case ATOP:
310                 return from_ascii("atop");
311         }
312         // shut up stupid compiler
313         return docstring();
314 }
315
316
317 bool InsetMathFrac::extraBraces() const
318 {
319         return kind_ == ATOP || kind_ == OVER;
320 }
321
322
323 void InsetMathFrac::maple(MapleStream & os) const
324 {
325         os << '(' << cell(0) << ")/(" << cell(1) << ')';
326 }
327
328
329 void InsetMathFrac::mathematica(MathematicaStream & os) const
330 {
331         os << '(' << cell(0) << ")/(" << cell(1) << ')';
332 }
333
334
335 void InsetMathFrac::octave(OctaveStream & os) const
336 {
337         os << '(' << cell(0) << ")/(" << cell(1) << ')';
338 }
339
340
341 void InsetMathFrac::mathmlize(MathStream & os) const
342 {
343         os << MTag("mfrac") << cell(0) << cell(1) << ETag("mfrac");
344 }
345
346
347 void InsetMathFrac::validate(LaTeXFeatures & features) const
348 {
349         if (kind_ == NICEFRAC || kind_ == UNITFRAC || kind_ == UNIT)
350                 features.require("units");
351         InsetMathNest::validate(features);
352 }
353
354
355 /////////////////////////////////////////////////////////////////////
356 //
357 // InsetMathDFrac
358 //
359 /////////////////////////////////////////////////////////////////////
360
361
362 Inset * InsetMathDFrac::clone() const
363 {
364         return new InsetMathDFrac(*this);
365 }
366
367
368 void InsetMathDFrac::metrics(MetricsInfo & mi, Dimension & dim) const
369 {
370         Dimension dim0, dim1;
371         cell(0).metrics(mi, dim0);
372         cell(1).metrics(mi, dim1);
373         dim.wid = max(dim0.wid, dim1.wid) + 2;
374         dim.asc = dim0.height() + 2 + 5;
375         dim.des = dim1.height() + 2 - 5;
376 }
377
378
379 void InsetMathDFrac::draw(PainterInfo & pi, int x, int y) const
380 {
381         Dimension const dim = dimension(*pi.base.bv);
382         Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
383         Dimension const & dim1 = cell(1).dimension(*pi.base.bv);
384         int m = x + dim.wid / 2;
385         cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 2 - 5);
386         cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc  + 2 - 5);
387         pi.pain.line(x + 1, y - 5, x + dim.wid - 2, y - 5, Color_math);
388         setPosCache(pi, x, y);
389 }
390
391
392 docstring InsetMathDFrac::name() const
393 {
394         return from_ascii("dfrac");
395 }
396
397
398 void InsetMathDFrac::mathmlize(MathStream & os) const
399 {
400         os << MTag("mdfrac") << cell(0) << cell(1) << ETag("mdfrac");
401 }
402
403
404 void InsetMathDFrac::validate(LaTeXFeatures & features) const
405 {
406         features.require("amsmath");
407         InsetMathNest::validate(features);
408 }
409
410
411 /////////////////////////////////////////////////////////////////////
412 //
413 // InsetMathTFrac
414 //
415 /////////////////////////////////////////////////////////////////////
416
417
418 Inset * InsetMathTFrac::clone() const
419 {
420         return new InsetMathTFrac(*this);
421 }
422
423
424 void InsetMathTFrac::metrics(MetricsInfo & mi, Dimension & dim) const
425 {
426         StyleChanger dummy(mi.base, LM_ST_SCRIPT);
427         Dimension dim0;
428         cell(0).metrics(mi, dim0);
429         Dimension dim1;
430         cell(1).metrics(mi, dim1);
431         dim.wid = max(dim0.width(), dim1.width()) + 2;
432         dim.asc = dim0.height() + 2 + 5;
433         dim.des = dim1.height() + 2 - 5;
434 }
435
436
437 void InsetMathTFrac::draw(PainterInfo & pi, int x, int y) const
438 {
439         StyleChanger dummy(pi.base, LM_ST_SCRIPT);
440         Dimension const dim = dimension(*pi.base.bv);
441         Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
442         Dimension const & dim1 = cell(1).dimension(*pi.base.bv);
443         int m = x + dim.wid / 2;
444         cell(0).draw(pi, m - dim0.width() / 2, y - dim0.descent() - 2 - 5);
445         cell(1).draw(pi, m - dim1.width() / 2, y + dim1.ascent()  + 2 - 5);
446         pi.pain.line(x + 1, y - 5, x + dim.wid - 2, y - 5, Color_math);
447         setPosCache(pi, x, y);
448 }
449
450
451 docstring InsetMathTFrac::name() const
452 {
453         return from_ascii("tfrac");
454 }
455
456
457 void InsetMathTFrac::mathmlize(MathStream & os) const
458 {
459         os << MTag("mtfrac") << cell(0) << cell(1) << ETag("mtfrac");
460 }
461
462
463 void InsetMathTFrac::validate(LaTeXFeatures & features) const
464 {
465         features.require("amsmath");
466         InsetMathNest::validate(features);
467 }
468
469
470 /////////////////////////////////////////////////////////////////////
471 //
472 // InsetMathCFrac
473 //
474 /////////////////////////////////////////////////////////////////////
475
476
477 Inset * InsetMathCFrac::clone() const
478 {
479         return new InsetMathCFrac(*this);
480 }
481
482
483 void InsetMathCFrac::metrics(MetricsInfo & mi, Dimension & dim) const
484 {
485         Dimension dim0, dim1;
486         cell(0).metrics(mi, dim0);
487         cell(1).metrics(mi, dim1);
488         dim.wid = max(dim0.wid, dim1.wid) + 2;
489         dim.asc = dim0.height() + 2 + 5;
490         dim.des = dim1.height() + 2 - 5;
491 }
492
493
494 void InsetMathCFrac::draw(PainterInfo & pi, int x, int y) const
495 {
496         Dimension const dim = dimension(*pi.base.bv);
497         Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
498         Dimension const & dim1 = cell(1).dimension(*pi.base.bv);
499         int m = x + dim.wid / 2;
500         cell(0).draw(pi, m - dim0.wid / 2, y - dim0.des - 2 - 5);
501         cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc  + 2 - 5);
502         pi.pain.line(x + 1, y - 5, x + dim.wid - 2, y - 5, Color_math);
503         setPosCache(pi, x, y);
504 }
505
506
507 docstring InsetMathCFrac::name() const
508 {
509         return from_ascii("cfrac");
510 }
511
512
513 void InsetMathCFrac::mathmlize(MathStream & os) const
514 {
515         os << MTag("mcfrac") << cell(0) << cell(1) << ETag("mcfrac");
516 }
517
518
519 void InsetMathCFrac::validate(LaTeXFeatures & features) const
520 {
521         features.require("amsmath");
522         InsetMathNest::validate(features);
523 }
524
525
526 /////////////////////////////////////////////////////////////////////
527 //
528 // InsetMathBinom
529 //
530 /////////////////////////////////////////////////////////////////////
531
532
533 InsetMathBinom::InsetMathBinom(Kind kind)
534         : kind_(kind)
535 {}
536
537
538 Inset * InsetMathBinom::clone() const
539 {
540         return new InsetMathBinom(*this);
541 }
542
543
544 int InsetMathBinom::dw(int height) const
545 {
546         int w = height / 5;
547         if (w > 15)
548                 w = 15;
549         if (w < 6)
550                 w = 6;
551         return w;
552 }
553
554
555 void InsetMathBinom::metrics(MetricsInfo & mi, Dimension & dim) const
556 {
557         FracChanger dummy(mi.base);
558         Dimension dim0, dim1;
559         cell(0).metrics(mi, dim0);
560         cell(1).metrics(mi, dim1);
561         dim.asc = dim0.height() + 4 + 5;
562         dim.des = dim1.height() + 4 - 5;
563         dim.wid = max(dim0.width(), dim1.wid) + 2 * dw(dim.height()) + 4;
564         metricsMarkers2(dim);
565 }
566
567
568 void InsetMathBinom::draw(PainterInfo & pi, int x, int y) const
569 {
570         Dimension const dim = dimension(*pi.base.bv);
571         Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
572         Dimension const & dim1 = cell(1).dimension(*pi.base.bv);
573         docstring const bra = kind_ == BRACE ? from_ascii("{") :
574                               kind_ == BRACK ? from_ascii("[") : from_ascii("(");
575         docstring const ket = kind_ == BRACE ? from_ascii("}") :
576                               kind_ == BRACK ? from_ascii("]") : from_ascii(")");
577         int m = x + dim.width() / 2;
578         FracChanger dummy(pi.base);
579         cell(0).draw(pi, m - dim0.width() / 2, y - dim0.des - 3 - 5);
580         cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc  + 3 - 5);
581         mathed_draw_deco(pi, x, y - dim.ascent(), dw(dim.height()), dim.height(), bra);
582         mathed_draw_deco(pi, x + dim.width() - dw(dim.height()), y - dim.ascent(),
583                 dw(dim.height()), dim.height(), ket);
584         drawMarkers2(pi, x, y);
585 }
586
587
588 bool InsetMathBinom::extraBraces() const
589 {
590         return kind_ == CHOOSE || kind_ == BRACE || kind_ == BRACK;
591 }
592
593
594 void InsetMathBinom::write(WriteStream & os) const
595 {
596         MathEnsurer ensurer(os);
597         switch (kind_) {
598         case BINOM:
599                 os << "\\binom{" << cell(0) << "}{" << cell(1) << '}';
600                 break;
601         case CHOOSE:
602                 os << '{' << cell(0) << " \\choose " << cell(1) << '}';
603                 break;
604         case BRACE:
605                 os << '{' << cell(0) << " \\brace " << cell(1) << '}';
606                 break;
607         case BRACK:
608                 os << '{' << cell(0) << " \\brack " << cell(1) << '}';
609                 break;
610         }
611 }
612
613
614 void InsetMathBinom::normalize(NormalStream & os) const
615 {
616         os << "[binom " << cell(0) << ' ' << cell(1) << ']';
617 }
618
619
620 void InsetMathBinom::validate(LaTeXFeatures & features) const
621 {
622         if (kind_ == BINOM)
623                 features.require("binom");
624         InsetMathNest::validate(features);
625 }
626
627
628 /////////////////////////////////////////////////////////////////////
629 //
630 // InsetMathDBinom
631 //
632 /////////////////////////////////////////////////////////////////////
633
634 Inset * InsetMathDBinom::clone() const
635 {
636         return new InsetMathDBinom(*this);
637 }
638
639
640 int InsetMathDBinom::dw(int height) const
641 {
642         int w = height / 5;
643         if (w > 15)
644                 w = 15;
645         if (w < 6)
646                 w = 6;
647         return w;
648 }
649
650
651 void InsetMathDBinom::metrics(MetricsInfo & mi, Dimension & dim) const
652 {
653         Dimension dim0, dim1;
654         cell(0).metrics(mi, dim0);
655         cell(1).metrics(mi, dim1);
656         dim.asc = dim0.height() + 4 + 5;
657         dim.des = dim1.height() + 4 - 5;
658         dim.wid = max(dim0.width(), dim1.wid) + 2 * dw(dim.height()) + 4;
659         metricsMarkers2(dim);
660 }
661
662
663 void InsetMathDBinom::draw(PainterInfo & pi, int x, int y) const
664 {
665         Dimension const dim = dimension(*pi.base.bv);
666         Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
667         Dimension const & dim1 = cell(1).dimension(*pi.base.bv);
668         int m = x + dim.width() / 2;
669         cell(0).draw(pi, m - dim0.width() / 2, y - dim0.des - 3 - 5);
670         cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc  + 3 - 5);
671         mathed_draw_deco(pi, x, y - dim.ascent(), dw(dim.height()), dim.height(), from_ascii("("));
672         mathed_draw_deco(pi, x + dim.width() - dw(dim.height()), y - dim.ascent(),
673                 dw(dim.height()), dim.height(), from_ascii(")"));
674         drawMarkers2(pi, x, y);
675 }
676
677
678 docstring InsetMathDBinom::name() const
679 {
680         return from_ascii("dbinom");
681 }
682
683 void InsetMathDBinom::mathmlize(MathStream & os) const
684 {
685         os << MTag("mdbinom") << cell(0) << cell(1) << ETag("mdbinom");
686 }
687
688 void InsetMathDBinom::validate(LaTeXFeatures & features) const
689 {
690         features.require("amsmath");
691         InsetMathNest::validate(features);
692 }
693
694
695 /////////////////////////////////////////////////////////////////////
696 //
697 // InsetMathTBinom
698 //
699 /////////////////////////////////////////////////////////////////////
700
701 Inset * InsetMathTBinom::clone() const
702 {
703         return new InsetMathTBinom(*this);
704 }
705
706
707 int InsetMathTBinom::dw(int height) const
708 {
709         int w = height / 5;
710         if (w > 15)
711                 w = 15;
712         if (w < 6)
713                 w = 6;
714         return w;
715 }
716
717
718 void InsetMathTBinom::metrics(MetricsInfo & mi, Dimension & dim) const
719 {
720         StyleChanger dummy(mi.base, LM_ST_SCRIPT);
721         Dimension dim0, dim1;
722         cell(0).metrics(mi, dim0);
723         cell(1).metrics(mi, dim1);
724         dim.asc = dim0.height() + 4 + 5;
725         dim.des = dim1.height() + 4 - 5;
726         dim.wid = max(dim0.width(), dim1.wid) + 2 * dw(dim.height()) + 4;
727         metricsMarkers2(dim);
728 }
729
730
731 void InsetMathTBinom::draw(PainterInfo & pi, int x, int y) const
732 {
733         StyleChanger dummy(pi.base, LM_ST_SCRIPT);
734         Dimension const dim = dimension(*pi.base.bv);
735         Dimension const & dim0 = cell(0).dimension(*pi.base.bv);
736         Dimension const & dim1 = cell(1).dimension(*pi.base.bv);
737         int m = x + dim.width() / 2;
738         cell(0).draw(pi, m - dim0.width() / 2, y - dim0.des - 3 - 5);
739         cell(1).draw(pi, m - dim1.wid / 2, y + dim1.asc  + 3 - 5);
740         mathed_draw_deco(pi, x, y - dim.ascent(), dw(dim.height()), dim.height(), from_ascii("("));
741         mathed_draw_deco(pi, x + dim.width() - dw(dim.height()), y - dim.ascent(),
742                 dw(dim.height()), dim.height(), from_ascii(")"));
743         drawMarkers2(pi, x, y);
744 }
745
746
747 docstring InsetMathTBinom::name() const
748 {
749         return from_ascii("tbinom");
750 }
751
752 void InsetMathTBinom::mathmlize(MathStream & os) const
753 {
754         os << MTag("mtbinom") << cell(0) << cell(1) << ETag("mtbinom");
755 }
756
757 void InsetMathTBinom::validate(LaTeXFeatures & features) const
758 {
759         features.require("amsmath");
760         InsetMathNest::validate(features);
761 }
762
763 } // namespace lyx