]> git.lyx.org Git - lyx.git/blob - src/tex2lyx/math.cpp
Fix #10778 (issue with CJK and language nesting)
[lyx.git] / src / tex2lyx / math.cpp
1 /**
2  * \file math.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 // {[(
12
13 #include <config.h>
14
15 #include "Preamble.h"
16 #include "tex2lyx.h"
17
18 #include <iostream>
19
20 using namespace std;
21
22 namespace lyx {
23
24
25 bool is_math_env(string const & name)
26 {
27         return known_math_environments.find(name) != known_math_environments.end();
28 }
29
30
31 bool is_display_math_env(string const & name)
32 {
33         CommandMap::const_iterator it = known_math_environments.find(name);
34         if (it != known_math_environments.end())
35                 if (!it->second.empty())
36                         return it->second.back() == displaymath;
37         return false;
38 }
39
40
41 void parse_math(Parser & p, ostream & os, unsigned flags, const mode_type mode)
42 {
43         while (p.good()) {
44                 Token const & t = p.get_token();
45
46 #ifdef FILEDEBUG
47                 cerr << "t: " << t << " flags: " << flags << "\n";
48 #endif
49
50                 if (flags & FLAG_ITEM) {
51                         if (t.cat() == catSpace)
52                                 continue;
53
54                         flags &= ~FLAG_ITEM;
55                         if (t.cat() == catBegin) {
56                                 // skip the brace and collect everything to the next matching
57                                 // closing brace
58                                 flags |= FLAG_BRACE_LAST;
59                                 continue;
60                         }
61
62                         // handle only this single token, leave the loop if done
63                         flags |= FLAG_LEAVE;
64                 }
65
66
67                 //
68                 // cat codes
69                 //
70                 if (t.cat() == catMath) {
71                         if (mode == MATHTEXT_MODE) {
72                                 // we are inside some text mode thing, so opening new math is allowed
73                                 Token const & n = p.get_token();
74                                 if (n.cat() == catMath) {
75                                         // TeX's $$...$$ syntax for displayed math
76                                         os << "\\[";
77                                         parse_math(p, os, FLAG_SIMPLE, MATH_MODE);
78                                         os << "\\]";
79                                         p.get_token(); // skip the second '$' token
80                                 } else {
81                                         // simple $...$  stuff
82                                         p.putback();
83                                         os << '$';
84                                         parse_math(p, os, FLAG_SIMPLE, MATH_MODE);
85                                         os << '$';
86                                 }
87                         }
88
89                         else if (flags & FLAG_SIMPLE) {
90                                 // this is the end of the formula
91                                 return;
92                         }
93
94                         else {
95                                 cerr << "\nmode: " << mode << endl;
96                                 p.error("something strange in the parser\n");
97                                 break;
98                         }
99                 }
100
101                 else if (t.cat() == catLetter ||
102                                t.cat() == catSuper ||
103                                t.cat() == catSub ||
104                                t.cat() == catOther ||
105                                t.cat() == catAlign ||
106                                t.cat() == catActive ||
107                                t.cat() == catParameter)
108                         os << t.cs();
109
110                 else if (t.cat() == catBegin) {
111                         os << '{';
112                         parse_math(p, os, FLAG_BRACE_LAST, mode);
113                         os << '}';
114                 }
115
116                 else if (t.cat() == catEnd) {
117                         if (flags & FLAG_BRACE_LAST)
118                                 return;
119                         os << "unexpected '}' in math\n";
120                 }
121
122                 else if (t.cat() == catComment) {
123                         if (!t.cs().empty())
124                                 os << t.asInput();
125                         else
126                                 // "%\n" combination
127                                 p.skip_spaces();
128                 }
129
130                 //
131                 // control sequences
132                 //
133
134                 else if (t.cs() == "(") {
135                         os << "\\(";
136                         parse_math(p, os, FLAG_SIMPLE2, MATH_MODE);
137                         os << "\\)";
138                 }
139
140                 else if (t.cs() == "[") {
141                         // special handling of a few common SW user quirks
142                         p.skip_spaces();
143                         //if (p.next_token().cs() ==
144                         os << "\\[";
145                         parse_math(p, os, FLAG_EQUATION, MATH_MODE);
146                         os << "\\]";
147                 }
148
149                 else if (t.cs() == "protect")
150                         // ignore \\protect, will hopefully be re-added during output
151                         ;
152
153                 else if (t.cs() == "begin") {
154                         string const name = p.getArg('{', '}');
155                         active_environments.push_back(name);
156                         os << "\\begin{" << name << "}";
157                         if (name == "tabular")
158                                 parse_math(p, os, FLAG_END, MATHTEXT_MODE);
159                         else
160                                 parse_math(p, os, FLAG_END, mode);
161                         os << "\\end{" << name << "}";
162                         active_environments.pop_back();
163                 }
164
165                 else if (t.cs() == "end") {
166                         if (flags & FLAG_END) {
167                                 // eat environment name
168                                 string const name = p.getArg('{', '}');
169                                 if (name != active_environment())
170                                         p.error("\\end{" + name + "} does not match \\begin{"
171                                                 + active_environment() + "}");
172                                 return;
173                         }
174                         p.error("found 'end' unexpectedly");
175                 }
176
177                 else if (t.cs() == ")") {
178                         if (flags & FLAG_SIMPLE2)
179                                 return;
180                         p.error("found '\\)' unexpectedly");
181                 }
182
183                 else if (t.cs() == "]") {
184                         if (flags & FLAG_EQUATION)
185                                 return;
186                         p.error("found '\\]' unexpectedly");
187                 }
188
189                 else if (t.cs() == "textrm" || t.cs() == "textsf" || t.cs() == "textbf"
190                                 || t.cs() == "texttt" || t.cs() == "textsc"
191                                 || t.cs() == "text" || t.cs() == "intertext") {
192                         os << '\\' << t.cs() << '{';
193                         parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
194                         os << '}';
195                 }
196
197                 else if (t.cs() == "tag") {
198                         os << '\\' << t.cs();
199                         if (p.next_token().asInput() == "*") {
200                                 p.get_token();
201                                 os << '*';
202                         }
203                         os << '{';
204                         parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
205                         os << '}';
206                 }
207
208                 else if (t.cs() == "mbox" || t.cs() == "fbox") {
209                         os << "\\" << t.cs() << '{';
210                         parse_math(p, os, FLAG_ITEM, MATHTEXT_MODE);
211                         os << '}';
212                 }
213
214                 else if (t.cs() == "\"") {
215                         string const name = p.verbatim_item();
216                              if (name == "a") os << '\xe4';
217                         else if (name == "o") os << '\xf6';
218                         else if (name == "u") os << '\xfc';
219                         else if (name == "A") os << '\xc4';
220                         else if (name == "O") os << '\xd6';
221                         else if (name == "U") os << '\xdc';
222                         else os << "\"{" << name << "}";
223                 }
224
225                 else if (t.cs() == "ss")
226                         os << "\xdf";
227
228                 else if (t.cs() == "cr") {
229                         // lyx can't handle \\cr
230                         cerr << "Warning: Converting TeX '\\cr' to LaTeX '\\\\'."
231                              << endl;
232                         os << "\\\\";
233                 }
234
235                 else if (t.cs() == "vref" || t.cs() == "vpageref") {
236                         os << t.asInput();
237                         preamble.registerAutomaticallyLoadedPackage("varioref");
238                 }
239
240                 else if (t.cs() == "textipa") {
241                         os << t.asInput();
242                         preamble.registerAutomaticallyLoadedPackage("tipa");
243                 }
244
245                 else
246                         os << t.asInput();
247
248                 if (flags & FLAG_LEAVE) {
249                         flags &= ~FLAG_LEAVE;
250                         break;
251                 }
252         }
253 }
254
255
256
257
258 // }])
259
260
261 } // namespace lyx