]> git.lyx.org Git - lyx.git/blob - src/mathed/MathStream.cpp
MathML: add M/ETagInline.
[lyx.git] / src / mathed / MathStream.cpp
1 /**
2  * \file MathStream.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "MathStream.h"
14
15 #include "MathFactory.h"
16 #include "MathData.h"
17 #include "MathExtern.h"
18
19 #include "TexRow.h"
20
21
22 #include "support/debug.h"
23 #include "support/docstring.h"
24 #include "support/textutils.h"
25
26 #include <algorithm>
27 #include <cstring>
28 #include <ostream>
29
30 using namespace std;
31
32 namespace lyx {
33
34
35 //////////////////////////////////////////////////////////////////////
36
37
38 NormalStream & operator<<(NormalStream & ns, MathAtom const & at)
39 {
40         at->normalize(ns);
41         return ns;
42 }
43
44
45 NormalStream & operator<<(NormalStream & ns, MathData const & ar)
46 {
47         normalize(ar, ns);
48         return ns;
49 }
50
51
52 NormalStream & operator<<(NormalStream & ns, docstring const & s)
53 {
54         ns.os() << s;
55         return ns;
56 }
57
58
59 NormalStream & operator<<(NormalStream & ns, const string & s)
60 {
61         ns.os() << from_utf8(s);
62         return ns;
63 }
64
65
66 NormalStream & operator<<(NormalStream & ns, char const * s)
67 {
68         ns.os() << s;
69         return ns;
70 }
71
72
73 NormalStream & operator<<(NormalStream & ns, char c)
74 {
75         ns.os() << c;
76         return ns;
77 }
78
79
80 NormalStream & operator<<(NormalStream & ns, int i)
81 {
82         ns.os() << i;
83         return ns;
84 }
85
86
87
88 /////////////////////////////////////////////////////////////////
89
90
91 TeXMathStream & operator<<(TeXMathStream & ws, docstring const & s)
92 {
93         // Skip leading '\n' if we had already output a newline char
94         size_t const first =
95                 (s.length() > 0 && (s[0] != '\n' || ws.canBreakLine())) ? 0 : 1;
96
97         // Check whether there's something to output
98         if (s.length() <= first)
99                 return ws;
100
101         if (ws.pendingBrace()) {
102                 ws.os() << '}';
103                 ws.pendingBrace(false);
104                 ws.pendingSpace(false);
105                 ws.textMode(true);
106         } else if (ws.pendingSpace()) {
107                 if (isAlphaASCII(s[first]))
108                         ws.os() << ' ';
109                 else if (s[first] == '[' && ws.useBraces())
110                         ws.os() << "{}";
111                 else if (s[first] == ' ' && ws.textMode())
112                         ws.os() << '\\';
113                 ws.pendingSpace(false);
114         } else if (ws.useBraces()) {
115                 if (s[first] == '\'')
116                         ws.os() << "{}";
117                 ws.useBraces(false);
118         }
119         ws.os() << s.substr(first);
120         int lf = 0;
121         char_type lastchar = 0;
122         docstring::const_iterator dit = s.begin() + first;
123         docstring::const_iterator end = s.end();
124         for (; dit != end; ++dit) {
125                 lastchar = *dit;
126                 if (lastchar == '\n')
127                         ++lf;
128         }
129         ws.addlines(lf);
130         ws.canBreakLine(lastchar != '\n');
131         return ws;
132 }
133
134
135 TeXMathStream::TeXMathStream(otexrowstream & os, bool fragile, bool latex,
136                              OutputType output, Encoding const * encoding)
137         : os_(os), fragile_(fragile), latex_(latex),
138           output_(output), encoding_(encoding)
139 {}
140
141
142 TeXMathStream::~TeXMathStream()
143 {
144         if (pendingbrace_)
145                 os_ << '}';
146         else if (pendingspace_)
147                 os_ << ' ';
148 }
149
150
151 void TeXMathStream::addlines(unsigned int n)
152 {
153         line_ += n;
154 }
155
156
157 void TeXMathStream::pendingSpace(bool space)
158 {
159         pendingspace_ = space;
160         if (!space)
161                 usebraces_ = false;
162 }
163
164
165 void TeXMathStream::useBraces(bool braces)
166 {
167         usebraces_ = braces;
168 }
169
170
171 void TeXMathStream::pendingBrace(bool brace)
172 {
173         pendingbrace_ = brace;
174 }
175
176
177 void TeXMathStream::textMode(bool textmode)
178 {
179         textmode_ = textmode;
180 }
181
182
183 void TeXMathStream::lockedMode(bool locked)
184 {
185         locked_ = locked;
186 }
187
188
189 void TeXMathStream::asciiOnly(bool ascii)
190 {
191         ascii_ = ascii;
192 }
193
194
195 Changer TeXMathStream::changeRowEntry(TexRow::RowEntry entry)
196 {
197         return changeVar(row_entry_, entry);
198 }
199
200
201 bool TeXMathStream::startOuterRow()
202 {
203         if (TexRow::isNone(row_entry_))
204                 return false;
205         return texrow().start(row_entry_);
206 }
207
208
209 TeXMathStream & operator<<(TeXMathStream & ws, MathAtom const & at)
210 {
211         at->write(ws);
212         return ws;
213 }
214
215
216 TeXMathStream & operator<<(TeXMathStream & ws, MathData const & ar)
217 {
218         write(ar, ws);
219         return ws;
220 }
221
222
223 TeXMathStream & operator<<(TeXMathStream & ws, char const * s)
224 {
225         ws << from_utf8(s);
226         return ws;
227 }
228
229
230 TeXMathStream & operator<<(TeXMathStream & ws, char c)
231 {
232         if (c == '\n' && !ws.canBreakLine())
233                 return ws;
234
235         if (ws.pendingBrace()) {
236                 ws.os() << '}';
237                 ws.pendingBrace(false);
238                 ws.pendingSpace(false);
239                 ws.textMode(true);
240         } else if (ws.pendingSpace()) {
241                 if (isAlphaASCII(c))
242                         ws.os() << ' ';
243                 else if (c == '[' && ws.useBraces())
244                         ws.os() << "{}";
245                 else if (c == ' ' && ws.textMode())
246                         ws.os() << '\\';
247                 ws.pendingSpace(false);
248         } else if (ws.useBraces()) {
249                 if (c == '\'')
250                         ws.os() << "{}";
251                 ws.useBraces(false);
252         }
253         ws.os() << c;
254         if (c == '\n')
255                 ws.addlines(1);
256         ws.canBreakLine(c != '\n');
257         return ws;
258 }
259
260
261 TeXMathStream & operator<<(TeXMathStream & ws, int i)
262 {
263         if (ws.pendingBrace()) {
264                 ws.os() << '}';
265                 ws.pendingBrace(false);
266                 ws.textMode(true);
267         }
268         ws.os() << i;
269         ws.canBreakLine(true);
270         return ws;
271 }
272
273
274 TeXMathStream & operator<<(TeXMathStream & ws, unsigned int i)
275 {
276         if (ws.pendingBrace()) {
277                 ws.os() << '}';
278                 ws.pendingBrace(false);
279                 ws.textMode(true);
280         }
281         ws.os() << i;
282         ws.canBreakLine(true);
283         return ws;
284 }
285
286
287 //////////////////////////////////////////////////////////////////////
288
289
290 MathMLStream::MathMLStream(odocstream & os, std::string const & xmlns, bool xmlMode)
291         : os_(os), tab_(0), line_(0), in_text_(false), xmlns_(xmlns), xml_mode_(xmlMode)
292 {}
293
294
295 void MathMLStream::cr()
296 {
297         os() << '\n';
298         for (int i = 0; i < tab(); ++i)
299                 os() << ' ';
300 }
301
302
303 void MathMLStream::defer(docstring const & s)
304 {
305         deferred_ << s;
306 }
307
308
309 void MathMLStream::defer(string const & s)
310 {
311         deferred_ << from_utf8(s);
312 }
313
314
315 docstring MathMLStream::deferred() const
316 {
317         return deferred_.str();
318 }
319
320
321 MathMLStream & operator<<(MathMLStream & ms, MathAtom const & at)
322 {
323         at->mathmlize(ms);
324         return ms;
325 }
326
327
328 MathMLStream & operator<<(MathMLStream & ms, MathData const & ar)
329 {
330         mathmlize(ar, ms);
331         return ms;
332 }
333
334
335 MathMLStream & operator<<(MathMLStream & ms, char const * s)
336 {
337         ms.os() << s;
338         return ms;
339 }
340
341
342 MathMLStream & operator<<(MathMLStream & ms, char c)
343 {
344         ms.os() << c;
345         return ms;
346 }
347
348
349 MathMLStream & operator<<(MathMLStream & ms, char_type c)
350 {
351         ms.os().put(c);
352         return ms;
353 }
354
355
356 MathMLStream & operator<<(MathMLStream & ms, MTag const & t)
357 {
358         ++ms.tab();
359         ms.cr();
360         ms.os() << '<' << from_ascii(ms.namespacedTag(t.tag_));
361         if (!t.attr_.empty())
362                 ms.os() << " " << from_ascii(t.attr_);
363         ms << ">";
364         return ms;
365 }
366
367
368 MathMLStream & operator<<(MathMLStream & ms, MTagInline const & t)
369 {
370         ms.cr();
371         ms.os() << '<' << from_ascii(ms.namespacedTag(t.tag_));
372         if (!t.attr_.empty())
373                 ms.os() << " " << from_ascii(t.attr_);
374         ms << ">";
375         return ms;
376 }
377
378
379 MathMLStream & operator<<(MathMLStream & ms, ETag const & t)
380 {
381         ms.cr();
382         if (ms.tab() > 0)
383                 --ms.tab();
384         ms.os() << "</" << from_ascii(ms.namespacedTag(t.tag_)) << ">";
385         return ms;
386 }
387
388
389 MathMLStream & operator<<(MathMLStream & ms, ETagInline const & t)
390 {
391         ms.os() << "</" << from_ascii(ms.namespacedTag(t.tag_)) << ">";
392         return ms;
393 }
394
395
396 MathMLStream & operator<<(MathMLStream & ms, CTag const & t)
397 {
398         ms.cr();
399         ms.os() << "<" << from_ascii(ms.namespacedTag(t.tag_));
400     if (!t.attr_.empty())
401         ms.os() << " " << from_utf8(t.attr_);
402     ms.os() << "/>";
403         return ms;
404 }
405
406
407 MathMLStream & operator<<(MathMLStream & ms, docstring const & s)
408 {
409         ms.os() << s;
410         return ms;
411 }
412
413
414 //////////////////////////////////////////////////////////////////////
415
416
417 HtmlStream::HtmlStream(odocstream & os)
418         : os_(os), tab_(0), line_(0), in_text_(false)
419 {}
420
421
422 void HtmlStream::defer(docstring const & s)
423 {
424         deferred_ << s;
425 }
426
427
428 void HtmlStream::defer(string const & s)
429 {
430         deferred_ << from_utf8(s);
431 }
432
433
434 docstring HtmlStream::deferred() const
435 {
436         return deferred_.str();
437 }
438
439
440 HtmlStream & operator<<(HtmlStream & ms, MathAtom const & at)
441 {
442         at->htmlize(ms);
443         return ms;
444 }
445
446
447 HtmlStream & operator<<(HtmlStream & ms, MathData const & ar)
448 {
449         htmlize(ar, ms);
450         return ms;
451 }
452
453
454 HtmlStream & operator<<(HtmlStream & ms, char const * s)
455 {
456         ms.os() << s;
457         return ms;
458 }
459
460
461 HtmlStream & operator<<(HtmlStream & ms, char c)
462 {
463         ms.os() << c;
464         return ms;
465 }
466
467
468 HtmlStream & operator<<(HtmlStream & ms, char_type c)
469 {
470         ms.os().put(c);
471         return ms;
472 }
473
474
475 HtmlStream & operator<<(HtmlStream & ms, MTag const & t)
476 {
477         ms.os() << '<' << from_ascii(t.tag_);
478         if (!t.attr_.empty())
479                 ms.os() << " " << from_ascii(t.attr_);
480         ms << '>';
481         return ms;
482 }
483
484
485 HtmlStream & operator<<(HtmlStream & ms, ETag const & t)
486 {
487         ms.os() << "</" << from_ascii(t.tag_) << '>';
488         return ms;
489 }
490
491
492 HtmlStream & operator<<(HtmlStream & ms, docstring const & s)
493 {
494         ms.os() << s;
495         return ms;
496 }
497
498
499 //////////////////////////////////////////////////////////////////////
500
501
502 SetMode::SetMode(MathMLStream & ms, bool text)
503         : ms_(ms)
504 {
505         was_text_ = ms_.inText();
506         ms_.setTextMode(text);
507 }
508
509
510 SetMode::~SetMode()
511 {
512         ms_.setTextMode(was_text_);
513 }
514
515
516 //////////////////////////////////////////////////////////////////////
517
518
519 SetHTMLMode::SetHTMLMode(HtmlStream & os, bool text)
520         : os_(os)
521 {
522         was_text_ = os_.inText();
523         os_.setTextMode(text);
524 }
525
526
527 SetHTMLMode::~SetHTMLMode()
528 {
529         os_.setTextMode(was_text_);
530 }
531
532
533 //////////////////////////////////////////////////////////////////////
534
535
536 MapleStream & operator<<(MapleStream & ms, MathAtom const & at)
537 {
538         at->maple(ms);
539         return ms;
540 }
541
542
543 MapleStream & operator<<(MapleStream & ms, MathData const & ar)
544 {
545         maple(ar, ms);
546         return ms;
547 }
548
549
550 MapleStream & operator<<(MapleStream & ms, char const * s)
551 {
552         ms.os() << s;
553         return ms;
554 }
555
556
557 MapleStream & operator<<(MapleStream & ms, char c)
558 {
559         ms.os() << c;
560         return ms;
561 }
562
563
564 MapleStream & operator<<(MapleStream & ms, int i)
565 {
566         ms.os() << i;
567         return ms;
568 }
569
570
571 MapleStream & operator<<(MapleStream & ms, char_type c)
572 {
573         ms.os().put(c);
574         return ms;
575 }
576
577
578 MapleStream & operator<<(MapleStream & ms, docstring const & s)
579 {
580         ms.os() << s;
581         return ms;
582 }
583
584
585 //////////////////////////////////////////////////////////////////////
586
587
588 MaximaStream & operator<<(MaximaStream & ms, MathAtom const & at)
589 {
590         at->maxima(ms);
591         return ms;
592 }
593
594
595 MaximaStream & operator<<(MaximaStream & ms, MathData const & ar)
596 {
597         maxima(ar, ms);
598         return ms;
599 }
600
601
602 MaximaStream & operator<<(MaximaStream & ms, char const * s)
603 {
604         ms.os() << s;
605         return ms;
606 }
607
608
609 MaximaStream & operator<<(MaximaStream & ms, char c)
610 {
611         ms.os() << c;
612         return ms;
613 }
614
615
616 MaximaStream & operator<<(MaximaStream & ms, int i)
617 {
618         ms.os() << i;
619         return ms;
620 }
621
622
623 MaximaStream & operator<<(MaximaStream & ms, docstring const & s)
624 {
625         ms.os() << s;
626         return ms;
627 }
628
629
630 MaximaStream & operator<<(MaximaStream & ms, char_type c)
631 {
632         ms.os().put(c);
633         return ms;
634 }
635
636
637 //////////////////////////////////////////////////////////////////////
638
639
640 MathematicaStream & operator<<(MathematicaStream & ms, MathAtom const & at)
641 {
642         at->mathematica(ms);
643         return ms;
644 }
645
646
647 MathematicaStream & operator<<(MathematicaStream & ms, MathData const & ar)
648 {
649         mathematica(ar, ms);
650         return ms;
651 }
652
653
654 MathematicaStream & operator<<(MathematicaStream & ms, char const * s)
655 {
656         ms.os() << s;
657         return ms;
658 }
659
660
661 MathematicaStream & operator<<(MathematicaStream & ms, char c)
662 {
663         ms.os() << c;
664         return ms;
665 }
666
667
668 MathematicaStream & operator<<(MathematicaStream & ms, int i)
669 {
670         ms.os() << i;
671         return ms;
672 }
673
674
675 MathematicaStream & operator<<(MathematicaStream & ms, docstring const & s)
676 {
677         ms.os() << s;
678         return ms;
679 }
680
681
682 MathematicaStream & operator<<(MathematicaStream & ms, char_type c)
683 {
684         ms.os().put(c);
685         return ms;
686 }
687
688
689 //////////////////////////////////////////////////////////////////////
690
691
692 OctaveStream & operator<<(OctaveStream & ns, MathAtom const & at)
693 {
694         at->octave(ns);
695         return ns;
696 }
697
698
699 OctaveStream & operator<<(OctaveStream & ns, MathData const & ar)
700 {
701         octave(ar, ns);
702         return ns;
703 }
704
705
706 OctaveStream & operator<<(OctaveStream & ns, char const * s)
707 {
708         ns.os() << s;
709         return ns;
710 }
711
712
713 OctaveStream & operator<<(OctaveStream & ns, char c)
714 {
715         ns.os() << c;
716         return ns;
717 }
718
719
720 OctaveStream & operator<<(OctaveStream & ns, int i)
721 {
722         ns.os() << i;
723         return ns;
724 }
725
726
727 OctaveStream & operator<<(OctaveStream & ns, docstring const & s)
728 {
729         ns.os() << s;
730         return ns;
731 }
732
733
734 OctaveStream & operator<<(OctaveStream & ns, char_type c)
735 {
736         ns.os().put(c);
737         return ns;
738 }
739
740
741 OctaveStream & operator<<(OctaveStream & os, string const & s)
742 {
743         os.os() << from_utf8(s);
744         return os;
745 }
746
747
748 docstring convertDelimToXMLEscape(docstring const & name, bool xmlmode)
749 {
750         // For the basic symbols, no difference between XML and HTML.
751         if (name.size() == 1) {
752                 char_type const c = name[0];
753                 if (c == '<')
754                         return from_ascii("&lt;");
755                 else if (c == '>')
756                         return from_ascii("&gt;");
757                 else
758                         return name;
759         } else if (name.size() == 2 && name[0] == '\\') {
760                 char_type const c = name[1];
761                 if (c == '{')
762                         return from_ascii("&#123;");
763                 else if (c == '}')
764                         return from_ascii("&#125;");
765         }
766         MathWordList const & words = mathedWordList();
767         MathWordList::const_iterator it = words.find(name);
768         if (it != words.end()) {
769                 // Only difference between XML and HTML, based on the contents read by MathFactory.
770                 docstring const escape = xmlmode ? it->second.xmlname : it->second.htmlname;
771                 return escape;
772         }
773         LYXERR0("Unable to find `" << name <<"' in the mathWordList.");
774         return name;
775 }
776
777 } // namespace lyx