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