2 * \file InsetMathMacro.C
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alejandro Aguilar Sierra
9 * Full author contact details are available in file CREDITS.
14 #include "InsetMathMacro.h"
15 #include "MathSupport.h"
16 #include "MathExtern.h"
17 #include "MathStream.h"
22 #include "BufferView.h"
23 #include "LaTeXFeatures.h"
24 #include "frontends/Painter.h"
36 /// This class is the value of a macro argument, technically
37 /// a wrapper of the cells of MathMacro.
38 class MathMacroArgumentValue : public InsetMathDim {
41 MathMacroArgumentValue(MathArray const * value) : value_(value) {}
43 bool metrics(MetricsInfo & mi, Dimension & dim) const;
45 void draw(PainterInfo &, int x, int y) const;
48 std::auto_ptr<InsetBase> doClone() const;
49 MathArray const * value_;
53 auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const
55 return auto_ptr<InsetBase>(new MathMacroArgumentValue(*this));
59 bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const
61 value_->metrics(mi, dim);
70 void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const
72 value_->draw(pi, x, y);
77 MathMacro::MathMacro(docstring const & name)
78 : InsetMathNest(0), name_(name)
82 auto_ptr<InsetBase> MathMacro::doClone() const
84 return auto_ptr<InsetBase>(new MathMacro(*this));
88 docstring MathMacro::name() const
94 void MathMacro::cursorPos(BufferView const & bv,
95 CursorSlice const & sl, bool boundary, int & x, int & y) const
97 // We may have 0 arguments, but InsetMathNest requires at least one.
99 InsetMathNest::cursorPos(bv, sl, boundary, x, y);
103 bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
105 if (!MacroTable::globalMacros().has(name())) {
106 mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
107 } else if (editing(mi.base.bv)) {
109 asArray(MacroTable::globalMacros().get(name()).def(), tmpl_);
110 LyXFont font = mi.base.font;
111 augmentFont(font, from_ascii("lyxtex"));
112 tmpl_.metrics(mi, dim);
114 dim.wid += mathed_string_width(font, name()) + 10;
116 int ww = mathed_string_width(font, from_ascii("#1: "));
117 for (idx_type i = 0; i < nargs(); ++i) {
118 MathArray const & c = cell(i);
120 dim.wid = max(dim.wid, c.width() + ww);
121 dim.des += c.height() + 10;
124 // create MathMacroArgumentValue object pointing to the cells of the macro
125 MacroData const & macro = MacroTable::globalMacros().get(name());
126 vector<MathArray> values(nargs());
127 for (size_t i = 0; i != nargs(); ++i)
128 values[i].insert(0, MathAtom(new MathMacroArgumentValue(&cells_[i])));
129 macro.expand(values, expanded_);
130 expanded_.metrics(mi, dim);
132 metricsMarkers2(dim);
140 void MathMacro::draw(PainterInfo & pi, int x, int y) const
142 if (!MacroTable::globalMacros().has(name())) {
144 drawStrRed(pi, x, y, "Unknown: " + name());
145 } else if (editing(pi.base.bv)) {
146 LyXFont font = pi.base.font;
147 augmentFont(font, from_ascii("lyxtex"));
148 int h = y - dim_.ascent() + 2 + tmpl_.ascent();
149 pi.pain.text(x + 3, h, name(), font);
150 int const w = mathed_string_width(font, name());
151 tmpl_.draw(pi, x + w + 12, h);
152 h += tmpl_.descent();
154 docstring t = from_ascii("#1: ");
155 mathed_string_dim(font, t, ldim);
156 for (idx_type i = 0; i < nargs(); ++i) {
157 MathArray const & c = cell(i);
158 h += max(c.ascent(), ldim.asc) + 5;
159 c.draw(pi, x + ldim.wid, h);
160 char_type str[] = { '#', '1', ':', '\0' };
161 str[1] += static_cast<char_type>(i);
162 pi.pain.text(x + 3, h, str, font);
163 h += max(c.descent(), ldim.des) + 5;
166 expanded_.draw(pi, x, y);
168 drawMarkers2(pi, x, y);
172 void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
174 // We may have 0 arguments, but InsetMathNest requires at least one.
176 InsetMathNest::drawSelection(pi, x, y);
180 void MathMacro::validate(LaTeXFeatures & features) const
182 if (name() == "binom" || name() == "mathcircumflex")
183 features.require(to_utf8(name()));
187 InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
189 // We may have 0 arguments, but InsetMathNest requires at least one.
191 return InsetMathNest::editXY(cur, x, y);
197 void MathMacro::detachArguments(std::vector<MathArray> &args)
200 cells_ = std::vector<MathArray>();
204 void MathMacro::attachArguments(std::vector<MathArray> const &args)
210 bool MathMacro::idxFirst(LCursor & cur) const
212 cur.updateFlags(Update::Force);
213 return InsetMathNest::idxFirst(cur);
217 bool MathMacro::idxLast(LCursor & cur) const
219 cur.updateFlags(Update::Force);
220 return InsetMathNest::idxLast(cur);
224 bool MathMacro::notifyCursorLeaves(LCursor & cur)
226 cur.updateFlags(Update::Force);
227 return InsetMathNest::notifyCursorLeaves(cur);
231 void MathMacro::maple(MapleStream & os) const
233 lyx::maple(expanded_, os);
237 void MathMacro::mathmlize(MathStream & os) const
239 lyx::mathmlize(expanded_, os);
243 void MathMacro::octave(OctaveStream & os) const
245 lyx::octave(expanded_, os);
249 void MathMacro::infoize(odocstream & os) const
251 os << "Macro: " << name();
255 void MathMacro::infoize2(odocstream & os) const
257 os << "Macro: " << name();