]> git.lyx.org Git - features.git/blob - src/mathed/formula.C
4bf5d1faf11f16c0c5eb0930f65ef3629c0bd6dd
[features.git] / src / mathed / formula.C
1 /**
2  * \file formula.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 "formula.h"
15 #include "math_cursor.h"
16 #include "math_parser.h"
17 #include "math_hullinset.h"
18 #include "math_mathmlstream.h"
19 #include "textpainter.h"
20
21 #include "debug.h"
22 #include "latexrunparams.h"
23 #include "Lsstream.h"
24
25
26 #include "frontends/Painter.h"
27
28 #include "graphics/PreviewedInset.h"
29 #include "graphics/PreviewImage.h"
30
31
32 using std::ostream;
33 using std::vector;
34 using std::auto_ptr;
35 using std::endl;
36
37
38 class InsetFormula::PreviewImpl : public lyx::graphics::PreviewedInset {
39 public:
40         ///
41         PreviewImpl(InsetFormula & p) : PreviewedInset(p) {}
42
43 private:
44         ///
45         bool previewWanted() const;
46         ///
47         string const latexString() const;
48         ///
49         InsetFormula & parent() const
50         {
51                 return *static_cast<InsetFormula*>(inset());
52         }
53 };
54
55
56
57 InsetFormula::InsetFormula(bool chemistry)
58         : par_(MathAtom(new MathHullInset)),
59           preview_(new PreviewImpl(*this))
60 {
61         if (chemistry)
62                 mutate("chemistry");
63 }
64
65
66 InsetFormula::InsetFormula(InsetFormula const & other)
67         : InsetFormulaBase(other),
68           par_(other.par_),
69           preview_(new PreviewImpl(*this))
70 {}
71
72
73 InsetFormula::InsetFormula(BufferView *)
74         : par_(MathAtom(new MathHullInset)),
75           preview_(new PreviewImpl(*this))
76 {
77         //view_ = bv->owner()->view();
78 }
79
80
81 InsetFormula::InsetFormula(string const & data)
82         : par_(MathAtom(new MathHullInset)),
83           preview_(new PreviewImpl(*this))
84 {
85         if (!data.size())
86                 return;
87         if (!mathed_parse_normal(par_, data))
88                 lyxerr << "cannot interpret '" << data << "' as math" << endl;
89 }
90
91
92
93 InsetFormula::~InsetFormula()
94 {}
95
96
97 auto_ptr<InsetBase> InsetFormula::clone() const
98 {
99         return auto_ptr<InsetBase>(new InsetFormula(*this));
100 }
101
102
103 void InsetFormula::write(Buffer const &, ostream & os) const
104 {
105         WriteStream wi(os, false, false);
106         os << par_->fileInsetLabel() << ' ';
107         par_->write(wi);
108 }
109
110
111 int InsetFormula::latex(Buffer const &, ostream & os,
112                         LatexRunParams const & runparams) const
113 {
114         WriteStream wi(os, runparams.moving_arg, true);
115         par_->write(wi);
116         return wi.line();
117 }
118
119
120 int InsetFormula::ascii(Buffer const &, ostream & os, int) const
121 {
122         if (0 && display()) {
123                 Dimension dim;
124                 TextMetricsInfo mi;
125                 par()->metricsT(mi, dim);
126                 TextPainter tpain(dim.width(), dim.height());
127                 par()->drawT(tpain, 0, dim.ascent());
128                 tpain.show(os, 3);
129                 // reset metrics cache to "real" values
130                 //metrics();
131                 return tpain.textheight();
132         } else {
133                 WriteStream wi(os, false, true);
134                 wi << ' ' << (par_->asNestInset()->cell(0)) << ' ';
135                 return wi.line();
136         }
137 }
138
139
140 int InsetFormula::linuxdoc(Buffer const & buf, ostream & os) const
141 {
142         return docbook(buf, os, false);
143 }
144
145
146 int InsetFormula::docbook(Buffer const & buf, ostream & os, bool) const
147 {
148         MathMLStream ms(os);
149         ms << MTag("equation");
150         ms <<   MTag("alt");
151         ms <<    "<[CDATA[";
152         int res = ascii(buf, ms.os(), 0);
153         ms <<    "]]>";
154         ms <<   ETag("alt");
155         ms <<   MTag("math");
156         ms <<    par_;
157         ms <<   ETag("math");
158         ms << ETag("equation");
159         return ms.line() + res;
160 }
161
162
163 void InsetFormula::read(Buffer const &, LyXLex & lex)
164 {
165         mathed_parse_normal(par_, lex);
166         // remove extra 'mathrm' for chemistry stuff.
167         // will be re-added on write
168         if (par_->asHullInset()->getType() =="chemistry")  {
169                 lyxerr << "this is chemistry" << endl;
170                 if (par_->cell(0).size() == 1) {
171                         lyxerr << "this is size 1" << endl;
172                         if (par_->cell(0)[0]->asFontInset()) {
173                                 lyxerr << "this is a font inset "
174                                        << "replacing " << par_.nucleus()->cell(0) <<
175                                         " with " << par_->cell(0)[0]->cell(0) << endl;
176                         }
177                 }
178         }
179         //metrics();
180 }
181
182
183 //ostream & operator<<(ostream & os, LyXCursor const & c)
184 //{
185 //      os << '[' << c.x() << ' ' << c.y() << ' ' << c.pos() << ']';
186 //      return os;
187 //}
188
189
190 void InsetFormula::draw(PainterInfo & pi, int x, int y) const
191 {
192         cache(pi.base.bv);
193         // This initiates the loading of the preview, so should come
194         // before the metrics are computed.
195         bool const use_preview = preview_->previewReady();
196
197         int const w = dim_.wid;
198         int const d = dim_.des;
199         int const a = dim_.asc;
200         int const h = a + d;
201
202         if (use_preview) {
203                 pi.pain.image(x + 1, y - a, w, h,   // one pixel gap in front
204                               *(preview_->pimage()->image()));
205         } else {
206                 PainterInfo p(pi.base.bv);
207                 p.base.style = LM_ST_TEXT;
208                 p.base.font  = pi.base.font;
209                 p.base.font.setColor(LColor::math);
210                 if (lcolor.getX11Name(LColor::mathbg)
211                             != lcolor.getX11Name(LColor::background))
212                         p.pain.fillRectangle(x, y - a, w, h, LColor::mathbg);
213
214                 if (mathcursor &&
215                                 const_cast<InsetFormulaBase const *>(mathcursor->formula()) == this)
216                 {
217                         mathcursor->drawSelection(pi);
218                         //p.pain.rectangle(x, y - a, w, h, LColor::mathframe);
219                 }
220
221                 par_->draw(p, x + offset_, y);
222         }
223
224         xo_ = x;
225         yo_ = y;
226 }
227
228
229 void InsetFormula::getLabelList(vector<string> & res) const
230 {
231         par()->getLabelList(res);
232 }
233
234
235 InsetOld::Code InsetFormula::lyxCode() const
236 {
237         return InsetOld::MATH_CODE;
238 }
239
240
241 void InsetFormula::validate(LaTeXFeatures & features) const
242 {
243         par_->validate(features);
244 }
245
246
247 bool InsetFormula::insetAllowed(InsetOld::Code code) const
248 {
249         return
250                    code == InsetOld::LABEL_CODE
251                 || code == InsetOld::REF_CODE
252                 || code == InsetOld::ERT_CODE;
253 }
254
255
256 void InsetFormula::metrics(MetricsInfo & m, Dimension & dim) const
257 {
258         view_ = m.base.bv;
259         if (preview_->previewReady()) {
260                 dim.asc = preview_->pimage()->ascent();
261                 dim.des = preview_->pimage()->descent();
262                 // insert a one pixel gap in front of the formula
263                 dim.wid = 1 + preview_->pimage()->width();
264                 if (display())
265                         dim.des += 12;
266         } else {
267                 MetricsInfo mi = m;
268                 mi.base.style = LM_ST_TEXT;
269                 mi.base.font.setColor(LColor::math);
270                 par()->metrics(mi, dim);
271                 dim.asc += 1;
272                 dim.des += 1;
273         }
274
275         if (display()) {
276                 offset_ = (m.base.textwidth - dim.wid) / 2;
277                 dim.wid = m.base.textwidth;
278         } else {
279                 offset_ = 0;
280         }
281
282         dim_ = dim;
283 }
284
285
286 void InsetFormula::mutate(string const & type)
287 {
288         par_.nucleus()->mutate(type);
289 }
290
291
292 //
293 // preview stuff
294 //
295
296 void InsetFormula::addPreview(lyx::graphics::PreviewLoader & ploader) const
297 {
298         preview_->addPreview(ploader);
299 }
300
301
302 void InsetFormula::generatePreview() const
303 {
304         preview_->generatePreview();
305 }
306
307
308 bool InsetFormula::PreviewImpl::previewWanted() const
309 {
310         return !parent().par_->asNestInset()->editing();
311 }
312
313
314 string const InsetFormula::PreviewImpl::latexString() const
315 {
316         ostringstream ls;
317         WriteStream wi(ls, false, false);
318         parent().par_->write(wi);
319         return STRCONV(ls.str());
320 }