]> git.lyx.org Git - lyx.git/blob - src/mathed/MathMacroTemplate.C
do not create invalid .lyx files when importing \i{}, \j{}, \l{} or \L{}.
[lyx.git] / src / mathed / MathMacroTemplate.C
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 "cursor.h"
19 #include "debug.h"
20 #include "gettext.h"
21 #include "lyxlex.h"
22 #include "LColor.h"
23
24 #include "frontends/FontMetrics.h"
25 #include "frontends/Painter.h"
26
27 #include "support/lstrings.h"
28
29
30 namespace lyx {
31
32 using support::bformat;
33
34 using std::auto_ptr;
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, MathArray const & ar1, MathArray 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         MathArray 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 auto_ptr<InsetBase> MathMacroTemplate::doClone() const
76 {
77         return auto_ptr<InsetBase>(new MathMacroTemplate(*this));
78 }
79
80
81 void MathMacroTemplate::edit(LCursor & 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         // FIXME UNICODE
109         // delete the conversion when bformat() will return a docstring.
110         // delete the conversion when bformat() takes a docstring arg.
111         return bformat(_(" Macro: %1$s: "), name_);
112 }
113
114
115 bool MathMacroTemplate::metrics(MetricsInfo & mi, Dimension & dim) const
116 {
117         cell(0).metrics(mi);
118         cell(1).metrics(mi);
119         docstring dp = prefix();
120         dim.wid = cell(0).width() + cell(1).width() + 20
121                 + theFontMetrics(mi.base.font).width(dp);
122         dim.asc = std::max(cell(0).ascent(),  cell(1).ascent())  + 7;
123         dim.des = std::max(cell(0).descent(), cell(1).descent()) + 7;
124         if (dim_ == dim)
125                 return false;
126         dim_ = dim;
127         return true;
128 }
129
130
131 void MathMacroTemplate::draw(PainterInfo & p, int x, int y) const
132 {
133         setPosCache(p, x, y);
134
135         // label
136         LyXFont font = p.base.font;
137         font.setColor(LColor::math);
138
139         PainterInfo pi(p.base.bv, p.pain);
140         pi.base.style = LM_ST_TEXT;
141         pi.base.font  = font;
142
143         int const a = y - dim_.asc + 1;
144         int const w = dim_.wid - 2;
145         int const h = dim_.height() - 2;
146
147         // LColor::mathbg used to be "AntiqueWhite" but is "linen" now, too
148         // the next line would overwrite the selection!
149         //pi.pain.fillRectangle(x, a, w, h, LColor::mathmacrobg);
150         pi.pain.rectangle(x, a, w, h, LColor::mathframe);
151
152 #ifdef WITH_WARNINGS
153 #warning FIXME
154 #endif
155 #if 0
156         LCursor & cur = p.base.bv->cursor();
157         if (cur.isInside(this))
158                 cur.drawSelection(pi);
159 #endif
160         docstring dp = prefix();
161         pi.pain.text(x + 2, y, dp, font);
162         // FIXME: Painter text should retain the drawn text width
163         x += theFontMetrics(font).width(dp) + 6;
164
165         int const w0 = cell(0).width();
166         int const w1 = cell(1).width();
167         cell(0).draw(pi, x + 2, y + 1);
168         pi.pain.rectangle(x, y - dim_.ascent() + 3,
169                 w0 + 4, dim_.height() - 6, LColor::mathline);
170         cell(1).draw(pi, x + 8 + w0, y + 1);
171         pi.pain.rectangle(x + w0 + 6, y - dim_.ascent() + 3,
172                 w1 + 4, dim_.height() - 6, LColor::mathline);
173 }
174
175
176 void MathMacroTemplate::read(Buffer const &, LyXLex & lex)
177 {
178         MathArray ar;
179         lex.next(); // eat \begin_inset FormulaMacro line
180         docstring const str = lex.getDocString();
181         lex.next(); // eat that macro definition
182         lex.next(); // eat the \\end_insrt line
183         //lyxerr << "Got to read from: " << to_utf8(str) << endl;
184         mathed_parse_cell(ar, str);
185         if (ar.size() != 1 || !ar[0]->asMacroTemplate()) {
186                 lyxerr << "Cannot read macro from '" << ar << "'" << endl;
187                 lyxerr << "Read: " << to_utf8(asString(ar)) << endl;
188                 return;
189         }
190         operator=( *(ar[0]->asMacroTemplate()) );
191 }
192
193
194 void MathMacroTemplate::write(Buffer const &, std::ostream & os) const
195 {
196         odocstringstream oss;
197         WriteStream wi(oss, false, false);
198         oss << "FormulaMacro\n";
199         write(wi);
200         os << to_utf8(oss.str());
201 }
202
203
204 void MathMacroTemplate::write(WriteStream & os) const
205 {
206         if (type_ == "def") {
207                 os << "\\def\\" << name_.c_str();
208                 for (int i = 1; i <= numargs_; ++i)
209                         os << '#' << i;
210         } else {
211                 // newcommand or renewcommand
212                 os << "\\" << type_.c_str() << "{\\" << name_.c_str() << '}';
213                 if (numargs_ > 0)
214                         os << '[' << numargs_ << ']';
215         }
216
217         os << '{' << cell(0) << "}";
218
219         if (os.latex()) {
220                 // writing .tex. done.
221                 os << "\n";
222         } else {
223                 // writing .lyx, write special .tex export only if necessary
224                 if (!cell(1).empty())
225                         os << "\n{" << cell(1) << '}';
226         }
227 }
228
229
230 MacroData MathMacroTemplate::asMacroData() const
231 {
232         return MacroData(asString(cell(0)), numargs(), asString(cell(1)), std::string());
233 }
234
235
236 } // namespace lyx