diff options
Diffstat (limited to 'hwpfilter/source/hwpeq.cxx')
-rw-r--r-- | hwpfilter/source/hwpeq.cxx | 754 |
1 files changed, 754 insertions, 0 deletions
diff --git a/hwpfilter/source/hwpeq.cxx b/hwpfilter/source/hwpeq.cxx new file mode 100644 index 000000000000..0808d5100b55 --- /dev/null +++ b/hwpfilter/source/hwpeq.cxx @@ -0,0 +1,754 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * + ************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +// DVO: always use standard headers: +#include <istream> +#include <sstream> +using namespace std; + +#include "mzstring.h" +#include "hwpeq.h" +#include <sal/types.h> +#include <sal/macros.h> + +/* @Man: hwp LaTeX ٲٱ */ +#ifdef WIN32 +# define ENDL "\r\n" +#else /* !WIN32 */ +# define ENDL "\n" +#endif + +#define WS " \t\r\n\v\f" + +#define EQ_CASE 0x01 // case sensitive cmd +#define EQ_ENV 0x02 // equiv to latex environment +#define EQ_ATOP 0x04 // must revert order + +#define IS_WS(ch) (strchr(WS, ch)) +#define IS_BINARY(ch) (strchr("+-<=>", ch)) + +#ifdef WIN32 +#define STRICMP stricmp +#else +#define STRICMP strcasecmp +#endif + +// sub and sup scipt script status +enum { SCRIPT_NONE, SCRIPT_SUB, SCRIPT_SUP, SCRIPT_ALL}; + +static int eq_word(MzString& outs, istream *strm, int script = SCRIPT_NONE); +static bool eq_sentence(MzString& outs, istream *strm, const char *end = 0); + +struct hwpeq { + const char *key; // hwp math keyword + const char *latex; // corresponding latex keywork + int nargs; // # of argument + unsigned char flag; // case sensitive? +}; + +static hwpeq eq_tbl[] = { + { "!=", "\\equiv ", 0, 0 }, + { "#", "\\\\", 0, 0 }, + { "+-", "\\pm ", 0, 0 }, + { "-+", "\\mp ", 0, 0 }, + { "<=", "\\leq ", 0, 0 }, + { "==", "\\equiv ", 0, 0 }, + { ">=", "\\geq ", 0, 0 }, + { "Pr", NULL, 0, 0 }, + { "^", "^", 1, 0 }, + { "_", "_", 1, 0 }, + { "`", "\\;", 0, 0 }, + { "acute", NULL, 1, 0 }, + { "aleph", NULL, 0, 0 }, + { "alpha", NULL, 0, EQ_CASE }, + { "amalg", NULL, 0, 0 }, + { "and", NULL, 0, 0 }, + { "angle", NULL, 0, 0 }, + { "angstrom", NULL, 0, 0 }, + { "approx", NULL, 0, 0 }, + { "arc", NULL, 0, 0 }, + { "arccos", NULL, 0, 0 }, + { "arch", NULL, 0, 0 }, + { "arcsin", NULL, 0, 0 }, + { "arctan", NULL, 0, 0 }, + { "arg", NULL, 0, 0 }, + { "assert", "\\vdash", 0, 0 }, + { "ast", NULL, 0, 0 }, + { "asymp", NULL, 0, 0 }, + { "atop", NULL, 1, EQ_ATOP }, + { "backslash", NULL, 0, 0 }, + { "bar", NULL, 1, 0 }, + { "because", NULL, 0, 0 }, + { "beta", NULL, 0, EQ_CASE }, + { "big", NULL, 0, EQ_CASE }, + { "bigcap", NULL, 0, 0 }, + { "bigcirc", NULL, 0, 0 }, + { "bigcup", NULL, 0, 0 }, + { "bigg", NULL, 0, EQ_CASE }, + { "bigodiv", NULL, 0, 0 }, + { "bigodot", NULL, 0, 0 }, + { "bigominus", NULL, 0, 0 }, + { "bigoplus", NULL, 0, 0 }, + { "bigotimes", NULL, 0, 0 }, + { "bigsqcap", NULL, 0, 0 }, + { "bigsqcup", NULL, 0, 0 }, + { "biguplus", NULL, 0, 0 }, + { "bigvee", NULL, 0, 0 }, + { "bigwedge", NULL, 0, 0 }, + { "binom", NULL, 2, 0 }, + { "bmatrix", NULL, 0, EQ_ENV }, + { "bold", NULL, 0, 0 }, + { "bot", NULL, 0, 0 }, + { "breve", NULL, 1, 0 }, + { "buildrel", NULL, 0, 0 }, // LATER + { "bullet", NULL, 0, 0 }, + { "cap", NULL, 0, 0 }, + { "cases", NULL, 0, EQ_ENV }, + { "ccol", NULL, 0, 0 }, /* η */ + { "cdot", NULL, 0, 0 }, + { "cdots", NULL, 0, 0 }, + { "check", NULL, 1, 0 }, + { "chi", NULL, 0, EQ_CASE }, + { "choose", NULL, 0, EQ_ATOP }, + { "circ", NULL, 0, 0 }, + { "col", NULL, 0, 0 }, // LATER + { "cong", NULL, 0, 0 }, + { "coprod", NULL, 0, 0 }, + { "cos", NULL, 0, 0 }, + { "cosec", NULL, 0, 0 }, + { "cosh", NULL, 0, 0 }, + { "cot", NULL, 0, 0 }, + { "coth", NULL, 0, 0 }, + { "cpile", NULL, 0, 0 }, // LATER + { "csc", NULL, 0, 0 }, + { "cup", NULL, 0, 0 }, + { "dagger", NULL, 0, 0 }, + { "dashv", NULL, 0, 0 }, + { "ddagger", NULL, 0, 0 }, + { "ddot", NULL, 1, 0 }, + { "ddots", NULL, 0, 0 }, + { "def", NULL, 0, 0 }, + { "deg", NULL, 0, 0 }, + { "del", NULL, 0, 0 }, + { "delta", NULL, 0, EQ_CASE }, + { "diamond", NULL, 0, 0 }, + { "dim", NULL, 0, 0 }, + { "div", NULL, 0, 0 }, + { "divide", NULL, 0, 0 }, + { "dline", NULL, 0, 0 }, + { "dmatrix", NULL, 0, EQ_ENV }, + { "dot", NULL, 1, 0 }, + { "doteq", NULL, 0, 0 }, + { "dotsaxis", NULL, 0, 0 }, + { "dotsdiag", NULL, 0, 0 }, + { "dotslow", "\\ldots", 0, 0 }, + { "dotsvert", "\\vdots", 0, 0 }, + { "downarrow", NULL, 0, EQ_CASE }, + { "dsum", "+", 0, 0 }, + { "dyad", NULL, 0, 0 }, // LATER + { "ell", NULL, 0, 0 }, + { "emptyset", NULL, 0, 0 }, + { "epsilon", NULL, 0, EQ_CASE }, + { "eqalign", NULL, 0, EQ_ENV }, + { "equiv", NULL, 0, 0 }, + { "eta", NULL, 0, EQ_CASE }, + { "exarrow", NULL, 0, 0 }, + { "exist", "\\exists", 0, 0 }, + { "exists", NULL, 0, 0 }, + { "exp", NULL, 0, EQ_CASE }, + { "for", NULL, 0, 0 }, + { "forall", NULL, 0, 0 }, + { "from", "_", 1, 0 }, + { "gamma", NULL, 0, EQ_CASE }, + { "gcd", NULL, 0, 0 }, + { "ge", "\\geq", 0, 0 }, + { "geq", NULL, 0, 0 }, + { "ggg", NULL, 0, 0 }, + { "grad", NULL, 0, 0 }, + { "grave", NULL, 1, 0 }, + { "hat", "\\widehat", 1, 0 }, + { "hbar", NULL, 0, 0 }, + { "hom", NULL, 0, 0 }, + { "hookleft", NULL, 0, 0 }, + { "hookright", NULL, 0, 0 }, + { "identical", NULL, 0, 0 }, // LATER + { "if", NULL, 0, 0 }, + { "imag", NULL, 0, 0 }, + { "image", NULL, 0, 0 }, + { "imath", NULL, 0, 0 }, + { "in", NULL, 0, 0 }, + { "inf", "\\infty", 0, 0 }, + { "infinity", "\\infty", 0, 0 }, + { "infty", NULL, 0, 0 }, + { "int", NULL, 0, 0 }, + { "integral", "\\int", 0, 0 }, + { "inter", "\\bigcap", 0, 0 }, + { "iota", NULL, 0, EQ_CASE }, + { "iso", NULL, 0, 0 }, // ams + { "it", NULL, 0, 0 }, + { "jmath", NULL, 0, 0 }, + { "kappa", NULL, 0, EQ_CASE }, + { "ker", NULL, 0, 0 }, + { "lambda", NULL, 0, EQ_CASE }, + { "land", NULL, 0, 0 }, // LATER + { "langle", NULL, 0, 0 }, + { "larrow", "\\leftarrow", 0, EQ_CASE }, + { "lbrace", NULL, 0, 0 }, + { "lbrack", "[", 0, 0 }, + { "lceil", NULL, 0, 0 }, + { "lcol", NULL, 0, 0 }, // LATER + { "ldots", NULL, 0, 0 }, + { "le", NULL, 0, 0 }, + { "left", NULL, 0, 0 }, + { "leftarrow", NULL, 0, EQ_CASE }, + { "leq", NULL, 0, 0 }, + { "lfloor", NULL, 0, 0 }, + { "lg", NULL, 0, 0 }, + { "lim", NULL, 0, EQ_CASE }, + { "line", "\\vert", 0, 0 }, + { "liter", "\\ell", 0, 0 }, + { "lll", NULL, 0, 0 }, // ams + { "ln", NULL, 0, 0 }, + { "log", NULL, 0, 0 }, + { "lor", "\\vee", 0, 0 }, + { "lparen", "(", 0, 0 }, + { "lpile", NULL, 0, 0 }, // LATER + { "lrarrow", "\\leftrightarrow", 0, EQ_CASE }, + { "lrharpoons", "\\leftrightharpoons",0, 0 }, + { "mapsto", NULL, 0, 0 }, + { "massert", "\\dashv", 0, 0 }, + { "matrix", NULL, 0, EQ_ENV }, + { "max", NULL, 0, 0 }, + { "mho", NULL, 0, 0 }, // ams + { "min", NULL, 0, 0 }, + { "minusplus", NULL, 0, 0 }, + { "mit", "", 0, 0 }, // font + { "mod", "\\bmod", 0, 0 }, + { "models", NULL, 0, 0 }, + { "msangle", NULL, 0, 0 }, // LATER + { "mu", NULL, 0, EQ_CASE }, + { "nabla", NULL, 0, 0 }, + { "ne", NULL, 0, 0 }, + { "nearrow", NULL, 0, 0 }, + { "neg", NULL, 0, 0 }, + { "neq", NULL, 0, 0 }, + { "nequiv", NULL, 0, 0 }, + { "ni", NULL, 0, 0 }, + { "not", NULL, 0, 0 }, + { "notin", NULL, 0, 0 }, + { "nu", NULL, 0, EQ_CASE }, + { "nwarrow", NULL, 0, 0 }, + { "odiv", NULL, 0, 0 }, + { "odot", NULL, 0, 0 }, + { "oint", NULL, 0, 0 }, + { "omega", NULL, 0, EQ_CASE }, + { "omicron", NULL, 0, EQ_CASE }, + { "ominus", NULL, 0, 0 }, + { "oplus", NULL, 0, 0 }, + { "or ", NULL, 0, 0 }, + { "oslash", NULL, 0, 0 }, + { "otimes", NULL, 0, 0 }, + { "over", NULL, 1, EQ_ATOP }, + { "overline", NULL, 1, 0 }, + { "owns", "\\ni", 0, 0 }, + { "parallel", NULL, 0, 0 }, + { "partial", NULL, 0, 0 }, + { "phantom", NULL, 0, 0 }, + { "phi", NULL, 0, EQ_CASE }, + { "pi", NULL, 0, EQ_CASE }, + { "pile", NULL, 0, 0 }, // LATER + { "plusminus", "\\pm", 0, 0 }, + { "pmatrix", NULL, 0, EQ_ENV }, + { "prec", NULL, 0, 0 }, + { "prep", NULL, 0, 0 }, + { "prime", NULL, 0, 0 }, + { "prod", NULL, 0, 0 }, + { "propto", NULL, 0, 0 }, + { "psi", NULL, 0, EQ_CASE }, + { "rangle", NULL, 0, 0 }, + { "rarrow", "\\rightarrow", 0, EQ_CASE }, + { "rbrace", "]", 0, 0 }, + { "rbrace", NULL, 0, 0 }, + { "rceil", NULL, 0, 0 }, + { "rcol", NULL, 0, 0 }, // LATER + { "real", "\\Re", 0, 0 }, + { "reimage", NULL, 0, 0 }, + { "rel", NULL, 0, 0 }, + { "rfloor", NULL, 0, 0 }, + { "rho", NULL, 0, EQ_CASE }, + { "right", NULL, 0, 0 }, + { "rightarrow", NULL, 0, EQ_CASE }, + { "rlharpoons", NULL, 0, 0 }, + { "rm", NULL, 0, 0 }, + { "root", "\\sqrt", 1, 0 }, + { "rparen", ")", 0, 0 }, + { "rpile", NULL, 0, 0 }, // LATER + { "rtangle", NULL, 0, 0 }, + { "sangle", NULL, 0, 0 }, + { "scale", NULL, 0, 0 }, + { "searrow", NULL, 0, 0 }, + { "sec", NULL, 0, 0 }, + { "sigma", NULL, 0, EQ_CASE }, + { "sim", NULL, 0, 0 }, + { "simeq", NULL, 0, 0 }, + { "sin", NULL, 0, 0 }, + { "sinh", NULL, 0, 0 }, + { "slash", NULL, 0, 0 }, + { "smallint", NULL, 0, 0 }, + { "smallinter", NULL, 0, 0 }, + { "smalloint", NULL, 0, 0 }, + { "smallprod", NULL, 0, 0 }, + { "smallsum", NULL, 0, 0 }, + { "smallunion", NULL, 0, 0 }, + { "smcoprod", NULL, 0, 0 }, + { "sqcap", NULL, 0, 0 }, + { "sqcup", NULL, 0, 0 }, + { "sqrt", NULL, 1, 0 }, + { "sqsubset", NULL, 0, 0 }, + { "sqsubseteq", NULL, 0, 0 }, + { "sqsupset", NULL, 0, 0 }, + { "sqsupseteq", NULL, 0, 0 }, + { "star", NULL, 0, 0 }, + { "sub", "_", 0, 0 }, + { "subset", NULL, 0, 0 }, + { "subseteq", NULL, 0, 0 }, + { "succ", NULL, 0, 0 }, + { "sum", NULL, 0, 0 }, + { "sup", "^", 0, 0 }, + { "superset", NULL, 0, 0 }, + { "supset", NULL, 0, 0 }, + { "supseteq", NULL, 0, 0 }, + { "swarrow", NULL, 0, 0 }, + { "tan", NULL, 0, 0 }, + { "tanh", NULL, 0, 0 }, + { "tau", NULL, 0, EQ_CASE }, + { "therefore", NULL, 0, 0 }, + { "theta", NULL, 0, EQ_CASE }, + { "tilde", "\\widetilde", 1, 0 }, + { "times", NULL, 0, 0 }, + { "to", "^", 1, 0 }, + { "top", NULL, 0, 0 }, + { "triangle", NULL, 0, 0 }, + { "triangled", NULL, 0, 0 }, + { "trianglel", NULL, 0, 0 }, + { "triangler", NULL, 0, 0 }, + { "triangleu", NULL, 0, 0 }, + { "udarrow", "\\updownarrow",0, EQ_CASE }, + { "under", "\\underline", 1, 0 }, + { "underline", "\\underline", 1, 0 }, + { "union", "\\bigcup", 0, 0 }, + { "uparrow", NULL, 0, EQ_CASE }, + { "uplus", NULL, 0, 0 }, + { "upsilon", NULL, 0, EQ_CASE }, + { "varepsilon", NULL, 0, 0 }, + { "varphi", NULL, 0, 0 }, + { "varpi", NULL, 0, 0 }, + { "varrho", NULL, 0, 0 }, + { "varsigma", NULL, 0, 0 }, + { "vartheta", NULL, 0, 0 }, + { "varupsilon", NULL, 0, 0 }, + { "vdash", NULL, 0, 0 }, + { "vdots", NULL, 0, 0 }, + { "vec", NULL, 1, 0 }, + { "vee", NULL, 0, 0 }, + { "vert", NULL, 0, 0 }, + { "wedge", NULL, 0, 0 }, + { "wp", NULL, 0, 0 }, + { "xi", NULL, 0, EQ_CASE }, + { "xor", NULL, 0, 0 }, + { "zeta", NULL, 0, EQ_CASE } +}; + +static hwpeq *lookup_eqn(char *str) +{ + static int eqCount = SAL_N_ELEMENTS(eq_tbl); + int m, k, l = 0, r = eqCount; + hwpeq *result = 0; + + while( l < r ) { + m = (l + r) / 2; + k = strcmp(eq_tbl[m].key, str); + if( k == 0 ) { + result = eq_tbl + m;; + break; + } + else if( k < 0 ) + l = m + 1; + else + r = m; + } + return result; +} + +/* ùڸ 빮̰ų 빮ڸ ҹڷ ٲ۴. */ + +static char *make_keyword( char *keyword, const char *token) +{ + assert(keyword); + char *ptr; + int result = true, len = strlen(token); + + if( 255 < len ) + strncpy(keyword, token, 255); + else + strcpy(keyword, token); + + if( (token[0] & 0x80) || islower(token[0]) || + strlen(token) < 2 ) + return keyword; + + int capital = isupper(keyword[1]); + for( ptr = keyword + 2; *ptr && result; ptr++ ) + if( (*ptr & 0x80) || + (!capital && isupper(*ptr)) || + (capital && islower(*ptr)) ) + result = false; + + if( result ) { + ptr = keyword; + while( *ptr ) { + if( isupper(*ptr) ) + *ptr = sal::static_int_cast<char>(tolower(*ptr)); + ptr++; + } + } + return keyword; +} + +// token reading funtion +struct eq_stack { + MzString white; + MzString token; + istream *strm; + + eq_stack() { strm = 0; }; + bool state(istream *s) { + if( strm != s) { white = 0; token = 0; } + return token.length() != 0; + } +}; + +static eq_stack *stk = 0; + +void push_token(MzString &white, MzString &token, istream *strm) +{ + // one time stack + assert(stk->state(strm) == false); + + stk->white = white; + stk->token = token; + stk->strm = strm; +} + +/*
ū ̸ ȯѴ. */ +/* control char, control sequence, binary sequence, + alphabet string, sigle character */ +static int next_token(MzString &white, MzString &token, istream *strm) +{ + register int ch = 0; + + if( stk->state(strm) ) { + white = stk->white; + token = stk->token; + stk->token = 0; + stk->white = 0; + return token.length(); + } + + token = 0; + white = 0; + if( !strm->good() || (ch = strm->get()) == EOF ) + return 0; + + // read preceeding ws + if( IS_WS(ch) ) { + do white << (char) ch; + while( IS_WS(ch = strm->get()) ); + } + + if( ch == '\\' || ch & 0x80 || isalpha(ch) ) { + if( ch == '\\' ) { + token << (char) ch; + ch = strm->get(); + } + do { + token << (char) ch; + ch = strm->get(); + } while( ch != EOF && (ch & 0x80 || isalpha(ch)) ) ; + strm->putback(sal::static_int_cast<char>(ch)); + /* sub, sub, over, atop Ư ó + next_state() ġ ̴. + */ + if( !STRICMP("sub", token) || !STRICMP("from", token) || + !STRICMP("sup", token) || !STRICMP("to", token) || + !STRICMP("over", token) || !STRICMP("atop", token) || + !STRICMP("left", token) || !STRICMP("right", token) ) + { + char buf[256]; + make_keyword(buf, token); + token = buf; + } + if( !token.compare("sub") || !token.compare("from") ) + token = "_"; + if( !token.compare("sup") || !token.compare("to") ) + token = "^"; + } + else if( IS_BINARY(ch) ) { + do token << (char) ch; + while( IS_BINARY(ch = strm->get()) ); + strm->putback(sal::static_int_cast<char>(ch)); + } + else if( isdigit(ch) ) { + do token << (char) ch; + while( isdigit(ch = strm->get()) ); + strm->putback(sal::static_int_cast<char>(ch)); + } + else + token << (char) ch; + + return token.length(); +} + +static int read_white_space(MzString& outs, istream *strm) +{ + int result; + + if( stk->state(strm) ) { + outs << stk->white; + stk->white = 0; + result = stk->token[0]; + } + else { + int ch; + while( IS_WS(ch = strm->get()) ) + outs << (char )ch; + strm->putback(sal::static_int_cast<char>(ch)); + result = ch; + } + return result; +} + +/* μ ʿ space brace + sqrt {ab}c = sqrt{ab} c + (, } grouping + ^, _ յڷ Ѵ. + + sqrt μ ִ + sqrt a -> sqrt{a} + sqrt {a} -> sqrt{a} + 1 ̻ μ ִ μ鰣 ش. + \frac a b -> frac{a}{b} + over + a over b -> {a}over{b} + */ + +static int eq_word(MzString& outs, istream *strm, int status) +{ + MzString token, white, state; + int result; + char keyword[256]; + hwpeq *eq; + + next_token(white, token, strm); + if (token.length() <= 0) + return 0; + result = token[0]; + + if( token.compare("{") == 0 ) { + state << white << token; + eq_sentence(state, strm, "}"); + } + else if( token.compare("left") == 0 ) { + state << white << token; + next_token(white, token, strm); + state << white << token; + + eq_sentence(state, strm, "right"); + + next_token(white, token, strm); + state << white << token; + } + else { + /* token */ + int script_status = SCRIPT_NONE; + while( 1 ) { + state << white << token; + make_keyword(keyword, token); + if( token[0] == '^' ) + script_status |= SCRIPT_SUP; + else if( token[0] == '_' ) + script_status |= SCRIPT_SUB; + else + script_status = SCRIPT_NONE; + + if( 0 != (eq = lookup_eqn(keyword)) ) { + int nargs = eq->nargs; + int ch; + while( nargs-- ) { + ch = read_white_space(state, strm); + if( ch != '{' ) state << '{'; + eq_word(state, strm, script_status); + if( ch != '{' ) state << '}'; + } + } + + if( !next_token(white, token, strm) ) + break; + // end loop and restart with this + if( (token[0] == '^' && status && !(status & SCRIPT_SUP)) || + (token[0] == '_' && status && !(status & SCRIPT_SUB)) || + strcmp("over", token) == 0 || strcmp("atop", token) == 0 || + strchr("{}#&`", token[0]) || + (!strchr("^_", token[0]) && white.length()) ) { + push_token(white, token, strm); + break; + } + } + } + outs << state; + + return result; +} + +static bool eq_sentence(MzString& outs, istream *strm, const char *end) +{ + MzString state; + MzString white, token; + bool multiline = false; + + read_white_space(outs, strm); + while( eq_word(state, strm) ) { + if( !next_token(white, token, strm) || + (end && strcmp(token.c_str(), end) == 0) ) + { + state << white << token; + break; + } + push_token(white, token, strm); + if( !token.compare("atop") || !token.compare("over") ) + outs << '{' << state << '}'; + else { + if( !token.compare("#") ) + multiline = true; + outs << state; + } + state = 0; + read_white_space(outs, strm); + } + outs << state; + return multiline; +} + +static char eq2ltxconv(MzString& sstr, istream *strm, const char *sentinel) +{ + MzString white, token; + char key[256]; + int ch, result; + hwpeq *eq = 0; + + while( 0 != (result = next_token(white, token, strm)) ) { + if( sentinel && (result == 1) && strchr(sentinel, token[0]) ) + break; + make_keyword(key, token); + if( (eq = lookup_eqn(key)) != 0 ) { + if( eq->latex ) + strcpy(key, eq->latex); + else { + key[0] = '\\'; + strcpy(key + 1, eq->key); + } + if( (eq->flag & EQ_CASE) && isupper(token[0]) ) + key[1] = sal::static_int_cast<char>(toupper(key[1])); + token = key; + } + + if( token[0] == '{' ) { // grouping + sstr << white << token; + eq2ltxconv(sstr, strm, "}"); + sstr << '}'; + } + else if( eq && (eq->flag & EQ_ENV) ) { + next_token(white, token, strm); + if( token[0] != '{' ) return 0; + sstr << "\\begin" << "{" << eq->key << "}" << ENDL ; + eq2ltxconv(sstr, strm, "}"); + if( sstr[sstr.length() - 1] != '\n' ) + sstr << ENDL ; + sstr << "\\end" << "{" << eq->key << "}" << ENDL ; + } + else if( eq && (eq->flag & EQ_ATOP) ) { + if( sstr.length() == 0 ) + sstr << '{'; + else { + int pos = sstr.rfind('}'); + if( 0 < pos) + sstr.replace(pos, ' '); + } + sstr << token; + while( (ch = strm->get()) != EOF && IS_WS(ch) ) + sstr << (char)ch; + if( ch != '{' ) + sstr << "{}"; + else { + eq2ltxconv(sstr, strm, "}"); + sstr << '}'; + } + } + else + sstr << white << token; + } + return token[0]; +} + +void eq2latex(MzString& outs, char *s) +{ + assert(s); + if( stk == 0 ) + stk = new eq_stack; + + MzString tstr; + + istringstream tstrm(s); + bool eqnarray = eq_sentence(tstr, &tstrm); + istringstream strm(tstr.c_str()); + + if( eqnarray ) + outs << "\\begin{array}{rllll}" << ENDL; + eq2ltxconv(outs, &strm, 0); + outs << ENDL; + if( eqnarray ) + outs << "\\end{array}" << ENDL; + delete stk; + stk = 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |