/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: formula.cpp,v $ * $Revision: 1.5 $ * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "formula.h" #include "mzstring.h" #include "nodes.h" #include "mapping.h" #include "hwpeq.h" #include extern LinkedList nodelist; #ifndef DEBUG #include "hcode.h" static hchar entity[32]; #define ascii(x) OUString::createFromAscii(x) #define rstartEl(x,y) rDocumentHandler->startElement(x,y) #define rendEl(x) rDocumentHandler->endElement(x) #define rchars(x) rDocumentHandler->characters(ascii(x)) #define runistr(x) rDocumentHandler->characters(OUString(x)) #define reucstr(x,y) rDocumentHandler->characters(OUString(x,y, RTL_TEXTENCODING_EUC_KR)) #define padd(x,y,z) pList->addAttribute(x,y,z) #else static char entity[32]; 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 extern Node *mainParse(const char *); void Formula::makeMathML(Node *res) { Node *tmp = res; if( !tmp ) return; #ifdef DEBUG inds; fprintf(stderr,"\n"); #else padd(ascii("xmlns:math"), ascii("CDATA"), ascii("http://www.w3.org/1998/Math/MathML")); rstartEl(ascii("math:math"), rList); pList->clear(); rstartEl(ascii("math:semantics"), rList); #endif if( tmp->child ) makeLines( tmp->child ); #ifdef DEBUG inds; fprintf(stderr,"\n"); indo; inde; fprintf(stderr,"\n"); #else rendEl(ascii("math:semantics")); rendEl(ascii("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,"\n"); #else rstartEl(ascii("math:mrow"), rList); #endif if( res->child ) makeExprList( res->child ); #ifdef DEBUG inde; fprintf(stderr,"\n"); #else rendEl(ascii("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,"\n"); #else rstartEl(ascii("math:mrow"), rList); #endif } makePrimary(tmp); if( tmp->next ){ #ifdef DEBUG inde; fprintf(stderr,"\n"); #else rendEl(ascii("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: makeArrow(tmp); 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); case ID_BEGIN: makeBegin(tmp); case ID_END: makeEnd(tmp); 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,"%s\n",tmp->value); indo; #else rstartEl(ascii("math:mi"), rList); rchars(tmp->value); rendEl(ascii("math:mi")); #endif break; case ID_STRING : { #ifdef DEBUG #else rstartEl(ascii("math:mi"), rList); reucstr(tmp->value, strlen(tmp->value)); rendEl(ascii("math:mi")); #endif } break; case ID_IDENTIFIER : #ifdef DEBUG inds; fprintf(stderr,"%s\n",getMathMLEntity(tmp->value, entity)); indo; #else rstartEl(ascii("math:mi"), rList); runistr(getMathMLEntity(tmp->value, entity)); rendEl(ascii("math:mi")); #endif break; case ID_NUMBER : #ifdef DEBUG inds; fprintf(stderr,"%s\n",tmp->value); indo; #else rstartEl(ascii("math:mn"), rList); rchars(tmp->value); rendEl(ascii("math:mn")); #endif break; case ID_OPERATOR : case ID_DELIMETER : { #ifdef DEBUG inds; fprintf(stderr,"%s\n",tmp->value); indo; #else rstartEl(ascii("math:mo"), rList); runistr(getMathMLEntity(tmp->value,entity)); rendEl(ascii("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,"\n"); else if( res->id == ID_SUPEXPR ) fprintf(stderr,"\n"); else fprintf(stderr,"\n"); #else if( res->id == ID_SUBEXPR ) rstartEl(ascii("math:msub"), rList); else if( res->id == ID_SUPEXPR ) rstartEl(ascii("math:msup"), rList); else rstartEl(ascii("math:msubsup"), rList); #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,"\n"); else if( res->id == ID_SUPEXPR ) fprintf(stderr,"\n"); else fprintf(stderr,"\n"); #else if( res->id == ID_SUBEXPR ) rendEl(ascii("math:msub")); else if( res->id == ID_SUPEXPR ) rendEl(ascii("math:msup")); else rendEl(ascii("math:msubsup")); #endif } void Formula::makeUnderOver(Node *res) { Node *tmp = res; if( !tmp ) return; #ifdef DEBUG inds; if( res->id == ID_SUBEXPR ) fprintf(stderr,"\n"); else if( res->id == ID_SUPEXPR ) fprintf(stderr,"\n"); else fprintf(stderr,"\n"); #else if( res->id == ID_SUBEXPR ) rstartEl(ascii("math:munder"), rList); else if( res->id == ID_SUPEXPR ) rstartEl(ascii("math:mover"), rList); else rstartEl(ascii("math:munderover"), rList); #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,"\n"); else if( res->id == ID_SUPEXPR ) fprintf(stderr,"\n"); else fprintf(stderr,"\n"); #else if( res->id == ID_SUBEXPR ) rendEl(ascii("math:munder")); else if( res->id == ID_SUPEXPR ) rendEl(ascii("math:mover")); else rendEl(ascii("math:munderover")); #endif } void Formula::makeFraction(Node *res) { Node *tmp = res; if( !tmp ) return; #ifdef DEBUG inds; fprintf(stderr,"\n"); #else rstartEl(ascii("math:mfrac"), rList); #endif tmp = tmp->child; #ifdef DEBUG inds; fprintf(stderr,"\n"); #else rstartEl(ascii("math:mrow"), rList); #endif if( res->id == ID_FRACTIONEXPR ) makeBlock(tmp); else makeExprList(tmp); #ifdef DEBUG inde; fprintf(stderr,"\n"); inds; fprintf(stderr,"\n"); #else rendEl(ascii("math:mrow")); rstartEl(ascii("math:mrow"), rList); #endif if( res->id == ID_FRACTIONEXPR ) makeBlock(tmp->next); else makeExprList(tmp->next); #ifdef DEBUG inde; fprintf(stderr,"\n"); inde; fprintf(stderr,"\n"); #else rendEl(ascii("math:mrow")); rendEl(ascii("math:mfrac")); #endif } void Formula::makeDecoration(Node *res) { int isover = 1; Node *tmp = res->child; if( !tmp ) return; if( !strncmp(tmp->value,"under", 5) ) isover = 0; #ifdef DEBUG inds; if( isover ) fprintf(stderr,"\n"); else fprintf(stderr,"\n"); #else /* accent´Â ¾ðÁ¦ trueÀÌ°í, ¾ðÁ¦, falseÀÎÁö ¸ð¸£°Ú´Ù. */ if( isover ){ padd(ascii("accent"),ascii("CDATA"),ascii("true")); rstartEl(ascii("math:mover"), rList); } else{ padd(ascii("accentunder"),ascii("CDATA"),ascii("true")); rstartEl(ascii("math:munder"), rList); } pList->clear(); #endif makeBlock(tmp->next); #ifdef DEBUG inds; fprintf(stderr,"%s\n", getMathMLEntity(tmp->value,entity)); indo; #else rstartEl(ascii("math:mo"), rList); runistr(getMathMLEntity(tmp->value,entity)); rendEl(ascii("math:mo")); #endif #ifdef DEBUG inde; if( isover ) fprintf(stderr,"\n"); else fprintf(stderr,"\n"); #else if( isover ) rendEl(ascii("math:mover")); else rendEl(ascii("math:munder")); #endif } void Formula::makeRoot(Node *res) { Node *tmp = res; if( !tmp ) return; #ifdef DEBUG inds; if( tmp->id == ID_SQRTEXPR ) fprintf(stderr,"\n"); else fprintf(stderr,"\n"); #else if( tmp->id == ID_SQRTEXPR ) rstartEl(ascii("math:msqrt"), rList); else rstartEl(ascii("math:mroot"), rList); #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,"\n"); else fprintf(stderr,"\n"); #else if( tmp->id == ID_SQRTEXPR ) rendEl(ascii("math:msqrt")); else rendEl(ascii("math:mroot")); #endif } // DVO: add space to avoid warning void Formula::makeArrow(Node * /*res*/) { } void Formula::makeAccent(Node *res) { makeDecoration( res ); } void Formula::makeParenth(Node *res) { Node *tmp = res; if( !tmp ) return; #ifdef DEBUG inds; fprintf(stderr,"\n"); inds; if( tmp->id == ID_PARENTH ){ fprintf(stderr,"(\n"); } else fprintf(stderr,"|\n"); indo; inds; fprintf(stderr,"\n"); #else rstartEl(ascii("math:mrow"), rList); rstartEl(ascii("math:mo"), rList); if( tmp->id == ID_PARENTH ) rchars("("); else rchars("|"); rendEl(ascii("math:mo")); rstartEl(ascii("math:mrow"), rList); #endif if( tmp->child ) makeExprList(tmp->child); #ifdef DEBUG inde; fprintf(stderr,"\n"); inds; if( tmp->id == ID_PARENTH ) fprintf(stderr,")\n"); else fprintf(stderr,"|\n"); indo; inde; fprintf(stderr,"\n"); #else rendEl(ascii("math:mrow")); rstartEl(ascii("math:mo"), rList); if( tmp->id == ID_PARENTH ) rchars(")"); else rchars("|"); rendEl(ascii("math:mo")); rendEl(ascii("math:mrow")); #endif } void Formula::makeFence(Node *res) { Node *tmp = res->child; #ifdef DEBUG inds; fprintf(stderr,"\n",getMathMLEntity(tmp->value, entity), getMathMLEntity(tmp->next->next->value,entity)); #else padd(ascii("open"), ascii("CDATA"), OUString(getMathMLEntity(tmp->value,entity)) ); padd(ascii("close"), ascii("CDATA"), OUString(getMathMLEntity(tmp->next->next->value,entity)) ); rstartEl(ascii("math:mfenced"), rList); pList->clear(); #endif makeExprList(tmp->next); #ifdef DEBUG inde; fprintf(stderr,"\n"); #else rendEl(ascii("math:mfenced")); #endif } void Formula::makeBracket(Node *res) { makeBlock(res); } void Formula::makeBlock(Node *res) { #ifdef DEBUG inds; fprintf(stderr,"\n"); #else rstartEl(ascii("math:mrow"), rList); #endif if( res->child ) makeExprList(res->child); #ifdef DEBUG inde; fprintf(stderr,"\n"); #else rendEl(ascii("math:mrow")); #endif } void Formula::makeOperator(Node *res) { #ifdef DEBUG inds; fprintf(stderr,"%s\n",getMathMLEntity(res->value, entity)); indo; #else rstartEl(ascii("math:mo"), rList); runistr(getMathMLEntity(res->value,entity)); rendEl(ascii("math:mo")); #endif } void Formula::makeDelimeter(Node *res) { if( res->value != NULL ){ #ifdef DEBUG inds; fprintf(stderr,"%s\n",getMathMLEntity(res->value, entity)); indo; #else rstartEl(ascii("math:mi"), rList); runistr(getMathMLEntity(res->value, entity)); rendEl(ascii("math:mi")); #endif } } // DVO: add space to avoid warning void Formula::makeBegin(Node * /*res*/) { } // DVO: add space to avoid warning void Formula::makeEnd(Node * /*res*/) { } int Formula::parse() { Node *res = 0L; if( !eq ) return 0; if( isHwpEQ ){ MzString a; // fprintf(stderr,"\n\n[BEFORE]\n[%s]\n",eq); eq2latex(a,eq); int idx=a.find(sal::static_int_cast(0xff)); while(idx){ //printf("idx = [%d]\n",idx); a.replace(idx,0x20); if((idx = a.find(sal::static_int_cast(0xff),idx+1)) < 0) break; } char *buf = (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( strlen(buf) > 0 ) res = mainParse( a.c_str() ); else res = 0L; free(buf); } else{ res = mainParse( eq ); } if( res ){ makeMathML( res ); } Node *tmpNode; int count = nodelist.count(); for( int i = 0 ; i < count ; i++ ){ tmpNode = nodelist.remove(0); delete tmpNode; } return 0; } void Formula::trim() { int len = strlen(eq); char *buf = (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( strlen(buf) > 0 ) strcpy(eq, buf); else eq = 0L; free(buf); }