diff options
-rw-r--r-- | apache-commons/patches/codec.patch | 17 | ||||
-rw-r--r-- | filter/source/xslt/odf2xhtml/export/common/body.xsl | 422 | ||||
-rw-r--r-- | filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl | 355 | ||||
-rw-r--r-- | hwpfilter/source/hwpeq.cpp | 765 |
4 files changed, 1559 insertions, 0 deletions
diff --git a/apache-commons/patches/codec.patch b/apache-commons/patches/codec.patch new file mode 100644 index 000000000000..dea25ad263d2 --- /dev/null +++ b/apache-commons/patches/codec.patch @@ -0,0 +1,17 @@ +--- misc/build/commons-codec-1.3/build.xml-old 2008-01-31 15:28:58.000000000 +0100 ++++ misc/build/commons-codec-1.3/build.xml 2008-01-31 15:29:21.000000000 +0100 +@@ -90,14 +90,12 @@ + </target>
+ <target name="dist" depends="compile,javadoc" description="Create binary distribution">
+ <mkdir dir="${dist.home}"/>
+- <copy file="../LICENSE" todir="${dist.home}"/>
+ <copy file="${basedir}/RELEASE-NOTES.txt" todir="${dist.home}"/>
+ <antcall target="jar"/>
+ </target>
+ <target name="jar" depends="compile" description="Create jar">
+ <mkdir dir="${dist.home}"/>
+ <mkdir dir="${build.home}/classes/META-INF"/>
+- <copy file="../LICENSE" tofile="${build.home}/classes/META-INF/LICENSE.txt"/>
+ <jar jarfile="${dist.home}/${final.name}.jar" basedir="${build.home}/classes" manifest="${build.home}/conf/MANIFEST.MF"/>
+ </target>
+ <target name="install-jar" depends="jar" description="--> Installs jar file in ${lib.repo}">
diff --git a/filter/source/xslt/odf2xhtml/export/common/body.xsl b/filter/source/xslt/odf2xhtml/export/common/body.xsl new file mode 100644 index 000000000000..96f7d3ce691c --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/body.xsl @@ -0,0 +1,422 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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> + for a copy of the LGPLv3 License. + +-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://xml.apache.org/xslt/java" xmlns:urlencoder="http://www.jclark.com/xt/java/java.net.URLEncoder" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi java urlencoder">
+
+
+ <xsl:include href="table_of_content.xsl"/>
+
+
+ <!-- ****************** -->
+ <!-- *** Whitespace *** -->
+ <!-- ****************** -->
+
+ <xsl:template match="text:s">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="@text:c"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace">
+ <xsl:param name="whitespaces"/>
+
+ <!--write two space chars as the normal white space character will be stripped
+ and the other is able to break -->
+ <xsl:text> </xsl:text>
+ <xsl:if test="$whitespaces >= 2">
+ <xsl:call-template name="write-breakable-whitespace-2">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace-2">
+ <xsl:param name="whitespaces"/>
+ <!--write two space chars as the normal white space character will be stripped
+ and the other is able to break -->
+ <xsl:text> </xsl:text>
+ <xsl:if test="$whitespaces >= 2">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- currentSolution: 8 non-breakable-spaces instead of a TAB is an approximation.
+ Sometimes less spaces than 8 might be needed and the output might be more difficult to read-->
+ <xsl:template match="text:tab">
+ <xsl:param name="globalData"/>
+
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="8"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+
+ <!-- *************** -->
+ <!-- *** Textbox *** -->
+ <!-- *************** -->
+
+ <!-- ID / NAME of text-box -->
+ <xsl:template match="@draw:name">
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(.,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(., '
&<>.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(., '
&<>.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:template>
+
+
+ <xsl:template match="text:line-break">
+ <xsl:param name="listIndent"/>
+
+ <xsl:element namespace="{$namespace}" name="br"/>
+
+ <!-- line breaks in lists need an indent similar to the list label -->
+ <xsl:if test="$listIndent">
+ <xsl:element namespace="{$namespace}" name="span">
+ <xsl:attribute name="style">margin-left:<xsl:value-of select="$listIndent"/>cm</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+
+ <!-- currently there have to be an explicit call of the style attribute nodes, maybe the attributes nodes have no priority only order relevant-->
+ <xsl:template name="apply-styles-and-content">
+ <xsl:param name="globalData"/>
+ <xsl:param name="footnotePrefix" />
+ <xsl:apply-templates select="@*">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ <!-- the footnote symbol is the prefix for a footnote in the footer -->
+ <xsl:copy-of select="$footnotePrefix"/>
+ <xsl:apply-templates select="node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <!-- ******************* -->
+ <!-- *** References *** -->
+ <!-- ******************* -->
+
+ <xsl:template match="text:reference-ref | text:sequence-ref">
+ <xsl:param name="globalData"/>
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:attribute name="href">
+ <xsl:text>#</xsl:text>
+ <xsl:choose>
+ <xsl:when test="number(substring(@text:ref-name,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <xsl:apply-templates select="@* | node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="@text:name">
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(.,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(., '
&<>.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(., '
&<>.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:template>
+
+ <xsl:template match="text:sequence">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@*" />
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(@text:ref-name,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="text:reference-mark">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@*" />
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(@text:name,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(@text:name, '
&<>.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(@text:name, '
&<>.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <xsl:template match="text:reference-mark-start">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@*" />
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:bibliography-mark">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@* | node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- @text:title exist only in text:bibliography-mark -->
+ <xsl:template match="@text:title">
+ <xsl:attribute name="title">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!-- @text:url exist only in text:bibliography-mark -->
+ <xsl:template match="@text:url">
+ <xsl:attribute name="href">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <xsl:template match="text:user-defined">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+
+ <xsl:template match="office:annotation">
+ <xsl:element name="span">
+ <xsl:attribute name="title">annotation</xsl:attribute>
+ <xsl:attribute name="class">annotation_style_by_filter</xsl:attribute>
+ <xsl:apply-templates select="@*" />
+ <br/>
+ <xsl:text>[ANNOTATION:</xsl:text>
+ <br/>
+ <xsl:apply-templates select="*" mode="annotation"/>
+ <xsl:text>]</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:p" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:text>NOTE: '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="dc:creator" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:attribute name="title">dc:creator</xsl:attribute>
+ <xsl:text>BY '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="dc:date" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:attribute name="title">dc:date</xsl:attribute>
+ <xsl:text>ON '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="meta:date-string" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:attribute name="title">meta-date-string</xsl:attribute>
+ <xsl:text>META DATE '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- *************** -->
+ <!-- *** HELPER *** -->
+ <!-- *************** -->
+
+
+ <xsl:template name="create-href">
+ <xsl:param name="href"/>
+
+ <xsl:choose>
+ <!-- internal OOo URL used in content tables -->
+ <xsl:when test="contains($href, '%7Coutline')">
+ <!-- the simple workaround for content tables in a single document is to create create an anchor from every heading element
+ work-around downside: Multiple identical headings won't refer always to the first.
+ -->
+ <xsl:text>#</xsl:text>
+ <xsl:variable name="title">
+ <xsl:apply-templates mode="concatenate"/>
+ </xsl:variable>
+
+ <xsl:value-of select="concat('a_', translate(normalize-space($title), '.,;: %()[]/\+', '_____________'))"/>
+ </xsl:when>
+ <xsl:when test="self::draw:image[office:binary-data]">
+ <xsl:text>data:image/*;base64,</xsl:text><xsl:value-of select="office:binary-data"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- in case of packed open office document -->
+ <xsl:when test="starts-with($sourceBaseURL, 'jar:') or $isPackageFormat">
+ <xsl:choose>
+ <!-- for images relative to open office document -->
+ <xsl:when test="starts-with($href, '../')">
+ <!-- creating an absolute http URL to the packed image file (removing the '.')-->
+ <xsl:value-of select="concat(substring-after(substring-before($sourceBaseURL, '!'), 'jar:'), '/', $href, $optionalURLSuffix)"/>
+ </xsl:when>
+ <!-- for absolute URLs & absolute paths -->
+ <xsl:when test="contains($href, ':') or starts-with($href, '/')">
+ <xsl:value-of select="concat($href, $optionalURLSuffix)"/>
+ </xsl:when>
+ <!-- for images jared in open office document -->
+ <xsl:otherwise>
+ <xsl:value-of select="concat($sourceBaseURL, $href, $optionalURLSuffix)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- for absolute URLs & Paths -->
+ <xsl:when test="contains($href, ':') or starts-with($href, '/')">
+ <xsl:value-of select="concat($href, $optionalURLSuffix)"/>
+ </xsl:when>
+ <!-- for relative URLs -->
+ <xsl:otherwise>
+ <xsl:value-of select="concat($sourceBaseURL, $href, $optionalURLSuffix)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+ <xsl:template match="text()" mode="concatenate">
+ <xsl:value-of select="."/>
+ </xsl:template>
+ <xsl:template match="*" mode="concatenate">
+ <xsl:apply-templates mode="concatenate"/>
+ </xsl:template>
+
+
+ <!-- ******************** -->
+ <!-- *** Common Rules *** -->
+ <!-- ******************** -->
+
+ <!-- ignore / neglect the following elements -->
+ <xsl:template match="draw:custom-shape | draw:g | office:forms | text:alphabetical-index-mark | text:alphabetical-index-mark-end | text:alphabetical-index-mark-start | text:bibliography-source | text:number | text:reference-mark-end | text:sequence-decls | text:soft-page-break | text:table-of-content-source | text:tracked-changes | text:user-field-decls"/>
+
+ <!-- default template used by purpose-->
+ <xsl:template match="text:bibliography | text:change-end | text:change-start">
+ <xsl:param name="globalData"/>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- default template for not recognized elements -->
+ <xsl:template match="*">
+ <xsl:param name="globalData"/>
+ <xsl:message>Using default element rule for ODF element '<xsl:value-of select="name()"/>'.</xsl:message>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="@*"/>
+
+ <!-- allowing all matched text nodes -->
+ <xsl:template match="text()">
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl b/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl new file mode 100644 index 000000000000..cfd38dcd9a3d --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl @@ -0,0 +1,355 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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> + for a copy of the LGPLv3 License. + +-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi">
+
+
+ <!-- *** Properties with a 'fo:' prefix *** -->
+ <xsl:template match="@fo:background-color">
+ <xsl:text>background-color:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@fo:border | @fo:border-top | @fo:border-bottom | @fo:border-left | @fo:border-right">
+ <xsl:variable name="borderType" select="substring-after(name(), ':')"/>
+ <xsl:choose>
+ <xsl:when test=". = 'none'">
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-style:none; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="borderWidth" select="substring-before(., ' ')"/>
+ <xsl:variable name="borderStyle" select="substring-before(substring-after(., ' '), ' ')"/>
+ <xsl:variable name="borderColor" select="substring-after(substring-after(., ' '), ' ')"/>
+
+ <!-- More information at template 'round-up-border-width' -->
+ <xsl:variable name="borderWidthFixed">
+ <xsl:call-template name="round-up-border-width">
+ <xsl:with-param name="borderWidth" select="$borderWidth"/>
+ <xsl:with-param name="multiplier">
+ <xsl:choose>
+ <xsl:when test="$borderStyle = 'double'">3</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-width:</xsl:text>
+ <xsl:value-of select="$borderWidthFixed"/>
+ <xsl:text>; </xsl:text>
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-style:</xsl:text>
+ <xsl:value-of select="$borderStyle"/>
+ <xsl:text>; </xsl:text>
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-color:</xsl:text>
+ <xsl:value-of select="$borderColor"/>
+ <xsl:text>; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- NOTE: Still there have to be placed a <br clear='all' /> to disable the flow!!!!-->
+ <xsl:template match="@fo:clear">
+ <xsl:text>clear:both; </xsl:text>
+ </xsl:template>
+
+ <!-- text-shadow is a CSS2 feature and yet not common used in user-agents -->
+ <xsl:template match="@fo:color |@svg:font-family |@fo:font-size |@fo:font-style |@fo:font-weight |@fo:text-indent |@fo:text-shadow">
+ <xsl:value-of select="substring-after(name(), ':')"/>
+ <xsl:text>:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <!-- Maps fo:margin as well fo:margin-top, fo:margin-bottom, fo:padding-left, fo:margin-right -->
+ <!-- Maps fo:padding as well fo:padding-top, fo:padding-bottom, fo:padding-left, fo:padding-right -->
+ <xsl:template match="@fo:letter-spacing | @fo:line-height | @fo:width |@fo:margin | @fo:margin-top | @fo:margin-bottom | @fo:margin-left | @fo:margin-right | @fo:padding | @fo:padding-top | @fo:padding-bottom | @fo:padding-left | @fo:padding-right">
+ <xsl:value-of select="substring-after(name(), ':')"/>
+ <xsl:text>:</xsl:text>
+ <!-- Map once erroneusly used inch shortage 'inch' to CSS shortage 'in' -->
+ <xsl:choose>
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@fo:text-align">
+ <!-- 'important' is necessary as table cell value alignment is decided by runtime over the valuetype
+ Otherwise a table cell style-class would always be outnumbered by the run-time alignment value -->
+ <xsl:choose>
+ <xsl:when test="contains(., 'start')">
+ <xsl:choose>
+ <xsl:when test="parent::*/@style:writing-mode and contains(parent::*/@style:writing-mode, 'rl')">
+ <xsl:text>text-align:right ! important; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>text-align:left ! important; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="contains(., 'end')">
+ <xsl:choose>
+ <xsl:when test="parent::*/@style:writing-mode and contains(parent::*/@style:writing-mode, 'rl')">
+ <xsl:text>text-align:left ! important;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>text-align:right ! important; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>text-align:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text> ! important; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@style:vertical-align">
+ <xsl:choose>
+ <xsl:when test="contains(., 'bottom')">
+ <xsl:text>vertical-align:bottom; </xsl:text>
+ </xsl:when>
+ <xsl:when test="contains(., 'middle')">
+ <xsl:text>vertical-align:middle; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>vertical-align:top; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+<!-- *** Properties with a 'style:' prefix *** -->
+ <!-- NOTE: Can 'inside' | 'from-inside' better be handled:
+ <!ATTLIST * style:horizontal-pos (from-left|left|center|right|from-inside|inside|outside)#IMPLIED>-->
+ <xsl:template match="@style:horizontal-pos">
+ <xsl:choose>
+ <xsl:when test=".='left'">
+ <xsl:text>text-align:left; </xsl:text>
+ </xsl:when>
+ <xsl:when test=". = 'right'">
+ <xsl:text>text-align:right; </xsl:text>
+ </xsl:when>
+ <xsl:when test=".='center'">
+ <xsl:text>text-align:center; </xsl:text>
+ </xsl:when>
+ <!-- NOTE: currently other values are not used.
+ If the property value is from-left or from-inside,
+ the svg:x attribute associated with the frame element specifies
+ the horizontal position of the frame.
+ Otherwise the svg:x attribute is ignored for text documents.
+ -->
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@style:column-width">
+ <xsl:text>width:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@style:text-underline-style">
+ <xsl:text>text-decoration:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test=".='none'">
+ <xsl:text>none ! important</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>underline</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@style:font-name">
+ <xsl:param name="globalData" />
+
+ <xsl:text>font-family:</xsl:text>
+ <xsl:variable name="content" select="."/>
+ <xsl:variable name="quote">'</xsl:variable>
+ <xsl:variable name="fontName" select="$globalData/office:font-face-decls/style:font-face[@style:name=$content]/@svg:font-family" />
+ <xsl:value-of select="translate($fontName, $quote, '')"/>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@style:row-height">
+ <xsl:text>height:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@svg:strikethrough-position">
+ <xsl:if test="not(.='none')">
+ <xsl:text>text-decoration:line-through; </xsl:text>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="@style:text-position">
+ <xsl:if test="contains(., 'sub')">
+ <xsl:text>vertical-align:sub; </xsl:text>
+ <xsl:if test="contains(., '%')">
+ <xsl:text>font-size:</xsl:text>
+ <xsl:value-of select="substring-after(., 'sub ')"/>
+ <xsl:text>;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="contains(., 'super')">
+ <xsl:text>vertical-align:super; </xsl:text>
+ <xsl:if test="contains(., '%')">
+ <xsl:text>font-size:</xsl:text>
+ <xsl:value-of select="substring-after(., 'super ')"/>
+ <xsl:text>;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="@style:vertical-pos">
+ <xsl:choose>
+ <xsl:when test=".='from-top'">
+ <xsl:text>vertical-align:top; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>vertical-align:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@style:width">
+ <xsl:text>width:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+ <xsl:template match="@style:wrap">
+ <xsl:choose>
+ <xsl:when test=".='left'">
+ <xsl:text>float:right; </xsl:text>
+ </xsl:when>
+ <xsl:when test=".='right'">
+ <xsl:text>float:left; </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="@style:writing-mode">
+ <xsl:text>writing-mode:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+ <!-- *** Properties with a no 'fo:' or 'style:' prefix *** -->
+ <xsl:template match="@table:align">
+ <xsl:choose>
+ <xsl:when test=".='left'">
+ <!-- Note: problems with meeting minutes example
+ <xsl:text>float:right; </xsl:text> --></xsl:when>
+ <xsl:when test=".='right'">
+ <!-- Note: problems with meeting minutes example
+ <xsl:text>float:left; </xsl:text> --></xsl:when>
+ <xsl:otherwise>
+ <xsl:text>float:none; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="style:background-image">
+ <xsl:text>background-image:url(</xsl:text>
+ <xsl:value-of select="@xlink:href"/>
+ <xsl:text>); </xsl:text>
+ <xsl:choose>
+ <xsl:when test="@style:repeat = 'repeat'">
+ <xsl:text>background-repeat:repeat; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>background-repeat:no-repeat; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Changing border width measure to cm and enlarging border-width to the Mozilla browser(1.7)
+ visible minimum width
+ - 0.0133cm for solid style
+ - 0.0399cm for double style
+ as there are three border lines painted -->
+ <xsl:template name="round-up-border-width">
+ <xsl:param name="borderWidth"/>
+ <xsl:param name="multiplier"/>
+
+ <xsl:variable name="borderWidthByCentimeter">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$borderWidth"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="minimalBorderWidth" select="0.0133 * $multiplier"/>
+ <xsl:choose>
+ <xsl:when test="number($borderWidthByCentimeter) < $minimalBorderWidth">
+ <xsl:value-of select="$minimalBorderWidth"/>
+ <xsl:text>cm</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$borderWidthByCentimeter"/>
+ <xsl:text>cm</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
+
diff --git a/hwpfilter/source/hwpeq.cpp b/hwpfilter/source/hwpeq.cpp new file mode 100644 index 000000000000..5e68170f6a5d --- /dev/null +++ b/hwpfilter/source/hwpeq.cpp @@ -0,0 +1,765 @@ +/************************************************************************* + * + * 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 "stdafx.h" + +#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> +//#define TEST +//#define DEBUG + + +/* @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 = sizeof(eq_tbl) / sizeof(eq_tbl[0]); + 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; + // cout << "WHITE : " << "|" << white.c_str() << "|" << endl ; + // cout << "TOKEN : " << "|" << token.c_str() << "|" << endl ; + return token.length(); +} + +static int read_white_space(MzString& outs, istream *strm) +{ + int ch, result; + + if( stk->state(strm) ) { + outs << stk->white; + stk->white = 0; + result = stk->token[0]; + } + else { + 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 ch, result, nargs; + char keyword[256]; + hwpeq *eq; +#ifdef DEBUG + static int slevel = 0; + + slevel++; +#endif + 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)) ) { + nargs = eq->nargs; + 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; +#ifdef DEBUG + //if( slevel == 1 ) + // cout << "LEVEL[" << slevel << "]" << state << "\n"; + slevel--; +#endif + 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[20]; + 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); +#ifdef TEST + cout << "Step1: " << endl << tstr.c_str() << endl; +#endif + 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; +} |