]> git.lyx.org Git - lyx.git/blob - src/mathed/MathStream.h
7da9a9b9f9177d0949a6a1c71f4ac8e0b3d750ba
[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() { in_text_ = true; }
303         ///
304         void setMathMode() { in_text_ = false; }
305         ///
306         odocstream & os_;
307         ///
308         int tab_;
309         ///
310         int line_;
311         ///
312         bool in_text_;
313         ///
314         odocstringstream deferred_;
315         ///
316         friend class SetMode;
317 };
318
319 ///
320 MathStream & operator<<(MathStream &, MathAtom const &);
321 ///
322 MathStream & operator<<(MathStream &, MathData const &);
323 ///
324 MathStream & operator<<(MathStream &, docstring const &);
325 ///
326 MathStream & operator<<(MathStream &, char const *);
327 ///
328 MathStream & operator<<(MathStream &, char);
329 ///
330 MathStream & operator<<(MathStream &, char_type);
331 ///
332 MathStream & operator<<(MathStream &, MTag const &);
333 ///
334 MathStream & operator<<(MathStream &, ETag const &);
335
336
337 /// A simpler version of ModeSpecifier, for MathML
338 // FIXME There are still problems here with nesting, at least
339 // potentially. The problem is that true nesting of text mode isn't
340 // actually possible. I.e., we can't have: 
341 //              <mtext><mtext></mtext></mtext>
342 // So we have to have:
343 //              <mtext></mtext><mtext></mtext><mtext></mtext>
344 // instead, where the last is really a continuation of the first.
345 // We'll need some kind of stack to remember all that.
346 class SetMode {
347 public:
348         ///
349         explicit SetMode(MathStream & os, bool text, std::string const & attrs);
350         ///
351         explicit SetMode(MathStream & os, bool text);
352         ///
353         ~SetMode();
354 private:
355         ///
356         void init(bool, std::string const &);
357         ///
358         MathStream & os_;
359         ///
360         bool opened_;
361         ///
362         bool was_text_;
363 };
364
365
366 class HtmlStream {
367 public:
368         ///
369         explicit HtmlStream(odocstream & os);
370         ///
371         void cr();
372         ///
373         odocstream & os() { return os_; }
374         ///
375         int line() const { return line_; }
376         ///
377         int & tab() { return tab_; }
378         ///
379         friend HtmlStream & operator<<(HtmlStream &, char const *);
380         ///
381         void defer(docstring const &);
382         ///
383         void defer(std::string const &);
384         ///
385         docstring deferred() const;
386         ///
387         bool inText() const { return in_text_; }
388 private:
389         ///
390         void setTextMode() { in_text_ = true; }
391         ///
392         void setMathMode() { in_text_ = false; }
393         ///
394         odocstream & os_;
395         ///
396         int tab_;
397         ///
398         int line_;
399         ///
400         bool in_text_;
401         ///
402         odocstringstream deferred_;
403         ///
404         friend class SetHTMLMode;
405 };
406
407 ///
408 HtmlStream & operator<<(HtmlStream &, MathAtom const &);
409 ///
410 HtmlStream & operator<<(HtmlStream &, MathData const &);
411 ///
412 HtmlStream & operator<<(HtmlStream &, docstring const &);
413 ///
414 HtmlStream & operator<<(HtmlStream &, char const *);
415 ///
416 HtmlStream & operator<<(HtmlStream &, char);
417 ///
418 HtmlStream & operator<<(HtmlStream &, char_type);
419 ///
420 HtmlStream & operator<<(HtmlStream &, MTag const &);
421 ///
422 HtmlStream & operator<<(HtmlStream &, ETag const &);
423
424
425 class SetHTMLMode {
426 public:
427         ///
428         explicit SetHTMLMode(HtmlStream & os, bool text, std::string attrs);
429         ///
430         explicit SetHTMLMode(HtmlStream & os, bool text);
431         ///
432         ~SetHTMLMode();
433 private:
434         ///
435         void init(bool, std::string const &);
436         ///
437         HtmlStream & os_;
438         ///
439         bool opened_;
440         ///
441         bool was_text_;
442 };
443
444
445 //
446 // Debugging
447 //
448
449 class NormalStream {
450 public:
451         ///
452         explicit NormalStream(odocstream & os) : os_(os) {}
453         ///
454         odocstream & os() { return os_; }
455 private:
456         ///
457         odocstream & os_;
458 };
459
460 ///
461 NormalStream & operator<<(NormalStream &, MathAtom const &);
462 ///
463 NormalStream & operator<<(NormalStream &, MathData const &);
464 ///
465 NormalStream & operator<<(NormalStream &, docstring const &);
466 ///
467 NormalStream & operator<<(NormalStream &, char const *);
468 ///
469 NormalStream & operator<<(NormalStream &, char);
470 ///
471 NormalStream & operator<<(NormalStream &, int);
472
473
474 //
475 // Maple
476 //
477
478
479 class MapleStream {
480 public:
481         ///
482         explicit MapleStream(odocstream & os) : os_(os) {}
483         ///
484         odocstream & os() { return os_; }
485 private:
486         ///
487         odocstream & os_;
488 };
489
490
491 ///
492 MapleStream & operator<<(MapleStream &, MathAtom const &);
493 ///
494 MapleStream & operator<<(MapleStream &, MathData const &);
495 ///
496 MapleStream & operator<<(MapleStream &, docstring const &);
497 ///
498 MapleStream & operator<<(MapleStream &, char_type);
499 ///
500 MapleStream & operator<<(MapleStream &, char const *);
501 ///
502 MapleStream & operator<<(MapleStream &, char);
503 ///
504 MapleStream & operator<<(MapleStream &, int);
505
506
507 //
508 // Maxima
509 //
510
511
512 class MaximaStream {
513 public:
514         ///
515         explicit MaximaStream(odocstream & os) : os_(os) {}
516         ///
517         odocstream & os() { return os_; }
518 private:
519         ///
520         odocstream & os_;
521 };
522
523
524 ///
525 MaximaStream & operator<<(MaximaStream &, MathAtom const &);
526 ///
527 MaximaStream & operator<<(MaximaStream &, MathData const &);
528 ///
529 MaximaStream & operator<<(MaximaStream &, docstring const &);
530 ///
531 MaximaStream & operator<<(MaximaStream &, char_type);
532 ///
533 MaximaStream & operator<<(MaximaStream &, char const *);
534 ///
535 MaximaStream & operator<<(MaximaStream &, char);
536 ///
537 MaximaStream & operator<<(MaximaStream &, int);
538
539
540 //
541 // Mathematica
542 //
543
544
545 class MathematicaStream {
546 public:
547         ///
548         explicit MathematicaStream(odocstream & os) : os_(os) {}
549         ///
550         odocstream & os() { return os_; }
551 private:
552         ///
553         odocstream & os_;
554 };
555
556
557 ///
558 MathematicaStream & operator<<(MathematicaStream &, MathAtom const &);
559 ///
560 MathematicaStream & operator<<(MathematicaStream &, MathData const &);
561 ///
562 MathematicaStream & operator<<(MathematicaStream &, docstring const &);
563 ///
564 MathematicaStream & operator<<(MathematicaStream &, char const *);
565 ///
566 MathematicaStream & operator<<(MathematicaStream &, char);
567 ///
568 MathematicaStream & operator<<(MathematicaStream &, int);
569
570
571 //
572 // Octave
573 //
574
575
576 class OctaveStream {
577 public:
578         ///
579         explicit OctaveStream(odocstream & os) : os_(os) {}
580         ///
581         odocstream & os() { return os_; }
582 private:
583         ///
584         odocstream & os_;
585 };
586
587 ///
588 OctaveStream & operator<<(OctaveStream &, MathAtom const &);
589 ///
590 OctaveStream & operator<<(OctaveStream &, MathData const &);
591 ///
592 OctaveStream & operator<<(OctaveStream &, docstring const &);
593 ///
594 OctaveStream & operator<<(OctaveStream &, char_type);
595 ///
596 OctaveStream & operator<<(OctaveStream &, char const *);
597 ///
598 OctaveStream & operator<<(OctaveStream &, char);
599 ///
600 OctaveStream & operator<<(OctaveStream &, int);
601
602 } // namespace lyx
603
604 #endif