]> git.lyx.org Git - lyx.git/blob - src/mathed/MathStream.h
Fix bug #3325: Labels with special characters in equations do not work
[lyx.git] / src / mathed / MathStream.h
1 // -*- C++ -*-
2 /**
3  * \file MathStream.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #ifndef MATH_MATHMLSTREAM_H
13 #define MATH_MATHMLSTREAM_H
14
15 #include "support/strfwd.h"
16
17 #include "InsetMath.h"
18 // FIXME: Move to individual insets
19 #include "MetricsInfo.h"
20
21
22 namespace lyx {
23
24 class Encoding;
25 class InsetMath;
26 class MathAtom;
27 class MathData;
28
29 //
30 // LaTeX/LyX
31 //
32
33 class WriteStream {
34 public:
35         ///
36         enum OutputType {
37                 wsDefault,
38                 wsDryrun,
39                 wsPreview
40         };
41         ///
42         WriteStream(odocstream & os, bool fragile, bool latex, OutputType output,
43                 Encoding const * encoding = 0);
44         ///
45         explicit WriteStream(odocstream & os);
46         ///
47         ~WriteStream();
48         ///
49         int line() const { return line_; }
50         ///
51         bool fragile() const { return fragile_; }
52         ///
53         bool latex() const { return latex_; }
54         ///
55         OutputType output() const { return output_; }
56         ///
57         odocstream & os() { return os_; }
58         ///
59         bool & firstitem() { return firstitem_; }
60         ///
61         void addlines(unsigned int);
62         /// writes space if next thing is isalpha()
63         void pendingSpace(bool how);
64         /// writes space if next thing is isalpha()
65         bool pendingSpace() const { return pendingspace_; }
66         /// tell whether to write the closing brace of \ensuremath
67         void pendingBrace(bool brace);
68         /// tell whether to write the closing brace of \ensuremath
69         bool pendingBrace() const { return pendingbrace_; }
70         /// tell whether we are in text mode or not when producing latex code
71         void textMode(bool textmode);
72         /// tell whether we are in text mode or not when producing latex code
73         bool textMode() const { return textmode_; }
74         /// tell whether we are allowed to switch mode when producing latex code
75         void lockedMode(bool locked);
76         /// tell whether we are allowed to switch mode when producing latex code
77         bool lockedMode() const { return locked_; }
78         /// tell whether to use only ascii chars when producing latex code
79         void asciiOnly(bool ascii);
80         /// tell whether to use only ascii chars when producing latex code
81         bool asciiOnly() const { return ascii_; }
82         /// LaTeX encoding
83         Encoding const * encoding() const { return encoding_; }
84 private:
85         ///
86         odocstream & os_;
87         /// do we have to write \\protect sometimes
88         bool fragile_;
89         /// are we at the beginning of an MathData?
90         bool firstitem_;
91         /// are we writing to .tex?
92         int latex_;
93         /// output type (default, source preview, instant preview)?
94         OutputType output_;
95         /// do we have a space pending?
96         bool pendingspace_;
97         /// do we have a brace pending?
98         bool pendingbrace_;
99         /// are we in text mode when producing latex code?
100         bool textmode_;
101         /// are we allowed to switch mode when producing latex code?
102         bool locked_;
103         /// should we use only ascii chars when producing latex code?
104         bool ascii_;
105         ///
106         int line_;
107         ///
108         Encoding const * encoding_;
109 };
110
111 ///
112 WriteStream & operator<<(WriteStream &, MathAtom const &);
113 ///
114 WriteStream & operator<<(WriteStream &, MathData const &);
115 ///
116 WriteStream & operator<<(WriteStream &, docstring const &);
117 ///
118 WriteStream & operator<<(WriteStream &, char const * const);
119 ///
120 WriteStream & operator<<(WriteStream &, char);
121 ///
122 WriteStream & operator<<(WriteStream &, int);
123 ///
124 WriteStream & operator<<(WriteStream &, unsigned int);
125
126 /// ensure math mode, possibly by opening \ensuremath
127 bool ensureMath(WriteStream & os, bool needs_math_mode = true, bool macro = false);
128
129 /// ensure the requested mode, possibly by closing \ensuremath
130 int ensureMode(WriteStream & os, InsetMath::mode_type mode, bool locked);
131
132
133 /**
134  * MathEnsurer - utility class for ensuring math mode
135  *
136  * A local variable of this type can be used to either ensure math mode
137  * or delay the writing of a pending brace when outputting LaTeX.
138  *
139  * Example 1:
140  *
141  *      MathEnsurer ensurer(os);
142  *
143  * If not already in math mode, inserts an \ensuremath command followed
144  * by an open brace. This brace will be automatically closed when exiting
145  * math mode. Math mode is automatically exited when writing something
146  * that doesn't explicitly require math mode.
147  *
148  * Example 2:
149  *
150  *      MathEnsurer ensurer(os, false);
151  *
152  * Simply suspend writing a closing brace until the end of ensurer's scope.
153  *
154  * Example 3:
155  *
156  *      MathEnsurer ensurer(os, needs_math_mode, true);
157  *
158  * The third parameter is set to true only for a user defined macro, which
159  * needs special handling. When it is a MathMacro, the needs_math_mode
160  * parameter is true and the behavior is as in Example 1. When the
161  * needs_math_mode parameter is false (not a MathMacro) and the macro
162  * was entered in a text box and we are in math mode, the mode is reset
163  * to text. This is because the macro was probably designed for text mode
164  * (given that it was entered in text mode and we have no way to tell the
165  * contrary).
166  */
167 class MathEnsurer
168 {
169 public:
170         ///
171         explicit MathEnsurer(WriteStream & os, bool needs_math_mode = true, bool macro = false)
172                 : os_(os), brace_(ensureMath(os, needs_math_mode, macro)) {}
173         ///
174         ~MathEnsurer() { os_.pendingBrace(brace_); }
175 private:
176         ///
177         WriteStream & os_;
178         ///
179         bool brace_;
180 };
181
182
183 /**
184  * ModeSpecifier - utility class for specifying a given mode (math or text)
185  *
186  * A local variable of this type can be used to specify that a command or
187  * environment works in a given mode. For example, \mbox works in text
188  * mode, but \boxed works in math mode. Note that no mode changing commands
189  * are needed, but we have to track the current mode, hence this class.
190  * This is only used when exporting to latex and helps determining whether
191  * the mode needs being temporarily switched when a command would not work
192  * in the current mode. As there are cases where this switching is to be
193  * avoided, the optional third parameter can be used to lock the mode.
194  *
195  * Example 1:
196  *
197  *      ModeSpecifier specifier(os, TEXT_MODE);
198  *
199  * Sets the current mode to text mode and allows mode switching.
200  *
201  * Example 2:
202  *
203  *      ModeSpecifier specifier(os, TEXT_MODE, true);
204  *
205  * Sets the current mode to text mode and disallows mode switching.
206  *
207  * At the end of specifier's scope the mode is reset to its previous value.
208  */
209 class ModeSpecifier
210 {
211 public:
212         ///
213         explicit ModeSpecifier(WriteStream & os, InsetMath::mode_type mode,
214                                 bool locked = false)
215                 : os_(os), oldmodes_(ensureMode(os, mode, locked)) {}
216         ///
217         ~ModeSpecifier()
218         {
219                 os_.textMode(oldmodes_ & 1);
220                 os_.lockedMode(oldmodes_ & 2);
221         }
222 private:
223         ///
224         WriteStream & os_;
225         ///
226         int oldmodes_;
227 };
228
229
230
231 //
232 //  MathML
233 //
234
235 class MTag {
236 public:
237         ///
238         MTag(char const * const tag, std::string attr = "") 
239                 : tag_(tag), attr_(attr) {}
240         ///
241         char const * const tag_;
242         ///
243         std::string attr_;
244 };
245
246 class ETag {
247 public:
248         ///
249         ETag(char const * const tag) : tag_(tag) {}
250         ///
251         char const * const tag_;
252 };
253
254
255 class MathStream {
256 public:
257         ///
258         explicit MathStream(odocstream & os);
259         ///
260         void cr();
261         ///
262         odocstream & os() { return os_; }
263         ///
264         int line() const { return line_; }
265         ///
266         int & tab() { return tab_; }
267         ///
268         friend MathStream & operator<<(MathStream &, char const *);
269         ///
270         void defer(docstring const &);
271         ///
272         void defer(std::string const &);
273         ///
274         docstring deferred() const;
275         ///
276         bool inText() const { return in_text_; }
277 private:
278         ///
279         void setTextMode() { in_text_ = true; }
280         ///
281         void setMathMode() { in_text_ = false; }
282         ///
283         odocstream & os_;
284         ///
285         int tab_;
286         ///
287         int line_;
288         ///
289         char lastchar_;
290         ///
291         bool in_text_;
292         ///
293         odocstringstream deferred_;
294         ///
295         friend class SetMode;
296 };
297
298 ///
299 MathStream & operator<<(MathStream &, MathAtom const &);
300 ///
301 MathStream & operator<<(MathStream &, MathData const &);
302 ///
303 MathStream & operator<<(MathStream &, docstring const &);
304 ///
305 MathStream & operator<<(MathStream &, char const *);
306 ///
307 MathStream & operator<<(MathStream &, char);
308 ///
309 MathStream & operator<<(MathStream &, char_type);
310 ///
311 MathStream & operator<<(MathStream &, MTag const &);
312 ///
313 MathStream & operator<<(MathStream &, ETag const &);
314
315
316 /// A simpler version of ModeSpecifier, for MathML
317 // FIXME There are still problems here with nesting, at least
318 // potentially. The problem is that true nesting of text mode isn't
319 // actually possible. I.e., we can't have: 
320 //              <mtext><mtext></mtext></mtext>
321 // So we have to have:
322 //              <mtext></mtext><mtext></mtext><mtext></mtext>
323 // instead, where the last is really a continuation of the first.
324 // We'll need some kind of stack to remember all that.
325 class SetMode {
326 public:
327         ///
328         explicit SetMode(MathStream & os, bool text, docstring attrs);
329         ///
330         explicit SetMode(MathStream & os, bool text);
331         ///
332         ~SetMode();
333 private:
334         ///
335         void init(bool, docstring);
336         ///
337         MathStream & os_;
338         ///
339         bool opened_;
340         ///
341         bool was_text_;
342 };
343
344
345 //
346 // Debugging
347 //
348
349 class NormalStream {
350 public:
351         ///
352         explicit NormalStream(odocstream & os) : os_(os) {}
353         ///
354         odocstream & os() { return os_; }
355 private:
356         ///
357         odocstream & os_;
358 };
359
360 ///
361 NormalStream & operator<<(NormalStream &, MathAtom const &);
362 ///
363 NormalStream & operator<<(NormalStream &, MathData const &);
364 ///
365 NormalStream & operator<<(NormalStream &, docstring const &);
366 ///
367 NormalStream & operator<<(NormalStream &, char const *);
368 ///
369 NormalStream & operator<<(NormalStream &, char);
370 ///
371 NormalStream & operator<<(NormalStream &, int);
372
373
374 //
375 // Maple
376 //
377
378
379 class MapleStream {
380 public:
381         ///
382         explicit MapleStream(odocstream & os) : os_(os) {}
383         ///
384         odocstream & os() { return os_; }
385 private:
386         ///
387         odocstream & os_;
388 };
389
390
391 ///
392 MapleStream & operator<<(MapleStream &, MathAtom const &);
393 ///
394 MapleStream & operator<<(MapleStream &, MathData const &);
395 ///
396 MapleStream & operator<<(MapleStream &, docstring const &);
397 ///
398 MapleStream & operator<<(MapleStream &, char_type);
399 ///
400 MapleStream & operator<<(MapleStream &, char const *);
401 ///
402 MapleStream & operator<<(MapleStream &, char);
403 ///
404 MapleStream & operator<<(MapleStream &, int);
405
406
407 //
408 // Maxima
409 //
410
411
412 class MaximaStream {
413 public:
414         ///
415         explicit MaximaStream(odocstream & os) : os_(os) {}
416         ///
417         odocstream & os() { return os_; }
418 private:
419         ///
420         odocstream & os_;
421 };
422
423
424 ///
425 MaximaStream & operator<<(MaximaStream &, MathAtom const &);
426 ///
427 MaximaStream & operator<<(MaximaStream &, MathData const &);
428 ///
429 MaximaStream & operator<<(MaximaStream &, docstring const &);
430 ///
431 MaximaStream & operator<<(MaximaStream &, char_type);
432 ///
433 MaximaStream & operator<<(MaximaStream &, char const *);
434 ///
435 MaximaStream & operator<<(MaximaStream &, char);
436 ///
437 MaximaStream & operator<<(MaximaStream &, int);
438
439
440 //
441 // Mathematica
442 //
443
444
445 class MathematicaStream {
446 public:
447         ///
448         explicit MathematicaStream(odocstream & os) : os_(os) {}
449         ///
450         odocstream & os() { return os_; }
451 private:
452         ///
453         odocstream & os_;
454 };
455
456
457 ///
458 MathematicaStream & operator<<(MathematicaStream &, MathAtom const &);
459 ///
460 MathematicaStream & operator<<(MathematicaStream &, MathData const &);
461 ///
462 MathematicaStream & operator<<(MathematicaStream &, docstring const &);
463 ///
464 MathematicaStream & operator<<(MathematicaStream &, char const *);
465 ///
466 MathematicaStream & operator<<(MathematicaStream &, char);
467 ///
468 MathematicaStream & operator<<(MathematicaStream &, int);
469
470
471 //
472 // Octave
473 //
474
475
476 class OctaveStream {
477 public:
478         ///
479         explicit OctaveStream(odocstream & os) : os_(os) {}
480         ///
481         odocstream & os() { return os_; }
482 private:
483         ///
484         odocstream & os_;
485 };
486
487 ///
488 OctaveStream & operator<<(OctaveStream &, MathAtom const &);
489 ///
490 OctaveStream & operator<<(OctaveStream &, MathData const &);
491 ///
492 OctaveStream & operator<<(OctaveStream &, docstring const &);
493 ///
494 OctaveStream & operator<<(OctaveStream &, char_type);
495 ///
496 OctaveStream & operator<<(OctaveStream &, char const *);
497 ///
498 OctaveStream & operator<<(OctaveStream &, char);
499 ///
500 OctaveStream & operator<<(OctaveStream &, int);
501
502 } // namespace lyx
503
504 #endif