summaryrefslogtreecommitdiffstats
path: root/part/kxesyntaxhighlighter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'part/kxesyntaxhighlighter.cpp')
-rw-r--r--part/kxesyntaxhighlighter.cpp257
1 files changed, 257 insertions, 0 deletions
diff --git a/part/kxesyntaxhighlighter.cpp b/part/kxesyntaxhighlighter.cpp
new file mode 100644
index 0000000..c783077
--- /dev/null
+++ b/part/kxesyntaxhighlighter.cpp
@@ -0,0 +1,257 @@
+/***************************************************************************
+ kxesyntaxhighlighter.cpp - XML Syntax highlighter
+ -------------------
+ begin : Ne pro 14 2003
+ copyright : (C) 2003 by The KXMLEditor Team
+ email : lvanek.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kxesyntaxhighlighter.h"
+
+#include <iostream>
+
+#include <qcolor.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <ktextedit.h>
+
+// Regular expressions for parsing XML borrowed from:
+// http://www.cs.sfu.ca/~cameron/REX.html
+
+KXESyntaxHighlighter::KXESyntaxHighlighter(QTextEdit *textEdit)
+ : QSyntaxHighlighter(textEdit)
+{
+ m_clrDefaultText.setRgb(0, 0, 0);
+ m_clrElementName.setRgb(128, 0, 0);
+ m_clrAttributeName.setRgb(0, 255, 255);
+ m_clrAttributeValue.setRgb(0, 255, 0);
+ m_clrXmlSyntaxChar.setRgb(0, 0, 128);
+ m_clrComment.setRgb(128, 128, 128);
+ m_clrSyntaxError.setRgb(255, 0, 0);
+}
+
+KXESyntaxHighlighter::~KXESyntaxHighlighter()
+{
+}
+
+
+int KXESyntaxHighlighter::highlightParagraph(const QString& text, int endStateOfLastPara)
+{
+ //first I format the given line to default so any remaining highlighting is removed (Qt does not do it by itself)
+ setFormat(0 , text.length(), QColor(0, 0, 0));
+
+ int iBracketNesting = 0;
+ m_eParserState = parsingNone;
+ int pos;
+ unsigned int i = 0;
+
+ if(endStateOfLastPara == 1)
+ {
+ QRegExp patternComment("[^-]*-([^-][^-]*-)*->"); // search end of comment
+ pos=patternComment.search(text, i);
+
+ if(pos >= 0) // end comment found ?
+ {
+ int l = patternComment.matchedLength();
+
+ setFormat(0, l - 3, m_clrComment);
+ setFormat(l - 3, 3, m_clrXmlSyntaxChar );
+ i += l; // skip comment
+ }
+ else
+ {
+ setFormat(0, text.length(), m_clrComment);
+ return 1; // return 1 to signify "in comment"
+ }
+ }
+
+ for(; i < text.length() - 1; i++)
+ {
+ switch(text[i])
+ {
+ case '<':
+ iBracketNesting++;
+
+ if(iBracketNesting == 1)
+ { setFormat( i, 1, m_clrXmlSyntaxChar );
+ m_eParserState = expectElementNameOrSlash;
+ }
+ else
+ setFormat( i, 1, m_clrSyntaxError ); // wrong bracket nesting
+
+ break;
+
+ case '>':
+ iBracketNesting--;
+
+ if(iBracketNesting == 0)
+ setFormat( i, 1, m_clrXmlSyntaxChar );
+ else
+ setFormat( i, 1, m_clrSyntaxError ); // wrong bracket nesting
+
+ m_eParserState = parsingNone;
+
+ break;
+
+ case '/':
+
+ if(m_eParserState == expectElementNameOrSlash)
+ {
+ m_eParserState = expectElementName;
+ setFormat( i, 1, m_clrXmlSyntaxChar );
+ }
+ else
+ {
+ if(m_eParserState == expectAtttributeOrEndOfElement)
+ setFormat( i, 1, m_clrXmlSyntaxChar );
+ else
+ processDefaultText(i, text);
+ }
+
+ break;
+
+ case '=':
+ if(m_eParserState == expectEqual)
+ {
+ m_eParserState = expectAttributeValue;
+ setFormat( i, 1, m_clrXmlSyntaxChar );
+ }
+ else
+ {
+ processDefaultText(i, text);
+ }
+ break;
+
+ case '\"':
+
+ if(m_eParserState == expectAttributeValue)
+ {
+ QRegExp patternAttribute("\"[^<\"]*\"|'[^<']*'"); // search attribute value
+ pos=patternAttribute.search(text, i);
+
+ if(pos == (int) i) // attribute value found ?
+ {
+ int l = patternAttribute.matchedLength();
+
+ setFormat(i, 1, m_clrXmlSyntaxChar );
+ setFormat(i+1, l - 2, m_clrAttributeValue);
+ setFormat(i+l-1, 1, m_clrXmlSyntaxChar );
+
+ i += l - 1; // skip attribute value
+ m_eParserState = expectAtttributeOrEndOfElement;
+ }
+ else
+ processDefaultText(i, text);
+ }
+ else
+ processDefaultText(i, text);
+
+ break;
+
+ case '!':
+ if(m_eParserState == expectElementNameOrSlash)
+ {
+ QRegExp patternComment("<!--[^-]*-([^-][^-]*-)*->"); // search comment
+ pos=patternComment.search(text, i-1);
+
+ if(pos == (int) i-1) // comment found ?
+ {
+ int l = patternComment.matchedLength();
+
+ setFormat(pos, 4, m_clrXmlSyntaxChar);
+ setFormat(pos + 4, l - 7, m_clrComment);
+ setFormat(l - 3, 3, m_clrXmlSyntaxChar);
+ i += l - 2; // skip comment
+ m_eParserState = parsingNone;
+ iBracketNesting--;
+ }
+ else
+ { // Try find multiline comment
+ QRegExp patternCommentStart("<!--"); // search comment start
+ pos=patternCommentStart.search(text, i-1);
+
+ if(pos == (int)i-1) // comment found ?
+ {
+ setFormat(i, 3, m_clrXmlSyntaxChar );
+ setFormat(i + 3, text.length() - i - 3, m_clrComment);
+ return 1; // return 1 to signify "in comment"
+ }
+ else
+ processDefaultText(i, text);
+ }
+ }
+ else
+ processDefaultText(i, text);
+
+ break;
+
+ default:
+ int iLenght = processDefaultText(i, text);
+ if(iLenght > 0)
+ i += iLenght - 1;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int KXESyntaxHighlighter::processDefaultText(int i, const QString& text)
+{
+ int l = 0; // length of matched text
+
+ switch(m_eParserState)
+ {
+ case expectElementNameOrSlash:
+ case expectElementName:
+ {
+ QRegExp patternName("([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*"); // search element name
+ int pos=patternName.search(text, i);
+
+ if(pos == i) // found ?
+ {
+ l = patternName.matchedLength();
+
+ setFormat(pos, l, m_clrElementName);
+ m_eParserState = expectAtttributeOrEndOfElement;
+ }
+ else
+ setFormat( i, 1, m_clrDefaultText );
+ }
+ break;
+
+ case expectAtttributeOrEndOfElement:
+ {
+ QRegExp patternName("([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*"); // search attribute name
+ int pos=patternName.search(text, i);
+
+ if(pos == i) // found ?
+ {
+ l = patternName.matchedLength();
+
+ setFormat(pos, l, m_clrAttributeName);
+ m_eParserState = expectEqual;
+ }
+ else
+ setFormat( i, 1, m_clrDefaultText );
+ }
+ break;
+
+ default:
+ setFormat( i, 1, m_clrDefaultText );
+ break;
+ }
+ return l;
+}
+