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