summaryrefslogtreecommitdiffstats
path: root/lib/kformula/bracketelement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kformula/bracketelement.cpp')
-rw-r--r--lib/kformula/bracketelement.cpp1005
1 files changed, 1005 insertions, 0 deletions
diff --git a/lib/kformula/bracketelement.cpp b/lib/kformula/bracketelement.cpp
new file mode 100644
index 00000000..45aa5469
--- /dev/null
+++ b/lib/kformula/bracketelement.cpp
@@ -0,0 +1,1005 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Andrea Rizzi <[email protected]>
+ Ulrich Kuettler <[email protected]>
+
+ 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 <tqptrlist.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpointarray.h>
+
+#include <kdebug.h>
+#include <tdelocale.h>
+
+#include "bracketelement.h"
+#include "elementvisitor.h"
+#include "fontstyle.h"
+#include "formulacursor.h"
+#include "formulaelement.h"
+#include "sequenceelement.h"
+
+KFORMULA_NAMESPACE_BEGIN
+
+SingleContentElement::SingleContentElement(BasicElement* parent )
+ : BasicElement( parent )
+{
+ content = new SequenceElement( this );
+}
+
+
+SingleContentElement::SingleContentElement( const SingleContentElement& other )
+ : BasicElement( other )
+{
+ content = new SequenceElement( other.content );
+ content->setParent( this );
+}
+
+
+SingleContentElement::~SingleContentElement()
+{
+ delete content;
+}
+
+
+TQChar SingleContentElement::getCharacter() const
+{
+ // This is meant to make the SingleContentElement text only.
+ // This "fixes" the parenthesis problem (parenthesis too large).
+ // I'm not sure if we really want this. There should be better ways.
+ if ( content->isTextOnly() ) {
+ return '\\';
+ }
+ return content->getCharacter();
+}
+
+BasicElement* SingleContentElement::goToPos( FormulaCursor* cursor, bool& handled,
+ const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
+{
+ BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
+ if (e != 0) {
+ LuPixelPoint myPos(parentOrigin.x() + getX(),
+ parentOrigin.y() + getY());
+
+ e = content->goToPos(cursor, handled, point, myPos);
+ if (e != 0) {
+ return e;
+ }
+ return this;
+ }
+ return 0;
+}
+
+void SingleContentElement::dispatchFontCommand( FontCommand* cmd )
+{
+ content->dispatchFontCommand( cmd );
+}
+
+void SingleContentElement::moveLeft(FormulaCursor* cursor, BasicElement* from)
+{
+ if (cursor->isSelectionMode()) {
+ getParent()->moveLeft(cursor, this);
+ }
+ else {
+ //bool linear = cursor->getLinearMovement();
+ if (from == getParent()) {
+ content->moveLeft(cursor, this);
+ }
+ else {
+ getParent()->moveLeft(cursor, this);
+ }
+ }
+}
+
+void SingleContentElement::moveRight(FormulaCursor* cursor, BasicElement* from)
+{
+ if (cursor->isSelectionMode()) {
+ getParent()->moveRight(cursor, this);
+ }
+ else {
+ //bool linear = cursor->getLinearMovement();
+ if (from == getParent()) {
+ content->moveRight(cursor, this);
+ }
+ else {
+ getParent()->moveRight(cursor, this);
+ }
+ }
+}
+
+void SingleContentElement::moveUp(FormulaCursor* cursor, BasicElement* /*from*/)
+{
+ getParent()->moveUp(cursor, this);
+}
+
+void SingleContentElement::moveDown(FormulaCursor* cursor, BasicElement* /*from*/)
+{
+ getParent()->moveDown(cursor, this);
+}
+
+void SingleContentElement::remove( FormulaCursor* cursor,
+ TQPtrList<BasicElement>& removedChildren,
+ Direction direction )
+{
+ switch (cursor->getPos()) {
+ case contentPos:
+ BasicElement* parent = getParent();
+ parent->selectChild(cursor, this);
+ parent->remove(cursor, removedChildren, direction);
+ }
+}
+
+void SingleContentElement::normalize( FormulaCursor* cursor, Direction direction )
+{
+ if (direction == beforeCursor) {
+ content->moveLeft(cursor, this);
+ }
+ else {
+ content->moveRight(cursor, this);
+ }
+}
+
+SequenceElement* SingleContentElement::getMainChild()
+{
+ return content;
+}
+
+void SingleContentElement::selectChild(FormulaCursor* cursor, BasicElement* child)
+{
+ if (child == content) {
+ cursor->setTo(this, contentPos);
+ }
+}
+
+void SingleContentElement::writeDom(TQDomElement element)
+{
+ BasicElement::writeDom(element);
+
+ TQDomDocument doc = element.ownerDocument();
+
+ TQDomElement con = doc.createElement("CONTENT");
+ con.appendChild(content->getElementDom(doc));
+ element.appendChild(con);
+}
+
+bool SingleContentElement::readContentFromDom(TQDomNode& node)
+{
+ if (!BasicElement::readContentFromDom(node)) {
+ return false;
+ }
+
+ if ( !buildChild( content, node, "CONTENT" ) ) {
+ kdWarning( DEBUGID ) << "Empty content in " << getTagName() << endl;
+ return false;
+ }
+ node = node.nextSibling();
+
+ return true;
+}
+
+int SingleContentElement::readContentFromMathMLDom( TQDomNode& node )
+{
+ if ( BasicElement::readContentFromMathMLDom( node ) == -1 ) {
+ return -1;
+ }
+
+ int nodeCounter = content->buildMathMLChild( node );
+ if ( nodeCounter == -1 ) {
+ kdWarning( DEBUGID) << "Empty content in SingleContentElement\n";
+ return -1;
+ }
+
+ return nodeCounter;
+}
+
+void SingleContentElement::writeMathMLContent( TQDomDocument& doc, TQDomElement& element, bool oasisFormat ) const
+{
+ content->writeMathML( doc, element, oasisFormat );
+}
+
+
+
+BracketElement::BracketElement(SymbolType l, SymbolType r, BasicElement* parent)
+ : SingleContentElement(parent),
+ left( 0 ), right( 0 ),
+ leftType( l ), rightType( r ),
+ m_operator( false ), m_customLeft( false ), m_customRight( false )
+{
+}
+
+
+BracketElement::~BracketElement()
+{
+ delete left;
+ delete right;
+}
+
+
+BracketElement::BracketElement( const BracketElement& other )
+ : SingleContentElement( other ),
+ left( 0 ), right( 0 ),
+ leftType( other.leftType ), rightType( other.rightType ),
+ m_operator( other.m_operator ),
+ m_customLeft( other.m_customLeft ), m_customRight( other.m_customRight )
+{
+}
+
+
+bool BracketElement::accept( ElementVisitor* visitor )
+{
+ return visitor->visit( this );
+}
+
+
+void BracketElement::entered( SequenceElement* /*child*/ )
+{
+ formula()->tell( i18n( "Delimited list" ) );
+}
+
+
+BasicElement* BracketElement::goToPos( FormulaCursor* cursor, bool& handled,
+ const LuPixelPoint& point, const LuPixelPoint& parentOrigin )
+{
+ BasicElement* e = BasicElement::goToPos(cursor, handled, point, parentOrigin);
+ if (e != 0) {
+ LuPixelPoint myPos(parentOrigin.x() + getX(),
+ parentOrigin.y() + getY());
+ e = getContent()->goToPos(cursor, handled, point, myPos);
+ if (e != 0) {
+ return e;
+ }
+
+ // We are in one of those gaps.
+ luPixel dx = point.x() - myPos.x();
+ luPixel dy = point.y() - myPos.y();
+
+ if ((dx > getContent()->getX()+getContent()->getWidth()) ||
+ (dy > getContent()->getY()+getContent()->getHeight())) {
+ getContent()->moveEnd(cursor);
+ handled = true;
+ return getContent();
+ }
+ return this;
+ }
+ return 0;
+}
+
+
+/**
+ * Calculates our width and height and
+ * our children's parentPosition.
+ */
+void BracketElement::calcSizes( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ ContextStyle::IndexStyle istyle,
+ StyleAttributes& style )
+{
+ SequenceElement* content = getContent();
+ content->calcSizes( context, tstyle, istyle, style );
+
+ //if ( left == 0 ) {
+ delete left;
+ delete right;
+ left = context.fontStyle().createArtwork( leftType );
+ right = context.fontStyle().createArtwork( rightType );
+ //}
+
+ double factor = style.sizeFactor();
+ if (content->isTextOnly()) {
+ left->calcSizes(context, tstyle, factor);
+ right->calcSizes(context, tstyle, factor);
+
+ setBaseline(TQMAX(content->getBaseline(),
+ TQMAX(left->getBaseline(), right->getBaseline())));
+
+ content->setY(getBaseline() - content->getBaseline());
+ left ->setY(getBaseline() - left ->getBaseline());
+ right ->setY(getBaseline() - right ->getBaseline());
+
+ //setMidline(content->getY() + content->getMidline());
+ setHeight(TQMAX(content->getY() + content->getHeight(),
+ TQMAX(left ->getY() + left ->getHeight(),
+ right->getY() + right->getHeight())));
+ }
+ else {
+ //kdDebug( DEBUGID ) << "BracketElement::calcSizes " << content->axis( context, tstyle ) << " " << content->getHeight() << endl;
+ luPixel contentHeight = 2 * TQMAX( content->axis( context, tstyle, factor ),
+ content->getHeight() - content->axis( context, tstyle, factor ) );
+ left->calcSizes( context, tstyle, factor, contentHeight );
+ right->calcSizes( context, tstyle, factor, contentHeight );
+
+ // height
+ setHeight(TQMAX(contentHeight,
+ TQMAX(left->getHeight(), right->getHeight())));
+ //setMidline(getHeight() / 2);
+
+ content->setY(getHeight() / 2 - content->axis( context, tstyle, factor ));
+ setBaseline(content->getBaseline() + content->getY());
+
+ if ( left->isNormalChar() ) {
+ left->setY(getBaseline() - left->getBaseline());
+ }
+ else {
+ left->setY((getHeight() - left->getHeight())/2);
+ }
+ if ( right->isNormalChar() ) {
+ right->setY(getBaseline() - right->getBaseline());
+ }
+ else {
+ right->setY((getHeight() - right->getHeight())/2);
+ }
+
+// kdDebug() << "BracketElement::calcSizes" << endl
+// << "getHeight(): " << getHeight() << endl
+// << "left->getHeight(): " << left->getHeight() << endl
+// << "right->getHeight(): " << right->getHeight() << endl
+// << "left->getY(): " << left->getY() << endl
+// << "right->getY(): " << right->getY() << endl
+// << endl;
+ }
+
+ // width
+ setWidth(left->getWidth() + content->getWidth() + right->getWidth());
+ content->setX(left->getWidth());
+ right ->setX(left->getWidth()+content->getWidth());
+}
+
+
+/**
+ * Draws the whole element including its children.
+ * The `parentOrigin' is the point this element's parent starts.
+ * We can use our parentPosition to get our own origin then.
+ */
+void BracketElement::draw( TQPainter& painter, const LuPixelRect& r,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ ContextStyle::IndexStyle istyle,
+ StyleAttributes& style,
+ const LuPixelPoint& parentOrigin )
+{
+ LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
+ //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
+ // return;
+
+ SequenceElement* content = getContent();
+ content->draw(painter, r, context, tstyle, istyle, style, myPos);
+
+ if (content->isTextOnly()) {
+ left->draw(painter, r, context, tstyle, style, myPos);
+ right->draw(painter, r, context, tstyle, style, myPos);
+ }
+ else {
+ double factor = style.sizeFactor();
+ luPixel contentHeight = 2 * TQMAX(content->axis( context, tstyle, factor ),
+ content->getHeight() - content->axis( context, tstyle, factor ));
+ left->draw(painter, r, context, tstyle, style, contentHeight, myPos);
+ right->draw(painter, r, context, tstyle, style, contentHeight, myPos);
+ }
+
+ // Debug
+#if 0
+ painter.setBrush( TQt::NoBrush );
+ painter.setPen( TQt::red );
+ painter.drawRect( context.layoutUnitToPixelX( myPos.x()+left->getX() ),
+ context.layoutUnitToPixelY( myPos.y()+left->getY() ),
+ context.layoutUnitToPixelX( left->getWidth() ),
+ context.layoutUnitToPixelY( left->getHeight() ) );
+ painter.drawRect( context.layoutUnitToPixelX( myPos.x()+right->getX() ),
+ context.layoutUnitToPixelY( myPos.y()+right->getY() ),
+ context.layoutUnitToPixelX( right->getWidth() ),
+ context.layoutUnitToPixelY( right->getHeight() ) );
+#endif
+}
+
+
+/**
+ * Appends our attributes to the dom element.
+ */
+void BracketElement::writeDom(TQDomElement element)
+{
+ SingleContentElement::writeDom(element);
+ element.setAttribute("LEFT", leftType);
+ element.setAttribute("RIGHT", rightType);
+}
+
+/**
+ * Reads our attributes from the element.
+ * Returns false if it failed.
+ */
+bool BracketElement::readAttributesFromDom(TQDomElement element)
+{
+ if (!BasicElement::readAttributesFromDom(element)) {
+ return false;
+ }
+ TQString leftStr = element.attribute("LEFT");
+ if(!leftStr.isNull()) {
+ leftType = static_cast<SymbolType>(leftStr.toInt());
+ }
+ TQString rightStr = element.attribute("RIGHT");
+ if(!rightStr.isNull()) {
+ rightType = static_cast<SymbolType>(rightStr.toInt());
+ }
+ return true;
+}
+
+/**
+ * Reads our attributes from the MathML element.
+ * Returns false if it failed.
+ */
+bool BracketElement::readAttributesFromMathMLDom(const TQDomElement& element)
+{
+ if ( !BasicElement::readAttributesFromMathMLDom( element ) ) {
+ return false;
+ }
+
+ if ( element.tagName().lower() == "mo" ) {
+ m_operator = true;
+ // TODO: parse attributes in section 3.2.5.2
+ }
+ else { // mfenced, see attributes in section 3.3.8.2
+ leftType = LeftRoundBracket;
+ rightType = RightRoundBracket;
+ TQString openStr = element.attribute( "open" ).stripWhiteSpace();
+ if ( !openStr.isNull() ) {
+ m_customLeft = true;
+ if ( openStr == "[" )
+ leftType = LeftSquareBracket;
+ else if ( openStr == "]" )
+ leftType = RightSquareBracket;
+ else if ( openStr == "{" )
+ leftType = LeftCurlyBracket;
+ else if ( openStr == "}" )
+ leftType = RightCurlyBracket;
+ else if ( openStr == "<" )
+ leftType = LeftCornerBracket;
+ else if ( openStr == ">" )
+ leftType = RightCornerBracket;
+ else if ( openStr == "(" )
+ leftType = LeftRoundBracket;
+ else if ( openStr == ")" )
+ leftType = RightRoundBracket;
+ else if ( openStr == "/" )
+ leftType = SlashBracket;
+ else if ( openStr == "\\" )
+ leftType = BackSlashBracket;
+ else // TODO: Check for entity references
+ leftType = LeftRoundBracket;
+ }
+ TQString closeStr = element.attribute( "close" ).stripWhiteSpace();
+ if ( !closeStr.isNull() ) {
+ m_customRight = true;
+ if ( closeStr == "[" )
+ rightType = LeftSquareBracket;
+ else if ( closeStr == "]" )
+ rightType = RightSquareBracket;
+ else if ( closeStr == "{" )
+ rightType = LeftCurlyBracket;
+ else if ( closeStr == "}" )
+ rightType = RightCurlyBracket;
+ else if ( closeStr == "<" )
+ rightType = LeftCornerBracket;
+ else if ( closeStr == ">" )
+ rightType = RightCornerBracket;
+ else if ( closeStr == "(" )
+ rightType = LeftRoundBracket;
+ else if ( closeStr == ")" )
+ rightType = RightRoundBracket;
+ else if ( closeStr == "/" )
+ rightType = SlashBracket;
+ else if ( closeStr == "\\" )
+ rightType = BackSlashBracket;
+ else // TODO: Check for entity references
+ rightType = LeftRoundBracket;
+ }
+ m_separators = element.attribute( "separators" ).simplifyWhiteSpace();
+ }
+ return true;
+}
+
+/**
+ * Reads our content from the MathML node. Sets the node to the next node
+ * that needs to be read.
+ * Returns false if it failed.
+ */
+int BracketElement::readContentFromMathMLDom(TQDomNode& node)
+{
+ bool empty = false;
+ int nodeCounter = 0;
+ if ( m_operator ) {
+ node = node.parentNode();
+ TQDomNode open = node;
+ TQDomNode parent = node.parentNode();
+ if ( ! operatorType( node, true ) )
+ return -1;
+ int nodeNum = searchOperator( node );
+ if ( nodeNum == -1 ) // Closing bracket not found
+ return -1;
+ if ( nodeNum == 0 ) { // Empty content
+ empty = true;
+ }
+ else if ( nodeNum == 1 ) {
+ do {
+ node = node.nextSibling();
+ nodeCounter++;
+ } while ( ! node.isElement() );
+ }
+ else { // More than two elements inside, infer a mrow
+ nodeCounter += nodeNum;
+ kdWarning() << "NodeNum: " << nodeNum << endl;
+ TQDomDocument doc = node.ownerDocument();
+ TQDomElement de = doc.createElement( "mrow" );
+ int i = 0;
+ do {
+ TQDomNode n = node.nextSibling();
+ de.appendChild( node.toElement() );
+ node = n;
+ } while ( ++i < nodeNum );
+ parent.insertAfter( de, open );
+ node = de;
+ kdWarning() << doc.toString() << endl;
+ }
+ }
+ else {
+ // if it's a mfence tag, we need to convert to equivalent expanded form.
+ // See section 3.3.8
+ while ( ! node.isNull() && ! node.isElement() )
+ node = node.nextSibling();
+ TQDomNode next = node.nextSibling();
+ while ( ! next.isNull() && ! next.isElement() )
+ next = next.nextSibling();
+ if ( ! next.isNull()) {
+ TQDomDocument doc = node.ownerDocument();
+ TQDomNode parent = node.parentNode();
+ TQString ns = parent.prefix();
+ TQDomElement de = doc.createElementNS( ns, "mrow" );
+ uint pos = 0;
+ while ( ! node.isNull() ) {
+ TQDomNode no = node.nextSibling();
+ while ( ! no.isNull() && ! no.isElement() )
+ no = no.nextSibling();
+ de.appendChild( node.toElement() );
+ if ( ! no.isNull() && ( m_separators.isNull() || ! m_separators.isEmpty() ) ) {
+ TQDomElement sep = doc.createElementNS( ns, "mo" );
+ de.appendChild( sep );
+ if ( m_separators.isNull() ) {
+ sep.appendChild( doc.createTextNode( "," ) );
+ }
+ else {
+ if ( m_separators.at( pos ).isSpace() ) {
+ pos++;
+ }
+ sep.appendChild( doc.createTextNode( TQString ( m_separators.at( pos ) ) ) );
+ }
+ if ( pos < m_separators.length() - 1 ) {
+ pos++;
+ }
+ }
+ node = no;
+ }
+ parent.appendChild( de );
+ node = parent.firstChild();
+ while ( ! node.isElement() )
+ node = node.nextSibling();
+ }
+ }
+ if ( ! empty ) {
+ int contentNumber = inherited::readContentFromMathMLDom( node );
+ if ( contentNumber == -1 )
+ return -1;
+ nodeCounter += contentNumber;
+ for (int i = 0; i < contentNumber; i++ ) {
+ if ( node.isNull() ) {
+ return -1;
+ }
+ node = node.nextSibling();
+ }
+ }
+ if ( m_operator ) {
+ int operatorNumber = operatorType( node, false );
+ if ( operatorNumber == -1 ) {
+ return -1;
+ }
+ nodeCounter += operatorNumber;
+ }
+ kdDebug( DEBUGID ) << "Number of bracket nodes: " << nodeCounter << endl;
+ return nodeCounter;
+}
+
+TQString BracketElement::toLatex()
+{
+ TQString ls,rs,cs;
+ cs=getContent()->toLatex();
+ ls="\\left"+latexString(leftType) + " ";
+ rs=" \\right"+latexString(rightType);
+
+ return ls+cs+rs;
+}
+
+TQString BracketElement::latexString(char type)
+{
+ switch (type) {
+ case ']':
+ return "]";
+ case '[':
+ return "[";
+ case '{':
+ return "\\{";
+ case '}':
+ return "\\}";
+ case '(':
+ return "(";
+ case ')':
+ return ")";
+ case '|':
+ return "|";
+ case '<':
+ return "\\langle";
+ case '>':
+ return "\\rangle";
+ case '/':
+ return "/";
+ case '\\':
+ return "\\backslash";
+ }
+ return ".";
+}
+
+TQString BracketElement::formulaString()
+{
+ return "(" + getContent()->formulaString() + ")";
+}
+
+int BracketElement::operatorType( TQDomNode& node, bool open )
+{
+ int counter = 1;
+ SymbolType* type = open ? &leftType : &rightType;
+ while ( ! node.isNull() && ! node.isElement() ) {
+ node = node.nextSibling();
+ counter++;
+ }
+ if ( node.isElement() ) {
+ TQDomElement e = node.toElement();
+ TQDomNode child = e.firstChild();
+ if ( child.isEntityReference() ) {
+ kdWarning() << "Entity Reference\n";
+ TQString name = node.nodeName();
+ // TODO: To fully support these, SymbolType has to be extended,
+ // and better Unicode support is a must
+ // CloseCurlyDoubleQuote 0x201D
+ // CloseCurlyQoute 0x2019
+ // LeftCeiling 0x2308
+ // LeftDoubleBracket 0x301A
+ // LeftFloor 0x230A
+ // OpenCurlyDoubleQuote 0x201C
+ // OpenCurlyQuote 0x2018
+ // RightCeiling 0x2309
+ // RightDoubleBracket 0x301B
+ // RightFloor 0x230B
+ if ( name == "LeftAngleBracket" ) {
+ *type = LeftCornerBracket;
+ }
+ else if ( name == "RightAngleBracket" ) {
+ *type = RightCornerBracket;
+ }
+ else {
+ if ( open ) {
+ *type = LeftRoundBracket;
+ }
+ else
+ *type = RightRoundBracket;
+ }
+ }
+ else {
+ TQString s = e.text();
+ if ( s.isNull() )
+ return -1;
+ *type = static_cast<SymbolType>( TQString::number( s.at( 0 ).latin1() ).toInt() );
+ }
+ }
+ else {
+ return -1;
+ }
+ return counter;
+}
+
+int BracketElement::searchOperator( const TQDomNode& node )
+{
+ TQDomNode n = node;
+ for ( int i = -2; ! n.isNull(); n = n.nextSibling() ) {
+ if ( n.isElement() ) {
+ i++;
+ TQDomElement e = n.toElement();
+ if ( e.tagName().lower() == "mo" ) {
+ // Try to guess looking at attributes
+ TQString form = e.attribute( "form" );
+ TQString f;
+ if ( ! form.isNull() ) {
+ f = form.stripWhiteSpace().lower();
+ }
+ TQString fence = e.attribute( "fence" );
+ if ( ! fence.isNull() ) {
+ if ( fence.stripWhiteSpace().lower() == "false" ) {
+ continue;
+ }
+ if ( ! f.isNull() ) {
+ if ( f == "postfix" ) {
+ return i;
+ }
+ else {
+ continue;
+ }
+ }
+ }
+
+ // Guess looking at contents
+ TQDomNode child = e.firstChild();
+ TQString name;
+ if ( child.isText() )
+ name = child.toText().data().stripWhiteSpace();
+ else if ( child.isEntityReference() )
+ name = child.nodeName();
+ else
+ continue;
+ if ( name == ")"
+ || name == "]"
+ || name == "}"
+ || name == "CloseCurlyDoubleQuote"
+ || name == "CloseCurlyQuote"
+ || name == "RightAngleBracket"
+ || name == "RightCeiling"
+ || name == "RightDoubleBracket"
+ || name == "RightFloor" ) {
+ if ( f.isNull() || f == "postfix" )
+ return i;
+ }
+ if ( name == "("
+ || name == "["
+ || name == "{"
+ || name == "LeftAngleBracket"
+ || name == "LeftCeiling"
+ || name == "LeftDoubleBracket"
+ || name == "LeftFloor"
+ || name == "OpenCurlyQuote" ) {
+ if ( ! f.isNull() && f == "postfix" )
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+
+void BracketElement::writeMathMLAttributes( TQDomElement& element ) const
+{
+ if ( left->getType() != LeftRoundBracket ||
+ right->getType() != RightRoundBracket )
+ {
+ element.setAttribute( "open", TQString( TQChar( leftType ) ) );
+ element.setAttribute( "close", TQString( TQChar( rightType ) ) );
+ }
+ if ( ! m_separators.isNull() ) {
+ element.setAttribute( "separators", m_separators );
+ }
+}
+
+OverlineElement::OverlineElement( BasicElement* parent )
+ : SingleContentElement( parent )
+{
+}
+
+OverlineElement::~OverlineElement()
+{
+}
+
+OverlineElement::OverlineElement( const OverlineElement& other )
+ : SingleContentElement( other )
+{
+}
+
+
+bool OverlineElement::accept( ElementVisitor* visitor )
+{
+ return visitor->visit( this );
+}
+
+
+void OverlineElement::entered( SequenceElement* /*child*/ )
+{
+ formula()->tell( i18n( "Overline" ) );
+}
+
+
+void OverlineElement::calcSizes( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ ContextStyle::IndexStyle istyle,
+ StyleAttributes& style )
+{
+ SequenceElement* content = getContent();
+ content->calcSizes(context, tstyle,
+ context.convertIndexStyleLower(istyle), style );
+
+ //luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle, style.sizeFactor() ) );
+ luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, style.sizeFactor() ) );
+ //luPixel unit = (content->getHeight() + distY)/ 3;
+
+ setWidth( content->getWidth() );
+ setHeight( content->getHeight() + distY );
+
+ content->setX( 0 );
+ content->setY( distY );
+ setBaseline(content->getBaseline() + content->getY());
+}
+
+void OverlineElement::draw( TQPainter& painter, const LuPixelRect& r,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ ContextStyle::IndexStyle istyle,
+ StyleAttributes& style,
+ const LuPixelPoint& parentOrigin )
+{
+ LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
+ //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
+ // return;
+
+ SequenceElement* content = getContent();
+ content->draw( painter, r, context, tstyle,
+ context.convertIndexStyleLower( istyle ), style, myPos );
+
+ luPixel x = myPos.x();
+ luPixel y = myPos.y();
+ //int distX = context.getDistanceX(tstyle);
+ double factor = style.sizeFactor();
+ luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
+ //luPixel unit = (content->getHeight() + distY)/ 3;
+
+ painter.setPen( TQPen( context.getDefaultColor(),
+ context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) );
+
+ painter.drawLine( context.layoutUnitToPixelX( x ),
+ context.layoutUnitToPixelY( y+distY/3 ),
+ context.layoutUnitToPixelX( x+content->getWidth() ),
+ context.layoutUnitToPixelY( y+distY/3 ) );
+}
+
+
+TQString OverlineElement::toLatex()
+{
+ return "\\overline{" + getContent()->toLatex() + "}";
+}
+
+TQString OverlineElement::formulaString()
+{
+ return getContent()->formulaString();
+}
+
+void OverlineElement::writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat ) const
+{
+ TQDomElement de = doc.createElement( oasisFormat ? "math:mover" : "mover" );
+ SingleContentElement::writeMathML( doc, de, oasisFormat );
+ TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
+ // is this the right entity? Mozilla renders it correctly.
+ op.appendChild( doc.createEntityReference( "OverBar" ) );
+ de.appendChild( op );
+ parent.appendChild( de );
+}
+
+
+UnderlineElement::UnderlineElement( BasicElement* parent )
+ : SingleContentElement( parent )
+{
+}
+
+UnderlineElement::~UnderlineElement()
+{
+}
+
+
+UnderlineElement::UnderlineElement( const UnderlineElement& other )
+ : SingleContentElement( other )
+{
+}
+
+
+bool UnderlineElement::accept( ElementVisitor* visitor )
+{
+ return visitor->visit( this );
+}
+
+
+void UnderlineElement::entered( SequenceElement* /*child*/ )
+{
+ formula()->tell( i18n( "Underline" ) );
+}
+
+
+void UnderlineElement::calcSizes( const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ ContextStyle::IndexStyle istyle,
+ StyleAttributes& style )
+{
+ SequenceElement* content = getContent();
+ double factor = style.sizeFactor();
+ content->calcSizes(context, tstyle,
+ context.convertIndexStyleLower(istyle), style );
+
+ //luPixel distX = context.ptToPixelX( context.getThinSpace( tstyle ) );
+ luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle, factor ) );
+ //luPixel unit = (content->getHeight() + distY)/ 3;
+
+ setWidth( content->getWidth() );
+ setHeight( content->getHeight() + distY );
+
+ content->setX( 0 );
+ content->setY( 0 );
+ setBaseline(content->getBaseline() + content->getY());
+}
+
+void UnderlineElement::draw( TQPainter& painter, const LuPixelRect& r,
+ const ContextStyle& context,
+ ContextStyle::TextStyle tstyle,
+ ContextStyle::IndexStyle istyle,
+ StyleAttributes& style,
+ const LuPixelPoint& parentOrigin )
+{
+ LuPixelPoint myPos( parentOrigin.x()+getX(), parentOrigin.y()+getY() );
+ //if ( !LuPixelRect( myPos.x(), myPos.y(), getWidth(), getHeight() ).intersects( r ) )
+ // return;
+
+ SequenceElement* content = getContent();
+ content->draw( painter, r, context, tstyle,
+ context.convertIndexStyleLower( istyle ), style, myPos );
+
+ luPixel x = myPos.x();
+ luPixel y = myPos.y();
+ //int distX = context.getDistanceX(tstyle);
+ //luPixel distY = context.ptToPixelY( context.getThinSpace( tstyle ) );
+ //luPixel unit = (content->getHeight() + distY)/ 3;
+
+ double factor = style.sizeFactor();
+ painter.setPen( TQPen( context.getDefaultColor(),
+ context.layoutUnitToPixelY( context.getLineWidth( factor ) ) ) );
+
+ painter.drawLine( context.layoutUnitToPixelX( x ),
+ context.layoutUnitToPixelY( y+getHeight()-context.getLineWidth( factor ) ),
+ context.layoutUnitToPixelX( x+content->getWidth() ),
+ context.layoutUnitToPixelY( y+getHeight()-context.getLineWidth( factor ) ) );
+}
+
+
+TQString UnderlineElement::toLatex()
+{
+ return "\\underline{" + getContent()->toLatex() + "}";
+}
+
+TQString UnderlineElement::formulaString()
+{
+ return getContent()->formulaString();
+}
+
+void UnderlineElement::writeMathML( TQDomDocument& doc, TQDomNode& parent, bool oasisFormat ) const
+{
+ TQDomElement de = doc.createElement( oasisFormat ? "math:munder" : "munder" );
+ SingleContentElement::writeMathML( doc, de, oasisFormat );
+ TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
+ // is this the right entity? Mozilla renders it correctly.
+ op.appendChild( doc.createEntityReference( "UnderBar" ) );
+ de.appendChild( op );
+ parent.appendChild( de );
+}
+
+KFORMULA_NAMESPACE_END