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("&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
723