]> git.lyx.org Git - features.git/blob - src/mathed/InsetMathMacro.C
6db0b05e45f9c8fd0da6f4df842186f662fcf0f3
[features.git] / src / mathed / InsetMathMacro.C
1 /**
2  * \file InsetMathMacro.C
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  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetMathMacro.h"
15 #include "MathSupport.h"
16 #include "MathExtern.h"
17 #include "MathStream.h"
18
19 #include "buffer.h"
20 #include "cursor.h"
21 #include "debug.h"
22 #include "BufferView.h"
23 #include "LaTeXFeatures.h"
24 #include "frontends/Painter.h"
25
26
27 namespace lyx {
28
29 using std::string;
30 using std::max;
31 using std::auto_ptr;
32 using std::endl;
33 using std::vector;
34
35
36 /// This class is the value of a macro argument, technically 
37 /// a wrapper of the cells of MathMacro.
38 class MathMacroArgumentValue : public InsetMathDim {
39 public:
40         ///
41         MathMacroArgumentValue(MathArray const * value) : value_(value) {}
42         ///
43         bool metrics(MetricsInfo & mi, Dimension & dim) const;
44         ///
45         void draw(PainterInfo &, int x, int y) const;
46         
47 private:
48         std::auto_ptr<InsetBase> doClone() const;
49         MathArray const * value_;
50 };
51
52
53 auto_ptr<InsetBase> MathMacroArgumentValue::doClone() const 
54 {
55         return auto_ptr<InsetBase>(new MathMacroArgumentValue(*this));
56 }
57
58
59 bool MathMacroArgumentValue::metrics(MetricsInfo & mi, Dimension & dim) const 
60 {
61         value_->metrics(mi, dim);
62         metricsMarkers2(dim);
63         if (dim_ == dim)
64                 return false;
65         dim_ = dim;
66         return true;
67 }
68
69
70 void MathMacroArgumentValue::draw(PainterInfo & pi, int x, int y) const 
71 {
72         value_->draw(pi, x, y);
73 }
74
75
76
77 MathMacro::MathMacro(docstring const & name)
78         : InsetMathNest(0), name_(name)
79 {}
80
81
82 auto_ptr<InsetBase> MathMacro::doClone() const
83 {
84         return auto_ptr<InsetBase>(new MathMacro(*this));
85 }
86
87
88 docstring MathMacro::name() const
89 {
90         return name_;
91 }
92
93
94 void MathMacro::cursorPos(BufferView const & bv,
95                 CursorSlice const & sl, bool boundary, int & x, int & y) const
96 {
97         // We may have 0 arguments, but InsetMathNest requires at least one.
98         if (nargs() > 0)
99                 InsetMathNest::cursorPos(bv, sl, boundary, x, y);
100 }
101
102
103 bool MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
104 {
105         if (!MacroTable::globalMacros().has(name())) {
106                 mathed_string_dim(mi.base.font, "Unknown: " + name(), dim);
107         } else if (editing(mi.base.bv)) {
108                 // FIXME UNICODE
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);
113                 // FIXME UNICODE
114                 dim.wid += mathed_string_width(font, name()) + 10;
115                 // FIXME UNICODE
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);
119                         c.metrics(mi);
120                         dim.wid  = max(dim.wid, c.width() + ww);
121                         dim.des += c.height() + 10;
122                 }
123         } else {
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);
131         }
132         metricsMarkers2(dim);
133         if (dim_ == dim)
134                 return false;
135         dim_ = dim;
136         return true;
137 }
138
139
140 void MathMacro::draw(PainterInfo & pi, int x, int y) const
141 {
142         if (!MacroTable::globalMacros().has(name())) {
143                 // FIXME UNICODE
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();
153                 Dimension ldim;
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;
164                 }
165         } else {
166                 expanded_.draw(pi, x, y);
167         }
168         drawMarkers2(pi, x, y);
169 }
170
171
172 void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
173 {
174         // We may have 0 arguments, but InsetMathNest requires at least one.
175         if (nargs() > 0)
176                 InsetMathNest::drawSelection(pi, x, y);
177 }
178
179
180 void MathMacro::validate(LaTeXFeatures & features) const
181 {
182         if (name() == "binom" || name() == "mathcircumflex")
183                 features.require(to_utf8(name()));
184 }
185
186
187 InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
188 {
189         // We may have 0 arguments, but InsetMathNest requires at least one.
190         if (nargs() > 0) 
191                 return InsetMathNest::editXY(cur, x, y);
192         else 
193                 return this;
194 }
195
196
197 void MathMacro::detachArguments(std::vector<MathArray> &args)
198 {
199         args = cells_;
200         cells_ = std::vector<MathArray>();
201 }
202
203
204 void MathMacro::attachArguments(std::vector<MathArray> const &args)
205 {
206         cells_ = args;
207 }
208
209
210 bool MathMacro::idxFirst(LCursor & cur) const 
211 {
212         cur.updateFlags(Update::Force);
213         return InsetMathNest::idxFirst(cur);
214 }
215
216
217 bool MathMacro::idxLast(LCursor & cur) const 
218 {
219         cur.updateFlags(Update::Force);
220         return InsetMathNest::idxLast(cur);
221 }
222
223
224 bool MathMacro::notifyCursorLeaves(LCursor & cur)
225 {
226         cur.updateFlags(Update::Force);
227         return InsetMathNest::notifyCursorLeaves(cur);
228 }
229
230
231 void MathMacro::maple(MapleStream & os) const
232 {
233         lyx::maple(expanded_, os);
234 }
235
236
237 void MathMacro::mathmlize(MathStream & os) const
238 {
239         lyx::mathmlize(expanded_, os);
240 }
241
242
243 void MathMacro::octave(OctaveStream & os) const
244 {
245         lyx::octave(expanded_, os);
246 }
247
248
249 void MathMacro::infoize(odocstream & os) const
250 {
251         os << "Macro: " << name();
252 }
253
254
255 void MathMacro::infoize2(odocstream & os) const
256 {
257         os << "Macro: " << name();
258 }
259
260
261 } // namespace lyx