]> git.lyx.org Git - lyx.git/blob - src/mathed/MathStream.h
Fix unwanted curly braces in formula (bug #8679)
[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         /// record whether we can write an immediately following newline char
63         void canBreakLine(bool breakline) { canbreakline_ = breakline; }
64         /// tell whether we can write an immediately following newline char
65         bool canBreakLine() const { return canbreakline_; }
66         /// writes space if next thing is isalpha()
67         void pendingSpace(bool how);
68         /// writes space if next thing is isalpha()
69         bool pendingSpace() const { return pendingspace_; }
70         /// tell whether to write the closing brace of \ensuremath
71         void pendingBrace(bool brace);
72         /// tell whether to write the closing brace of \ensuremath
73         bool pendingBrace() const { return pendingbrace_; }
74         /// tell whether we are in text mode or not when producing latex code
75         void textMode(bool textmode);
76         /// tell whether we are in text mode or not when producing latex code
77         bool textMode() const { return textmode_; }
78         /// tell whether we are allowed to switch mode when producing latex code
79         void lockedMode(bool locked);
80         /// tell whether we are allowed to switch mode when producing latex code
81         bool lockedMode() const { return locked_; }
82         /// tell whether to use only ascii chars when producing latex code
83         void asciiOnly(bool ascii);
84         /// tell whether to use only ascii chars when producing latex code
85         bool asciiOnly() const { return ascii_; }
86         /// LaTeX encoding
87         Encoding const * encoding() const { return encoding_; }
88 private:
89         ///
90         odocstream & os_;
91         /// do we have to write \\protect sometimes
92         bool fragile_;
93         /// are we at the beginning of an MathData?
94         bool firstitem_;
95         /// are we writing to .tex?
96         int latex_;
97         /// output type (default, source preview, instant preview)?
98         OutputType output_;
99         /// do we have a space pending?
100         bool pendingspace_;
101         /// do we have a brace pending?
102         bool pendingbrace_;
103         /// are we in text mode when producing latex code?
104         bool textmode_;
105         /// are we allowed to switch mode when producing latex code?
106         bool locked_;
107         /// should we use only ascii chars when producing latex code?
108         bool ascii_;
109         /// are we allowed to output an immediately following newline?
110         bool canbreakline_;
111         ///
112         int line_;
113         ///
114         Encoding const * encoding_;
115 };
116
117 ///
118 WriteStream & operator<<(WriteStream &, MathAtom const &);
119 ///
120 WriteStream & operator<<(WriteStream &, MathData const &);
121 ///
122 WriteStream & operator<<(WriteStream &, docstring const &);
123 ///
124 WriteStream & operator<<(WriteStream &, char const * const);
125 ///
126 WriteStream & operator<<(WriteStream &, char);
127 ///
128 WriteStream & operator<<(WriteStream &, int);
129 ///
130 WriteStream & operator<<(WriteStream &, unsigned int);
131
132 /// ensure math mode, possibly by opening \ensuremath
133 bool ensureMath(WriteStream & os, bool needs_math_mode = true, bool macro = false);
134
135 /// ensure the requested mode, possibly by closing \ensuremath
136 int ensureMode(WriteStream & os, InsetMath::mode_type mode, bool locked, bool ascii);
137
138
139 /**
140  * MathEnsurer - utility class for ensuring math mode
141  *
142  * A local variable of this type can be used to either ensure math mode
143  * or delay the writing of a pending brace when outputting LaTeX.
144  *
145  * Example 1:
146  *
147  *      MathEnsurer ensurer(os);
148  *
149  * If not already in math mode, inserts an \ensuremath command followed
150  * by an open brace. This brace will be automatically closed when exiting
151  * math mode. Math mode is automatically exited when writing something
152  * that doesn't explicitly require math mode.
153  *
154  * Example 2:
155  *
156  *      MathEnsurer ensurer(os, false);
157  *
158  * Simply suspend writing a closing brace until the end of ensurer's scope.
159  *
160  * Example 3:
161  *
162  *      MathEnsurer ensurer(os, needs_math_mode, true);
163  *
164  * The third parameter is set to true only for a user defined macro, which
165  * needs special handling. When it is a MathMacro, the needs_math_mode
166  * parameter is true and the behavior is as in Example 1. When the
167  * needs_math_mode parameter is false (not a MathMacro) and the macro
168  * was entered in a text box and we are in math mode, the mode is reset
169  * to text. This is because the macro was probably designed for text mode
170  * (given that it was entered in text mode and we have no way to tell the
171  * contrary).
172  */
173 class MathEnsurer
174 {
175 public:
176         ///
177         explicit MathEnsurer(WriteStream & os, bool needs_math_mode = true, bool macro = false)
178                 : os_(os), brace_(ensureMath(os, needs_math_mode, macro)) {}
179         ///
180         ~MathEnsurer() { os_.pendingBrace(brace_); }
181 private:
182         ///
183         WriteStream & os_;
184         ///
185         bool brace_;
186 };
187
188
189 /**
190  * ModeSpecifier - utility class for specifying a given mode (math or text)
191  *
192  * A local variable of this type can be used to specify that a command or
193  * environment works in a given mode. For example, \mbox works in text
194  * mode, but \boxed works in math mode. Note that no mode changing commands
195  * are needed, but we have to track the current mode, hence this class.
196  * This is only used when exporting to latex and helps determining whether
197  * the mode needs being temporarily switched when a command would not work
198  * in the current mode. As there are cases where this switching is to be
199  * avoided, the optional third parameter can be used to lock the mode.
200  * When the mode is locked, the optional fourth parameter specifies whether
201  * strings are to be output by using a suitable ascii representation.
202  *
203  * Example 1:
204  *
205  *      ModeSpecifier specifier(os, TEXT_MODE);
206  *
207  * Sets the current mode to text mode and allows mode switching.
208  *
209  * Example 2:
210  *
211  *      ModeSpecifier specifier(os, TEXT_MODE, true);
212  *
213  * Sets the current mode to text mode and disallows mode switching.
214  *
215  * Example 3:
216  *
217  *      ModeSpecifier specifier(os, TEXT_MODE, true, true);
218  *
219  * Sets the current mode to text mode, disallows mode switching, and outputs
220  * strings as ascii only.
221  *
222  * At the end of specifier's scope the mode is reset to its previous value.
223  */
224 class ModeSpecifier
225 {
226 public:
227         ///
228         explicit ModeSpecifier(WriteStream & os, InsetMath::mode_type mode,
229                                 bool locked = false, bool ascii = false)
230                 : os_(os), oldmodes_(ensureMode(os, mode, locked, ascii)) {}
231         ///
232         ~ModeSpecifier()
233         {
234                 os_.textMode(oldmodes_ & 0x01);
235                 os_.lockedMode(oldmodes_ & 0x02);
236                 os_.asciiOnly(oldmodes_ & 0x04);
237         }
238 private:
239         ///
240         WriteStream & os_;
241         ///
242         int oldmodes_;
243 };
244
245
246
247 //
248 //  MathML
249 //
250
251 class MTag {
252 public:
253         ///
254         MTag(char const * const tag, std::string attr = "") 
255                 : tag_(tag), attr_(attr) {}
256         ///
257         char const * const tag_;
258         ///
259         std::string attr_;
260 };
261
262 class ETag {
263 public:
264         ///
265         ETag(char const * const tag) : tag_(tag) {}
266         ///
267         char const * const tag_;
268 };
269
270
271 /// Throw MathExportException to signal that the attempt to export
272 /// some math in the current format did not succeed. E.g., we can't
273 /// export xymatrix as MathML, so that will throw, and we'll fall back
274 /// to images.
275 class MathExportException : public std::exception {};
276
277
278 class MathStream {
279 public:
280         ///
281         explicit MathStream(odocstream & os);
282         ///
283         void cr();
284         ///
285         odocstream & os() { return os_; }
286         ///
287         int line() const { return line_; }
288         ///
289         int & tab() { return tab_; }
290         ///
291         friend MathStream & operator<<(MathStream &, char const *);
292         ///
293         void defer(docstring const &);
294         ///
295         void defer(std::string const &);
296         ///
297         docstring deferred() const;
298         ///
299         bool inText() const { return in_text_; }
300 private:
301         ///
302         void setTextMode(bool t) { in_text_ = t; }
303         ///
304         odocstream & os_;
305         ///
306         int tab_;
307         ///
308         int line_;
309         ///
310         bool in_text_;
311         ///
312         odocstringstream deferred_;
313         ///
314         friend class SetMode;
315 };
316
317 ///
318 MathStream & operator<<(MathStream &, MathAtom const &);
319 ///
320 MathStream & operator<<(MathStream &, MathData const &);
321 ///
322 MathStream & operator<<(MathStream &, docstring const &);
323 ///
324 MathStream & operator<<(MathStream &, char const *);
325 ///
326 MathStream & operator<<(MathStream &, char);
327 ///
328 MathStream & operator<<(MathStream &, char_type);
329 ///
330 MathStream & operator<<(MathStream &, MTag const &);
331 ///
332 MathStream & operator<<(MathStream &, ETag const &);
333
334
335 /// A simpler version of ModeSpecifier, for MathML
336 class SetMode {
337 public:
338         ///
339         explicit SetMode(MathStream & os, bool text);
340         ///
341         ~SetMode();
342 private:
343         ///
344         MathStream & os_;
345         ///
346         bool was_text_;
347 };
348
349
350 class HtmlStream {
351 public:
352         ///
353         explicit HtmlStream(odocstream & os);
354         ///
355         void cr();
356         ///
357         odocstream & os() { return os_; }
358         ///
359         int line() const { return line_; }
360         ///
361         int & tab() { return tab_; }
362         ///
363         friend HtmlStream & operator<<(HtmlStream &, char const *);
364         ///
365         void defer(docstring const &);
366         ///
367         void defer(std::string const &);
368         ///
369         docstring deferred() const;
370         ///
371         bool inText() const { return in_text_; }
372 private:
373         ///
374         void setTextMode(bool t) { in_text_ = t; }
375         ///
376         odocstream & os_;
377         ///
378         int tab_;
379         ///
380         int line_;
381         ///
382         bool in_text_;
383         ///
384         odocstringstream deferred_;
385         ///
386         friend class SetHTMLMode;
387 };
388
389 ///
390 HtmlStream & operator<<(HtmlStream &, MathAtom const &);
391 ///
392 HtmlStream & operator<<(HtmlStream &, MathData const &);
393 ///
394 HtmlStream & operator<<(HtmlStream &, docstring const &);
395 ///
396 HtmlStream & operator<<(HtmlStream &, char const *);
397 ///
398 HtmlStream & operator<<(HtmlStream &, char);
399 ///
400 HtmlStream & operator<<(HtmlStream &, char_type);
401 ///
402 HtmlStream & operator<<(HtmlStream &, MTag const &);
403 ///
404 HtmlStream & operator<<(HtmlStream &, ETag const &);
405
406
407 class SetHTMLMode {
408 public:
409         ///
410         explicit SetHTMLMode(HtmlStream & os, bool text);
411         ///
412         ~SetHTMLMode();
413 private:
414         ///
415         HtmlStream & os_;
416         ///
417         bool was_text_;
418 };
419
420
421 //
422 // Debugging
423 //
424
425 class NormalStream {
426 public:
427         ///
428         explicit NormalStream(odocstream & os) : os_(os) {}
429         ///
430         odocstream & os() { return os_; }
431 private:
432         ///
433         odocstream & os_;
434 };
435
436 ///
437 NormalStream & operator<<(NormalStream &, MathAtom const &);
438 ///
439 NormalStream & operator<<(NormalStream &, MathData const &);
440 ///
441 NormalStream & operator<<(NormalStream &, docstring const &);
442 ///
443 NormalStream & operator<<(NormalStream &, char const *);
444 ///
445 NormalStream & operator<<(NormalStream &, char);
446 ///
447 NormalStream & operator<<(NormalStream &, int);
448
449
450 //
451 // Maple
452 //
453
454
455 class MapleStream {
456 public:
457         ///
458         explicit MapleStream(odocstream & os) : os_(os) {}
459         ///
460         odocstream & os() { return os_; }
461 private:
462         ///
463         odocstream & os_;
464 };
465
466
467 ///
468 MapleStream & operator<<(MapleStream &, MathAtom const &);
469 ///
470 MapleStream & operator<<(MapleStream &, MathData const &);
471 ///
472 MapleStream & operator<<(MapleStream &, docstring const &);
473 ///
474 MapleStream & operator<<(MapleStream &, char_type);
475 ///
476 MapleStream & operator<<(MapleStream &, char const *);
477 ///
478 MapleStream & operator<<(MapleStream &, char);
479 ///
480 MapleStream & operator<<(MapleStream &, int);
481
482
483 //
484 // Maxima
485 //
486
487
488 class MaximaStream {
489 public:
490         ///
491         explicit MaximaStream(odocstream & os) : os_(os) {}
492         ///
493         odocstream & os() { return os_; }
494 private:
495         ///
496         odocstream & os_;
497 };
498
499
500 ///
501 MaximaStream & operator<<(MaximaStream &, MathAtom const &);
502 ///
503 MaximaStream & operator<<(MaximaStream &, MathData const &);
504 ///
505 MaximaStream & operator<<(MaximaStream &, docstring const &);
506 ///
507 MaximaStream & operator<<(MaximaStream &, char_type);
508 ///
509 MaximaStream & operator<<(MaximaStream &, char const *);
510 ///
511 MaximaStream & operator<<(MaximaStream &, char);
512 ///
513 MaximaStream & operator<<(MaximaStream &, int);
514
515
516 //
517 // Mathematica
518 //
519
520
521 class MathematicaStream {
522 public:
523         ///
524         explicit MathematicaStream(odocstream & os) : os_(os) {}
525         ///
526         odocstream & os() { return os_; }
527 private:
528         ///
529         odocstream & os_;
530 };
531
532
533 ///
534 MathematicaStream & operator<<(MathematicaStream &, MathAtom const &);
535 ///
536 MathematicaStream & operator<<(MathematicaStream &, MathData const &);
537 ///
538 MathematicaStream & operator<<(MathematicaStream &, docstring const &);
539 ///
540 MathematicaStream & operator<<(MathematicaStream &, char const *);
541 ///
542 MathematicaStream & operator<<(MathematicaStream &, char);
543 ///
544 MathematicaStream & operator<<(MathematicaStream &, int);
545
546
547 //
548 // Octave
549 //
550
551
552 class OctaveStream {
553 public:
554         ///
555         explicit OctaveStream(odocstream & os) : os_(os) {}
556         ///
557         odocstream & os() { return os_; }
558 private:
559         ///
560         odocstream & os_;
561 };
562
563 ///
564 OctaveStream & operator<<(OctaveStream &, MathAtom const &);
565 ///
566 OctaveStream & operator<<(OctaveStream &, MathData const &);
567 ///
568 OctaveStream & operator<<(OctaveStream &, docstring const &);
569 ///
570 OctaveStream & operator<<(OctaveStream &, char_type);
571 ///
572 OctaveStream & operator<<(OctaveStream &, char const *);
573 ///
574 OctaveStream & operator<<(OctaveStream &, char);
575 ///
576 OctaveStream & operator<<(OctaveStream &, int);
577
578 } // namespace lyx
579
580 #endif