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