7 #include "math_hullinset.h"
8 #include "math_mathmlstream.h"
9 #include "math_streamstr.h"
10 #include "math_support.h"
13 #include "LaTeXFeatures.h"
14 #include "support/LAssert.h"
22 int getCols(MathInsetTypes type)
38 // returns position of first relation operator in the array
39 // used for "intelligent splitting"
40 int firstRelOp(MathArray const & ar)
42 for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
44 return it - ar.begin();
49 char const * star(bool numbered)
51 return numbered ? "" : "*";
54 MathInsetTypes typecode(string const & s)
56 if (s == "equation") return LM_OT_EQUATION;
57 if (s == "display") return LM_OT_EQUATION;
58 if (s == "eqnarray") return LM_OT_EQNARRAY;
59 if (s == "align") return LM_OT_ALIGN;
60 if (s == "alignat") return LM_OT_ALIGNAT;
61 if (s == "xalignat") return LM_OT_XALIGNAT;
62 if (s == "xxalignat") return LM_OT_XXALIGNAT;
63 if (s == "multline") return LM_OT_MULTLINE;
64 if (s == "gather") return LM_OT_GATHER;
69 string normalName(MathInsetTypes t)
72 case LM_OT_EQUATION: return "equation";
73 case LM_OT_EQNARRAY: return "eqnarray";
74 case LM_OT_ALIGN: return "align";
75 case LM_OT_ALIGNAT: return "alignat";
76 case LM_OT_XALIGNAT: return "xalignat";
77 case LM_OT_XXALIGNAT: return "xxalignat";
78 case LM_OT_MULTLINE: return "multline";
79 case LM_OT_GATHER: return "gather";
80 case LM_OT_SIMPLE: return "simple";
86 } // end anon namespace
89 MathHullInset::MathHullInset()
90 : MathGridInset(1, 1), objtype_(LM_OT_SIMPLE), nonum_(1), label_(1)
96 MathHullInset::MathHullInset(MathInsetTypes t)
97 : MathGridInset(getCols(t), 1), objtype_(t), nonum_(1), label_(1)
103 MathHullInset::MathHullInset(MathInsetTypes t, col_type cols)
104 : MathGridInset(cols, 1), objtype_(t), nonum_(1), label_(1)
110 MathInset * MathHullInset::clone() const
112 return new MathHullInset(*this);
116 char MathHullInset::defaultColAlign(col_type col)
122 case LM_OT_XXALIGNAT:
123 return "rl"[col & 1];
132 int MathHullInset::defaultColSpace(col_type col)
139 return (col & 1) ? 20 : 0;
140 case LM_OT_XXALIGNAT:
141 return (col & 1) ? 40 : 0;
148 void MathHullInset::metrics(MathMetricsInfo const & mi) const
151 mi_.style = (getType() == LM_OT_SIMPLE) ? LM_ST_TEXT : LM_ST_DISPLAY;
153 // let the cells adjust themselves
154 MathGridInset::metrics(mi_);
161 if (numberedType()) {
163 for (row_type row = 0; row < nrows(); ++row)
164 l = std::max(l, mathed_string_width(LM_TC_BF, mi_, nicelabel(row)));
170 // make it at least as high as the current font
173 math_font_max_dim(LM_TC_TEXTRM, mi_, asc, des);
174 ascent_ = std::max(ascent_, asc);
175 descent_ = std::max(descent_, des);
179 void MathHullInset::draw(Painter & pain, int x, int y) const
181 MathGridInset::draw(pain, x, y);
183 if (numberedType()) {
184 int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20;
185 for (row_type row = 0; row < nrows(); ++row) {
186 int const yy = y + rowinfo_[row].offset_;
187 drawStr(pain, LM_TC_BF, mi_, xx, yy, nicelabel(row));
193 string MathHullInset::label(row_type row) const
195 row_type n = nrows();
196 lyx::Assert(row < n);
201 void MathHullInset::label(row_type row, string const & label)
207 void MathHullInset::numbered(row_type row, bool num)
213 bool MathHullInset::numbered(row_type row) const
219 bool MathHullInset::ams() const
224 objtype_ == LM_OT_ALIGN ||
225 objtype_ == LM_OT_MULTLINE ||
226 objtype_ == LM_OT_GATHER ||
227 objtype_ == LM_OT_ALIGNAT ||
228 objtype_ == LM_OT_XALIGNAT ||
229 objtype_ == LM_OT_XXALIGNAT;
233 bool MathHullInset::display() const
235 return getType() != LM_OT_SIMPLE;
239 std::vector<string> const MathHullInset::getLabelList() const
241 std::vector<string> res;
242 for (row_type row = 0; row < nrows(); ++row)
243 if (!label_[row].empty() && nonum_[row] != 1)
244 res.push_back(label_[row]);
249 bool MathHullInset::numberedType() const
251 if (getType() == LM_OT_SIMPLE || getType() == LM_OT_XXALIGNAT)
253 for (row_type row = 0; row < nrows(); ++row)
260 void MathHullInset::validate(LaTeXFeatures & features) const
263 features.require("amsstyle");
266 // Validation is necessary only if not using AMS math.
267 // To be safe, we will always run mathedvalidate.
268 //if (features.amsstyle)
271 features.require("boldsymbol");
272 //features.binom = true;
274 MathNestInset::validate(features);
278 void MathHullInset::header_write(WriteStream & os) const
280 bool n = numberedType();
291 os << "\\begin{equation" << star(n) << "}\n";
297 os << "\\begin{eqnarray" << star(n) << "}\n";
301 os << "\\begin{align" << star(n) << "}\n";
305 os << "\\begin{alignat" << star(n) << "}"
306 << "{" << static_cast<unsigned int>(ncols()/2) << "}\n";
310 os << "\\begin{xalignat" << star(n) << "}"
311 << "{" << static_cast<unsigned int>(ncols()/2) << "}\n";
314 case LM_OT_XXALIGNAT:
315 os << "\\begin{xxalignat}"
316 << "{" << static_cast<unsigned int>(ncols()/2) << "}\n";
320 os << "\\begin{multline}\n";
324 os << "\\begin{gather}\n";
328 os << "\\begin{unknown" << star(n) << "}";
333 void MathHullInset::footer_write(WriteStream & os) const
335 bool n = numberedType();
344 os << "\\end{equation" << star(n) << "}\n";
350 os << "\n\\end{eqnarray" << star(n) << "}\n";
354 os << "\n\\end{align" << star(n) << "}\n";
358 os << "\n\\end{alignat" << star(n) << "}\n";
362 os << "\n\\end{xalignat" << star(n) << "}\n";
365 case LM_OT_XXALIGNAT:
366 os << "\n\\end{xxalignat}\n";
370 os << "\n\\end{multline}\n";
374 os << "\n\\end{gather}\n";
378 os << "\\end{unknown" << star(n) << "}";
383 void MathHullInset::addRow(row_type row)
385 nonum_.insert(nonum_.begin() + row + 1, !numberedType());
386 label_.insert(label_.begin() + row + 1, string());
387 MathGridInset::addRow(row);
391 void MathHullInset::appendRow()
393 nonum_.push_back(!numberedType());
394 label_.push_back(string());
395 MathGridInset::appendRow();
399 void MathHullInset::delRow(row_type row)
401 MathGridInset::delRow(row);
402 nonum_.erase(nonum_.begin() + row);
403 label_.erase(label_.begin() + row);
407 void MathHullInset::addCol(col_type col)
411 mutate(LM_OT_EQNARRAY);
420 mutate(LM_OT_ALIGNAT);
426 case LM_OT_XXALIGNAT:
427 MathGridInset::addCol(col);
428 MathGridInset::addCol(col + 1);
437 void MathHullInset::delCol(col_type col)
442 case LM_OT_XXALIGNAT:
443 MathGridInset::delCol(col + 1);
444 MathGridInset::delCol(col);
452 string MathHullInset::nicelabel(row_type row) const
456 if (label_[row].empty())
457 return string("(#)");
458 return "(" + label_[row] + ")";
462 void MathHullInset::mutate(string const & newtype)
464 if (newtype == "dump") {
468 //lyxerr << "mutating from '" << getType() << "' to '" << newtype << "'\n";
469 mutate(typecode(newtype));
473 void MathHullInset::glueall()
476 for (idx_type i = 0; i < nargs(); ++i)
477 ar.push_back(cell(i));
478 *this = MathHullInset(LM_OT_SIMPLE);
483 MathInsetTypes MathHullInset::getType() const
489 void MathHullInset::setType(MathInsetTypes t)
497 void MathHullInset::mutate(MathInsetTypes newtype)
499 //lyxerr << "mutating from '" << getType() << "' to '" << newtype << "'\n";
501 if (newtype == getType())
506 setType(LM_OT_EQUATION);
514 setType(LM_OT_SIMPLE);
520 case LM_OT_XXALIGNAT: {
522 MathGridInset::addCol(1);
525 pos_type pos = firstRelOp(cell(0));
527 cell(0).erase(pos, cell(0).size());
528 cell(1).erase(0, pos);
529 setType(LM_OT_ALIGN);
536 MathGridInset::addCol(1);
537 MathGridInset::addCol(1);
539 // split it "nicely" on the firest relop
540 pos_type pos = firstRelOp(cell(0));
541 cell(1) = MathArray(cell(0), pos, cell(0).size());
542 cell(0).erase(pos, cell(0).size());
544 if (cell(1).size()) {
545 cell(2) = MathArray(cell(1), 1, cell(1).size());
546 cell(1).erase(1, cell(1).size());
549 setType(LM_OT_EQNARRAY);
558 case LM_OT_EQUATION: {
559 // set correct (no)numbering
560 bool allnonum = true;
561 for (row_type row = 0; row < nrows(); ++row) {
566 // set first non-empty label
568 for (row_type row = 0; row < nrows(); ++row) {
569 if (!label_[row].empty()) {
577 nonum_[0] = allnonum;
586 case LM_OT_XXALIGNAT:
588 for (row_type row = 0; row < nrows(); ++row) {
589 idx_type c = 3 * row + 1;
590 cell(c).push_back(cell(c + 1));
592 MathGridInset::delCol(2);
593 setType(LM_OT_ALIGN);
605 MathGridInset::addCol(1);
606 setType(LM_OT_EQNARRAY);
612 case LM_OT_XXALIGNAT:
617 lyxerr << "mutation from '" << getType()
618 << "' to '" << newtype << "' not implemented"
627 setType(LM_OT_GATHER);
630 lyxerr << "mutation from '" << getType()
631 << "' to '" << newtype << "' not implemented"
639 setType(LM_OT_MULTLINE);
642 lyxerr << "mutation from '" << getType()
643 << "' to '" << newtype << "' not implemented"
649 lyxerr << "mutation from '" << getType()
650 << "' to '" << newtype << "' not implemented"
657 void MathHullInset::write(WriteStream & os) const
661 bool n = numberedType();
663 for (row_type row = 0; row < nrows(); ++row) {
664 for (col_type col = 0; col < ncols(); ++col)
665 os << cell(index(row, col)) << eocString(col);
667 if (!label_[row].empty())
668 os << "\\label{" << label_[row] << "}";
672 os << eolString(row);
679 void MathHullInset::normalize(NormalStream & os) const
681 os << "[formula " << normalName(getType()) << " ";
682 MathGridInset::normalize(os);
687 void MathHullInset::mathmlize(MathMLStream & os) const
689 MathGridInset::mathmlize(os);
693 void MathHullInset::check() const
695 lyx::Assert(nonum_.size() == nrows());
696 lyx::Assert(label_.size() == nrows());