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