update dev300-m58
[ooovba.git] / hwpfilter / source / hwpeq.cpp
blob915714d4148547fb4bc77c6003dd3d111bfeac17
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hwpeq.cpp,v $
11 * $Revision: 1.6 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
29 ************************************************************************/
31 //#include "stdafx.h"
33 #include <assert.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <ctype.h>
38 // DVO: always use standard headers:
39 #include <istream>
40 #include <sstream>
41 using namespace std;
43 #include "mzstring.h"
44 #include "hwpeq.h"
45 #include <sal/types.h>
46 //#define TEST
47 //#define DEBUG
50 /* @Man: hwp¼ö½ÄÀ» LaTeXÀ¸·Î ¹Ù²Ù±â */
51 #ifdef WIN32
52 # define ENDL "\r\n"
53 #else /* !WIN32 */
54 # define ENDL "\n"
55 #endif
57 #define WS " \t\r\n\v\f"
59 #define EQ_CASE 0x01 // case sensitive cmd
60 #define EQ_ENV 0x02 // equiv to latex environment
61 #define EQ_ATOP 0x04 // must revert order
63 #define IS_WS(ch) (strchr(WS, ch))
64 #define IS_BINARY(ch) (strchr("+-<=>", ch))
66 #ifdef WIN32
67 #define STRICMP stricmp
68 #else
69 #define STRICMP strcasecmp
70 #endif
72 // sub and sup scipt script status
73 enum { SCRIPT_NONE, SCRIPT_SUB, SCRIPT_SUP, SCRIPT_ALL};
75 static int eq_word(MzString& outs, istream *strm, int script = SCRIPT_NONE);
76 static bool eq_sentence(MzString& outs, istream *strm, const char *end = 0);
78 struct hwpeq {
79 const char *key; // hwp math keyword
80 const char *latex; // corresponding latex keywork
81 int nargs; // # of argument
82 unsigned char flag; // case sensitive?
85 static hwpeq eq_tbl[] = {
86 { "!=", "\\equiv ", 0, 0 },
87 { "#", "\\\\", 0, 0 },
88 { "+-", "\\pm ", 0, 0 },
89 { "-+", "\\mp ", 0, 0 },
90 { "<=", "\\leq ", 0, 0 },
91 { "==", "\\equiv ", 0, 0 },
92 { ">=", "\\geq ", 0, 0 },
93 { "Pr", NULL, 0, 0 },
94 { "^", "^", 1, 0 },
95 { "_", "_", 1, 0 },
96 { "`", "\\;", 0, 0 },
97 { "acute", NULL, 1, 0 },
98 { "aleph", NULL, 0, 0 },
99 { "alpha", NULL, 0, EQ_CASE },
100 { "amalg", NULL, 0, 0 },
101 { "and", NULL, 0, 0 },
102 { "angle", NULL, 0, 0 },
103 { "angstrom", NULL, 0, 0 },
104 { "approx", NULL, 0, 0 },
105 { "arc", NULL, 0, 0 },
106 { "arccos", NULL, 0, 0 },
107 { "arch", NULL, 0, 0 },
108 { "arcsin", NULL, 0, 0 },
109 { "arctan", NULL, 0, 0 },
110 { "arg", NULL, 0, 0 },
111 { "assert", "\\vdash", 0, 0 },
112 { "ast", NULL, 0, 0 },
113 { "asymp", NULL, 0, 0 },
114 { "atop", NULL, 1, EQ_ATOP },
115 { "backslash", NULL, 0, 0 },
116 { "bar", NULL, 1, 0 },
117 { "because", NULL, 0, 0 },
118 { "beta", NULL, 0, EQ_CASE },
119 { "big", NULL, 0, EQ_CASE },
120 { "bigcap", NULL, 0, 0 },
121 { "bigcirc", NULL, 0, 0 },
122 { "bigcup", NULL, 0, 0 },
123 { "bigg", NULL, 0, EQ_CASE },
124 { "bigodiv", NULL, 0, 0 },
125 { "bigodot", NULL, 0, 0 },
126 { "bigominus", NULL, 0, 0 },
127 { "bigoplus", NULL, 0, 0 },
128 { "bigotimes", NULL, 0, 0 },
129 { "bigsqcap", NULL, 0, 0 },
130 { "bigsqcup", NULL, 0, 0 },
131 { "biguplus", NULL, 0, 0 },
132 { "bigvee", NULL, 0, 0 },
133 { "bigwedge", NULL, 0, 0 },
134 { "binom", NULL, 2, 0 },
135 { "bmatrix", NULL, 0, EQ_ENV },
136 { "bold", NULL, 0, 0 },
137 { "bot", NULL, 0, 0 },
138 { "breve", NULL, 1, 0 },
139 { "buildrel", NULL, 0, 0 }, // LATER
140 { "bullet", NULL, 0, 0 },
141 { "cap", NULL, 0, 0 },
142 { "cases", NULL, 0, EQ_ENV },
143 { "ccol", NULL, 0, 0 }, /* ¼¼·Î·Î °¡¿îµ¥ */
144 { "cdot", NULL, 0, 0 },
145 { "cdots", NULL, 0, 0 },
146 { "check", NULL, 1, 0 },
147 { "chi", NULL, 0, EQ_CASE },
148 { "choose", NULL, 0, EQ_ATOP },
149 { "circ", NULL, 0, 0 },
150 { "col", NULL, 0, 0 }, // LATER
151 { "cong", NULL, 0, 0 },
152 { "coprod", NULL, 0, 0 },
153 { "cos", NULL, 0, 0 },
154 { "cosec", NULL, 0, 0 },
155 { "cosh", NULL, 0, 0 },
156 { "cot", NULL, 0, 0 },
157 { "coth", NULL, 0, 0 },
158 { "cpile", NULL, 0, 0 }, // LATER
159 { "csc", NULL, 0, 0 },
160 { "cup", NULL, 0, 0 },
161 { "dagger", NULL, 0, 0 },
162 { "dashv", NULL, 0, 0 },
163 { "ddagger", NULL, 0, 0 },
164 { "ddot", NULL, 1, 0 },
165 { "ddots", NULL, 0, 0 },
166 { "def", NULL, 0, 0 },
167 { "deg", NULL, 0, 0 },
168 { "del", NULL, 0, 0 },
169 { "delta", NULL, 0, EQ_CASE },
170 { "diamond", NULL, 0, 0 },
171 { "dim", NULL, 0, 0 },
172 { "div", NULL, 0, 0 },
173 { "divide", NULL, 0, 0 },
174 { "dline", NULL, 0, 0 },
175 { "dmatrix", NULL, 0, EQ_ENV },
176 { "dot", NULL, 1, 0 },
177 { "doteq", NULL, 0, 0 },
178 { "dotsaxis", NULL, 0, 0 },
179 { "dotsdiag", NULL, 0, 0 },
180 { "dotslow", "\\ldots", 0, 0 },
181 { "dotsvert", "\\vdots", 0, 0 },
182 { "downarrow", NULL, 0, EQ_CASE },
183 { "dsum", "+", 0, 0 },
184 { "dyad", NULL, 0, 0 }, // LATER
185 { "ell", NULL, 0, 0 },
186 { "emptyset", NULL, 0, 0 },
187 { "epsilon", NULL, 0, EQ_CASE },
188 { "eqalign", NULL, 0, EQ_ENV },
189 { "equiv", NULL, 0, 0 },
190 { "eta", NULL, 0, EQ_CASE },
191 { "exarrow", NULL, 0, 0 },
192 { "exist", "\\exists", 0, 0 },
193 { "exists", NULL, 0, 0 },
194 { "exp", NULL, 0, EQ_CASE },
195 { "for", NULL, 0, 0 },
196 { "forall", NULL, 0, 0 },
197 { "from", "_", 1, 0 },
198 { "gamma", NULL, 0, EQ_CASE },
199 { "gcd", NULL, 0, 0 },
200 { "ge", "\\geq", 0, 0 },
201 { "geq", NULL, 0, 0 },
202 { "ggg", NULL, 0, 0 },
203 { "grad", NULL, 0, 0 },
204 { "grave", NULL, 1, 0 },
205 { "hat", "\\widehat", 1, 0 },
206 { "hbar", NULL, 0, 0 },
207 { "hom", NULL, 0, 0 },
208 { "hookleft", NULL, 0, 0 },
209 { "hookright", NULL, 0, 0 },
210 { "identical", NULL, 0, 0 }, // LATER
211 { "if", NULL, 0, 0 },
212 { "imag", NULL, 0, 0 },
213 { "image", NULL, 0, 0 },
214 { "imath", NULL, 0, 0 },
215 { "in", NULL, 0, 0 },
216 { "inf", "\\infty", 0, 0 },
217 { "infinity", "\\infty", 0, 0 },
218 { "infty", NULL, 0, 0 },
219 { "int", NULL, 0, 0 },
220 { "integral", "\\int", 0, 0 },
221 { "inter", "\\bigcap", 0, 0 },
222 { "iota", NULL, 0, EQ_CASE },
223 { "iso", NULL, 0, 0 }, // ams
224 { "it", NULL, 0, 0 },
225 { "jmath", NULL, 0, 0 },
226 { "kappa", NULL, 0, EQ_CASE },
227 { "ker", NULL, 0, 0 },
228 { "lambda", NULL, 0, EQ_CASE },
229 { "land", NULL, 0, 0 }, // LATER
230 { "langle", NULL, 0, 0 },
231 { "larrow", "\\leftarrow", 0, EQ_CASE },
232 { "lbrace", NULL, 0, 0 },
233 { "lbrack", "[", 0, 0 },
234 { "lceil", NULL, 0, 0 },
235 { "lcol", NULL, 0, 0 }, // LATER
236 { "ldots", NULL, 0, 0 },
237 { "le", NULL, 0, 0 },
238 { "left", NULL, 0, 0 },
239 { "leftarrow", NULL, 0, EQ_CASE },
240 { "leq", NULL, 0, 0 },
241 { "lfloor", NULL, 0, 0 },
242 { "lg", NULL, 0, 0 },
243 { "lim", NULL, 0, EQ_CASE },
244 { "line", "\\vert", 0, 0 },
245 { "liter", "\\ell", 0, 0 },
246 { "lll", NULL, 0, 0 }, // ams
247 { "ln", NULL, 0, 0 },
248 { "log", NULL, 0, 0 },
249 { "lor", "\\vee", 0, 0 },
250 { "lparen", "(", 0, 0 },
251 { "lpile", NULL, 0, 0 }, // LATER
252 { "lrarrow", "\\leftrightarrow", 0, EQ_CASE },
253 { "lrharpoons", "\\leftrightharpoons",0, 0 },
254 { "mapsto", NULL, 0, 0 },
255 { "massert", "\\dashv", 0, 0 },
256 { "matrix", NULL, 0, EQ_ENV },
257 { "max", NULL, 0, 0 },
258 { "mho", NULL, 0, 0 }, // ams
259 { "min", NULL, 0, 0 },
260 { "minusplus", NULL, 0, 0 },
261 { "mit", "", 0, 0 }, // font
262 { "mod", "\\bmod", 0, 0 },
263 { "models", NULL, 0, 0 },
264 { "msangle", NULL, 0, 0 }, // LATER
265 { "mu", NULL, 0, EQ_CASE },
266 { "nabla", NULL, 0, 0 },
267 { "ne", NULL, 0, 0 },
268 { "nearrow", NULL, 0, 0 },
269 { "neg", NULL, 0, 0 },
270 { "neq", NULL, 0, 0 },
271 { "nequiv", NULL, 0, 0 },
272 { "ni", NULL, 0, 0 },
273 { "not", NULL, 0, 0 },
274 { "notin", NULL, 0, 0 },
275 { "nu", NULL, 0, EQ_CASE },
276 { "nwarrow", NULL, 0, 0 },
277 { "odiv", NULL, 0, 0 },
278 { "odot", NULL, 0, 0 },
279 { "oint", NULL, 0, 0 },
280 { "omega", NULL, 0, EQ_CASE },
281 { "omicron", NULL, 0, EQ_CASE },
282 { "ominus", NULL, 0, 0 },
283 { "oplus", NULL, 0, 0 },
284 { "or ", NULL, 0, 0 },
285 { "oslash", NULL, 0, 0 },
286 { "otimes", NULL, 0, 0 },
287 { "over", NULL, 1, EQ_ATOP },
288 { "overline", NULL, 1, 0 },
289 { "owns", "\\ni", 0, 0 },
290 { "parallel", NULL, 0, 0 },
291 { "partial", NULL, 0, 0 },
292 { "phantom", NULL, 0, 0 },
293 { "phi", NULL, 0, EQ_CASE },
294 { "pi", NULL, 0, EQ_CASE },
295 { "pile", NULL, 0, 0 }, // LATER
296 { "plusminus", "\\pm", 0, 0 },
297 { "pmatrix", NULL, 0, EQ_ENV },
298 { "prec", NULL, 0, 0 },
299 { "prep", NULL, 0, 0 },
300 { "prime", NULL, 0, 0 },
301 { "prod", NULL, 0, 0 },
302 { "propto", NULL, 0, 0 },
303 { "psi", NULL, 0, EQ_CASE },
304 { "rangle", NULL, 0, 0 },
305 { "rarrow", "\\rightarrow", 0, EQ_CASE },
306 { "rbrace", "]", 0, 0 },
307 { "rbrace", NULL, 0, 0 },
308 { "rceil", NULL, 0, 0 },
309 { "rcol", NULL, 0, 0 }, // LATER
310 { "real", "\\Re", 0, 0 },
311 { "reimage", NULL, 0, 0 },
312 { "rel", NULL, 0, 0 },
313 { "rfloor", NULL, 0, 0 },
314 { "rho", NULL, 0, EQ_CASE },
315 { "right", NULL, 0, 0 },
316 { "rightarrow", NULL, 0, EQ_CASE },
317 { "rlharpoons", NULL, 0, 0 },
318 { "rm", NULL, 0, 0 },
319 { "root", "\\sqrt", 1, 0 },
320 { "rparen", ")", 0, 0 },
321 { "rpile", NULL, 0, 0 }, // LATER
322 { "rtangle", NULL, 0, 0 },
323 { "sangle", NULL, 0, 0 },
324 { "scale", NULL, 0, 0 },
325 { "searrow", NULL, 0, 0 },
326 { "sec", NULL, 0, 0 },
327 { "sigma", NULL, 0, EQ_CASE },
328 { "sim", NULL, 0, 0 },
329 { "simeq", NULL, 0, 0 },
330 { "sin", NULL, 0, 0 },
331 { "sinh", NULL, 0, 0 },
332 { "slash", NULL, 0, 0 },
333 { "smallint", NULL, 0, 0 },
334 { "smallinter", NULL, 0, 0 },
335 { "smalloint", NULL, 0, 0 },
336 { "smallprod", NULL, 0, 0 },
337 { "smallsum", NULL, 0, 0 },
338 { "smallunion", NULL, 0, 0 },
339 { "smcoprod", NULL, 0, 0 },
340 { "sqcap", NULL, 0, 0 },
341 { "sqcup", NULL, 0, 0 },
342 { "sqrt", NULL, 1, 0 },
343 { "sqsubset", NULL, 0, 0 },
344 { "sqsubseteq", NULL, 0, 0 },
345 { "sqsupset", NULL, 0, 0 },
346 { "sqsupseteq", NULL, 0, 0 },
347 { "star", NULL, 0, 0 },
348 { "sub", "_", 0, 0 },
349 { "subset", NULL, 0, 0 },
350 { "subseteq", NULL, 0, 0 },
351 { "succ", NULL, 0, 0 },
352 { "sum", NULL, 0, 0 },
353 { "sup", "^", 0, 0 },
354 { "superset", NULL, 0, 0 },
355 { "supset", NULL, 0, 0 },
356 { "supseteq", NULL, 0, 0 },
357 { "swarrow", NULL, 0, 0 },
358 { "tan", NULL, 0, 0 },
359 { "tanh", NULL, 0, 0 },
360 { "tau", NULL, 0, EQ_CASE },
361 { "therefore", NULL, 0, 0 },
362 { "theta", NULL, 0, EQ_CASE },
363 { "tilde", "\\widetilde", 1, 0 },
364 { "times", NULL, 0, 0 },
365 { "to", "^", 1, 0 },
366 { "top", NULL, 0, 0 },
367 { "triangle", NULL, 0, 0 },
368 { "triangled", NULL, 0, 0 },
369 { "trianglel", NULL, 0, 0 },
370 { "triangler", NULL, 0, 0 },
371 { "triangleu", NULL, 0, 0 },
372 { "udarrow", "\\updownarrow",0, EQ_CASE },
373 { "under", "\\underline", 1, 0 },
374 { "underline", "\\underline", 1, 0 },
375 { "union", "\\bigcup", 0, 0 },
376 { "uparrow", NULL, 0, EQ_CASE },
377 { "uplus", NULL, 0, 0 },
378 { "upsilon", NULL, 0, EQ_CASE },
379 { "varepsilon", NULL, 0, 0 },
380 { "varphi", NULL, 0, 0 },
381 { "varpi", NULL, 0, 0 },
382 { "varrho", NULL, 0, 0 },
383 { "varsigma", NULL, 0, 0 },
384 { "vartheta", NULL, 0, 0 },
385 { "varupsilon", NULL, 0, 0 },
386 { "vdash", NULL, 0, 0 },
387 { "vdots", NULL, 0, 0 },
388 { "vec", NULL, 1, 0 },
389 { "vee", NULL, 0, 0 },
390 { "vert", NULL, 0, 0 },
391 { "wedge", NULL, 0, 0 },
392 { "wp", NULL, 0, 0 },
393 { "xi", NULL, 0, EQ_CASE },
394 { "xor", NULL, 0, 0 },
395 { "zeta", NULL, 0, EQ_CASE }
398 static hwpeq *lookup_eqn(char *str)
400 static int eqCount = sizeof(eq_tbl) / sizeof(eq_tbl[0]);
401 int m, k, l = 0, r = eqCount;
402 hwpeq *result = 0;
404 while( l < r ) {
405 m = (l + r) / 2;
406 k = strcmp(eq_tbl[m].key, str);
407 if( k == 0 ) {
408 result = eq_tbl + m;;
409 break;
411 else if( k < 0 )
412 l = m + 1;
413 else
414 r = m;
416 return result;
419 /* ùÀÚ¸¸ ´ë¹®ÀÚÀ̰ųª ÀüºÎ ´ë¹®ÀÚ¸é ¼Ò¹®ÀÚ·Î ¹Ù²Û´Ù. */
421 static char *make_keyword( char *keyword, const char *token)
423 assert(keyword);
424 char *ptr;
425 int result = true, len = strlen(token);
427 if( 255 < len )
428 strncpy(keyword, token, 255);
429 else
430 strcpy(keyword, token);
432 if( (token[0] & 0x80) || islower(token[0]) ||
433 strlen(token) < 2 )
434 return keyword;
436 int capital = isupper(keyword[1]);
437 for( ptr = keyword + 2; *ptr && result; ptr++ )
438 if( (*ptr & 0x80) ||
439 (!capital && isupper(*ptr)) ||
440 (capital && islower(*ptr)) )
441 result = false;
443 if( result ) {
444 ptr = keyword;
445 while( *ptr ) {
446 if( isupper(*ptr) )
447 *ptr = sal::static_int_cast<char>(tolower(*ptr));
448 ptr++;
451 return keyword;
454 // token reading funtion
455 struct eq_stack {
456 MzString white;
457 MzString token;
458 istream *strm;
460 eq_stack() { strm = 0; };
461 bool state(istream *s) {
462 if( strm != s) { white = 0; token = 0; }
463 return token.length() != 0;
467 static eq_stack *stk = 0;
469 void push_token(MzString &white, MzString &token, istream *strm)
471 // one time stack
472 assert(stk->state(strm) == false);
474 stk->white = white;
475 stk->token = token;
476 stk->strm = strm;
479 /* ÀÐÀº ÅäÅ«ÀÇ ±æÀ̸¦ ¹ÝȯÇÑ´Ù. */
480 /* control char, control sequence, binary sequence,
481 alphabet string, sigle character */
482 static int next_token(MzString &white, MzString &token, istream *strm)
484 register int ch = 0;
486 if( stk->state(strm) ) {
487 white = stk->white;
488 token = stk->token;
489 stk->token = 0;
490 stk->white = 0;
491 return token.length();
494 token = 0;
495 white = 0;
496 if( !strm->good() || (ch = strm->get()) == EOF )
497 return 0;
499 // read preceeding ws
500 if( IS_WS(ch) ) {
501 do white << (char) ch;
502 while( IS_WS(ch = strm->get()) );
505 if( ch == '\\' || ch & 0x80 || isalpha(ch) ) {
506 if( ch == '\\' ) {
507 token << (char) ch;
508 ch = strm->get();
510 do {
511 token << (char) ch;
512 ch = strm->get();
513 } while( ch != EOF && (ch & 0x80 || isalpha(ch)) ) ;
514 strm->putback(sal::static_int_cast<char>(ch));
515 /* sub, sub, over, atop Ư¼ö ó¸®
516 ±× ÀÌÀ¯´Â next_state()¿¡ ¿µÇâÀ» ¹ÌÄ¡±â ¶§¹®ÀÌ´Ù.
518 if( !STRICMP("sub", token) || !STRICMP("from", token) ||
519 !STRICMP("sup", token) || !STRICMP("to", token) ||
520 !STRICMP("over", token) || !STRICMP("atop", token) ||
521 !STRICMP("left", token) || !STRICMP("right", token) )
523 char buf[256];
524 make_keyword(buf, token);
525 token = buf;
527 if( !token.compare("sub") || !token.compare("from") )
528 token = "_";
529 if( !token.compare("sup") || !token.compare("to") )
530 token = "^";
532 else if( IS_BINARY(ch) ) {
533 do token << (char) ch;
534 while( IS_BINARY(ch = strm->get()) );
535 strm->putback(sal::static_int_cast<char>(ch));
537 else if( isdigit(ch) ) {
538 do token << (char) ch;
539 while( isdigit(ch = strm->get()) );
540 strm->putback(sal::static_int_cast<char>(ch));
542 else
543 token << (char) ch;
544 // cout << "WHITE : " << "|" << white.c_str() << "|" << endl ;
545 // cout << "TOKEN : " << "|" << token.c_str() << "|" << endl ;
546 return token.length();
549 static int read_white_space(MzString& outs, istream *strm)
551 int ch, result;
553 if( stk->state(strm) ) {
554 outs << stk->white;
555 stk->white = 0;
556 result = stk->token[0];
558 else {
559 while( IS_WS(ch = strm->get()) )
560 outs << (char )ch;
561 strm->putback(sal::static_int_cast<char>(ch));
562 result = ch;
564 return result;
567 /* Àμö°¡ ÇÊ¿äÇÏÁö ¾ÊÀº °æ¿ì °¢ Ç׸ñ°£ÀÇ ±¸ºÐÀº space¿Í brace
568 sqrt {ab}c = sqrt{ab} c
569 (, }´Â grouping
570 ^, _ ´Â ¾ÕµÚ·Î °áÇÕÇÑ´Ù.
572 sqrt µî°ú °°ÀÌ Àμö°¡ ÀÖ´Â Çü½Ä Á¤¸®
573 sqrt a -> sqrt{a}
574 sqrt {a} -> sqrt{a}
575 1 ÀÌ»óÀÇ Àμö°¡ ÀÖ´Â °æ¿ì Àμöµé°£ÀÇ ¿ª¹éÀº ¾ø¾Ø´Ù.
576 \frac a b -> frac{a}{b}
577 overÀÇ Çü½Ä Á¤¸®
578 a over b -> {a}over{b}
581 static int eq_word(MzString& outs, istream *strm, int status)
583 MzString token, white, state;
584 int ch, result, nargs;
585 char keyword[256];
586 hwpeq *eq;
587 #ifdef DEBUG
588 static int slevel = 0;
590 slevel++;
591 #endif
592 next_token(white, token, strm);
593 if (token.length() <= 0)
594 return 0;
595 result = token[0];
597 if( token.compare("{") == 0 ) {
598 state << white << token;
599 eq_sentence(state, strm, "}");
601 else if( token.compare("left") == 0 ) {
602 state << white << token;
603 next_token(white, token, strm);
604 state << white << token;
606 eq_sentence(state, strm, "right");
608 next_token(white, token, strm);
609 state << white << token;
611 else {
612 /* Á¤»óÀûÀÎ token */
613 int script_status = SCRIPT_NONE;
614 while( 1 ) {
615 state << white << token;
616 make_keyword(keyword, token);
617 if( token[0] == '^' )
618 script_status |= SCRIPT_SUP;
619 else if( token[0] == '_' )
620 script_status |= SCRIPT_SUB;
621 else
622 script_status = SCRIPT_NONE;
624 if( 0 != (eq = lookup_eqn(keyword)) ) {
625 nargs = eq->nargs;
626 while( nargs-- ) {
627 ch = read_white_space(state, strm);
628 if( ch != '{' ) state << '{';
629 eq_word(state, strm, script_status);
630 if( ch != '{' ) state << '}';
634 if( !next_token(white, token, strm) )
635 break;
636 // end loop and restart with this
637 if( (token[0] == '^' && status && !(status & SCRIPT_SUP)) ||
638 (token[0] == '_' && status && !(status & SCRIPT_SUB)) ||
639 strcmp("over", token) == 0 || strcmp("atop", token) == 0 ||
640 strchr("{}#&`", token[0]) ||
641 (!strchr("^_", token[0]) && white.length()) ) {
642 push_token(white, token, strm);
643 break;
647 outs << state;
648 #ifdef DEBUG
649 //if( slevel == 1 )
650 // cout << "LEVEL[" << slevel << "]" << state << "\n";
651 slevel--;
652 #endif
653 return result;
656 static bool eq_sentence(MzString& outs, istream *strm, const char *end)
658 MzString state;
659 MzString white, token;
660 bool multiline = false;
662 read_white_space(outs, strm);
663 while( eq_word(state, strm) ) {
664 if( !next_token(white, token, strm) ||
665 (end && strcmp(token.c_str(), end) == 0) )
667 state << white << token;
668 break;
670 push_token(white, token, strm);
671 if( !token.compare("atop") || !token.compare("over") )
672 outs << '{' << state << '}';
673 else {
674 if( !token.compare("#") )
675 multiline = true;
676 outs << state;
678 state = 0;
679 read_white_space(outs, strm);
681 outs << state;
682 return multiline;
685 static char eq2ltxconv(MzString& sstr, istream *strm, const char *sentinel)
687 MzString white, token;
688 char key[20];
689 int ch, result;
690 hwpeq *eq = 0;
692 while( 0 != (result = next_token(white, token, strm)) ) {
693 if( sentinel && (result == 1) && strchr(sentinel, token[0]) )
694 break;
695 make_keyword(key, token);
696 if( (eq = lookup_eqn(key)) != 0 ) {
697 if( eq->latex )
698 strcpy(key, eq->latex);
699 else {
700 key[0] = '\\';
701 strcpy(key + 1, eq->key);
703 if( (eq->flag & EQ_CASE) && isupper(token[0]) )
704 key[1] = sal::static_int_cast<char>(toupper(key[1]));
705 token = key;
708 if( token[0] == '{' ) { // grouping
709 sstr << white << token;
710 eq2ltxconv(sstr, strm, "}");
711 sstr << '}';
713 else if( eq && (eq->flag & EQ_ENV) ) {
714 next_token(white, token, strm);
715 if( token[0] != '{' ) return 0;
716 sstr << "\\begin" << "{" << eq->key << "}" << ENDL ;
717 eq2ltxconv(sstr, strm, "}");
718 if( sstr[sstr.length() - 1] != '\n' )
719 sstr << ENDL ;
720 sstr << "\\end" << "{" << eq->key << "}" << ENDL ;
722 else if( eq && (eq->flag & EQ_ATOP) ) {
723 if( sstr.length() == 0 )
724 sstr << '{';
725 else {
726 int pos = sstr.rfind('}');
727 if( 0 < pos)
728 sstr.replace(pos, ' ');
730 sstr << token;
731 while( (ch = strm->get()) != EOF && IS_WS(ch) )
732 sstr << (char)ch;
733 if( ch != '{' )
734 sstr << "{}";
735 else {
736 eq2ltxconv(sstr, strm, "}");
737 sstr << '}';
740 else
741 sstr << white << token;
743 return token[0];
746 void eq2latex(MzString& outs, char *s)
748 assert(s);
749 if( stk == 0 )
750 stk = new eq_stack;
752 MzString tstr;
754 istringstream tstrm(s);
755 bool eqnarray = eq_sentence(tstr, &tstrm);
756 #ifdef TEST
757 cout << "Step1: " << endl << tstr.c_str() << endl;
758 #endif
759 istringstream strm(tstr.c_str());
761 if( eqnarray )
762 outs << "\\begin{array}{rllll}" << ENDL;
763 eq2ltxconv(outs, &strm, 0);
764 outs << ENDL;
765 if( eqnarray )
766 outs << "\\end{array}" << ENDL;
767 delete stk;
768 stk = 0;