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