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