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