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