2 * \file math_hullinset.C
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
13 #include "math_charinset.h"
14 #include "math_colorinset.h"
15 #include "math_data.h"
16 #include "math_extern.h"
17 #include "math_factory.h"
18 #include "math_hullinset.h"
19 #include "math_mathmlstream.h"
20 #include "math_streamstr.h"
21 #include "math_support.h"
24 #include "bufferparams.h"
25 #include "BufferView.h"
26 #include "CutAndPaste.h"
27 #include "FuncStatus.h"
29 #include "LaTeXFeatures.h"
32 #include "dispatchresult.h"
33 #include "funcrequest.h"
37 #include "outputparams.h"
39 #include "textpainter.h"
42 #include "insets/render_preview.h"
43 #include "insets/insetlabel.h"
45 #include "frontends/Dialogs.h"
46 #include "frontends/LyXView.h"
48 #include "graphics/PreviewImage.h"
49 #include "graphics/PreviewLoader.h"
51 #include "support/lstrings.h"
53 #include <boost/bind.hpp>
58 using lyx::cap::grabAndEraseSelection;
59 using lyx::support::bformat;
60 using lyx::support::subst;
67 using std::istringstream;
69 using std::ostringstream;
77 int getCols(HullType type)
94 // returns position of first relation operator in the array
95 // used for "intelligent splitting"
96 size_t firstRelOp(MathArray const & ar)
98 for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it)
100 return it - ar.begin();
105 char const * star(bool numbered)
107 return numbered ? "" : "*";
111 } // end anon namespace
114 HullType hullType(std::string const & s)
116 if (s == "none") return hullNone;
117 if (s == "simple") return hullSimple;
118 if (s == "equation") return hullEquation;
119 if (s == "eqnarray") return hullEqnArray;
120 if (s == "align") return hullAlign;
121 if (s == "alignat") return hullAlignAt;
122 if (s == "xalignat") return hullXAlignAt;
123 if (s == "xxalignat") return hullXXAlignAt;
124 if (s == "multline") return hullMultline;
125 if (s == "gather") return hullGather;
126 if (s == "flalign") return hullFlAlign;
127 lyxerr << "unknown hull type '" << s << "'" << endl;
132 std::string hullName(HullType type)
135 case hullNone: return "none";
136 case hullSimple: return "simple";
137 case hullEquation: return "equation";
138 case hullEqnArray: return "eqnarray";
139 case hullAlign: return "align";
140 case hullAlignAt: return "alignat";
141 case hullXAlignAt: return "xalignat";
142 case hullXXAlignAt: return "xxalignat";
143 case hullMultline: return "multline";
144 case hullGather: return "gather";
145 case hullFlAlign: return "flalign";
147 lyxerr << "unknown hull type '" << type << "'" << endl;
153 MathHullInset::MathHullInset()
154 : MathGridInset(1, 1), type_(hullNone), nonum_(1), label_(1),
155 preview_(new RenderPreview(this))
157 //lyxerr << "sizeof MathInset: " << sizeof(MathInset) << endl;
158 //lyxerr << "sizeof MetricsInfo: " << sizeof(MetricsInfo) << endl;
159 //lyxerr << "sizeof MathCharInset: " << sizeof(MathCharInset) << endl;
160 //lyxerr << "sizeof LyXFont: " << sizeof(LyXFont) << endl;
166 MathHullInset::MathHullInset(HullType type)
167 : MathGridInset(getCols(type), 1), type_(type), nonum_(1), label_(1),
168 preview_(new RenderPreview(this))
175 MathHullInset::MathHullInset(MathHullInset const & other)
176 : MathGridInset(other),
177 type_(other.type_), nonum_(other.nonum_), label_(other.label_),
178 preview_(new RenderPreview(this))
182 MathHullInset::~MathHullInset()
186 auto_ptr<InsetBase> MathHullInset::doClone() const
188 return auto_ptr<InsetBase>(new MathHullInset(*this));
192 MathHullInset & MathHullInset::operator=(MathHullInset const & other)
196 *static_cast<MathGridInset*>(this) = MathGridInset(other);
198 nonum_ = other.nonum_;
199 label_ = other.label_;
200 preview_.reset(new RenderPreview(*other.preview_, this));
206 InsetBase * MathHullInset::editXY(LCursor & cur, int x, int y)
212 return MathNestInset::editXY(cur, x, y);
216 MathInset::mode_type MathHullInset::currentMode() const
218 if (type_ == hullNone)
219 return UNDECIDED_MODE;
220 // definitely math mode ...
225 bool MathHullInset::idxFirst(LCursor & cur) const
233 bool MathHullInset::idxLast(LCursor & cur) const
235 cur.idx() = nargs() - 1;
236 cur.pos() = cur.lastpos();
241 char MathHullInset::defaultColAlign(col_type col)
243 if (type_ == hullEqnArray)
245 if (type_ >= hullAlign)
246 return "rl"[col & 1];
251 int MathHullInset::defaultColSpace(col_type col)
253 if (type_ == hullAlign || type_ == hullAlignAt)
255 if (type_ == hullXAlignAt)
256 return (col & 1) ? 20 : 0;
257 if (type_ == hullXXAlignAt || type_ == hullFlAlign)
258 return (col & 1) ? 40 : 0;
263 char const * MathHullInset::standardFont() const
265 return type_ == hullNone ? "lyxnochange" : "mathnormal";
269 bool MathHullInset::previewState(BufferView * bv) const
271 if (!editing(bv) && RenderPreview::status() == LyXRC::PREVIEW_ON) {
272 lyx::graphics::PreviewImage const * pimage =
273 preview_->getPreviewImage(*bv->buffer());
274 return pimage && pimage->image();
280 void MathHullInset::metrics(MetricsInfo & mi, Dimension & dim) const
282 if (previewState(mi.base.bv)) {
283 preview_->metrics(mi, dim);
284 // insert a one pixel gap in front of the formula
292 FontSetChanger dummy1(mi.base, standardFont());
293 StyleChanger dummy2(mi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT);
295 // let the cells adjust themselves
296 MathGridInset::metrics(mi, dim);
303 if (numberedType()) {
304 FontSetChanger dummy(mi.base, "mathbf");
306 for (row_type row = 0; row < nrows(); ++row)
307 l = max(l, mathed_string_width(mi.base.font, nicelabel(row)));
313 // make it at least as high as the current font
316 math_font_max_dim(mi.base.font, asc, des);
317 dim.asc = max(dim.asc, asc);
318 dim.des = max(dim.des, des);
324 void MathHullInset::draw(PainterInfo & pi, int x, int y) const
326 use_preview_ = previewState(pi.base.bv);
329 // one pixel gap in front
330 preview_->draw(pi, x + 1, y);
331 setPosCache(pi, x, y);
335 FontSetChanger dummy1(pi.base, standardFont());
336 StyleChanger dummy2(pi.base, display() ? LM_ST_DISPLAY : LM_ST_TEXT);
337 MathGridInset::draw(pi, x + 1, y);
339 if (numberedType()) {
340 int const xx = x + colinfo_.back().offset_ + colinfo_.back().width_ + 20;
341 for (row_type row = 0; row < nrows(); ++row) {
342 int const yy = y + rowinfo_[row].offset_;
343 FontSetChanger dummy(pi.base, "mathrm");
344 string const nl = nicelabel(row);
345 docstring const dnl(nl.begin(), nl.end());
346 pi.draw(xx, yy, dnl);
349 setPosCache(pi, x, y);
353 void MathHullInset::metricsT(TextMetricsInfo const & mi, Dimension & dim) const
356 MathGridInset::metricsT(mi, dim);
359 WriteStream wi(os, false, true);
361 dim.wid = os.str().size();
368 void MathHullInset::drawT(TextPainter & pain, int x, int y) const
371 MathGridInset::drawT(pain, x, y);
374 WriteStream wi(os, false, true);
376 pain.draw(x, y, os.str().c_str());
383 string const latex_string(MathHullInset const & inset)
386 WriteStream wi(ls, false, false);
394 void MathHullInset::addPreview(lyx::graphics::PreviewLoader & ploader) const
396 if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
397 string const snippet = latex_string(*this);
398 preview_->addPreview(snippet, ploader);
403 bool MathHullInset::notifyCursorLeaves(LCursor & cur)
405 if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
406 Buffer const & buffer = cur.buffer();
407 string const snippet = latex_string(*this);
408 preview_->addPreview(snippet, buffer);
409 preview_->startLoading(buffer);
415 string MathHullInset::label(row_type row) const
417 BOOST_ASSERT(row < nrows());
422 void MathHullInset::label(row_type row, string const & label)
424 //lyxerr << "setting label '" << label << "' for row " << row << endl;
429 void MathHullInset::numbered(row_type row, bool num)
435 bool MathHullInset::numbered(row_type row) const
441 bool MathHullInset::ams() const
444 type_ == hullAlign ||
445 type_ == hullFlAlign ||
446 type_ == hullMultline ||
447 type_ == hullGather ||
448 type_ == hullAlignAt ||
449 type_ == hullXAlignAt ||
450 type_ == hullXXAlignAt;
454 bool MathHullInset::display() const
456 return type_ != hullSimple && type_ != hullNone;
460 void MathHullInset::getLabelList(Buffer const &, vector<string> & labels) const
462 for (row_type row = 0; row < nrows(); ++row)
463 if (!label_[row].empty() && nonum_[row] != 1)
464 labels.push_back(label_[row]);
468 bool MathHullInset::numberedType() const
470 if (type_ == hullNone)
472 if (type_ == hullSimple)
474 if (type_ == hullXXAlignAt)
476 for (row_type row = 0; row < nrows(); ++row)
483 void MathHullInset::validate(LaTeXFeatures & features) const
486 features.require("amsmath");
489 // Validation is necessary only if not using AMS math.
490 // To be safe, we will always run mathedvalidate.
491 //if (features.amsstyle)
494 features.require("boldsymbol");
495 //features.binom = true;
497 MathGridInset::validate(features);
501 void MathHullInset::header_write(WriteStream & os) const
503 bool n = numberedType();
505 if (type_ == hullNone)
508 else if (type_ == hullSimple) {
514 else if (type_ == hullEquation) {
516 os << "\\begin{equation" << star(n) << "}\n";
521 else if (type_ == hullEqnArray || type_ == hullAlign || type_ ==
523 || type_ == hullGather || type_ == hullMultline)
524 os << "\\begin{" << type_ << star(n) << "}\n";
526 else if (type_ == hullAlignAt || type_ == hullXAlignAt)
527 os << "\\begin{" << type_ << star(n) << '}'
528 << '{' << static_cast<unsigned int>((ncols() + 1)/2) << "}\n";
530 else if (type_ == hullXXAlignAt)
531 os << "\\begin{" << type_ << '}'
532 << '{' << static_cast<unsigned int>((ncols() + 1)/2) << "}\n";
535 os << "\\begin{unknown" << star(n) << '}';
539 void MathHullInset::footer_write(WriteStream & os) const
541 bool n = numberedType();
543 if (type_ == hullNone)
546 else if (type_ == hullSimple)
549 else if (type_ == hullEquation)
551 os << "\\end{equation" << star(n) << "}\n";
555 else if (type_ == hullEqnArray || type_ == hullAlign || type_ ==
557 || type_ == hullAlignAt || type_ == hullXAlignAt
558 || type_ == hullGather || type_ == hullMultline)
559 os << "\\end{" << type_ << star(n) << "}\n";
561 else if (type_ == hullXXAlignAt)
562 os << "\\end{" << type_ << "}\n";
565 os << "\\end{unknown" << star(n) << '}';
569 bool MathHullInset::rowChangeOK() const
572 type_ == hullEqnArray || type_ == hullAlign ||
573 type_ == hullFlAlign || type_ == hullAlignAt ||
574 type_ == hullXAlignAt || type_ == hullXXAlignAt ||
575 type_ == hullGather || type_ == hullMultline;
579 bool MathHullInset::colChangeOK() const
582 type_ == hullAlign || type_ == hullFlAlign ||type_ == hullAlignAt ||
583 type_ == hullXAlignAt || type_ == hullXXAlignAt;
587 void MathHullInset::addRow(row_type row)
591 nonum_.insert(nonum_.begin() + row + 1, !numberedType());
592 label_.insert(label_.begin() + row + 1, string());
593 MathGridInset::addRow(row);
597 void MathHullInset::swapRow(row_type row)
601 if (row + 1 == nrows())
603 swap(nonum_[row], nonum_[row + 1]);
604 swap(label_[row], label_[row + 1]);
605 MathGridInset::swapRow(row);
609 void MathHullInset::delRow(row_type row)
611 if (nrows() <= 1 || !rowChangeOK())
613 MathGridInset::delRow(row);
614 // The last dummy row has no number info nor a label.
615 // Test nrows() + 1 because we have already erased the row.
616 if (row == nrows() + 1)
618 nonum_.erase(nonum_.begin() + row);
619 label_.erase(label_.begin() + row);
623 void MathHullInset::addCol(col_type col)
627 MathGridInset::addCol(col);
631 void MathHullInset::delCol(col_type col)
633 if (ncols() <= 1 || !colChangeOK())
635 MathGridInset::delCol(col);
639 string MathHullInset::nicelabel(row_type row) const
643 if (label_[row].empty())
644 return string("(#)");
645 return '(' + label_[row] + ')';
649 void MathHullInset::glueall()
652 for (idx_type i = 0; i < nargs(); ++i)
654 *this = MathHullInset(hullSimple);
660 void MathHullInset::splitTo2Cols()
662 BOOST_ASSERT(ncols() == 1);
663 MathGridInset::addCol(1);
664 for (row_type row = 0; row < nrows(); ++row) {
665 idx_type const i = 2 * row;
666 pos_type pos = firstRelOp(cell(i));
667 cell(i + 1) = MathArray(cell(i).begin() + pos, cell(i).end());
668 cell(i).erase(pos, cell(i).size());
673 void MathHullInset::splitTo3Cols()
675 BOOST_ASSERT(ncols() < 3);
678 MathGridInset::addCol(1);
679 for (row_type row = 0; row < nrows(); ++row) {
680 idx_type const i = 3 * row + 1;
681 if (cell(i).size()) {
682 cell(i + 1) = MathArray(cell(i).begin() + 1, cell(i).end());
683 cell(i).erase(1, cell(i).size());
689 void MathHullInset::changeCols(col_type cols)
693 else if (ncols() < cols) {
699 while (ncols() < cols)
700 MathGridInset::addCol(ncols() - 1);
706 for (row_type row = 0; row < nrows(); ++row) {
707 idx_type const i = row * ncols();
708 for (col_type col = cols; col < ncols(); ++col) {
709 cell(i + cols - 1).append(cell(i + col));
713 while (ncols() > cols) {
714 MathGridInset::delCol(ncols() - 1);
719 HullType MathHullInset::getType() const
725 void MathHullInset::setType(HullType type)
732 void MathHullInset::mutate(HullType newtype)
734 //lyxerr << "mutating from '" << type_ << "' to '" << newtype << "'" << endl;
736 // we try to move along the chain
737 // none <-> simple <-> equation <-> eqnarray -> *align* -> multline, gather -+
739 // +-------------------------------------+
740 // we use eqnarray as intermediate type for mutations that are not
741 // directly supported because it handles labels and numbering for
744 if (newtype == type_) {
748 else if (newtype < hullNone) {
753 else if (type_ == hullNone) {
759 else if (type_ == hullSimple) {
760 if (newtype == hullNone) {
764 setType(hullEquation);
770 else if (type_ == hullEquation) {
771 if (newtype < type_) {
775 } else if (newtype == hullEqnArray) {
776 // split it "nicely" on the first relop
778 setType(hullEqnArray);
779 } else if (newtype == hullMultline || newtype == hullGather) {
789 else if (type_ == hullEqnArray) {
790 if (newtype < type_) {
791 // set correct (no)numbering
792 bool allnonum = true;
793 for (row_type row = 0; row < nrows(); ++row)
797 // set first non-empty label
799 for (row_type row = 0; row < nrows(); ++row) {
800 if (!label_[row].empty()) {
807 nonum_[0] = allnonum;
810 } else { // align & Co.
817 else if (type_ == hullAlign || type_ == hullAlignAt ||
818 type_ == hullXAlignAt || type_ == hullFlAlign) {
819 if (newtype < hullAlign) {
821 setType(hullEqnArray);
823 } else if (newtype == hullGather || newtype == hullMultline) {
826 } else if (newtype == hullXXAlignAt) {
827 for (row_type row = 0; row < nrows(); ++row)
828 numbered(row, false);
835 else if (type_ == hullXXAlignAt) {
836 for (row_type row = 0; row < nrows(); ++row)
837 numbered(row, false);
838 if (newtype < hullAlign) {
840 setType(hullEqnArray);
842 } else if (newtype == hullGather || newtype == hullMultline) {
850 else if (type_ == hullMultline || type_ == hullGather) {
851 if (newtype == hullGather || newtype == hullMultline)
853 else if (newtype == hullAlign || newtype == hullFlAlign ||
854 newtype == hullAlignAt || newtype == hullXAlignAt) {
857 } else if (newtype == hullXXAlignAt) {
859 for (row_type row = 0; row < nrows(); ++row)
860 numbered(row, false);
864 setType(hullEqnArray);
870 lyxerr << "mutation from '" << type_
871 << "' to '" << newtype << "' not implemented" << endl;
876 string MathHullInset::eolString(row_type row, bool emptyline, bool fragile) const
879 if (numberedType()) {
880 if (!label_[row].empty() && !nonum_[row])
881 res += "\\label{" + label_[row] + '}';
882 if (nonum_[row] && (type_ != hullMultline))
883 res += "\\nonumber ";
885 return res + MathGridInset::eolString(row, emptyline, fragile);
889 void MathHullInset::write(WriteStream & os) const
892 MathGridInset::write(os);
897 void MathHullInset::normalize(NormalStream & os) const
899 os << "[formula " << type_ << ' ';
900 MathGridInset::normalize(os);
905 void MathHullInset::mathmlize(MathMLStream & os) const
907 MathGridInset::mathmlize(os);
911 void MathHullInset::infoize(ostream & os) const
913 os << "Type: " << type_;
917 void MathHullInset::check() const
919 BOOST_ASSERT(nonum_.size() == nrows());
920 BOOST_ASSERT(label_.size() == nrows());
924 void MathHullInset::doExtern(LCursor & cur, FuncRequest & func)
928 istringstream iss(lyx::to_utf8(func.argument()));
929 iss >> lang >> extra;
934 #warning temporarily disabled
935 //if (cur.selection()) {
938 // lyxerr << "use selection: " << ar << endl;
939 // insert(pipeThroughExtern(lang, extra, ar));
945 eq.push_back(MathAtom(new MathCharInset('=')));
947 // go to first item in line
948 cur.idx() -= cur.idx() % ncols();
951 if (getType() == hullSimple) {
952 size_type pos = cur.cell().find_last(eq);
954 if (cur.inMathed() && cur.selection()) {
955 asArray(grabAndEraseSelection(cur), ar);
956 } else if (pos == cur.cell().size()) {
958 lyxerr << "use whole cell: " << ar << endl;
960 ar = MathArray(cur.cell().begin() + pos + 1, cur.cell().end());
961 lyxerr << "use partial cell form pos: " << pos << endl;
963 cur.cell().append(eq);
964 cur.cell().append(pipeThroughExtern(lang, extra, ar));
965 cur.pos() = cur.lastpos();
969 if (getType() == hullEquation) {
970 lyxerr << "use equation inset" << endl;
971 mutate(hullEqnArray);
972 MathArray & ar = cur.cell();
973 lyxerr << "use cell: " << ar << endl;
977 cur.cell() = pipeThroughExtern(lang, extra, ar);
978 // move to end of line
979 cur.pos() = cur.lastpos();
984 lyxerr << "use eqnarray" << endl;
985 cur.idx() += 2 - cur.idx() % ncols();
987 MathArray ar = cur.cell();
988 lyxerr << "use cell: " << ar << endl;
990 #warning temporarily disabled
997 cur.cell() = pipeThroughExtern(lang, extra, ar);
998 cur.pos() = cur.lastpos();
1003 void MathHullInset::doDispatch(LCursor & cur, FuncRequest & cmd)
1005 //lyxerr << "action: " << cmd.action << endl;
1006 switch (cmd.action) {
1008 case LFUN_FINISHED_LEFT:
1009 case LFUN_FINISHED_RIGHT:
1010 case LFUN_FINISHED_UP:
1011 case LFUN_FINISHED_DOWN:
1012 //lyxerr << "action: " << cmd.action << endl;
1013 MathGridInset::doDispatch(cur, cmd);
1014 notifyCursorLeaves(cur);
1018 case LFUN_BREAK_PARAGRAPH:
1019 // just swallow this
1022 case LFUN_BREAK_LINE:
1023 // some magic for the common case
1024 if (type_ == hullSimple || type_ == hullEquation) {
1025 recordUndoInset(cur);
1027 cur.bv().buffer()->params().use_amsmath == BufferParams::AMS_ON;
1028 mutate(align ? hullAlign : hullEqnArray);
1030 cur.pos() = cur.lastpos();
1032 MathGridInset::doDispatch(cur, cmd);
1035 case LFUN_MATH_NUMBER:
1036 //lyxerr << "toggling all numbers" << endl;
1038 recordUndoInset(cur);
1039 bool old = numberedType();
1040 if (type_ == hullMultline)
1041 numbered(nrows() - 1, !old);
1043 for (row_type row = 0; row < nrows(); ++row)
1044 numbered(row, !old);
1045 cur.message(old ? _("No number") : _("Number"));
1049 case LFUN_MATH_NONUMBER:
1051 recordUndoInset(cur);
1052 row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
1053 bool old = numbered(r);
1054 cur.message(old ? _("No number") : _("Number"));
1059 case LFUN_LABEL_INSERT: {
1060 recordUndoInset(cur);
1061 row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
1062 string old_label = label(r);
1063 string const default_label =
1064 (lyxrc.label_init_length >= 0) ? "eq:" : "";
1065 if (old_label.empty())
1066 old_label = default_label;
1067 string const contents = cmd.argument().empty() ?
1068 old_label : lyx::to_utf8(cmd.argument());
1070 InsetCommandParams p("label", contents);
1071 string const data = InsetCommandMailer::params2string("label", p);
1073 if (cmd.argument().empty())
1074 cur.bv().owner()->getDialogs().show("label", data, 0);
1076 FuncRequest fr(LFUN_INSET_INSERT, data);
1082 case LFUN_INSET_INSERT: {
1083 //lyxerr << "arg: " << lyx::to_utf8(cmd.argument()) << endl;
1084 string const name = cmd.getArg(0);
1085 if (name == "label") {
1086 InsetCommandParams p;
1087 InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()), p);
1088 string str = p.getContents();
1089 recordUndoInset(cur);
1090 row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
1091 str = lyx::support::trim(str);
1094 string old = label(r);
1096 cur.bv().buffer()->changeRefsIfUnique(old, str);
1102 if (createMathInset_fromDialogStr(lyx::to_utf8(cmd.argument()), ar)) {
1110 case LFUN_MATH_EXTERN:
1111 recordUndoInset(cur);
1115 case LFUN_MATH_MUTATE: {
1116 recordUndoInset(cur);
1117 row_type row = cur.row();
1118 col_type col = cur.col();
1119 mutate(hullType(lyx::to_utf8(cmd.argument())));
1120 cur.idx() = row * ncols() + col;
1121 if (cur.idx() > cur.lastidx()) {
1122 cur.idx() = cur.lastidx();
1123 cur.pos() = cur.lastpos();
1125 if (cur.pos() > cur.lastpos())
1126 cur.pos() = cur.lastpos();
1127 //cur.dispatched(FINISHED);
1131 case LFUN_MATH_DISPLAY: {
1132 recordUndoInset(cur);
1133 mutate(type_ == hullSimple ? hullEquation : hullSimple);
1135 cur.pos() = cur.lastpos();
1136 //cur.dispatched(FINISHED);
1141 MathGridInset::doDispatch(cur, cmd);
1147 bool MathHullInset::getStatus(LCursor & cur, FuncRequest const & cmd,
1148 FuncStatus & status) const
1150 switch (cmd.action) {
1151 case LFUN_FINISHED_LEFT:
1152 case LFUN_FINISHED_RIGHT:
1153 case LFUN_FINISHED_UP:
1154 case LFUN_FINISHED_DOWN:
1155 status.enabled(true);
1157 case LFUN_BREAK_LINE:
1158 case LFUN_MATH_NUMBER:
1159 case LFUN_MATH_NONUMBER:
1160 case LFUN_MATH_EXTERN:
1161 case LFUN_MATH_MUTATE:
1162 case LFUN_MATH_DISPLAY:
1164 status.enabled(true);
1166 case LFUN_LABEL_INSERT:
1167 status.enabled(type_ != hullSimple);
1169 case LFUN_INSET_INSERT: {
1170 // Don't test createMathInset_fromDialogStr(), since
1171 // getStatus is not called with a valid reference and the
1172 // dialog would not be applyable.
1173 string const name = cmd.getArg(0);
1174 status.enabled(name == "ref" ||
1175 (name == "label" && type_ != hullSimple));
1178 case LFUN_TABULAR_FEATURE: {
1179 istringstream is(lyx::to_utf8(cmd.argument()));
1183 && (s == "append-row"
1184 || s == "delete-row"
1185 || s == "copy-row")) {
1186 status.message(bformat(
1187 N_("Can't change number of rows in '%1$s'"),
1189 status.enabled(false);
1193 && (s == "append-column"
1194 || s == "delete-column"
1195 || s == "copy-column")) {
1196 status.message(bformat(
1197 N_("Can't change number of columns in '%1$s'"),
1199 status.enabled(false);
1202 if ((type_ == hullSimple
1203 || type_ == hullEquation
1204 || type_ == hullNone) &&
1205 (s == "add-hline-above" || s == "add-hline-below")) {
1206 status.message(bformat(
1207 N_("Can't add horizontal grid lines in '%1$s'"),
1209 status.enabled(false);
1212 if (s == "add-vline-left" || s == "add-vline-right") {
1213 status.message(bformat(
1214 N_("Can't add vertical grid lines in '%1$s'"),
1216 status.enabled(false);
1219 if (s == "valign-top" || s == "valign-middle"
1220 || s == "valign-bottom" || s == "align-left"
1221 || s == "align-center" || s == "align-right") {
1222 status.enabled(false);
1225 return MathGridInset::getStatus(cur, cmd, status);
1228 return MathGridInset::getStatus(cur, cmd, status);
1231 // This cannot really happen, but inserted to shut-up gcc
1232 return MathGridInset::getStatus(cur, cmd, status);
1236 /////////////////////////////////////////////////////////////////////
1238 #include "math_arrayinset.h"
1239 #include "math_deliminset.h"
1240 #include "math_factory.h"
1241 #include "math_parser.h"
1242 #include "math_spaceinset.h"
1243 #include "ref_inset.h"
1245 #include "bufferview_funcs.h"
1246 #include "lyxtext.h"
1248 #include "frontends/LyXView.h"
1249 #include "frontends/Dialogs.h"
1251 #include "support/lyxlib.h"
1254 // simply scrap this function if you want
1255 void MathHullInset::mutateToText()
1258 // translate to latex
1260 latex(NULL, os, false, false);
1261 string str = os.str();
1264 LyXText * lt = view_->getLyXText();
1265 string::const_iterator cit = str.begin();
1266 string::const_iterator end = str.end();
1267 for (; cit != end; ++cit)
1268 view_->owner()->getIntl()->getTransManager().TranslateAndInsert(*cit, lt);
1271 //view_->owner()->dispatch(LFUN_ESCAPE);
1276 void MathHullInset::handleFont(LCursor & cur, string const & arg,
1277 string const & font)
1279 // this whole function is a hack and won't work for incremental font
1282 if (cur.inset().asMathInset()->name() == font)
1283 cur.handleFont(font);
1285 cur.handleNest(createMathInset(font));
1291 void MathHullInset::handleFont2(LCursor & cur, string const & arg)
1296 bv_funcs::string2font(arg, font, b);
1297 if (font.color() != LColor::inherit) {
1298 MathAtom at = MathAtom(new MathColorInset(true, font.color()));
1299 cur.handleNest(at, 0);
1304 void MathHullInset::edit(LCursor & cur, bool left)
1307 left ? idxFirst(cur) : idxLast(cur);
1311 string const MathHullInset::editMessage() const
1313 return _("Math editor mode");
1317 void MathHullInset::revealCodes(LCursor & cur) const
1319 if (!cur.inMathed())
1323 cur.message(os.str());
1325 // write something to the minibuffer
1326 // translate to latex
1330 string str = os.str();
1332 string::size_type pos = 0;
1334 for (string::iterator it = str.begin(); it != str.end(); ++it) {
1337 else if (*it == '\0') {
1339 pos = it - str.begin();
1345 res = res.substr(pos - 30);
1346 if (res.size() > 60)
1347 res = res.substr(0, 60);
1353 InsetBase::Code MathHullInset::lyxCode() const
1359 /////////////////////////////////////////////////////////////////////
1363 bool MathHullInset::searchForward(BufferView * bv, string const & str,
1366 #ifdef WITH_WARNINGS
1367 #warning completely broken
1369 static MathHullInset * lastformula = 0;
1370 static CursorBase current = DocIterator(ibegin(nucleus()));
1371 static MathArray ar;
1372 static string laststr;
1374 if (lastformula != this || laststr != str) {
1375 //lyxerr << "reset lastformula to " << this << endl;
1378 current = ibegin(nucleus());
1380 mathed_parse_cell(ar, str);
1384 //lyxerr << "searching '" << str << "' in " << this << ar << endl;
1386 for (DocIterator it = current; it != iend(nucleus()); increment(it)) {
1387 CursorSlice & top = it.back();
1388 MathArray const & a = top.asMathInset()->cell(top.idx_);
1389 if (a.matchpart(ar, top.pos_)) {
1390 bv->cursor().setSelection(it, ar.size());
1392 top.pos_ += ar.size();
1398 //lyxerr << "not found!" << endl;
1405 void MathHullInset::write(Buffer const &, std::ostream & os) const
1407 WriteStream wi(os, false, false);
1413 void MathHullInset::read(Buffer const &, LyXLex & lex)
1416 mathed_parse_normal(at, lex);
1417 operator=(*at->asHullInset());
1421 int MathHullInset::plaintext(Buffer const &, ostream & os,
1422 OutputParams const &) const
1424 if (0 && display()) {
1428 TextPainter tpain(dim.width(), dim.height());
1429 drawT(tpain, 0, dim.ascent());
1431 // reset metrics cache to "real" values
1433 return tpain.textheight();
1435 WriteStream wi(os, false, true);
1442 int MathHullInset::docbook(Buffer const & buf, ostream & os,
1443 OutputParams const & runparams) const
1445 MathMLStream ms(os);
1448 if (getType() == hullSimple)
1449 name = "inlineequation";
1451 name = "informalequation";
1453 string bname = name;
1454 if (!label(0).empty())
1455 bname += " id=\"" + sgml::cleanID(buf, runparams, label(0)) + "\"";
1456 ms << MTag(bname.c_str());
1459 if (runparams.flavor == OutputParams::XML) {
1460 ms << MTag("alt role=\"tex\" ");
1461 // Workaround for db2latex: db2latex always includes equations with
1462 // \ensuremath{} or \begin{display}\end{display}
1463 // so we strip LyX' math environment
1464 WriteStream wi(ls, false, false);
1465 MathGridInset::write(wi);
1466 ms << subst(subst(ls.str(), "&", "&"), "<", "<");
1469 MathGridInset::mathmlize(ms);
1472 ms << MTag("alt role=\"tex\"");
1473 res = latex(buf, ls, runparams);
1474 ms << subst(subst(ls.str(), "&", "&"), "<", "<");
1478 ms << "<graphic fileref=\"eqn/";
1479 if ( !label(0).empty())
1480 ms << sgml::cleanID(buf, runparams, label(0));
1482 ms << sgml::uniqueID("anon");
1484 if (runparams.flavor == OutputParams::XML)
1489 ms << ETag(name.c_str());
1490 return ms.line() + res;
1494 int MathHullInset::textString(Buffer const & buf, ostream & os,
1495 OutputParams const & op) const
1497 return plaintext(buf, os, op);