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
287 dim.des += displayMargin();
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);
299 dim.asc += displayMargin();
300 dim.des += displayMargin();
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);
1046 cur.message(old ? _("No number") : _("Number"));
1050 case LFUN_MATH_NONUMBER:
1052 recordUndoInset(cur);
1053 row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
1054 bool old = numbered(r);
1055 cur.message(old ? _("No number") : _("Number"));
1060 case LFUN_LABEL_INSERT: {
1061 recordUndoInset(cur);
1062 row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
1063 string old_label = label(r);
1064 string const default_label =
1065 (lyxrc.label_init_length >= 0) ? "eq:" : "";
1066 if (old_label.empty())
1067 old_label = default_label;
1068 string const contents = cmd.argument().empty() ?
1069 old_label : lyx::to_utf8(cmd.argument());
1071 InsetCommandParams p("label", contents);
1072 string const data = InsetCommandMailer::params2string("label", p);
1074 if (cmd.argument().empty())
1075 cur.bv().owner()->getDialogs().show("label", data, 0);
1077 FuncRequest fr(LFUN_INSET_INSERT, data);
1083 case LFUN_INSET_INSERT: {
1084 //lyxerr << "arg: " << lyx::to_utf8(cmd.argument()) << endl;
1085 string const name = cmd.getArg(0);
1086 if (name == "label") {
1087 InsetCommandParams p;
1088 InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()), p);
1089 string str = p.getContents();
1090 recordUndoInset(cur);
1091 row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
1092 str = lyx::support::trim(str);
1095 string old = label(r);
1097 cur.bv().buffer()->changeRefsIfUnique(old, str);
1103 if (createMathInset_fromDialogStr(lyx::to_utf8(cmd.argument()), ar)) {
1111 case LFUN_MATH_EXTERN:
1112 recordUndoInset(cur);
1116 case LFUN_MATH_MUTATE: {
1117 recordUndoInset(cur);
1118 row_type row = cur.row();
1119 col_type col = cur.col();
1120 mutate(hullType(lyx::to_utf8(cmd.argument())));
1121 cur.idx() = row * ncols() + col;
1122 if (cur.idx() > cur.lastidx()) {
1123 cur.idx() = cur.lastidx();
1124 cur.pos() = cur.lastpos();
1126 if (cur.pos() > cur.lastpos())
1127 cur.pos() = cur.lastpos();
1128 //cur.dispatched(FINISHED);
1132 case LFUN_MATH_DISPLAY: {
1133 recordUndoInset(cur);
1134 mutate(type_ == hullSimple ? hullEquation : hullSimple);
1136 cur.pos() = cur.lastpos();
1137 //cur.dispatched(FINISHED);
1142 MathGridInset::doDispatch(cur, cmd);
1148 bool MathHullInset::getStatus(LCursor & cur, FuncRequest const & cmd,
1149 FuncStatus & status) const
1151 switch (cmd.action) {
1152 case LFUN_FINISHED_LEFT:
1153 case LFUN_FINISHED_RIGHT:
1154 case LFUN_FINISHED_UP:
1155 case LFUN_FINISHED_DOWN:
1156 status.enabled(true);
1158 case LFUN_BREAK_LINE:
1159 case LFUN_MATH_NUMBER:
1160 case LFUN_MATH_NONUMBER:
1161 case LFUN_MATH_EXTERN:
1162 case LFUN_MATH_MUTATE:
1163 case LFUN_MATH_DISPLAY:
1165 status.enabled(true);
1167 case LFUN_LABEL_INSERT:
1168 status.enabled(type_ != hullSimple);
1170 case LFUN_INSET_INSERT: {
1171 // Don't test createMathInset_fromDialogStr(), since
1172 // getStatus is not called with a valid reference and the
1173 // dialog would not be applyable.
1174 string const name = cmd.getArg(0);
1175 status.enabled(name == "ref" ||
1176 (name == "label" && type_ != hullSimple));
1179 case LFUN_TABULAR_FEATURE: {
1180 istringstream is(lyx::to_utf8(cmd.argument()));
1184 && (s == "append-row"
1185 || s == "delete-row"
1186 || s == "copy-row")) {
1187 status.message(bformat(
1188 lyx::from_utf8(N_("Can't change number of rows in '%1$s'")),
1189 lyx::from_utf8(hullName(type_))));
1190 status.enabled(false);
1194 && (s == "append-column"
1195 || s == "delete-column"
1196 || s == "copy-column")) {
1197 status.message(bformat(
1198 lyx::from_utf8(N_("Can't change number of columns in '%1$s'")),
1199 lyx::from_utf8(hullName(type_))));
1200 status.enabled(false);
1203 if ((type_ == hullSimple
1204 || type_ == hullEquation
1205 || type_ == hullNone) &&
1206 (s == "add-hline-above" || s == "add-hline-below")) {
1207 status.message(bformat(
1208 lyx::from_utf8(N_("Can't add horizontal grid lines in '%1$s'")),
1209 lyx::from_utf8(hullName(type_))));
1210 status.enabled(false);
1213 if (s == "add-vline-left" || s == "add-vline-right") {
1214 status.message(bformat(
1215 lyx::from_utf8(N_("Can't add vertical grid lines in '%1$s'")),
1216 lyx::from_utf8(hullName(type_))));
1217 status.enabled(false);
1220 if (s == "valign-top" || s == "valign-middle"
1221 || s == "valign-bottom" || s == "align-left"
1222 || s == "align-center" || s == "align-right") {
1223 status.enabled(false);
1226 return MathGridInset::getStatus(cur, cmd, status);
1229 return MathGridInset::getStatus(cur, cmd, status);
1232 // This cannot really happen, but inserted to shut-up gcc
1233 return MathGridInset::getStatus(cur, cmd, status);
1237 /////////////////////////////////////////////////////////////////////
1239 #include "math_arrayinset.h"
1240 #include "math_deliminset.h"
1241 #include "math_factory.h"
1242 #include "math_parser.h"
1243 #include "math_spaceinset.h"
1244 #include "ref_inset.h"
1246 #include "bufferview_funcs.h"
1247 #include "lyxtext.h"
1249 #include "frontends/LyXView.h"
1250 #include "frontends/Dialogs.h"
1252 #include "support/lyxlib.h"
1255 // simply scrap this function if you want
1256 void MathHullInset::mutateToText()
1259 // translate to latex
1261 latex(NULL, os, false, false);
1262 string str = os.str();
1265 LyXText * lt = view_->getLyXText();
1266 string::const_iterator cit = str.begin();
1267 string::const_iterator end = str.end();
1268 for (; cit != end; ++cit)
1269 view_->owner()->getIntl()->getTransManager().TranslateAndInsert(*cit, lt);
1272 //view_->owner()->dispatch(LFUN_ESCAPE);
1277 void MathHullInset::handleFont(LCursor & cur, string const & arg,
1278 string const & font)
1280 // this whole function is a hack and won't work for incremental font
1283 if (cur.inset().asMathInset()->name() == font)
1284 cur.handleFont(font);
1286 cur.handleNest(createMathInset(font));
1292 void MathHullInset::handleFont2(LCursor & cur, string const & arg)
1297 bv_funcs::string2font(arg, font, b);
1298 if (font.color() != LColor::inherit) {
1299 MathAtom at = MathAtom(new MathColorInset(true, font.color()));
1300 cur.handleNest(at, 0);
1305 void MathHullInset::edit(LCursor & cur, bool left)
1308 left ? idxFirst(cur) : idxLast(cur);
1312 docstring const MathHullInset::editMessage() const
1314 return _("Math editor mode");
1318 void MathHullInset::revealCodes(LCursor & cur) const
1320 if (!cur.inMathed())
1324 cur.message(lyx::from_utf8(os.str()));
1326 // write something to the minibuffer
1327 // translate to latex
1331 string str = os.str();
1333 string::size_type pos = 0;
1335 for (string::iterator it = str.begin(); it != str.end(); ++it) {
1338 else if (*it == '\0') {
1340 pos = it - str.begin();
1346 res = res.substr(pos - 30);
1347 if (res.size() > 60)
1348 res = res.substr(0, 60);
1354 InsetBase::Code MathHullInset::lyxCode() const
1360 /////////////////////////////////////////////////////////////////////
1364 bool MathHullInset::searchForward(BufferView * bv, string const & str,
1367 #ifdef WITH_WARNINGS
1368 #warning completely broken
1370 static MathHullInset * lastformula = 0;
1371 static CursorBase current = DocIterator(ibegin(nucleus()));
1372 static MathArray ar;
1373 static string laststr;
1375 if (lastformula != this || laststr != str) {
1376 //lyxerr << "reset lastformula to " << this << endl;
1379 current = ibegin(nucleus());
1381 mathed_parse_cell(ar, str);
1385 //lyxerr << "searching '" << str << "' in " << this << ar << endl;
1387 for (DocIterator it = current; it != iend(nucleus()); increment(it)) {
1388 CursorSlice & top = it.back();
1389 MathArray const & a = top.asMathInset()->cell(top.idx_);
1390 if (a.matchpart(ar, top.pos_)) {
1391 bv->cursor().setSelection(it, ar.size());
1393 top.pos_ += ar.size();
1399 //lyxerr << "not found!" << endl;
1406 void MathHullInset::write(Buffer const &, std::ostream & os) const
1408 WriteStream wi(os, false, false);
1414 void MathHullInset::read(Buffer const &, LyXLex & lex)
1417 mathed_parse_normal(at, lex);
1418 operator=(*at->asHullInset());
1422 int MathHullInset::plaintext(Buffer const &, ostream & os,
1423 OutputParams const &) const
1425 if (0 && display()) {
1429 TextPainter tpain(dim.width(), dim.height());
1430 drawT(tpain, 0, dim.ascent());
1432 // reset metrics cache to "real" values
1434 return tpain.textheight();
1436 WriteStream wi(os, false, true);
1443 int MathHullInset::docbook(Buffer const & buf, ostream & os,
1444 OutputParams const & runparams) const
1446 MathMLStream ms(os);
1449 if (getType() == hullSimple)
1450 name = "inlineequation";
1452 name = "informalequation";
1454 string bname = name;
1455 if (!label(0).empty())
1456 bname += " id=\"" + sgml::cleanID(buf, runparams, label(0)) + "\"";
1457 ms << MTag(bname.c_str());
1460 if (runparams.flavor == OutputParams::XML) {
1461 ms << MTag("alt role=\"tex\" ");
1462 // Workaround for db2latex: db2latex always includes equations with
1463 // \ensuremath{} or \begin{display}\end{display}
1464 // so we strip LyX' math environment
1465 WriteStream wi(ls, false, false);
1466 MathGridInset::write(wi);
1467 ms << subst(subst(ls.str(), "&", "&"), "<", "<");
1470 MathGridInset::mathmlize(ms);
1473 ms << MTag("alt role=\"tex\"");
1474 res = latex(buf, ls, runparams);
1475 ms << subst(subst(ls.str(), "&", "&"), "<", "<");
1479 ms << "<graphic fileref=\"eqn/";
1480 if ( !label(0).empty())
1481 ms << sgml::cleanID(buf, runparams, label(0));
1483 ms << sgml::uniqueID("anon");
1485 if (runparams.flavor == OutputParams::XML)
1490 ms << ETag(name.c_str());
1491 return ms.line() + res;
1495 int MathHullInset::textString(Buffer const & buf, ostream & os,
1496 OutputParams const & op) const
1498 return plaintext(buf, os, op);