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