]> git.lyx.org Git - lyx.git/blob - src/mathed/MathStream.cpp
We only support gcc >= 4.9.
[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, ETag const & t)
369 {
370         ms.cr();
371         if (ms.tab() > 0)
372                 --ms.tab();
373         ms.os() << "</" << from_ascii(ms.namespacedTag(t.tag_)) << ">";
374         return ms;
375 }
376
377
378 MathMLStream & operator<<(MathMLStream & ms, CTag const & t)
379 {
380         ms.cr();
381         ms.os() << "<" << from_ascii(ms.namespacedTag(t.tag_));
382     if (!t.attr_.empty())
383         ms.os() << " " << from_utf8(t.attr_);
384     ms.os() << "/>";
385         return ms;
386 }
387
388
389 MathMLStream & operator<<(MathMLStream & ms, docstring const & s)
390 {
391         ms.os() << s;
392         return ms;
393 }
394
395
396 //////////////////////////////////////////////////////////////////////
397
398
399 HtmlStream::HtmlStream(odocstream & os)
400         : os_(os), tab_(0), line_(0), in_text_(false)
401 {}
402
403
404 void HtmlStream::defer(docstring const & s)
405 {
406         deferred_ << s;
407 }
408
409
410 void HtmlStream::defer(string const & s)
411 {
412         deferred_ << from_utf8(s);
413 }
414
415
416 docstring HtmlStream::deferred() const
417 {
418         return deferred_.str();
419 }
420
421
422 HtmlStream & operator<<(HtmlStream & ms, MathAtom const & at)
423 {
424         at->htmlize(ms);
425         return ms;
426 }
427
428
429 HtmlStream & operator<<(HtmlStream & ms, MathData const & ar)
430 {
431         htmlize(ar, ms);
432         return ms;
433 }
434
435
436 HtmlStream & operator<<(HtmlStream & ms, char const * s)
437 {
438         ms.os() << s;
439         return ms;
440 }
441
442
443 HtmlStream & operator<<(HtmlStream & ms, char c)
444 {
445         ms.os() << c;
446         return ms;
447 }
448
449
450 HtmlStream & operator<<(HtmlStream & ms, char_type c)
451 {
452         ms.os().put(c);
453         return ms;
454 }
455
456
457 HtmlStream & operator<<(HtmlStream & ms, MTag const & t)
458 {
459         ms.os() << '<' << from_ascii(t.tag_);
460         if (!t.attr_.empty())
461                 ms.os() << " " << from_ascii(t.attr_);
462         ms << '>';
463         return ms;
464 }
465
466
467 HtmlStream & operator<<(HtmlStream & ms, ETag const & t)
468 {
469         ms.os() << "</" << from_ascii(t.tag_) << '>';
470         return ms;
471 }
472
473
474 HtmlStream & operator<<(HtmlStream & ms, docstring const & s)
475 {
476         ms.os() << s;
477         return ms;
478 }
479
480
481 //////////////////////////////////////////////////////////////////////
482
483
484 SetMode::SetMode(MathMLStream & ms, bool text)
485         : ms_(ms)
486 {
487         was_text_ = ms_.inText();
488         ms_.setTextMode(text);
489 }
490
491
492 SetMode::~SetMode()
493 {
494         ms_.setTextMode(was_text_);
495 }
496
497
498 //////////////////////////////////////////////////////////////////////
499
500
501 SetHTMLMode::SetHTMLMode(HtmlStream & os, bool text)
502         : os_(os)
503 {
504         was_text_ = os_.inText();
505         os_.setTextMode(text);
506 }
507
508
509 SetHTMLMode::~SetHTMLMode()
510 {
511         os_.setTextMode(was_text_);
512 }
513
514
515 //////////////////////////////////////////////////////////////////////
516
517
518 MapleStream & operator<<(MapleStream & ms, MathAtom const & at)
519 {
520         at->maple(ms);
521         return ms;
522 }
523
524
525 MapleStream & operator<<(MapleStream & ms, MathData const & ar)
526 {
527         maple(ar, ms);
528         return ms;
529 }
530
531
532 MapleStream & operator<<(MapleStream & ms, char const * s)
533 {
534         ms.os() << s;
535         return ms;
536 }
537
538
539 MapleStream & operator<<(MapleStream & ms, char c)
540 {
541         ms.os() << c;
542         return ms;
543 }
544
545
546 MapleStream & operator<<(MapleStream & ms, int i)
547 {
548         ms.os() << i;
549         return ms;
550 }
551
552
553 MapleStream & operator<<(MapleStream & ms, char_type c)
554 {
555         ms.os().put(c);
556         return ms;
557 }
558
559
560 MapleStream & operator<<(MapleStream & ms, docstring const & s)
561 {
562         ms.os() << s;
563         return ms;
564 }
565
566
567 //////////////////////////////////////////////////////////////////////
568
569
570 MaximaStream & operator<<(MaximaStream & ms, MathAtom const & at)
571 {
572         at->maxima(ms);
573         return ms;
574 }
575
576
577 MaximaStream & operator<<(MaximaStream & ms, MathData const & ar)
578 {
579         maxima(ar, ms);
580         return ms;
581 }
582
583
584 MaximaStream & operator<<(MaximaStream & ms, char const * s)
585 {
586         ms.os() << s;
587         return ms;
588 }
589
590
591 MaximaStream & operator<<(MaximaStream & ms, char c)
592 {
593         ms.os() << c;
594         return ms;
595 }
596
597
598 MaximaStream & operator<<(MaximaStream & ms, int i)
599 {
600         ms.os() << i;
601         return ms;
602 }
603
604
605 MaximaStream & operator<<(MaximaStream & ms, docstring const & s)
606 {
607         ms.os() << s;
608         return ms;
609 }
610
611
612 MaximaStream & operator<<(MaximaStream & ms, char_type c)
613 {
614         ms.os().put(c);
615         return ms;
616 }
617
618
619 //////////////////////////////////////////////////////////////////////
620
621
622 MathematicaStream & operator<<(MathematicaStream & ms, MathAtom const & at)
623 {
624         at->mathematica(ms);
625         return ms;
626 }
627
628
629 MathematicaStream & operator<<(MathematicaStream & ms, MathData const & ar)
630 {
631         mathematica(ar, ms);
632         return ms;
633 }
634
635
636 MathematicaStream & operator<<(MathematicaStream & ms, char const * s)
637 {
638         ms.os() << s;
639         return ms;
640 }
641
642
643 MathematicaStream & operator<<(MathematicaStream & ms, char c)
644 {
645         ms.os() << c;
646         return ms;
647 }
648
649
650 MathematicaStream & operator<<(MathematicaStream & ms, int i)
651 {
652         ms.os() << i;
653         return ms;
654 }
655
656
657 MathematicaStream & operator<<(MathematicaStream & ms, docstring const & s)
658 {
659         ms.os() << s;
660         return ms;
661 }
662
663
664 MathematicaStream & operator<<(MathematicaStream & ms, char_type c)
665 {
666         ms.os().put(c);
667         return ms;
668 }
669
670
671 //////////////////////////////////////////////////////////////////////
672
673
674 OctaveStream & operator<<(OctaveStream & ns, MathAtom const & at)
675 {
676         at->octave(ns);
677         return ns;
678 }
679
680
681 OctaveStream & operator<<(OctaveStream & ns, MathData const & ar)
682 {
683         octave(ar, ns);
684         return ns;
685 }
686
687
688 OctaveStream & operator<<(OctaveStream & ns, char const * s)
689 {
690         ns.os() << s;
691         return ns;
692 }
693
694
695 OctaveStream & operator<<(OctaveStream & ns, char c)
696 {
697         ns.os() << c;
698         return ns;
699 }
700
701
702 OctaveStream & operator<<(OctaveStream & ns, int i)
703 {
704         ns.os() << i;
705         return ns;
706 }
707
708
709 OctaveStream & operator<<(OctaveStream & ns, docstring const & s)
710 {
711         ns.os() << s;
712         return ns;
713 }
714
715
716 OctaveStream & operator<<(OctaveStream & ns, char_type c)
717 {
718         ns.os().put(c);
719         return ns;
720 }
721
722
723 OctaveStream & operator<<(OctaveStream & os, string const & s)
724 {
725         os.os() << from_utf8(s);
726         return os;
727 }
728
729
730 docstring convertDelimToXMLEscape(docstring const & name, bool xmlmode)
731 {
732         // For the basic symbols, no difference between XML and HTML.
733         if (name.size() == 1) {
734                 char_type const c = name[0];
735                 if (c == '<')
736                         return from_ascii("&lt;");
737                 else if (c == '>')
738                         return from_ascii("&gt;");
739                 else
740                         return name;
741         } else if (name.size() == 2 && name[0] == '\\') {
742                 char_type const c = name[1];
743                 if (c == '{')
744                         return from_ascii("&#123;");
745                 else if (c == '}')
746                         return from_ascii("&#125;");
747         }
748         MathWordList const & words = mathedWordList();
749         MathWordList::const_iterator it = words.find(name);
750         if (it != words.end()) {
751                 // Only difference between XML and HTML, based on the contents read by MathFactory.
752                 docstring const escape = xmlmode ? it->second.xmlname : it->second.htmlname;
753                 return escape;
754         }
755         LYXERR0("Unable to find `" << name <<"' in the mathWordList.");
756         return name;
757 }
758
759 } // namespace lyx