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