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
operator <<(NormalStream & ns,MathAtom const & at)37 NormalStream & operator<<(NormalStream & ns, MathAtom const & at)
38 {
39 at->normalize(ns);
40 return ns;
41 }
42
43
operator <<(NormalStream & ns,MathData const & ar)44 NormalStream & operator<<(NormalStream & ns, MathData const & ar)
45 {
46 normalize(ar, ns);
47 return ns;
48 }
49
50
operator <<(NormalStream & ns,docstring const & s)51 NormalStream & operator<<(NormalStream & ns, docstring const & s)
52 {
53 ns.os() << s;
54 return ns;
55 }
56
57
operator <<(NormalStream & ns,const string & s)58 NormalStream & operator<<(NormalStream & ns, const string & s)
59 {
60 ns.os() << from_utf8(s);
61 return ns;
62 }
63
64
operator <<(NormalStream & ns,char const * s)65 NormalStream & operator<<(NormalStream & ns, char const * s)
66 {
67 ns.os() << s;
68 return ns;
69 }
70
71
operator <<(NormalStream & ns,char c)72 NormalStream & operator<<(NormalStream & ns, char c)
73 {
74 ns.os() << c;
75 return ns;
76 }
77
78
operator <<(NormalStream & ns,int i)79 NormalStream & operator<<(NormalStream & ns, int i)
80 {
81 ns.os() << i;
82 return ns;
83 }
84
85
86
87 /////////////////////////////////////////////////////////////////
88
89
operator <<(WriteStream & ws,docstring const & s)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
WriteStream(otexrowstream & os,bool fragile,bool latex,OutputType output,Encoding const * encoding)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)
135 {}
136
137
~WriteStream()138 WriteStream::~WriteStream()
139 {
140 if (pendingbrace_)
141 os_ << '}';
142 else if (pendingspace_)
143 os_ << ' ';
144 }
145
146
addlines(unsigned int n)147 void WriteStream::addlines(unsigned int n)
148 {
149 line_ += n;
150 }
151
152
pendingSpace(bool how)153 void WriteStream::pendingSpace(bool how)
154 {
155 pendingspace_ = how;
156 }
157
158
pendingBrace(bool brace)159 void WriteStream::pendingBrace(bool brace)
160 {
161 pendingbrace_ = brace;
162 }
163
164
textMode(bool textmode)165 void WriteStream::textMode(bool textmode)
166 {
167 textmode_ = textmode;
168 }
169
170
lockedMode(bool locked)171 void WriteStream::lockedMode(bool locked)
172 {
173 locked_ = locked;
174 }
175
176
asciiOnly(bool ascii)177 void WriteStream::asciiOnly(bool ascii)
178 {
179 ascii_ = ascii;
180 }
181
182
changeRowEntry(TexRow::RowEntry entry)183 Changer WriteStream::changeRowEntry(TexRow::RowEntry entry)
184 {
185 return make_change(row_entry_, entry);
186 }
187
188
startOuterRow()189 bool WriteStream::startOuterRow()
190 {
191 if (TexRow::isNone(row_entry_))
192 return false;
193 return texrow().start(row_entry_);
194 }
195
196
operator <<(WriteStream & ws,MathAtom const & at)197 WriteStream & operator<<(WriteStream & ws, MathAtom const & at)
198 {
199 at->write(ws);
200 return ws;
201 }
202
203
operator <<(WriteStream & ws,MathData const & ar)204 WriteStream & operator<<(WriteStream & ws, MathData const & ar)
205 {
206 write(ar, ws);
207 return ws;
208 }
209
210
operator <<(WriteStream & ws,char const * s)211 WriteStream & operator<<(WriteStream & ws, char const * s)
212 {
213 ws << from_utf8(s);
214 return ws;
215 }
216
217
operator <<(WriteStream & ws,char c)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
operator <<(WriteStream & ws,int i)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
operator <<(WriteStream & ws,unsigned int i)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
MathStream(odocstream & os)272 MathStream::MathStream(odocstream & os)
273 : os_(os), tab_(0), line_(0), in_text_(false)
274 {}
275
276
cr()277 void MathStream::cr()
278 {
279 os() << '\n';
280 for (int i = 0; i < tab(); ++i)
281 os() << ' ';
282 }
283
284
defer(docstring const & s)285 void MathStream::defer(docstring const & s)
286 {
287 deferred_ << s;
288 }
289
290
defer(string const & s)291 void MathStream::defer(string const & s)
292 {
293 deferred_ << from_utf8(s);
294 }
295
296
deferred() const297 docstring MathStream::deferred() const
298 {
299 return deferred_.str();
300 }
301
302
operator <<(MathStream & ms,MathAtom const & at)303 MathStream & operator<<(MathStream & ms, MathAtom const & at)
304 {
305 at->mathmlize(ms);
306 return ms;
307 }
308
309
operator <<(MathStream & ms,MathData const & ar)310 MathStream & operator<<(MathStream & ms, MathData const & ar)
311 {
312 mathmlize(ar, ms);
313 return ms;
314 }
315
316
operator <<(MathStream & ms,char const * s)317 MathStream & operator<<(MathStream & ms, char const * s)
318 {
319 ms.os() << s;
320 return ms;
321 }
322
323
operator <<(MathStream & ms,char c)324 MathStream & operator<<(MathStream & ms, char c)
325 {
326 ms.os() << c;
327 return ms;
328 }
329
330
operator <<(MathStream & ms,char_type c)331 MathStream & operator<<(MathStream & ms, char_type c)
332 {
333 ms.os().put(c);
334 return ms;
335 }
336
337
operator <<(MathStream & ms,MTag const & t)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
operator <<(MathStream & ms,ETag const & t)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
operator <<(MathStream & ms,docstring const & s)360 MathStream & operator<<(MathStream & ms, docstring const & s)
361 {
362 ms.os() << s;
363 return ms;
364 }
365
366
367 //////////////////////////////////////////////////////////////////////
368
369
HtmlStream(odocstream & os)370 HtmlStream::HtmlStream(odocstream & os)
371 : os_(os), tab_(0), line_(0), in_text_(false)
372 {}
373
374
defer(docstring const & s)375 void HtmlStream::defer(docstring const & s)
376 {
377 deferred_ << s;
378 }
379
380
defer(string const & s)381 void HtmlStream::defer(string const & s)
382 {
383 deferred_ << from_utf8(s);
384 }
385
386
deferred() const387 docstring HtmlStream::deferred() const
388 {
389 return deferred_.str();
390 }
391
392
operator <<(HtmlStream & ms,MathAtom const & at)393 HtmlStream & operator<<(HtmlStream & ms, MathAtom const & at)
394 {
395 at->htmlize(ms);
396 return ms;
397 }
398
399
operator <<(HtmlStream & ms,MathData const & ar)400 HtmlStream & operator<<(HtmlStream & ms, MathData const & ar)
401 {
402 htmlize(ar, ms);
403 return ms;
404 }
405
406
operator <<(HtmlStream & ms,char const * s)407 HtmlStream & operator<<(HtmlStream & ms, char const * s)
408 {
409 ms.os() << s;
410 return ms;
411 }
412
413
operator <<(HtmlStream & ms,char c)414 HtmlStream & operator<<(HtmlStream & ms, char c)
415 {
416 ms.os() << c;
417 return ms;
418 }
419
420
operator <<(HtmlStream & ms,char_type c)421 HtmlStream & operator<<(HtmlStream & ms, char_type c)
422 {
423 ms.os().put(c);
424 return ms;
425 }
426
427
operator <<(HtmlStream & ms,MTag const & t)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
operator <<(HtmlStream & ms,ETag const & t)438 HtmlStream & operator<<(HtmlStream & ms, ETag const & t)
439 {
440 ms.os() << "</" << from_ascii(t.tag_) << '>';
441 return ms;
442 }
443
444
operator <<(HtmlStream & ms,docstring const & s)445 HtmlStream & operator<<(HtmlStream & ms, docstring const & s)
446 {
447 ms.os() << s;
448 return ms;
449 }
450
451
452 //////////////////////////////////////////////////////////////////////
453
454
SetMode(MathStream & os,bool text)455 SetMode::SetMode(MathStream & os, bool text)
456 : os_(os)
457 {
458 was_text_ = os_.inText();
459 os_.setTextMode(text);
460 }
461
462
~SetMode()463 SetMode::~SetMode()
464 {
465 os_.setTextMode(was_text_);
466 }
467
468
469 //////////////////////////////////////////////////////////////////////
470
471
SetHTMLMode(HtmlStream & os,bool text)472 SetHTMLMode::SetHTMLMode(HtmlStream & os, bool text)
473 : os_(os)
474 {
475 was_text_ = os_.inText();
476 os_.setTextMode(text);
477 }
478
479
~SetHTMLMode()480 SetHTMLMode::~SetHTMLMode()
481 {
482 os_.setTextMode(was_text_);
483 }
484
485
486 //////////////////////////////////////////////////////////////////////
487
488
operator <<(MapleStream & ms,MathAtom const & at)489 MapleStream & operator<<(MapleStream & ms, MathAtom const & at)
490 {
491 at->maple(ms);
492 return ms;
493 }
494
495
operator <<(MapleStream & ms,MathData const & ar)496 MapleStream & operator<<(MapleStream & ms, MathData const & ar)
497 {
498 maple(ar, ms);
499 return ms;
500 }
501
502
operator <<(MapleStream & ms,char const * s)503 MapleStream & operator<<(MapleStream & ms, char const * s)
504 {
505 ms.os() << s;
506 return ms;
507 }
508
509
operator <<(MapleStream & ms,char c)510 MapleStream & operator<<(MapleStream & ms, char c)
511 {
512 ms.os() << c;
513 return ms;
514 }
515
516
operator <<(MapleStream & ms,int i)517 MapleStream & operator<<(MapleStream & ms, int i)
518 {
519 ms.os() << i;
520 return ms;
521 }
522
523
operator <<(MapleStream & ms,char_type c)524 MapleStream & operator<<(MapleStream & ms, char_type c)
525 {
526 ms.os().put(c);
527 return ms;
528 }
529
530
operator <<(MapleStream & ms,docstring const & s)531 MapleStream & operator<<(MapleStream & ms, docstring const & s)
532 {
533 ms.os() << s;
534 return ms;
535 }
536
537
538 //////////////////////////////////////////////////////////////////////
539
540
operator <<(MaximaStream & ms,MathAtom const & at)541 MaximaStream & operator<<(MaximaStream & ms, MathAtom const & at)
542 {
543 at->maxima(ms);
544 return ms;
545 }
546
547
operator <<(MaximaStream & ms,MathData const & ar)548 MaximaStream & operator<<(MaximaStream & ms, MathData const & ar)
549 {
550 maxima(ar, ms);
551 return ms;
552 }
553
554
operator <<(MaximaStream & ms,char const * s)555 MaximaStream & operator<<(MaximaStream & ms, char const * s)
556 {
557 ms.os() << s;
558 return ms;
559 }
560
561
operator <<(MaximaStream & ms,char c)562 MaximaStream & operator<<(MaximaStream & ms, char c)
563 {
564 ms.os() << c;
565 return ms;
566 }
567
568
operator <<(MaximaStream & ms,int i)569 MaximaStream & operator<<(MaximaStream & ms, int i)
570 {
571 ms.os() << i;
572 return ms;
573 }
574
575
operator <<(MaximaStream & ms,docstring const & s)576 MaximaStream & operator<<(MaximaStream & ms, docstring const & s)
577 {
578 ms.os() << s;
579 return ms;
580 }
581
582
operator <<(MaximaStream & ms,char_type c)583 MaximaStream & operator<<(MaximaStream & ms, char_type c)
584 {
585 ms.os().put(c);
586 return ms;
587 }
588
589
590 //////////////////////////////////////////////////////////////////////
591
592
operator <<(MathematicaStream & ms,MathAtom const & at)593 MathematicaStream & operator<<(MathematicaStream & ms, MathAtom const & at)
594 {
595 at->mathematica(ms);
596 return ms;
597 }
598
599
operator <<(MathematicaStream & ms,MathData const & ar)600 MathematicaStream & operator<<(MathematicaStream & ms, MathData const & ar)
601 {
602 mathematica(ar, ms);
603 return ms;
604 }
605
606
operator <<(MathematicaStream & ms,char const * s)607 MathematicaStream & operator<<(MathematicaStream & ms, char const * s)
608 {
609 ms.os() << s;
610 return ms;
611 }
612
613
operator <<(MathematicaStream & ms,char c)614 MathematicaStream & operator<<(MathematicaStream & ms, char c)
615 {
616 ms.os() << c;
617 return ms;
618 }
619
620
operator <<(MathematicaStream & ms,int i)621 MathematicaStream & operator<<(MathematicaStream & ms, int i)
622 {
623 ms.os() << i;
624 return ms;
625 }
626
627
operator <<(MathematicaStream & ms,docstring const & s)628 MathematicaStream & operator<<(MathematicaStream & ms, docstring const & s)
629 {
630 ms.os() << s;
631 return ms;
632 }
633
634
operator <<(MathematicaStream & ms,char_type c)635 MathematicaStream & operator<<(MathematicaStream & ms, char_type c)
636 {
637 ms.os().put(c);
638 return ms;
639 }
640
641
642 //////////////////////////////////////////////////////////////////////
643
644
operator <<(OctaveStream & ns,MathAtom const & at)645 OctaveStream & operator<<(OctaveStream & ns, MathAtom const & at)
646 {
647 at->octave(ns);
648 return ns;
649 }
650
651
operator <<(OctaveStream & ns,MathData const & ar)652 OctaveStream & operator<<(OctaveStream & ns, MathData const & ar)
653 {
654 octave(ar, ns);
655 return ns;
656 }
657
658
operator <<(OctaveStream & ns,char const * s)659 OctaveStream & operator<<(OctaveStream & ns, char const * s)
660 {
661 ns.os() << s;
662 return ns;
663 }
664
665
operator <<(OctaveStream & ns,char c)666 OctaveStream & operator<<(OctaveStream & ns, char c)
667 {
668 ns.os() << c;
669 return ns;
670 }
671
672
operator <<(OctaveStream & ns,int i)673 OctaveStream & operator<<(OctaveStream & ns, int i)
674 {
675 ns.os() << i;
676 return ns;
677 }
678
679
operator <<(OctaveStream & ns,docstring const & s)680 OctaveStream & operator<<(OctaveStream & ns, docstring const & s)
681 {
682 ns.os() << s;
683 return ns;
684 }
685
686
operator <<(OctaveStream & ns,char_type c)687 OctaveStream & operator<<(OctaveStream & ns, char_type c)
688 {
689 ns.os().put(c);
690 return ns;
691 }
692
693
operator <<(OctaveStream & os,string const & s)694 OctaveStream & operator<<(OctaveStream & os, string const & s)
695 {
696 os.os() << from_utf8(s);
697 return os;
698 }
699
700
convertDelimToXMLEscape(docstring const & name)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("<");
707 else if (c == '>')
708 return from_ascii(">");
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
723