summaryrefslogtreecommitdiffstats
path: root/lib/kformula/elementtype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kformula/elementtype.cpp')
-rw-r--r--lib/kformula/elementtype.cpp765
1 files changed, 765 insertions, 0 deletions
diff --git a/lib/kformula/elementtype.cpp b/lib/kformula/elementtype.cpp
new file mode 100644
index 000000000..bd2c33738
--- /dev/null
+++ b/lib/kformula/elementtype.cpp
@@ -0,0 +1,765 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
+ Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+#include <tqpainter.h>
+
+#include <kdebug.h>
+
+#include "basicelement.h"
+#include "contextstyle.h"
+#include "elementtype.h"
+#include "sequenceelement.h"
+#include "sequenceparser.h"
+#include "textelement.h"
+
+
+KFORMULA_NAMESPACE_BEGIN
+
+int ElementType::evilDestructionCount = 0;
+
+/*
+ * Converts CharStyle and CharFamily to the MathML 'mathvariant'
+ * attribute (see MathML spec 3.2.2).
+ */
+TQString format2variant( CharStyle style, CharFamily family )
+{
+ TQString result;
+
+ switch( family ) {
+ case normalFamily:
+ case anyFamily:
+ switch( style ) {
+ case normalChar:
+ result = "normal"; break;
+ case boldChar:
+ result = "bold"; break;
+ case italicChar:
+ result = "italic"; break;
+ case boldItalicChar:
+ result = "bold-italic"; break;
+ case anyChar:
+ break;
+ }
+ break;
+ case scriptFamily:
+ result = "script";
+ if ( style == boldChar || style == boldItalicChar )
+ result = "bold-" + result;
+ break;
+ case frakturFamily:
+ result = "fraktur";
+ if ( style == boldChar || style == boldItalicChar )
+ result = "bold-" + result;
+ break;
+ case doubleStruckFamily:
+ result = "double-struck"; break;
+ }
+
+ return result;
+}
+
+ElementType::ElementType( SequenceParser* parser )
+ : from( parser->getStart() ), to( parser->getEnd() ), prev( 0 )
+{
+ evilDestructionCount++;
+}
+
+ElementType::~ElementType()
+{
+ delete prev;
+ evilDestructionCount--;
+}
+
+
+TQString ElementType::text( SequenceElement* seq ) const
+{
+ TQString str;
+ for ( uint i=start(); i<end(); ++i ) {
+ str.append( seq->getChild( i )->getCharacter() );
+ }
+ return str;
+}
+
+
+luPt ElementType::getSpaceBefore( const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::getSpaceAfter( MultiElementType*,
+ const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::getSpaceAfter( OperatorType*,
+ const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::getSpaceAfter( RelationType*,
+ const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::getSpaceAfter( PunctuationType*,
+ const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::getSpaceAfter( BracketType*,
+ const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::getSpaceAfter( ComplexElementType*,
+ const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::getSpaceAfter( InnerElementType*,
+ const ContextStyle&,
+ ContextStyle::TextStyle,
+ double )
+{
+ return 0;
+}
+
+luPt ElementType::thinSpaceIfNotScript( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( !context.isScript( tstyle ) ) {
+ return context.getThinSpace( tstyle, factor );
+ }
+ return 0;
+}
+
+luPt ElementType::mediumSpaceIfNotScript( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( !context.isScript( tstyle ) ) {
+ return context.getMediumSpace( tstyle, factor );
+ }
+ return 0;
+}
+
+luPt ElementType::thickSpaceIfNotScript( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( !context.isScript( tstyle ) ) {
+ return context.getThickSpace( tstyle, factor );
+ }
+ return 0;
+}
+
+
+TQFont ElementType::getFont(const ContextStyle& context)
+{
+ return context.getDefaultFont();
+}
+
+void ElementType::setUpPainter(const ContextStyle& context, TQPainter& painter)
+{
+ painter.setPen(context.getDefaultColor());
+}
+
+void ElementType::append( ElementType* element )
+{
+ element->prev = this;
+}
+
+void ElementType::output()
+{
+ kdDebug( DEBUGID ) << start() << " - " << end() << endl;
+}
+
+void ElementType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
+{
+ for ( uint i = from; i < to; ++i ) {
+ se->getChild( i )->writeMathML( doc, de, oasisFormat );
+ }
+}
+
+
+SequenceType::SequenceType( SequenceParser* parser )
+ : ElementType( parser ), last( 0 )
+{
+ while ( true ) {
+ parser->nextToken();
+ //cerr << "SequenceType::SequenceType(): " << parser->getTokenType() << " "
+ // << parser->getStart() << " " << parser->getEnd() << endl;
+ if ( parser->getTokenType() == END ) {
+ break;
+ }
+ ElementType* nextType = parser->getPrimitive();
+ if ( nextType == 0 ) {
+ break;
+ }
+ if ( last != 0 ) {
+ last->append( nextType );
+ }
+ last = nextType;
+ }
+}
+
+SequenceType::~SequenceType()
+{
+ delete last;
+}
+
+
+void SequenceType::output()
+{
+}
+
+
+MultiElementType::MultiElementType( SequenceParser* parser )
+ : ElementType( parser )
+{
+ for ( uint i = start(); i < end(); i++ ) {
+ parser->setElementType( i, this );
+ }
+ m_text = parser->text();
+}
+
+
+luPt MultiElementType::getSpaceBefore( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( getPrev() != 0 ) {
+ return getPrev()->getSpaceAfter( this, context, tstyle, factor );
+ }
+ return 0;
+}
+
+luPt MultiElementType::getSpaceAfter( OperatorType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt MultiElementType::getSpaceAfter( RelationType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt MultiElementType::getSpaceAfter( InnerElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+
+TextType::TextType( SequenceParser* parser )
+ : MultiElementType( parser )
+{
+}
+
+void TextType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
+{
+ for ( uint i = start(); i < end(); ++i ) {
+ TQDomElement text = doc.createElement( oasisFormat ? "math:mi" : "mi" );
+ BasicElement* be = se->getChild( i );
+ TextElement* te = static_cast<TextElement*>( be );
+ TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily());
+ if ( !mathvariant.isNull() )
+ text.setAttribute( "mathvariant", mathvariant );
+
+ text.appendChild( doc.createTextNode( be->getCharacter() ) );
+
+ de.appendChild( text );
+ if ( i != end() - 1 ) {
+ TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
+ op.appendChild( doc.createEntityReference( "InvisibleTimes" ) );
+ de.appendChild( op );
+ }
+ }
+}
+
+
+NameType::NameType( SequenceParser* parser )
+ : MultiElementType( parser )
+{
+}
+
+void NameType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
+{
+ se->getChild( start() )->writeMathML( doc, de, oasisFormat );
+
+ /*
+ TQDomElement name = doc.createElement( "mi" );
+ TQString value;
+ for ( uint i = start(); i < end(); ++i ) {
+ BasicElement* be = se->getChild( i );
+ //TextElement* te = static_cast<TextElement*>( be );
+ value += be->getCharacter();
+ }
+ name.appendChild( doc.createTextNode( value ) );
+ de.appendChild( name );*/
+}
+
+
+TQFont NameType::getFont(const ContextStyle& context)
+{
+ return context.getNameFont();
+}
+
+NumberType::NumberType( SequenceParser* parser )
+ : MultiElementType( parser )
+{
+}
+
+TQFont NumberType::getFont(const ContextStyle& context)
+{
+ return context.getNumberFont();
+}
+
+void NumberType::setUpPainter(const ContextStyle& context, TQPainter& painter)
+{
+ painter.setPen(context.getNumberColor());
+}
+
+void NumberType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
+{
+ TQDomElement name = doc.createElement( oasisFormat ? "math:mn" : "mn" );
+ TQString value;
+ for ( uint i = start(); i < end(); ++i ) {
+ BasicElement* be = se->getChild( i );
+ value += be->getCharacter();
+ }
+ TextElement* te = static_cast<TextElement*>( se->getChild( start() ) );
+ TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
+ if ( !mathvariant.isNull() )
+ name.setAttribute( "mathvariant", mathvariant );
+
+ name.appendChild( doc.createTextNode( value ) );
+ de.appendChild( name );
+}
+
+
+SingleElementType::SingleElementType( SequenceParser* parser )
+ : ElementType( parser )
+{
+ parser->setElementType( start(), this );
+}
+
+AbstractOperatorType::AbstractOperatorType( SequenceParser* parser )
+ : SingleElementType( parser )
+{
+}
+
+void AbstractOperatorType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
+{
+ TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
+ BasicElement* be = se->getChild( start() );
+ if ( be->getCharacter().latin1() != 0 ) {
+ // latin-1 char
+ op.appendChild( doc.createTextNode( be->getCharacter() ) );
+ }
+ else {
+ // unicode char
+ TQString s;
+ op.appendChild( doc.createEntityReference( s.sprintf( "#x%05X", be->getCharacter().unicode() ) ) );
+ }
+ TextElement* te = static_cast<TextElement*>( be );
+ TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
+ if ( !mathvariant.isNull() )
+ op.setAttribute( "mathvariant", mathvariant );
+
+ de.appendChild( op );
+}
+
+OperatorType::OperatorType( SequenceParser* parser )
+ : AbstractOperatorType( parser )
+{
+}
+
+luPt OperatorType::getSpaceBefore( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( getPrev() != 0 ) {
+ return getPrev()->getSpaceAfter( this, context, tstyle, factor );
+ }
+ return 0;
+}
+
+luPt OperatorType::getSpaceAfter( MultiElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt OperatorType::getSpaceAfter( BracketType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt OperatorType::getSpaceAfter( ComplexElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt OperatorType::getSpaceAfter( InnerElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+
+TQFont OperatorType::getFont(const ContextStyle& context)
+{
+ return context.getOperatorFont();
+}
+
+void OperatorType::setUpPainter(const ContextStyle& context, TQPainter& painter)
+{
+ painter.setPen(context.getOperatorColor());
+}
+
+
+RelationType::RelationType( SequenceParser* parser )
+ : AbstractOperatorType( parser )
+{
+}
+
+luPt RelationType::getSpaceBefore( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( getPrev() != 0 ) {
+ return getPrev()->getSpaceAfter( this, context, tstyle, factor );
+ }
+ return 0;
+}
+
+luPt RelationType::getSpaceAfter( MultiElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt RelationType::getSpaceAfter( BracketType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt RelationType::getSpaceAfter( ComplexElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt RelationType::getSpaceAfter( InnerElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+TQFont RelationType::getFont( const ContextStyle& context )
+{
+ return context.getOperatorFont();
+}
+
+void RelationType::setUpPainter( const ContextStyle& context, TQPainter& painter )
+{
+ painter.setPen(context.getOperatorColor());
+}
+
+
+
+PunctuationType::PunctuationType( SequenceParser* parser )
+ : AbstractOperatorType( parser )
+{
+}
+
+luPt PunctuationType::getSpaceBefore( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( getPrev() != 0 ) {
+ return getPrev()->getSpaceAfter( this, context, tstyle, factor );
+ }
+ return 0;
+}
+
+luPt PunctuationType::getSpaceAfter( MultiElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt PunctuationType::getSpaceAfter( RelationType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt PunctuationType::getSpaceAfter( PunctuationType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt PunctuationType::getSpaceAfter( BracketType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt PunctuationType::getSpaceAfter( ComplexElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt PunctuationType::getSpaceAfter( InnerElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+TQFont PunctuationType::getFont( const ContextStyle& context )
+{
+ return context.getOperatorFont();
+}
+
+void PunctuationType::setUpPainter( const ContextStyle& context, TQPainter& painter )
+{
+ painter.setPen( context.getDefaultColor() );
+}
+
+
+BracketType::BracketType( SequenceParser* parser )
+ : SingleElementType( parser )
+{
+}
+
+luPt BracketType::getSpaceBefore( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( getPrev() != 0 ) {
+ return getPrev()->getSpaceAfter( this, context, tstyle, factor );
+ }
+ return 0;
+}
+
+luPt BracketType::getSpaceAfter( OperatorType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt BracketType::getSpaceAfter( RelationType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt BracketType::getSpaceAfter( InnerElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+
+ComplexElementType::ComplexElementType( SequenceParser* parser )
+ : SingleElementType( parser )
+{
+}
+
+luPt ComplexElementType::getSpaceBefore( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( getPrev() != 0 ) {
+ return getPrev()->getSpaceAfter( this, context, tstyle, factor );
+ }
+ return 0;
+}
+
+luPt ComplexElementType::getSpaceAfter( OperatorType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt ComplexElementType::getSpaceAfter( RelationType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt ComplexElementType::getSpaceAfter( InnerElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+
+InnerElementType::InnerElementType( SequenceParser* parser )
+ : SingleElementType( parser )
+{
+}
+
+luPt InnerElementType::getSpaceBefore( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ if ( getPrev() != 0 ) {
+ return getPrev()->getSpaceAfter( this, context, tstyle, factor );
+ }
+ return 0;
+}
+
+luPt InnerElementType::getSpaceAfter( MultiElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt InnerElementType::getSpaceAfter( OperatorType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return mediumSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt InnerElementType::getSpaceAfter( RelationType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thickSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt InnerElementType::getSpaceAfter( PunctuationType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt InnerElementType::getSpaceAfter( BracketType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt InnerElementType::getSpaceAfter( ComplexElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+luPt InnerElementType::getSpaceAfter( InnerElementType*,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ double factor )
+{
+ return thinSpaceIfNotScript( context, tstyle, factor );
+}
+
+
+KFORMULA_NAMESPACE_END