1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
25 // DVO: always use standard headers:
32 #include <sal/types.h>
33 #include <sal/macros.h>
35 /* @Man: hwp수식을 LaTeX으로 바꾸기 */
42 #define WS " \t\r\n\v\f"
44 #define EQ_CASE 0x01 // case sensitive cmd
45 #define EQ_ENV 0x02 // equiv to latex environment
46 #define EQ_ATOP 0x04 // must revert order
48 #define IS_WS(ch) (strchr(WS, ch))
49 #define IS_BINARY(ch) (strchr("+-<=>", ch))
52 #define STRICMP stricmp
54 #define STRICMP strcasecmp
57 // sub and sup scipt script status
58 enum { SCRIPT_NONE
, SCRIPT_SUB
, SCRIPT_SUP
, SCRIPT_ALL
};
60 static int eq_word(MzString
& outs
, istream
*strm
, int script
= SCRIPT_NONE
);
61 static bool eq_sentence(MzString
& outs
, istream
*strm
, const char *end
= 0);
64 const char *key
; // hwp math keyword
65 const char *latex
; // corresponding latex keywork
66 int nargs
; // # of argument
67 unsigned char flag
; // case sensitive?
70 static const hwpeq eq_tbl
[] = {
71 { "!=", "\\equiv ", 0, 0 },
72 { "#", "\\\\", 0, 0 },
73 { "+-", "\\pm ", 0, 0 },
74 { "-+", "\\mp ", 0, 0 },
75 { "<=", "\\leq ", 0, 0 },
76 { "==", "\\equiv ", 0, 0 },
77 { ">=", "\\geq ", 0, 0 },
82 { "acute", NULL
, 1, 0 },
83 { "aleph", NULL
, 0, 0 },
84 { "alpha", NULL
, 0, EQ_CASE
},
85 { "amalg", NULL
, 0, 0 },
86 { "and", NULL
, 0, 0 },
87 { "angle", NULL
, 0, 0 },
88 { "angstrom", NULL
, 0, 0 },
89 { "approx", NULL
, 0, 0 },
90 { "arc", NULL
, 0, 0 },
91 { "arccos", NULL
, 0, 0 },
92 { "arch", NULL
, 0, 0 },
93 { "arcsin", NULL
, 0, 0 },
94 { "arctan", NULL
, 0, 0 },
95 { "arg", NULL
, 0, 0 },
96 { "assert", "\\vdash", 0, 0 },
97 { "ast", NULL
, 0, 0 },
98 { "asymp", NULL
, 0, 0 },
99 { "atop", NULL
, 1, EQ_ATOP
},
100 { "backslash", NULL
, 0, 0 },
101 { "bar", NULL
, 1, 0 },
102 { "because", NULL
, 0, 0 },
103 { "beta", NULL
, 0, EQ_CASE
},
104 { "big", NULL
, 0, EQ_CASE
},
105 { "bigcap", NULL
, 0, 0 },
106 { "bigcirc", NULL
, 0, 0 },
107 { "bigcup", NULL
, 0, 0 },
108 { "bigg", NULL
, 0, EQ_CASE
},
109 { "bigodiv", NULL
, 0, 0 },
110 { "bigodot", NULL
, 0, 0 },
111 { "bigominus", NULL
, 0, 0 },
112 { "bigoplus", NULL
, 0, 0 },
113 { "bigotimes", NULL
, 0, 0 },
114 { "bigsqcap", NULL
, 0, 0 },
115 { "bigsqcup", NULL
, 0, 0 },
116 { "biguplus", NULL
, 0, 0 },
117 { "bigvee", NULL
, 0, 0 },
118 { "bigwedge", NULL
, 0, 0 },
119 { "binom", NULL
, 2, 0 },
120 { "bmatrix", NULL
, 0, EQ_ENV
},
121 { "bold", NULL
, 0, 0 },
122 { "bot", NULL
, 0, 0 },
123 { "breve", NULL
, 1, 0 },
124 { "buildrel", NULL
, 0, 0 }, // LATER
125 { "bullet", NULL
, 0, 0 },
126 { "cap", NULL
, 0, 0 },
127 { "cases", NULL
, 0, EQ_ENV
},
128 { "ccol", NULL
, 0, 0 }, /* 세로로 가운데 */
129 { "cdot", NULL
, 0, 0 },
130 { "cdots", NULL
, 0, 0 },
131 { "check", NULL
, 1, 0 },
132 { "chi", NULL
, 0, EQ_CASE
},
133 { "choose", NULL
, 0, EQ_ATOP
},
134 { "circ", NULL
, 0, 0 },
135 { "col", NULL
, 0, 0 }, // LATER
136 { "cong", NULL
, 0, 0 },
137 { "coprod", NULL
, 0, 0 },
138 { "cos", NULL
, 0, 0 },
139 { "cosec", NULL
, 0, 0 },
140 { "cosh", NULL
, 0, 0 },
141 { "cot", NULL
, 0, 0 },
142 { "coth", NULL
, 0, 0 },
143 { "cpile", NULL
, 0, 0 }, // LATER
144 { "csc", NULL
, 0, 0 },
145 { "cup", NULL
, 0, 0 },
146 { "dagger", NULL
, 0, 0 },
147 { "dashv", NULL
, 0, 0 },
148 { "ddagger", NULL
, 0, 0 },
149 { "ddot", NULL
, 1, 0 },
150 { "ddots", NULL
, 0, 0 },
151 { "def", NULL
, 0, 0 },
152 { "deg", NULL
, 0, 0 },
153 { "del", NULL
, 0, 0 },
154 { "delta", NULL
, 0, EQ_CASE
},
155 { "diamond", NULL
, 0, 0 },
156 { "dim", NULL
, 0, 0 },
157 { "div", NULL
, 0, 0 },
158 { "divide", NULL
, 0, 0 },
159 { "dline", NULL
, 0, 0 },
160 { "dmatrix", NULL
, 0, EQ_ENV
},
161 { "dot", NULL
, 1, 0 },
162 { "doteq", NULL
, 0, 0 },
163 { "dotsaxis", NULL
, 0, 0 },
164 { "dotsdiag", NULL
, 0, 0 },
165 { "dotslow", "\\ldots", 0, 0 },
166 { "dotsvert", "\\vdots", 0, 0 },
167 { "downarrow", NULL
, 0, EQ_CASE
},
168 { "dsum", "+", 0, 0 },
169 { "dyad", NULL
, 0, 0 }, // LATER
170 { "ell", NULL
, 0, 0 },
171 { "emptyset", NULL
, 0, 0 },
172 { "epsilon", NULL
, 0, EQ_CASE
},
173 { "eqalign", NULL
, 0, EQ_ENV
},
174 { "equiv", NULL
, 0, 0 },
175 { "eta", NULL
, 0, EQ_CASE
},
176 { "exarrow", NULL
, 0, 0 },
177 { "exist", "\\exists", 0, 0 },
178 { "exists", NULL
, 0, 0 },
179 { "exp", NULL
, 0, EQ_CASE
},
180 { "for", NULL
, 0, 0 },
181 { "forall", NULL
, 0, 0 },
182 { "from", "_", 1, 0 },
183 { "gamma", NULL
, 0, EQ_CASE
},
184 { "gcd", NULL
, 0, 0 },
185 { "ge", "\\geq", 0, 0 },
186 { "geq", NULL
, 0, 0 },
187 { "ggg", NULL
, 0, 0 },
188 { "grad", NULL
, 0, 0 },
189 { "grave", NULL
, 1, 0 },
190 { "hat", "\\widehat", 1, 0 },
191 { "hbar", NULL
, 0, 0 },
192 { "hom", NULL
, 0, 0 },
193 { "hookleft", NULL
, 0, 0 },
194 { "hookright", NULL
, 0, 0 },
195 { "identical", NULL
, 0, 0 }, // LATER
196 { "if", NULL
, 0, 0 },
197 { "imag", NULL
, 0, 0 },
198 { "image", NULL
, 0, 0 },
199 { "imath", NULL
, 0, 0 },
200 { "in", NULL
, 0, 0 },
201 { "inf", "\\infty", 0, 0 },
202 { "infinity", "\\infty", 0, 0 },
203 { "infty", NULL
, 0, 0 },
204 { "int", NULL
, 0, 0 },
205 { "integral", "\\int", 0, 0 },
206 { "inter", "\\bigcap", 0, 0 },
207 { "iota", NULL
, 0, EQ_CASE
},
208 { "iso", NULL
, 0, 0 }, // ams
209 { "it", NULL
, 0, 0 },
210 { "jmath", NULL
, 0, 0 },
211 { "kappa", NULL
, 0, EQ_CASE
},
212 { "ker", NULL
, 0, 0 },
213 { "lambda", NULL
, 0, EQ_CASE
},
214 { "land", NULL
, 0, 0 }, // LATER
215 { "langle", NULL
, 0, 0 },
216 { "larrow", "\\leftarrow", 0, EQ_CASE
},
217 { "lbrace", NULL
, 0, 0 },
218 { "lbrack", "[", 0, 0 },
219 { "lceil", NULL
, 0, 0 },
220 { "lcol", NULL
, 0, 0 }, // LATER
221 { "ldots", NULL
, 0, 0 },
222 { "le", NULL
, 0, 0 },
223 { "left", NULL
, 0, 0 },
224 { "leftarrow", NULL
, 0, EQ_CASE
},
225 { "leq", NULL
, 0, 0 },
226 { "lfloor", NULL
, 0, 0 },
227 { "lg", NULL
, 0, 0 },
228 { "lim", NULL
, 0, EQ_CASE
},
229 { "line", "\\vert", 0, 0 },
230 { "liter", "\\ell", 0, 0 },
231 { "lll", NULL
, 0, 0 }, // ams
232 { "ln", NULL
, 0, 0 },
233 { "log", NULL
, 0, 0 },
234 { "lor", "\\vee", 0, 0 },
235 { "lparen", "(", 0, 0 },
236 { "lpile", NULL
, 0, 0 }, // LATER
237 { "lrarrow", "\\leftrightarrow", 0, EQ_CASE
},
238 { "lrharpoons", "\\leftrightharpoons",0, 0 },
239 { "mapsto", NULL
, 0, 0 },
240 { "massert", "\\dashv", 0, 0 },
241 { "matrix", NULL
, 0, EQ_ENV
},
242 { "max", NULL
, 0, 0 },
243 { "mho", NULL
, 0, 0 }, // ams
244 { "min", NULL
, 0, 0 },
245 { "minusplus", NULL
, 0, 0 },
246 { "mit", "", 0, 0 }, // font
247 { "mod", "\\bmod", 0, 0 },
248 { "models", NULL
, 0, 0 },
249 { "msangle", NULL
, 0, 0 }, // LATER
250 { "mu", NULL
, 0, EQ_CASE
},
251 { "nabla", NULL
, 0, 0 },
252 { "ne", NULL
, 0, 0 },
253 { "nearrow", NULL
, 0, 0 },
254 { "neg", NULL
, 0, 0 },
255 { "neq", NULL
, 0, 0 },
256 { "nequiv", NULL
, 0, 0 },
257 { "ni", NULL
, 0, 0 },
258 { "not", NULL
, 0, 0 },
259 { "notin", NULL
, 0, 0 },
260 { "nu", NULL
, 0, EQ_CASE
},
261 { "nwarrow", NULL
, 0, 0 },
262 { "odiv", NULL
, 0, 0 },
263 { "odot", NULL
, 0, 0 },
264 { "oint", NULL
, 0, 0 },
265 { "omega", NULL
, 0, EQ_CASE
},
266 { "omicron", NULL
, 0, EQ_CASE
},
267 { "ominus", NULL
, 0, 0 },
268 { "oplus", NULL
, 0, 0 },
269 { "or ", NULL
, 0, 0 },
270 { "oslash", NULL
, 0, 0 },
271 { "otimes", NULL
, 0, 0 },
272 { "over", NULL
, 1, EQ_ATOP
},
273 { "overline", NULL
, 1, 0 },
274 { "owns", "\\ni", 0, 0 },
275 { "parallel", NULL
, 0, 0 },
276 { "partial", NULL
, 0, 0 },
277 { "phantom", NULL
, 0, 0 },
278 { "phi", NULL
, 0, EQ_CASE
},
279 { "pi", NULL
, 0, EQ_CASE
},
280 { "pile", NULL
, 0, 0 }, // LATER
281 { "plusminus", "\\pm", 0, 0 },
282 { "pmatrix", NULL
, 0, EQ_ENV
},
283 { "prec", NULL
, 0, 0 },
284 { "prep", NULL
, 0, 0 },
285 { "prime", NULL
, 0, 0 },
286 { "prod", NULL
, 0, 0 },
287 { "propto", NULL
, 0, 0 },
288 { "psi", NULL
, 0, EQ_CASE
},
289 { "rangle", NULL
, 0, 0 },
290 { "rarrow", "\\rightarrow", 0, EQ_CASE
},
291 { "rbrace", "]", 0, 0 },
292 { "rbrace", NULL
, 0, 0 },
293 { "rceil", NULL
, 0, 0 },
294 { "rcol", NULL
, 0, 0 }, // LATER
295 { "real", "\\Re", 0, 0 },
296 { "reimage", NULL
, 0, 0 },
297 { "rel", NULL
, 0, 0 },
298 { "rfloor", NULL
, 0, 0 },
299 { "rho", NULL
, 0, EQ_CASE
},
300 { "right", NULL
, 0, 0 },
301 { "rightarrow", NULL
, 0, EQ_CASE
},
302 { "rlharpoons", NULL
, 0, 0 },
303 { "rm", NULL
, 0, 0 },
304 { "root", "\\sqrt", 1, 0 },
305 { "rparen", ")", 0, 0 },
306 { "rpile", NULL
, 0, 0 }, // LATER
307 { "rtangle", NULL
, 0, 0 },
308 { "sangle", NULL
, 0, 0 },
309 { "scale", NULL
, 0, 0 },
310 { "searrow", NULL
, 0, 0 },
311 { "sec", NULL
, 0, 0 },
312 { "sigma", NULL
, 0, EQ_CASE
},
313 { "sim", NULL
, 0, 0 },
314 { "simeq", NULL
, 0, 0 },
315 { "sin", NULL
, 0, 0 },
316 { "sinh", NULL
, 0, 0 },
317 { "slash", NULL
, 0, 0 },
318 { "smallint", NULL
, 0, 0 },
319 { "smallinter", NULL
, 0, 0 },
320 { "smalloint", NULL
, 0, 0 },
321 { "smallprod", NULL
, 0, 0 },
322 { "smallsum", NULL
, 0, 0 },
323 { "smallunion", NULL
, 0, 0 },
324 { "smcoprod", NULL
, 0, 0 },
325 { "sqcap", NULL
, 0, 0 },
326 { "sqcup", NULL
, 0, 0 },
327 { "sqrt", NULL
, 1, 0 },
328 { "sqsubset", NULL
, 0, 0 },
329 { "sqsubseteq", NULL
, 0, 0 },
330 { "sqsupset", NULL
, 0, 0 },
331 { "sqsupseteq", NULL
, 0, 0 },
332 { "star", NULL
, 0, 0 },
333 { "sub", "_", 0, 0 },
334 { "subset", NULL
, 0, 0 },
335 { "subseteq", NULL
, 0, 0 },
336 { "succ", NULL
, 0, 0 },
337 { "sum", NULL
, 0, 0 },
338 { "sup", "^", 0, 0 },
339 { "superset", NULL
, 0, 0 },
340 { "supset", NULL
, 0, 0 },
341 { "supseteq", NULL
, 0, 0 },
342 { "swarrow", NULL
, 0, 0 },
343 { "tan", NULL
, 0, 0 },
344 { "tanh", NULL
, 0, 0 },
345 { "tau", NULL
, 0, EQ_CASE
},
346 { "therefore", NULL
, 0, 0 },
347 { "theta", NULL
, 0, EQ_CASE
},
348 { "tilde", "\\widetilde", 1, 0 },
349 { "times", NULL
, 0, 0 },
351 { "top", NULL
, 0, 0 },
352 { "triangle", NULL
, 0, 0 },
353 { "triangled", NULL
, 0, 0 },
354 { "trianglel", NULL
, 0, 0 },
355 { "triangler", NULL
, 0, 0 },
356 { "triangleu", NULL
, 0, 0 },
357 { "udarrow", "\\updownarrow",0, EQ_CASE
},
358 { "under", "\\underline", 1, 0 },
359 { "underline", "\\underline", 1, 0 },
360 { "union", "\\bigcup", 0, 0 },
361 { "uparrow", NULL
, 0, EQ_CASE
},
362 { "uplus", NULL
, 0, 0 },
363 { "upsilon", NULL
, 0, EQ_CASE
},
364 { "varepsilon", NULL
, 0, 0 },
365 { "varphi", NULL
, 0, 0 },
366 { "varpi", NULL
, 0, 0 },
367 { "varrho", NULL
, 0, 0 },
368 { "varsigma", NULL
, 0, 0 },
369 { "vartheta", NULL
, 0, 0 },
370 { "varupsilon", NULL
, 0, 0 },
371 { "vdash", NULL
, 0, 0 },
372 { "vdots", NULL
, 0, 0 },
373 { "vec", NULL
, 1, 0 },
374 { "vee", NULL
, 0, 0 },
375 { "vert", NULL
, 0, 0 },
376 { "wedge", NULL
, 0, 0 },
377 { "wp", NULL
, 0, 0 },
378 { "xi", NULL
, 0, EQ_CASE
},
379 { "xor", NULL
, 0, 0 },
380 { "zeta", NULL
, 0, EQ_CASE
}
383 static const hwpeq
*lookup_eqn(char *str
)
385 static const int eqCount
= SAL_N_ELEMENTS(eq_tbl
);
386 int l
= 0, r
= eqCount
;
387 const hwpeq
*result
= 0;
390 const int m
= (l
+ r
) / 2;
391 const int k
= strcmp(eq_tbl
[m
].key
, str
);
404 /* 첫자만 대문자이거나 전부 대문자면 소문자로 바꾼다. */
405 void make_keyword( char *keyword
, const char *token
)
409 int len
= strlen(token
);
416 memcpy(keyword
, token
, len
);
419 if( (token
[0] & 0x80) || islower(token
[0]) || strlen(token
) < 2 )
422 int capital
= isupper(keyword
[1]);
423 for( ptr
= keyword
+ 2; *ptr
&& result
; ptr
++ )
426 (!capital
&& isupper(*ptr
)) ||
427 (capital
&& islower(*ptr
)) )
439 *ptr
= sal::static_int_cast
<char>(tolower(*ptr
));
446 // token reading function
452 eq_stack() { strm
= 0; };
453 bool state(istream
*s
) {
454 if( strm
!= s
) { white
= 0; token
= 0; }
455 return token
.length() != 0;
459 static eq_stack
*stk
= 0;
461 void push_token(MzString
&white
, MzString
&token
, istream
*strm
)
464 assert(stk
->token
.length() == 0);
474 /* control char, control sequence, binary sequence,
475 alphabet string, sigle character */
476 static int next_token(MzString
&white
, MzString
&token
, istream
*strm
)
480 if( stk
->state(strm
) ) {
485 return token
.length();
490 if( !strm
->good() || (ch
= strm
->get()) == EOF
)
495 do white
<< (char) ch
;
496 while( IS_WS(ch
= strm
->get()) );
499 if( ch
== '\\' || ch
& 0x80 || isalpha(ch
) ) {
507 } while( ch
!= EOF
&& (ch
& 0x80 || isalpha(ch
)) ) ;
508 strm
->putback(sal::static_int_cast
<char>(ch
));
509 /* sub, sub, over, atop 특수 처리
510 그 이유는 next_state()에 영향을 미치기 때문이다.
512 if( !STRICMP("sub", token
) || !STRICMP("from", token
) ||
513 !STRICMP("sup", token
) || !STRICMP("to", token
) ||
514 !STRICMP("over", token
) || !STRICMP("atop", token
) ||
515 !STRICMP("left", token
) || !STRICMP("right", token
) )
518 make_keyword(buf
, token
);
521 if( !token
.compare("sub") || !token
.compare("from") )
523 if( !token
.compare("sup") || !token
.compare("to") )
526 else if( IS_BINARY(ch
) ) {
527 do token
<< (char) ch
;
528 while( IS_BINARY(ch
= strm
->get()) );
529 strm
->putback(sal::static_int_cast
<char>(ch
));
531 else if( isdigit(ch
) ) {
532 do token
<< (char) ch
;
533 while( isdigit(ch
= strm
->get()) );
534 strm
->putback(sal::static_int_cast
<char>(ch
));
539 return token
.length();
542 static int read_white_space(MzString
& outs
, istream
*strm
)
546 if( stk
->state(strm
) ) {
549 result
= stk
->token
[0];
553 while( IS_WS(ch
= strm
->get()) )
555 strm
->putback(sal::static_int_cast
<char>(ch
));
561 /* 인수가 필요하지 않은 경우 각 항목간의 구분은 space와 brace
562 sqrt {ab}c = sqrt{ab} c
566 sqrt 등과 같이 인수가 있는 형식 정리
569 1 이상의 인수가 있는 경우 인수들간의 역백은 없앤다.
570 \frac a b -> frac{a}{b}
572 a over b -> {a}over{b}
575 static int eq_word(MzString
& outs
, istream
*strm
, int status
)
577 MzString token
, white
, state
;
582 next_token(white
, token
, strm
);
583 if (token
.length() <= 0)
587 if( token
.compare("{") == 0 ) {
588 state
<< white
<< token
;
589 eq_sentence(state
, strm
, "}");
591 else if( token
.compare("left") == 0 ) {
592 state
<< white
<< token
;
593 next_token(white
, token
, strm
);
594 state
<< white
<< token
;
596 eq_sentence(state
, strm
, "right");
598 next_token(white
, token
, strm
);
599 state
<< white
<< token
;
603 int script_status
= SCRIPT_NONE
;
605 state
<< white
<< token
;
606 make_keyword(keyword
, token
);
607 if( token
[0] == '^' )
608 script_status
|= SCRIPT_SUP
;
609 else if( token
[0] == '_' )
610 script_status
|= SCRIPT_SUB
;
612 script_status
= SCRIPT_NONE
;
614 if( 0 != (eq
= lookup_eqn(keyword
)) ) {
615 int nargs
= eq
->nargs
;
617 const int ch
= read_white_space(state
, strm
);
618 if( ch
!= '{' ) state
<< '{';
619 eq_word(state
, strm
, script_status
);
620 if( ch
!= '{' ) state
<< '}';
624 if( !next_token(white
, token
, strm
) )
626 // end loop and restart with this
627 if( (token
[0] == '^' && status
&& !(status
& SCRIPT_SUP
)) ||
628 (token
[0] == '_' && status
&& !(status
& SCRIPT_SUB
)) ||
629 strcmp("over", token
) == 0 || strcmp("atop", token
) == 0 ||
630 strchr("{}#&`", token
[0]) ||
631 (!strchr("^_", token
[0]) && white
.length()) )
633 push_token(white
, token
, strm
);
643 static bool eq_sentence(MzString
& outs
, istream
*strm
, const char *end
)
646 MzString white
, token
;
647 bool multiline
= false;
649 read_white_space(outs
, strm
);
650 while( eq_word(state
, strm
) ) {
651 if( !next_token(white
, token
, strm
) ||
652 (end
&& strcmp(token
.c_str(), end
) == 0) )
654 state
<< white
<< token
;
657 push_token(white
, token
, strm
);
658 if( !token
.compare("atop") || !token
.compare("over") )
659 outs
<< '{' << state
<< '}';
661 if( !token
.compare("#") )
666 read_white_space(outs
, strm
);
672 static char eq2ltxconv(MzString
& sstr
, istream
*strm
, const char *sentinel
)
674 MzString white
, token
;
679 while( 0 != (result
= next_token(white
, token
, strm
)) ) {
680 if( sentinel
&& (result
== 1) && strchr(sentinel
, token
[0]) )
682 make_keyword(key
, token
);
683 if( (eq
= lookup_eqn(key
)) != 0 ) {
685 strcpy(key
, eq
->latex
);
688 strcpy(key
+ 1, eq
->key
);
690 if( (eq
->flag
& EQ_CASE
) && isupper(token
[0]) )
691 key
[1] = sal::static_int_cast
<char>(toupper(key
[1]));
695 if( token
[0] == '{' ) { // grouping
696 sstr
<< white
<< token
;
697 eq2ltxconv(sstr
, strm
, "}");
700 else if( eq
&& (eq
->flag
& EQ_ENV
) ) {
701 next_token(white
, token
, strm
);
702 if( token
[0] != '{' )
704 sstr
<< "\\begin" << "{" << eq
->key
<< "}" << ENDL
;
705 eq2ltxconv(sstr
, strm
, "}");
706 if( sstr
[sstr
.length() - 1] != '\n' )
708 sstr
<< "\\end" << "{" << eq
->key
<< "}" << ENDL
;
710 else if( eq
&& (eq
->flag
& EQ_ATOP
) ) {
711 if( sstr
.length() == 0 )
714 int pos
= sstr
.rfind('}');
716 sstr
.replace(pos
, ' ');
719 while( (ch
= strm
->get()) != EOF
&& IS_WS(ch
) )
724 eq2ltxconv(sstr
, strm
, "}");
729 sstr
<< white
<< token
;
734 void eq2latex(MzString
& outs
, char *s
)
742 istringstream
tstrm(s
);
743 bool eqnarray
= eq_sentence(tstr
, &tstrm
);
744 istringstream
strm(tstr
.c_str());
747 outs
<< "\\begin{array}{rllll}" << ENDL
;
748 eq2ltxconv(outs
, &strm
, 0);
751 outs
<< "\\end{array}" << ENDL
;
756 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */