summaryrefslogtreecommitdiffstats
path: root/hwpfilter/source/formula.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'hwpfilter/source/formula.cxx')
-rw-r--r--hwpfilter/source/formula.cxx651
1 files changed, 651 insertions, 0 deletions
diff --git a/hwpfilter/source/formula.cxx b/hwpfilter/source/formula.cxx
new file mode 100644
index 000000000..6093681b2
--- /dev/null
+++ b/hwpfilter/source/formula.cxx
@@ -0,0 +1,651 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "formula.h"
+#include "grammar.hxx"
+
+#include "mzstring.h"
+#include "nodes.h"
+#include "mapping.h"
+#include "hwpeq.h"
+#include <iostream>
+
+#ifndef DEBUG
+
+#include "hcode.h"
+
+#define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(false)
+#define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(false)
+#define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
+#define runistr(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
+#define reucstr(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(OUString(x,y, RTL_TEXTENCODING_EUC_KR)); } while(false)
+#define padd(x,y,z) mxList->addAttribute(x,y,z)
+#else
+static int indent = 0;
+#define inds indent++; for(int i = 0 ; i < indent ; i++) fprintf(stderr," ")
+#define inde for(int i = 0 ; i < indent ; i++) fprintf(stderr," "); indent--
+#define indo indent--;
+#endif
+
+void Formula::makeMathML(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return;
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:math xmlns:math=\"http://www.w3.org/1998/Math/MathML\">\n");
+#else
+ padd("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
+ rstartEl("math:math", mxList);
+ mxList->clear();
+ rstartEl("math:semantics", mxList);
+#endif
+ if( tmp->child )
+ makeLines( tmp->child );
+
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:semantics/>\n");
+ indo;
+ inde;
+ fprintf(stderr,"</math:math>\n");
+#else
+ rendEl("math:semantics");
+ rendEl("math:math");
+#endif
+}
+
+void Formula::makeLines(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return;
+
+ if( tmp->child ){
+ if( tmp->child->id == ID_LINES )
+ makeLines( tmp->child );
+ else
+ makeLine( tmp->child );
+ }
+ if( tmp->next )
+ makeLine( tmp->next );
+}
+
+void Formula::makeLine(Node *res)
+{
+ if( !res ) return;
+#ifdef DEBUG
+ inds; fprintf(stderr,"<math:mrow>\n");
+#else
+ rstartEl("math:mrow", mxList);
+#endif
+ if( res->child )
+ makeExprList( res->child );
+#ifdef DEBUG
+ inde; fprintf(stderr,"</math:mrow>\n");
+#else
+ rendEl("math:mrow");
+#endif
+}
+
+void Formula::makeExprList(Node *res)
+{
+ if( !res ) return;
+ Node *tmp = res->child;
+ if( !tmp ) return ;
+
+ if( tmp->id == ID_EXPRLIST ){
+ Node *next = tmp->next;
+ makeExprList( tmp ) ;
+ if( next )
+ makeExpr( next );
+ }
+ else
+ makeExpr( tmp );
+}
+
+void Formula::makeExpr(Node *res)
+{
+ if( !res ) return;
+ Node *tmp = res->child;
+ if( !tmp ) return;
+ switch( tmp->id ) {
+ case ID_PRIMARYEXPR:
+ if( tmp->next ){
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mrow>\n");
+#else
+ rstartEl("math:mrow", mxList);
+#endif
+ }
+
+ makePrimary(tmp);
+
+ if( tmp->next ){
+#ifdef DEBUG
+ inde; fprintf(stderr,"</math:mrow>\n");
+#else
+ rendEl("math:mrow");
+#endif
+ }
+ break;
+ case ID_SUBEXPR:
+ case ID_SUPEXPR:
+ case ID_SUBSUPEXPR:
+ makeSubSup(tmp);
+ break;
+ case ID_FRACTIONEXPR:
+ case ID_OVER:
+ makeFraction(tmp);
+ break;
+ case ID_DECORATIONEXPR:
+ makeDecoration(tmp);
+ break;
+ case ID_SQRTEXPR:
+ case ID_ROOTEXPR:
+ makeRoot(tmp);
+ break;
+ case ID_ARROWEXPR:
+ break;
+ case ID_ACCENTEXPR:
+ makeAccent(tmp);
+ break;
+ case ID_PARENTH:
+ case ID_ABS:
+ makeParenth(tmp);
+ break;
+ case ID_FENCE:
+ makeFence(tmp);
+ break;
+ case ID_BLOCK:
+ makeBlock(tmp);
+ break;
+ case ID_BEGIN:
+ case ID_END:
+ break;
+ }
+}
+
+void Formula::makeIdentifier(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return;
+ if( !tmp->value ) return;
+ switch( tmp->id ){
+ case ID_CHARACTER :
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mi>%s</math:mi>\n",tmp->value.get());
+ indo;
+#else
+ rstartEl("math:mi", mxList);
+ rchars(OUString::createFromAscii(tmp->value.get()));
+ rendEl("math:mi");
+#endif
+ break;
+ case ID_STRING :
+ {
+#ifdef DEBUG
+#else
+ rstartEl("math:mi", mxList);
+ reucstr(tmp->value.get(), strlen(tmp->value.get()));
+ rendEl("math:mi");
+#endif
+ }
+ break;
+ case ID_IDENTIFIER :
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mi>%s</math:mi>\n",
+ getMathMLEntity(tmp->value.get()).c_str());
+ indo;
+#else
+ rstartEl("math:mi", mxList);
+ runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
+ rendEl("math:mi");
+#endif
+ break;
+ case ID_NUMBER :
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mn>%s</math:mn>\n",tmp->value.get());
+ indo;
+#else
+ rstartEl("math:mn", mxList);
+ rchars(OUString::createFromAscii(tmp->value.get()));
+ rendEl("math:mn");
+#endif
+ break;
+ case ID_OPERATOR :
+ case ID_DELIMITER :
+ {
+#ifdef DEBUG
+ inds; fprintf(stderr,"<math:mo>%s</math:mo>\n",tmp->value.get()); indo;
+#else
+ rstartEl("math:mo", mxList);
+ runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
+ rendEl("math:mo");
+#endif
+ break;
+ }
+ }
+}
+void Formula::makePrimary(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return ;
+ if( tmp->child ){
+ if( tmp->child->id == ID_PRIMARYEXPR ){
+ makePrimary(tmp->child);
+ }
+ else{
+ makeIdentifier(tmp->child);
+ }
+ }
+ if( tmp->next ){
+ makeIdentifier(tmp->next);
+ }
+}
+
+void Formula::makeSubSup(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return;
+
+#ifdef DEBUG
+ inds;
+ if( res->id == ID_SUBEXPR )
+ fprintf(stderr,"<math:msub>\n");
+ else if( res->id == ID_SUPEXPR )
+ fprintf(stderr,"<math:msup>\n");
+ else
+ fprintf(stderr,"<math:msubsup>\n");
+#else
+ if( res->id == ID_SUBEXPR )
+ rstartEl("math:msub", mxList);
+ else if( res->id == ID_SUPEXPR )
+ rstartEl("math:msup", mxList);
+ else
+ rstartEl("math:msubsup", mxList);
+#endif
+
+ tmp = tmp->child;
+ if( res->id == ID_SUBSUPEXPR ) {
+ makeExpr(tmp);
+ makeBlock(tmp->next);
+ makeBlock(tmp->next->next);
+ }
+ else{
+ makeExpr(tmp);
+ makeExpr(tmp->next);
+ }
+
+#ifdef DEBUG
+ inde;
+ if( res->id == ID_SUBEXPR )
+ fprintf(stderr,"</math:msub>\n");
+ else if( res->id == ID_SUPEXPR )
+ fprintf(stderr,"</math:msup>\n");
+ else
+ fprintf(stderr,"</math:msubsup>\n");
+#else
+ if( res->id == ID_SUBEXPR )
+ rendEl("math:msub");
+ else if( res->id == ID_SUPEXPR )
+ rendEl("math:msup");
+ else
+ rendEl("math:msubsup");
+#endif
+}
+
+void Formula::makeFraction(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return;
+
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mfrac>\n");
+#else
+ rstartEl("math:mfrac", mxList);
+#endif
+
+ tmp = tmp->child;
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mrow>\n");
+#else
+ rstartEl("math:mrow", mxList);
+#endif
+
+ if( res->id == ID_FRACTIONEXPR )
+ makeBlock(tmp);
+ else
+ makeExprList(tmp);
+
+#ifdef DEBUG
+ inde;
+ fprintf(stderr,"</math:mrow>\n");
+ inds;
+ fprintf(stderr,"<math:mrow>\n");
+#else
+ rendEl("math:mrow");
+ rstartEl("math:mrow", mxList);
+#endif
+
+ if( res->id == ID_FRACTIONEXPR )
+ makeBlock(tmp->next);
+ else
+ makeExprList(tmp->next);
+
+#ifdef DEBUG
+ inde;
+ fprintf(stderr,"</math:mrow>\n");
+ inde;
+ fprintf(stderr,"</math:mfrac>\n");
+#else
+ rendEl("math:mrow");
+ rendEl("math:mfrac");
+#endif
+}
+
+void Formula::makeDecoration(Node *res)
+{
+ int isover = 1;
+ Node *tmp = res->child;
+ if( !tmp ) return;
+ if( !strncmp(tmp->value.get(),"under", 5) )
+ isover = 0;
+#ifdef DEBUG
+ inds;
+ if( isover )
+ fprintf(stderr,"<math:mover>\n");
+ else
+ fprintf(stderr,"<math:munder>\n");
+#else
+ /* FIXME: no idea when 'accent' is true or false. */
+ if( isover ){
+ padd("accent","CDATA","true");
+ rstartEl("math:mover", mxList);
+ }
+ else{
+ padd("accentunder","CDATA","true");
+ rstartEl("math:munder", mxList);
+ }
+ mxList->clear();
+#endif
+
+ makeBlock(tmp->next);
+
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mo>%s</math:mo>\n",
+ getMathMLEntity(tmp->value.get()).c_str());
+ indo;
+#else
+ rstartEl("math:mo", mxList);
+ runistr(fromHcharStringToOUString(getMathMLEntity(tmp->value.get())));
+ rendEl("math:mo");
+#endif
+
+#ifdef DEBUG
+ inde;
+ if( isover )
+ fprintf(stderr,"</math:mover>\n");
+ else
+ fprintf(stderr,"</math:munder>\n");
+#else
+ if( isover )
+ rendEl("math:mover");
+ else
+ rendEl("math:munder");
+#endif
+}
+
+void Formula::makeRoot(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return;
+#ifdef DEBUG
+ inds;
+ if( tmp->id == ID_SQRTEXPR )
+ fprintf(stderr,"<math:msqrt>\n");
+ else
+ fprintf(stderr,"<math:mroot>\n");
+#else
+ if( tmp->id == ID_SQRTEXPR )
+ rstartEl("math:msqrt", mxList);
+ else
+ rstartEl("math:mroot", mxList);
+#endif
+
+ if( tmp->id == ID_SQRTEXPR ){
+ makeBlock(tmp->child);
+ }
+ else{
+ makeBracket(tmp->child);
+ makeBlock(tmp->child->next);
+ }
+
+#ifdef DEBUG
+ inde;
+ if( tmp->id == ID_SQRTEXPR )
+ fprintf(stderr,"</math:msqrt>\n");
+ else
+ fprintf(stderr,"</math:mroot>\n");
+#else
+ if( tmp->id == ID_SQRTEXPR )
+ rendEl("math:msqrt");
+ else
+ rendEl("math:mroot");
+#endif
+}
+void Formula::makeAccent(Node *res)
+{
+ makeDecoration( res );
+}
+void Formula::makeParenth(Node *res)
+{
+ Node *tmp = res;
+ if( !tmp ) return;
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mrow>\n");
+ inds;
+ if( tmp->id == ID_PARENTH ){
+ fprintf(stderr,"<math:mo>(</math:mo>\n");
+ }
+ else
+ fprintf(stderr,"<math:mo>|</math:mo>\n");
+ indo; inds;
+ fprintf(stderr,"<math:mrow>\n");
+#else
+ rstartEl("math:mrow", mxList);
+ rstartEl("math:mo", mxList);
+ if( tmp->id == ID_PARENTH )
+ rchars("(");
+ else
+ rchars("|");
+ rendEl("math:mo");
+ rstartEl("math:mrow", mxList);
+#endif
+
+ if( tmp->child )
+ makeExprList(tmp->child);
+
+#ifdef DEBUG
+ inde;
+ fprintf(stderr,"</math:mrow>\n");
+ inds;
+ if( tmp->id == ID_PARENTH )
+ fprintf(stderr,"<math:mo>)</math:mo>\n");
+ else
+ fprintf(stderr,"<math:mo>|</math:mo>\n");
+ indo;
+ inde;
+ fprintf(stderr,"</math:mrow>\n");
+#else
+ rendEl("math:mrow");
+ rstartEl("math:mo", mxList);
+ if( tmp->id == ID_PARENTH )
+ rchars(")");
+ else
+ rchars("|");
+ rendEl("math:mo");
+ rendEl("math:mrow");
+#endif
+}
+
+void Formula::makeFence(Node *res)
+{
+ Node *tmp = res->child;
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mfenced open=\"%s\" close=\"%s\">\n",
+ getMathMLEntity(tmp->value.get()).c_str(),
+ getMathMLEntity(tmp->next->next->value.get()).c_str());
+#else
+ padd("open", "CDATA",
+ OUString(reinterpret_cast<sal_Unicode const *>(getMathMLEntity(tmp->value.get()).c_str())));
+ padd("close", "CDATA",
+ OUString(reinterpret_cast<sal_Unicode const *>(getMathMLEntity(tmp->next->next->value.get()).c_str())));
+ rstartEl("math:mfenced", mxList);
+ mxList->clear();
+#endif
+
+ makeExprList(tmp->next);
+
+#ifdef DEBUG
+ inde;
+ fprintf(stderr,"</math:mfenced>\n");
+#else
+ rendEl("math:mfenced");
+#endif
+}
+
+void Formula::makeBracket(Node *res)
+{
+ makeBlock(res);
+}
+
+void Formula::makeBlock(Node *res)
+{
+#ifdef DEBUG
+ inds;
+ fprintf(stderr,"<math:mrow>\n");
+#else
+ rstartEl("math:mrow", mxList);
+#endif
+
+ if( res->child )
+ makeExprList(res->child);
+
+#ifdef DEBUG
+ inde;
+ fprintf(stderr,"</math:mrow>\n");
+#else
+ rendEl("math:mrow");
+#endif
+}
+
+void Formula::parse()
+{
+ Node *res = nullptr;
+ if( !eq ) return;
+
+ MzString a;
+ // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq);
+ eq2latex(a,eq);
+
+ int idx=a.find(sal::static_int_cast<char>(0xff));
+ while(idx){
+ //printf("idx = [%d]\n",idx);
+ a.replace(idx,0x20);
+ if((idx = a.find(sal::static_int_cast<char>(0xff),idx+1)) < 0)
+ break;
+ }
+
+ char *buf = static_cast<char *>(malloc(a.length()+1));
+ bool bStart = false;
+ int i, j;
+ for( i = 0, j=0 ; i < a.length() ; i++){ // rtrim and ltrim 32 10 13
+ if( bStart ){
+ buf[j++] = a[i];
+ }
+ else{
+ if( a[i] != 32 && a[i] != 10 && a[i] != 13){
+ bStart = true;
+ buf[j++] = a[i];
+ }
+ }
+ }
+ buf[j] = 0;
+ for( i = j-1 ; i >= 0 ; i++ ){
+ if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
+ buf[i] = 0;
+ }
+ else
+ break;
+ }
+ // fprintf(stderr,"\n\n[RESULT]\n[%s]\n",a.c_str());
+ if( buf[0] != '\0' )
+ res = mainParse( a.c_str() );
+ else
+ res = nullptr;
+ free(buf);
+
+ if( res ){
+ makeMathML( res );
+ }
+ nodelist.clear();
+}
+
+void Formula::trim()
+{
+ int len = strlen(eq);
+ char *buf = static_cast<char *>(malloc(len+1));
+ bool bStart = false;
+ int i, j;
+ for( i = 0, j=0 ; i < len ; i++){ // rtrim and ltrim 32 10 13
+ if( bStart ){
+ buf[j++] = eq[i];
+ }
+ else{
+ if( eq[i] != 32 && eq[i] != 10 && eq[i] != 13){
+ bStart = true;
+ buf[j++] = eq[i];
+ }
+ }
+ }
+ buf[j] = 0;
+ for( i = j-1 ; i >= 0 ; i++ ){
+ if( buf[i] == 32 || buf[i] == 10 || buf[i] == 13 ){
+ buf[i] = 0;
+ }
+ else
+ break;
+ }
+ if( buf[0] != '\0' )
+ strcpy(eq, buf);
+ else
+ eq = nullptr;
+ free(buf);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */