diff options
Diffstat (limited to 'part/kxesyntaxhighlighter.cpp')
-rw-r--r-- | part/kxesyntaxhighlighter.cpp | 257 |
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; +} + |