]> git.lyx.org Git - lyx.git/blob - src/mathed/MathMacroTemplate.cpp
* up/down jumps between macro parameters
[lyx.git] / src / mathed / MathMacroTemplate.cpp
1 /**
2  * \file math_macrotemplate.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "MathMacroTemplate.h"
14 #include "MathStream.h"
15 #include "MathParser.h"
16 #include "MathSupport.h"
17
18 #include "Buffer.h"
19 #include "Cursor.h"
20 #include "debug.h"
21 #include "gettext.h"
22 #include "Lexer.h"
23 #include "Color.h"
24
25 #include "frontends/FontMetrics.h"
26 #include "frontends/Painter.h"
27
28 #include "support/lstrings.h"
29
30
31 namespace lyx {
32
33 using support::bformat;
34
35 using std::auto_ptr;
36 using std::ostream;
37 using std::endl;
38
39
40 MathMacroTemplate::MathMacroTemplate()
41         : InsetMathNest(2), numargs_(0), name_(), type_(from_ascii("newcommand"))
42 {
43         initMath();
44 }
45
46
47 MathMacroTemplate::MathMacroTemplate(docstring const & name, int numargs,
48                 docstring const & type, MathData const & ar1, MathData const & ar2)
49         : InsetMathNest(2), numargs_(numargs), name_(name), type_(type)
50 {
51         initMath();
52
53         if (numargs_ > 9)
54                 lyxerr << "MathMacroTemplate::MathMacroTemplate: wrong # of arguments: "
55                         << numargs_ << std::endl;
56         cell(0) = ar1;
57         cell(1) = ar2;
58 }
59
60
61 MathMacroTemplate::MathMacroTemplate(docstring const & str)
62         : InsetMathNest(2), numargs_(0), name_()
63 {
64         initMath();
65
66         MathData ar;
67         mathed_parse_cell(ar, str);
68         if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
69                 lyxerr << "Cannot read macro from '" << ar << "'" << endl;
70                 return;
71         }
72         operator=( *(ar[0]->asMacroTemplate()) );
73 }
74
75
76 auto_ptr<Inset> MathMacroTemplate::doClone() const
77 {
78         return auto_ptr<Inset>(new MathMacroTemplate(*this));
79 }
80
81
82 void MathMacroTemplate::edit(Cursor & cur, bool)
83 {
84         //lyxerr << "MathMacroTemplate: edit left/right" << endl;
85         cur.push(*this);
86 }
87
88
89 int MathMacroTemplate::numargs() const
90 {
91         return numargs_;
92 }
93
94
95 void MathMacroTemplate::numargs(int numargs)
96 {
97         numargs_ = numargs;
98 }
99
100
101 docstring MathMacroTemplate::name() const
102 {
103         return name_;
104 }
105
106
107 docstring MathMacroTemplate::prefix() const
108 {
109         return bformat(_(" Macro: %1$s: "), name_);
110 }
111
112
113 bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
114 {
115         bool lockMacro = MacroTable::globalMacros().has(name_);
116         if (lockMacro)
117                 MacroTable::globalMacros().get(name_).lock();
118
119         cell(0).metrics(mi);
120         cell(1).metrics(mi);
121         docstring dp = prefix();
122         dim.wid = cell(0).width() + cell(1).width() + 20
123                 + theFontMetrics(mi.base.font).width(dp);
124         dim.asc = std::max(cell(0).ascent(),  cell(1).ascent())  + 7;
125         dim.des = std::max(cell(0).descent(), cell(1).descent()) + 7;
126
127         if (lockMacro)
128                 MacroTable::globalMacros().get(name_).unlock();
129
130         if (dim_ == dim)
131                 return false;
132         dim_ = dim;
133         return true;
134 }
135
136
137 void MathMacroTemplate::draw(PainterInfo & p, int x, int y) const
138 {
139         bool lockMacro = MacroTable::globalMacros().has(name_);
140         if (lockMacro)
141                 MacroTable::globalMacros().get(name_).lock();
142
143         setPosCache(p, x, y);
144
145         // label
146         Font font = p.base.font;
147         font.setColor(Color::math);
148
149         PainterInfo pi(p.base.bv, p.pain);
150         pi.base.style = LM_ST_TEXT;
151         pi.base.font  = font;
152
153         int const a = y - dim_.asc + 1;
154         int const w = dim_.wid - 2;
155         int const h = dim_.height() - 2;
156
157         // Color::mathbg used to be "AntiqueWhite" but is "linen" now, too
158         // the next line would overwrite the selection!
159         //pi.pain.fillRectangle(x, a, w, h, Color::mathmacrobg);
160         pi.pain.rectangle(x, a, w, h, Color::mathframe);
161
162 #ifdef WITH_WARNINGS
163 #warning FIXME
164 #endif
165 #if 0
166         Cursor & cur = p.base.bv->cursor();
167         if (cur.isInside(this))
168                 cur.drawSelection(pi);
169 #endif
170         docstring dp = prefix();
171         pi.pain.text(x + 2, y, dp, font);
172         // FIXME: Painter text should retain the drawn text width
173         x += theFontMetrics(font).width(dp) + 6;
174
175         int const w0 = cell(0).width();
176         int const w1 = cell(1).width();
177         cell(0).draw(pi, x + 2, y + 1);
178         pi.pain.rectangle(x, y - dim_.ascent() + 3,
179                 w0 + 4, dim_.height() - 6, Color::mathline);
180         cell(1).draw(pi, x + 8 + w0, y + 1);
181         pi.pain.rectangle(x + w0 + 6, y - dim_.ascent() + 3,
182                 w1 + 4, dim_.height() - 6, Color::mathline);
183
184         if (lockMacro)
185                 MacroTable::globalMacros().get(name_).unlock();
186 }
187
188
189 void MathMacroTemplate::read(Buffer const &, Lexer & lex)
190 {
191         MathData ar;
192         mathed_parse_cell(ar, lex.getStream());
193         if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
194                 lyxerr << "Cannot read macro from '" << ar << "'" << endl;
195                 lyxerr << "Read: " << to_utf8(asString(ar)) << endl;
196                 return;
197         }
198         operator=( *(ar[0]->asMacroTemplate()) );
199 }
200
201
202 void MathMacroTemplate::write(Buffer const &, std::ostream & os) const
203 {
204         odocstringstream oss;
205         WriteStream wi(oss, false, false);
206         oss << "FormulaMacro\n";
207         write(wi);
208         os << to_utf8(oss.str());
209 }
210
211
212 void MathMacroTemplate::write(WriteStream & os) const
213 {
214         if (type_ == "def") {
215                 os << "\\def\\" << name_.c_str();
216                 for (int i = 1; i <= numargs_; ++i)
217                         os << '#' << i;
218         } else {
219                 // newcommand or renewcommand
220                 os << "\\" << type_.c_str() << "{\\" << name_.c_str() << '}';
221                 if (numargs_ > 0)
222                         os << '[' << numargs_ << ']';
223         }
224
225         os << '{' << cell(0) << "}";
226
227         if (os.latex()) {
228                 // writing .tex. done.
229                 os << "\n";
230         } else {
231                 // writing .lyx, write special .tex export only if necessary
232                 if (!cell(1).empty())
233                         os << "\n{" << cell(1) << '}';
234         }
235 }
236
237
238 int MathMacroTemplate::plaintext(Buffer const & buf, odocstream & os,
239                                  OutputParams const &) const
240 {
241         static docstring const str = '[' + buf.B_("math macro") + ']';
242
243         os << str;
244         return str.size();
245 }
246
247
248 MacroData MathMacroTemplate::asMacroData() const
249 {
250         return MacroData(asString(cell(0)), numargs(), asString(cell(1)), std::string());
251 }
252
253
254 } // namespace lyx