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