diff --git a/CMakeLists.txt b/CMakeLists.txt index 62f4ed8f..b790b95f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,7 @@ find_package(Qt5Widgets REQUIRED) find_package(Qt5LinguistTools REQUIRED) find_package(Qt5Network REQUIRED) find_package(Qt5Concurrent REQUIRED) +find_package(Qt5Xml REQUIRED) set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -106,7 +107,7 @@ set(SQLB_MOC_HDR src/VacuumDialog.h src/sqlitetablemodel.h src/sqltextedit.h - src/jsontextedit.h + src/docktextedit.h src/DbStructureModel.h src/Application.h src/CipherDialog.h @@ -144,7 +145,7 @@ set(SQLB_SRC src/sqlitetablemodel.cpp src/sqlitetypes.cpp src/sqltextedit.cpp - src/jsontextedit.cpp + src/docktextedit.cpp src/csvparser.cpp src/DbStructureModel.cpp src/grammar/Sqlite3Lexer.cpp @@ -334,7 +335,7 @@ add_executable(${PROJECT_NAME} ${SQLB_RESOURCES_RCC} ${SQLB_MISC}) -qt5_use_modules(${PROJECT_NAME} Gui Widgets Network Test PrintSupport Concurrent) +qt5_use_modules(${PROJECT_NAME} Gui Widgets Network Test PrintSupport Concurrent Xml) set(QT_LIBRARIES "") add_dependencies(${PROJECT_NAME} qhexedit qcustomplot) diff --git a/libs/qscintilla/Qt4Qt5/CMakeLists.txt b/libs/qscintilla/Qt4Qt5/CMakeLists.txt index a90f00b8..b3d70aef 100644 --- a/libs/qscintilla/Qt4Qt5/CMakeLists.txt +++ b/libs/qscintilla/Qt4Qt5/CMakeLists.txt @@ -23,6 +23,11 @@ set(QSCINTILLA_SRC qscilexercustom.cpp qscilexersql.cpp qscilexerjson.cpp + qscilexerhtml.cpp + qscilexerxml.cpp + qscilexerjavascript.cpp + qscilexercpp.cpp + qscilexerpython.cpp qscimacro.cpp qsciprinter.cpp qscistyle.cpp @@ -35,6 +40,7 @@ set(QSCINTILLA_SRC ScintillaQt.cpp ../lexers/LexSQL.cpp ../lexers/LexJSON.cpp + ../lexers/LexHTML.cpp ../lexlib/Accessor.cpp ../lexlib/CharacterCategory.cpp ../lexlib/CharacterSet.cpp @@ -146,6 +152,11 @@ set(QSCINTILLA_MOC_HDR ./Qsci/qscilexercustom.h ./Qsci/qscilexersql.h ./Qsci/qscilexerjson.h + ./Qsci/qscilexerhtml.h + ./Qsci/qscilexerxml.h + ./Qsci/qscilexerjavascript.h + ./Qsci/qscilexercpp.h + ./Qsci/qscilexerpython.h ./Qsci/qscimacro.h SciClasses.h ScintillaQt.h diff --git a/libs/qscintilla/Qt4Qt5/Qsci/qscilexercpp.h b/libs/qscintilla/Qt4Qt5/Qsci/qscilexercpp.h new file mode 100644 index 00000000..e823d072 --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/Qsci/qscilexercpp.h @@ -0,0 +1,398 @@ +// This defines the interface to the QsciLexerCPP class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#ifndef QSCILEXERCPP_H +#define QSCILEXERCPP_H + +#include + +#include +#include + + +//! \brief The QsciLexerCPP class encapsulates the Scintilla C++ +//! lexer. +class QSCINTILLA_EXPORT QsciLexerCPP : public QsciLexer +{ + Q_OBJECT + +public: + //! This enum defines the meanings of the different styles used by the + //! C++ lexer. + enum { + //! The default. + Default = 0, + InactiveDefault = Default + 64, + + //! A C comment. + Comment = 1, + InactiveComment = Comment + 64, + + //! A C++ comment line. + CommentLine = 2, + InactiveCommentLine = CommentLine + 64, + + //! A JavaDoc/Doxygen style C comment. + CommentDoc = 3, + InactiveCommentDoc = CommentDoc + 64, + + //! A number. + Number = 4, + InactiveNumber = Number + 64, + + //! A keyword. + Keyword = 5, + InactiveKeyword = Keyword + 64, + + //! A double-quoted string. + DoubleQuotedString = 6, + InactiveDoubleQuotedString = DoubleQuotedString + 64, + + //! A single-quoted string. + SingleQuotedString = 7, + InactiveSingleQuotedString = SingleQuotedString + 64, + + //! An IDL UUID. + UUID = 8, + InactiveUUID = UUID + 64, + + //! A pre-processor block. + PreProcessor = 9, + InactivePreProcessor = PreProcessor + 64, + + //! An operator. + Operator = 10, + InactiveOperator = Operator + 64, + + //! An identifier + Identifier = 11, + InactiveIdentifier = Identifier + 64, + + //! The end of a line where a string is not closed. + UnclosedString = 12, + InactiveUnclosedString = UnclosedString + 64, + + //! A C# verbatim string. + VerbatimString = 13, + InactiveVerbatimString = VerbatimString + 64, + + //! A JavaScript regular expression. + Regex = 14, + InactiveRegex = Regex + 64, + + //! A JavaDoc/Doxygen style C++ comment line. + CommentLineDoc = 15, + InactiveCommentLineDoc = CommentLineDoc + 64, + + //! A keyword defined in keyword set number 2. The class must be + //! sub-classed and re-implement keywords() to make use of this style. + KeywordSet2 = 16, + InactiveKeywordSet2 = KeywordSet2 + 64, + + //! A JavaDoc/Doxygen keyword. + CommentDocKeyword = 17, + InactiveCommentDocKeyword = CommentDocKeyword + 64, + + //! A JavaDoc/Doxygen keyword error. + CommentDocKeywordError = 18, + InactiveCommentDocKeywordError = CommentDocKeywordError + 64, + + //! A global class or typedef defined in keyword set number 5. The + //! class must be sub-classed and re-implement keywords() to make use + //! of this style. + GlobalClass = 19, + InactiveGlobalClass = GlobalClass + 64, + + //! A C++ raw string. + RawString = 20, + InactiveRawString = RawString + 64, + + //! A Vala triple-quoted verbatim string. + TripleQuotedVerbatimString = 21, + InactiveTripleQuotedVerbatimString = TripleQuotedVerbatimString + 64, + + //! A Pike hash-quoted string. + HashQuotedString = 22, + InactiveHashQuotedString = HashQuotedString + 64, + + //! A pre-processor stream comment. + PreProcessorComment = 23, + InactivePreProcessorComment = PreProcessorComment + 64, + + //! A JavaDoc/Doxygen style pre-processor comment. + PreProcessorCommentLineDoc = 24, + InactivePreProcessorCommentLineDoc = PreProcessorCommentLineDoc + 64, + + //! A user-defined literal. + UserLiteral = 25, + InactiveUserLiteral = UserLiteral + 64, + + //! A task marker. + TaskMarker = 26, + InactiveTaskMarker = TaskMarker + 64, + + //! An escape sequence. + EscapeSequence = 27, + InactiveEscapeSequence = EscapeSequence + 64, + }; + + //! Construct a QsciLexerCPP with parent \a parent. \a parent is typically + //! the QsciScintilla instance. \a caseInsensitiveKeywords is true if the + //! lexer ignores the case of keywords. + QsciLexerCPP(QObject *parent = 0, bool caseInsensitiveKeywords = false); + + //! Destroys the QsciLexerCPP instance. + virtual ~QsciLexerCPP(); + + //! Returns the name of the language. + const char *language() const; + + //! Returns the name of the lexer. Some lexers support a number of + //! languages. + const char *lexer() const; + + //! \internal Returns the character sequences that can separate + //! auto-completion words. + QStringList autoCompletionWordSeparators() const; + + //! \internal Returns a space separated list of words or characters in + //! a particular style that define the end of a block for + //! auto-indentation. The styles is returned via \a style. + const char *blockEnd(int *style = 0) const; + + //! \internal Returns a space separated list of words or characters in + //! a particular style that define the start of a block for + //! auto-indentation. The styles is returned via \a style. + const char *blockStart(int *style = 0) const; + + //! \internal Returns a space separated list of keywords in a + //! particular style that define the start of a block for + //! auto-indentation. The styles is returned via \a style. + const char *blockStartKeyword(int *style = 0) const; + + //! \internal Returns the style used for braces for brace matching. + int braceStyle() const; + + //! Returns the string of characters that comprise a word. + const char *wordCharacters() const; + + //! Returns the foreground colour of the text for style number \a style. + //! + //! \sa defaultPaper() + QColor defaultColor(int style) const; + + //! Returns the end-of-line fill for style number \a style. + bool defaultEolFill(int style) const; + + //! Returns the font for style number \a style. + QFont defaultFont(int style) const; + + //! Returns the background colour of the text for style number \a style. + //! + //! \sa defaultColor() + QColor defaultPaper(int style) const; + + //! Returns the set of keywords for the keyword set \a set recognised + //! by the lexer as a space separated string. Set 1 is normally used for + //! primary keywords and identifiers. Set 2 is normally used for secondary + //! keywords and identifiers. Set 3 is normally used for documentation + //! comment keywords. Set 4 is normally used for global classes and + //! typedefs. + const char *keywords(int set) const; + + //! Returns the descriptive name for style number \a style. If the + //! style is invalid for this language then an empty QString is returned. + //! This is intended to be used in user preference dialogs. + QString description(int style) const; + + //! Causes all properties to be refreshed by emitting the + //! propertyChanged() signal as required. + void refreshProperties(); + + //! Returns true if "} else {" lines can be folded. + //! + //! \sa setFoldAtElse() + bool foldAtElse() const {return fold_atelse;} + + //! Returns true if multi-line comment blocks can be folded. + //! + //! \sa setFoldComments() + bool foldComments() const {return fold_comments;} + + //! Returns true if trailing blank lines are included in a fold block. + //! + //! \sa setFoldCompact() + bool foldCompact() const {return fold_compact;} + + //! Returns true if preprocessor blocks can be folded. + //! + //! \sa setFoldPreprocessor() + bool foldPreprocessor() const {return fold_preproc;} + + //! Returns true if preprocessor lines (after the preprocessor + //! directive) are styled. + //! + //! \sa setStylePreprocessor() + bool stylePreprocessor() const {return style_preproc;} + + //! If \a allowed is true then '$' characters are allowed in identifier + //! names. The default is true. + //! + //! \sa dollarsAllowed() + void setDollarsAllowed(bool allowed); + + //! Returns true if '$' characters are allowed in identifier names. + //! + //! \sa setDollarsAllowed() + bool dollarsAllowed() const {return dollars;} + + //! If \a enabled is true then triple quoted strings are highlighted. The + //! default is false. + //! + //! \sa highlightTripleQuotedStrings() + void setHighlightTripleQuotedStrings(bool enabled); + + //! Returns true if triple quoted strings should be highlighted. + //! + //! \sa setHighlightTripleQuotedStrings() + bool highlightTripleQuotedStrings() const {return highlight_triple;} + + //! If \a enabled is true then hash quoted strings are highlighted. The + //! default is false. + //! + //! \sa highlightHashQuotedStrings() + void setHighlightHashQuotedStrings(bool enabled); + + //! Returns true if hash quoted strings should be highlighted. + //! + //! \sa setHighlightHashQuotedStrings() + bool highlightHashQuotedStrings() const {return highlight_hash;} + + //! If \a enabled is true then back-quoted raw strings are highlighted. + //! The default is false. + //! + //! \sa highlightBackQuotedStrings() + void setHighlightBackQuotedStrings(bool enabled); + + //! Returns true if back-quoted raw strings should be highlighted. + //! + //! \sa setHighlightBackQuotedStrings() + bool highlightBackQuotedStrings() const {return highlight_back;} + + //! If \a enabled is true then escape sequences in strings are highlighted. + //! The default is false. + //! + //! \sa highlightEscapeSequences() + void setHighlightEscapeSequences(bool enabled); + + //! Returns true if escape sequences in strings should be highlighted. + //! + //! \sa setHighlightEscapeSequences() + bool highlightEscapeSequences() const {return highlight_escape;} + + //! If \a allowed is true then escape sequences are allowed in verbatim + //! strings. The default is false. + //! + //! \sa verbatimStringEscapeSequencesAllowed() + void setVerbatimStringEscapeSequencesAllowed(bool allowed); + + //! Returns true if hash quoted strings should be highlighted. + //! + //! \sa setVerbatimStringEscapeSequencesAllowed() + bool verbatimStringEscapeSequencesAllowed() const {return vs_escape;} + +public slots: + //! If \a fold is true then "} else {" lines can be folded. The + //! default is false. + //! + //! \sa foldAtElse() + virtual void setFoldAtElse(bool fold); + + //! If \a fold is true then multi-line comment blocks can be folded. + //! The default is false. + //! + //! \sa foldComments() + virtual void setFoldComments(bool fold); + + //! If \a fold is true then trailing blank lines are included in a fold + //! block. The default is true. + //! + //! \sa foldCompact() + virtual void setFoldCompact(bool fold); + + //! If \a fold is true then preprocessor blocks can be folded. The + //! default is true. + //! + //! \sa foldPreprocessor() + virtual void setFoldPreprocessor(bool fold); + + //! If \a style is true then preprocessor lines (after the preprocessor + //! directive) are styled. The default is false. + //! + //! \sa stylePreprocessor() + virtual void setStylePreprocessor(bool style); + +protected: + //! The lexer's properties are read from the settings \a qs. \a prefix + //! (which has a trailing '/') should be used as a prefix to the key of + //! each setting. true is returned if there is no error. + //! + //! \sa writeProperties() + bool readProperties(QSettings &qs,const QString &prefix); + + //! The lexer's properties are written to the settings \a qs. + //! \a prefix (which has a trailing '/') should be used as a prefix to + //! the key of each setting. true is returned if there is no error. + //! + //! \sa readProperties() + bool writeProperties(QSettings &qs,const QString &prefix) const; + +private: + void setAtElseProp(); + void setCommentProp(); + void setCompactProp(); + void setPreprocProp(); + void setStylePreprocProp(); + void setDollarsProp(); + void setHighlightTripleProp(); + void setHighlightHashProp(); + void setHighlightBackProp(); + void setHighlightEscapeProp(); + void setVerbatimStringEscapeProp(); + + bool fold_atelse; + bool fold_comments; + bool fold_compact; + bool fold_preproc; + bool style_preproc; + bool dollars; + bool highlight_triple; + bool highlight_hash; + bool highlight_back; + bool highlight_escape; + bool vs_escape; + + bool nocase; + + QsciLexerCPP(const QsciLexerCPP &); + QsciLexerCPP &operator=(const QsciLexerCPP &); +}; + +#endif diff --git a/libs/qscintilla/Qt4Qt5/Qsci/qscilexerhtml.h b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerhtml.h new file mode 100644 index 00000000..33d24fa9 --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerhtml.h @@ -0,0 +1,532 @@ +// This defines the interface to the QsciLexerHTML class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#ifndef QSCILEXERHTML_H +#define QSCILEXERHTML_H + +#include + +#include +#include + + +//! \brief The QsciLexerHTML class encapsulates the Scintilla HTML lexer. +class QSCINTILLA_EXPORT QsciLexerHTML : public QsciLexer +{ + Q_OBJECT + +public: + //! This enum defines the meanings of the different styles used by the + //! HTML lexer. + enum { + //! The default. + Default = 0, + + //! A tag. + Tag = 1, + + //! An unknown tag. + UnknownTag = 2, + + //! An attribute. + Attribute = 3, + + //! An unknown attribute. + UnknownAttribute = 4, + + //! An HTML number. + HTMLNumber = 5, + + //! An HTML double-quoted string. + HTMLDoubleQuotedString = 6, + + //! An HTML single-quoted string. + HTMLSingleQuotedString = 7, + + //! Other text within a tag. + OtherInTag = 8, + + //! An HTML comment. + HTMLComment = 9, + + //! An entity. + Entity = 10, + + //! The end of an XML style tag. + XMLTagEnd = 11, + + //! The start of an XML fragment. + XMLStart = 12, + + //! The end of an XML fragment. + XMLEnd = 13, + + //! A script tag. + Script = 14, + + //! The start of an ASP fragment with @. + ASPAtStart = 15, + + //! The start of an ASP fragment. + ASPStart = 16, + + //! CDATA. + CDATA = 17, + + //! The start of a PHP fragment. + PHPStart = 18, + + //! An unquoted HTML value. + HTMLValue = 19, + + //! An ASP X-Code comment. + ASPXCComment = 20, + + //! The default for SGML. + SGMLDefault = 21, + + //! An SGML command. + SGMLCommand = 22, + + //! The first parameter of an SGML command. + SGMLParameter = 23, + + //! An SGML double-quoted string. + SGMLDoubleQuotedString = 24, + + //! An SGML single-quoted string. + SGMLSingleQuotedString = 25, + + //! An SGML error. + SGMLError = 26, + + //! An SGML special entity. + SGMLSpecial = 27, + + //! An SGML entity. + SGMLEntity = 28, + + //! An SGML comment. + SGMLComment = 29, + + //! A comment with the first parameter of an SGML command. + SGMLParameterComment = 30, + + //! The default for an SGML block. + SGMLBlockDefault = 31, + + //! The start of a JavaScript fragment. + JavaScriptStart = 40, + + //! The default for JavaScript. + JavaScriptDefault = 41, + + //! A JavaScript comment. + JavaScriptComment = 42, + + //! A JavaScript line comment. + JavaScriptCommentLine = 43, + + //! A JavaDoc style JavaScript comment. + JavaScriptCommentDoc = 44, + + //! A JavaScript number. + JavaScriptNumber = 45, + + //! A JavaScript word. + JavaScriptWord = 46, + + //! A JavaScript keyword. + JavaScriptKeyword = 47, + + //! A JavaScript double-quoted string. + JavaScriptDoubleQuotedString = 48, + + //! A JavaScript single-quoted string. + JavaScriptSingleQuotedString = 49, + + //! A JavaScript symbol. + JavaScriptSymbol = 50, + + //! The end of a JavaScript line where a string is not closed. + JavaScriptUnclosedString = 51, + + //! A JavaScript regular expression. + JavaScriptRegex = 52, + + //! The start of an ASP JavaScript fragment. + ASPJavaScriptStart = 55, + + //! The default for ASP JavaScript. + ASPJavaScriptDefault = 56, + + //! An ASP JavaScript comment. + ASPJavaScriptComment = 57, + + //! An ASP JavaScript line comment. + ASPJavaScriptCommentLine = 58, + + //! An ASP JavaDoc style JavaScript comment. + ASPJavaScriptCommentDoc = 59, + + //! An ASP JavaScript number. + ASPJavaScriptNumber = 60, + + //! An ASP JavaScript word. + ASPJavaScriptWord = 61, + + //! An ASP JavaScript keyword. + ASPJavaScriptKeyword = 62, + + //! An ASP JavaScript double-quoted string. + ASPJavaScriptDoubleQuotedString = 63, + + //! An ASP JavaScript single-quoted string. + ASPJavaScriptSingleQuotedString = 64, + + //! An ASP JavaScript symbol. + ASPJavaScriptSymbol = 65, + + //! The end of an ASP JavaScript line where a string is not + //! closed. + ASPJavaScriptUnclosedString = 66, + + //! An ASP JavaScript regular expression. + ASPJavaScriptRegex = 67, + + //! The start of a VBScript fragment. + VBScriptStart = 70, + + //! The default for VBScript. + VBScriptDefault = 71, + + //! A VBScript comment. + VBScriptComment = 72, + + //! A VBScript number. + VBScriptNumber = 73, + + //! A VBScript keyword. + VBScriptKeyword = 74, + + //! A VBScript string. + VBScriptString = 75, + + //! A VBScript identifier. + VBScriptIdentifier = 76, + + //! The end of a VBScript line where a string is not closed. + VBScriptUnclosedString = 77, + + //! The start of an ASP VBScript fragment. + ASPVBScriptStart = 80, + + //! The default for ASP VBScript. + ASPVBScriptDefault = 81, + + //! An ASP VBScript comment. + ASPVBScriptComment = 82, + + //! An ASP VBScript number. + ASPVBScriptNumber = 83, + + //! An ASP VBScript keyword. + ASPVBScriptKeyword = 84, + + //! An ASP VBScript string. + ASPVBScriptString = 85, + + //! An ASP VBScript identifier. + ASPVBScriptIdentifier = 86, + + //! The end of an ASP VBScript line where a string is not + //! closed. + ASPVBScriptUnclosedString = 87, + + //! The start of a Python fragment. + PythonStart = 90, + + //! The default for Python. + PythonDefault = 91, + + //! A Python comment. + PythonComment = 92, + + //! A Python number. + PythonNumber = 93, + + //! A Python double-quoted string. + PythonDoubleQuotedString = 94, + + //! A Python single-quoted string. + PythonSingleQuotedString = 95, + + //! A Python keyword. + PythonKeyword = 96, + + //! A Python triple single-quoted string. + PythonTripleSingleQuotedString = 97, + + //! A Python triple double-quoted string. + PythonTripleDoubleQuotedString = 98, + + //! The name of a Python class. + PythonClassName = 99, + + //! The name of a Python function or method. + PythonFunctionMethodName = 100, + + //! A Python operator. + PythonOperator = 101, + + //! A Python identifier. + PythonIdentifier = 102, + + //! The start of an ASP Python fragment. + ASPPythonStart = 105, + + //! The default for ASP Python. + ASPPythonDefault = 106, + + //! An ASP Python comment. + ASPPythonComment = 107, + + //! An ASP Python number. + ASPPythonNumber = 108, + + //! An ASP Python double-quoted string. + ASPPythonDoubleQuotedString = 109, + + //! An ASP Python single-quoted string. + ASPPythonSingleQuotedString = 110, + + //! An ASP Python keyword. + ASPPythonKeyword = 111, + + //! An ASP Python triple single-quoted string. + ASPPythonTripleSingleQuotedString = 112, + + //! An ASP Python triple double-quoted string. + ASPPythonTripleDoubleQuotedString = 113, + + //! The name of an ASP Python class. + ASPPythonClassName = 114, + + //! The name of an ASP Python function or method. + ASPPythonFunctionMethodName = 115, + + //! An ASP Python operator. + ASPPythonOperator = 116, + + //! An ASP Python identifier + ASPPythonIdentifier = 117, + + //! The default for PHP. + PHPDefault = 118, + + //! A PHP double-quoted string. + PHPDoubleQuotedString = 119, + + //! A PHP single-quoted string. + PHPSingleQuotedString = 120, + + //! A PHP keyword. + PHPKeyword = 121, + + //! A PHP number. + PHPNumber = 122, + + //! A PHP variable. + PHPVariable = 123, + + //! A PHP comment. + PHPComment = 124, + + //! A PHP line comment. + PHPCommentLine = 125, + + //! A PHP double-quoted variable. + PHPDoubleQuotedVariable = 126, + + //! A PHP operator. + PHPOperator = 127 + }; + + //! Construct a QsciLexerHTML with parent \a parent. \a parent is + //! typically the QsciScintilla instance. + QsciLexerHTML(QObject *parent = 0); + + //! Destroys the QsciLexerHTML instance. + virtual ~QsciLexerHTML(); + + //! Returns the name of the language. + const char *language() const; + + //! Returns the name of the lexer. Some lexers support a number of + //! languages. + const char *lexer() const; + + //! \internal Returns the auto-completion fillup characters. + const char *autoCompletionFillups() const; + + //! Returns the string of characters that comprise a word. + const char *wordCharacters() const; + + //! Returns the foreground colour of the text for style number \a style. + //! + //! \sa defaultPaper() + QColor defaultColor(int style) const; + + //! Returns the end-of-line fill for style number \a style. + bool defaultEolFill(int style) const; + + //! Returns the font for style number \a style. + QFont defaultFont(int style) const; + + //! Returns the background colour of the text for style number \a style. + //! + //! \sa defaultColor() + QColor defaultPaper(int style) const; + + //! Returns the set of keywords for the keyword set \a set recognised + //! by the lexer as a space separated string. + const char *keywords(int set) const; + + //! Returns the descriptive name for style number \a style. If the + //! style is invalid for this language then an empty QString is returned. + //! This is intended to be used in user preference dialogs. + QString description(int style) const; + + //! Causes all properties to be refreshed by emitting the + //! propertyChanged() signal as required. + void refreshProperties(); + + //! Returns true if tags are case sensitive. + //! + //! \sa setCaseSensitiveTags() + bool caseSensitiveTags() const {return case_sens_tags;} + + //! If \a enabled is true then Django templates are enabled. The default + //! is false. + //! + //! \sa djangoTemplates() + void setDjangoTemplates(bool enabled); + + //! Returns true if support for Django templates is enabled. + //! + //! \sa setDjangoTemplates() + bool djangoTemplates() const {return django_templates;} + + //! Returns true if trailing blank lines are included in a fold block. + //! + //! \sa setFoldCompact() + bool foldCompact() const {return fold_compact;} + + //! Returns true if preprocessor blocks can be folded. + //! + //! \sa setFoldPreprocessor() + bool foldPreprocessor() const {return fold_preproc;} + + //! If \a fold is true then script comments can be folded. The default is + //! false. + //! + //! \sa foldScriptComments() + void setFoldScriptComments(bool fold); + + //! Returns true if script comments can be folded. + //! + //! \sa setFoldScriptComments() + bool foldScriptComments() const {return fold_script_comments;} + + //! If \a fold is true then script heredocs can be folded. The default is + //! false. + //! + //! \sa foldScriptHeredocs() + void setFoldScriptHeredocs(bool fold); + + //! Returns true if script heredocs can be folded. + //! + //! \sa setFoldScriptHeredocs() + bool foldScriptHeredocs() const {return fold_script_heredocs;} + + //! If \a enabled is true then Mako templates are enabled. The default is + //! false. + //! + //! \sa makoTemplates() + void setMakoTemplates(bool enabled); + + //! Returns true if support for Mako templates is enabled. + //! + //! \sa setMakoTemplates() + bool makoTemplates() const {return mako_templates;} + +public slots: + //! If \a fold is true then trailing blank lines are included in a fold + //! block. The default is true. + //! + //! \sa foldCompact() + virtual void setFoldCompact(bool fold); + + //! If \a fold is true then preprocessor blocks can be folded. The + //! default is false. + //! + //! \sa foldPreprocessor() + virtual void setFoldPreprocessor(bool fold); + + //! If \a sens is true then tags are case sensitive. The default is false. + //! + //! \sa caseSensitiveTags() + virtual void setCaseSensitiveTags(bool sens); + +protected: + //! The lexer's properties are read from the settings \a qs. \a prefix + //! (which has a trailing '/') should be used as a prefix to the key of + //! each setting. true is returned if there is no error. + //! + bool readProperties(QSettings &qs,const QString &prefix); + + //! The lexer's properties are written to the settings \a qs. + //! \a prefix (which has a trailing '/') should be used as a prefix to + //! the key of each setting. true is returned if there is no error. + //! + bool writeProperties(QSettings &qs,const QString &prefix) const; + +private: + void setCompactProp(); + void setPreprocProp(); + void setCaseSensTagsProp(); + void setScriptCommentsProp(); + void setScriptHeredocsProp(); + void setDjangoProp(); + void setMakoProp(); + + bool fold_compact; + bool fold_preproc; + bool case_sens_tags; + bool fold_script_comments; + bool fold_script_heredocs; + bool django_templates; + bool mako_templates; + + QsciLexerHTML(const QsciLexerHTML &); + QsciLexerHTML &operator=(const QsciLexerHTML &); +}; + +#endif diff --git a/libs/qscintilla/Qt4Qt5/Qsci/qscilexerjavascript.h b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerjavascript.h new file mode 100644 index 00000000..081030a5 --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerjavascript.h @@ -0,0 +1,81 @@ +// This defines the interface to the QsciLexerJavaScript class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#ifndef QSCILEXERJSCRIPT_H +#define QSCILEXERJSCRIPT_H + +#include + +#include +#include + + +//! \brief The QsciLexerJavaScript class encapsulates the Scintilla JavaScript +//! lexer. +class QSCINTILLA_EXPORT QsciLexerJavaScript : public QsciLexerCPP +{ + Q_OBJECT + +public: + //! Construct a QsciLexerJavaScript with parent \a parent. \a parent is + //! typically the QsciScintilla instance. + QsciLexerJavaScript(QObject *parent = 0); + + //! Destroys the QsciLexerJavaScript instance. + virtual ~QsciLexerJavaScript(); + + //! Returns the name of the language. + const char *language() const; + + //! Returns the foreground colour of the text for style number \a style. + //! + //! \sa defaultPaper() + QColor defaultColor(int style) const; + + //! Returns the end-of-line fill for style number \a style. + bool defaultEolFill(int style) const; + + //! Returns the font for style number \a style. + QFont defaultFont(int style) const; + + //! Returns the background colour of the text for style number \a style. + //! + //! \sa defaultColor() + QColor defaultPaper(int style) const; + + //! Returns the set of keywords for the keyword set \a set recognised + //! by the lexer as a space separated string. + const char *keywords(int set) const; + + //! Returns the descriptive name for style number \a style. If the + //! style is invalid for this language then an empty QString is returned. + //! This is intended to be used in user preference dialogs. + QString description(int style) const; + +private: + friend class QsciLexerHTML; + + static const char *keywordClass; + + QsciLexerJavaScript(const QsciLexerJavaScript &); + QsciLexerJavaScript &operator=(const QsciLexerJavaScript &); +}; + +#endif diff --git a/libs/qscintilla/Qt4Qt5/Qsci/qscilexerpython.h b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerpython.h new file mode 100644 index 00000000..350785ca --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerpython.h @@ -0,0 +1,321 @@ +// This defines the interface to the QsciLexerPython class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#ifndef QSCILEXERPYTHON_H +#define QSCILEXERPYTHON_H + +#include + +#include +#include +#include "Qsci/qsciscintillabase.h" + + +//! \brief The QsciLexerPython class encapsulates the Scintilla Python lexer. +class QSCINTILLA_EXPORT QsciLexerPython : public QsciLexer +{ + Q_OBJECT + +public: + //! This enum defines the meanings of the different styles used by the + //! Python lexer. + enum { + //! The default. + Default = 0, + + //! A comment. + Comment = 1, + + //! A number. + Number = 2, + + //! A double-quoted string. + DoubleQuotedString = 3, + + //! A single-quoted string. + SingleQuotedString = 4, + + //! A keyword. + Keyword = 5, + + //! A triple single-quoted string. + TripleSingleQuotedString = 6, + + //! A triple double-quoted string. + TripleDoubleQuotedString = 7, + + //! The name of a class. + ClassName = 8, + + //! The name of a function or method. + FunctionMethodName = 9, + + //! An operator. + Operator = 10, + + //! An identifier + Identifier = 11, + + //! A comment block. + CommentBlock = 12, + + //! The end of a line where a string is not closed. + UnclosedString = 13, + + //! A highlighted identifier. These are defined by keyword set + //! 2. Reimplement keywords() to define keyword set 2. + HighlightedIdentifier = 14, + + //! A decorator. + Decorator = 15 + }; + + //! This enum defines the different conditions that can cause + //! indentations to be displayed as being bad. + enum IndentationWarning { + //! Bad indentation is not displayed differently. + NoWarning = 0, + + //! The indentation is inconsistent when compared to the + //! previous line, ie. it is made up of a different combination + //! of tabs and/or spaces. + Inconsistent = 1, + + //! The indentation is made up of spaces followed by tabs. + TabsAfterSpaces = 2, + + //! The indentation contains spaces. + Spaces = 3, + + //! The indentation contains tabs. + Tabs = 4 + }; + + //! Construct a QsciLexerPython with parent \a parent. \a parent is + //! typically the QsciScintilla instance. + QsciLexerPython(QObject *parent = 0); + + //! Destroys the QsciLexerPython instance. + virtual ~QsciLexerPython(); + + //! Returns the name of the language. + const char *language() const; + + //! Returns the name of the lexer. Some lexers support a number of + //! languages. + const char *lexer() const; + + //! \internal Returns the character sequences that can separate + //! auto-completion words. + QStringList autoCompletionWordSeparators() const; + + //! \internal Returns the number of lines prior to the current one when + //! determining the scope of a block when auto-indenting. + int blockLookback() const; + + //! \internal Returns a space separated list of words or characters in + //! a particular style that define the start of a block for + //! auto-indentation. The styles is returned via \a style. + const char *blockStart(int *style = 0) const; + + //! \internal Returns the style used for braces for brace matching. + int braceStyle() const; + + //! Returns the foreground colour of the text for style number \a style. + //! + //! \sa defaultPaper() + QColor defaultColor(int style) const; + + //! Returns the end-of-line fill for style number \a style. + bool defaultEolFill(int style) const; + + //! Returns the font for style number \a style. + QFont defaultFont(int style) const; + + //! Returns the background colour of the text for style number \a style. + //! + //! \sa defaultColor() + QColor defaultPaper(int style) const; + + //! \internal Returns the view used for indentation guides. + virtual int indentationGuideView() const; + + //! Returns the set of keywords for the keyword set \a set recognised + //! by the lexer as a space separated string. + const char *keywords(int set) const; + + //! Returns the descriptive name for style number \a style. If the + //! style is invalid for this language then an empty QString is returned. + //! This is intended to be used in user preference dialogs. + QString description(int style) const; + + //! Causes all properties to be refreshed by emitting the + //! propertyChanged() signal as required. + void refreshProperties(); + + //! Returns true if indented comment blocks can be folded. + //! + //! \sa setFoldComments() + bool foldComments() const {return fold_comments;} + + //! If \a fold is true then trailing blank lines are included in a fold + //! block. The default is true. + //! + //! \sa foldCompact() + void setFoldCompact(bool fold); + + //! Returns true if trailing blank lines are included in a fold block. + //! + //! \sa setFoldCompact() + bool foldCompact() const {return fold_compact;} + + //! Returns true if triple quoted strings can be folded. + //! + //! \sa setFoldQuotes() + bool foldQuotes() const {return fold_quotes;} + + //! Returns the condition that will cause bad indentations to be + //! displayed. + //! + //! \sa setIndentationWarning() + QsciLexerPython::IndentationWarning indentationWarning() const {return indent_warn;} + + //! If \a enabled is true then sub-identifiers defined in keyword set 2 + //! will be highlighted. For example, if it is false and "open" is defined + //! in keyword set 2 then "foo.open" will not be highlighted. The default + //! is true. + //! + //! \sa highlightSubidentifiers() + void setHighlightSubidentifiers(bool enabled); + + //! Returns true if string literals are allowed to span newline characters. + //! + //! \sa setHighlightSubidentifiers() + bool highlightSubidentifiers() const {return highlight_subids;} + + //! If \a allowed is true then string literals are allowed to span newline + //! characters. The default is false. + //! + //! \sa stringsOverNewlineAllowed() + void setStringsOverNewlineAllowed(bool allowed); + + //! Returns true if string literals are allowed to span newline characters. + //! + //! \sa setStringsOverNewlineAllowed() + bool stringsOverNewlineAllowed() const {return strings_over_newline;} + + //! If \a allowed is true then Python v2 unicode string literals (e.g. + //! u"utf8") are allowed. The default is true. + //! + //! \sa v2UnicodeAllowed() + void setV2UnicodeAllowed(bool allowed); + + //! Returns true if Python v2 unicode string literals (e.g. u"utf8") are + //! allowed. + //! + //! \sa setV2UnicodeAllowed() + bool v2UnicodeAllowed() const {return v2_unicode;} + + //! If \a allowed is true then Python v3 binary and octal literals (e.g. + //! 0b1011, 0o712) are allowed. The default is true. + //! + //! \sa v3BinaryOctalAllowed() + void setV3BinaryOctalAllowed(bool allowed); + + //! Returns true if Python v3 binary and octal literals (e.g. 0b1011, + //! 0o712) are allowed. + //! + //! \sa setV3BinaryOctalAllowed() + bool v3BinaryOctalAllowed() const {return v3_binary_octal;} + + //! If \a allowed is true then Python v3 bytes string literals (e.g. + //! b"bytes") are allowed. The default is true. + //! + //! \sa v3BytesAllowed() + void setV3BytesAllowed(bool allowed); + + //! Returns true if Python v3 bytes string literals (e.g. b"bytes") are + //! allowed. + //! + //! \sa setV3BytesAllowed() + bool v3BytesAllowed() const {return v3_bytes;} + +public slots: + //! If \a fold is true then indented comment blocks can be folded. The + //! default is false. + //! + //! \sa foldComments() + virtual void setFoldComments(bool fold); + + //! If \a fold is true then triple quoted strings can be folded. The + //! default is false. + //! + //! \sa foldQuotes() + virtual void setFoldQuotes(bool fold); + + //! Sets the condition that will cause bad indentations to be + //! displayed. + //! + //! \sa indentationWarning() + virtual void setIndentationWarning(QsciLexerPython::IndentationWarning warn); + +protected: + //! The lexer's properties are read from the settings \a qs. \a prefix + //! (which has a trailing '/') should be used as a prefix to the key of + //! each setting. true is returned if there is no error. + //! + bool readProperties(QSettings &qs,const QString &prefix); + + //! The lexer's properties are written to the settings \a qs. + //! \a prefix (which has a trailing '/') should be used as a prefix to + //! the key of each setting. true is returned if there is no error. + //! + bool writeProperties(QSettings &qs,const QString &prefix) const; + +private: + void setCommentProp(); + void setCompactProp(); + void setQuotesProp(); + void setTabWhingeProp(); + void setStringsOverNewlineProp(); + void setV2UnicodeProp(); + void setV3BinaryOctalProp(); + void setV3BytesProp(); + void setHighlightSubidsProp(); + + bool fold_comments; + bool fold_compact; + bool fold_quotes; + IndentationWarning indent_warn; + bool strings_over_newline; + bool v2_unicode; + bool v3_binary_octal; + bool v3_bytes; + bool highlight_subids; + + friend class QsciLexerHTML; + + static const char *keywordClass; + + QsciLexerPython(const QsciLexerPython &); + QsciLexerPython &operator=(const QsciLexerPython &); +}; + +#endif diff --git a/libs/qscintilla/Qt4Qt5/Qsci/qscilexerxml.h b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerxml.h new file mode 100644 index 00000000..2fc7f209 --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/Qsci/qscilexerxml.h @@ -0,0 +1,106 @@ +// This defines the interface to the QsciLexerXML class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#ifndef QSCILEXERXML_H +#define QSCILEXERXML_H + +#include + +#include +#include + + +//! \brief The QsciLexerXML class encapsulates the Scintilla XML lexer. +class QSCINTILLA_EXPORT QsciLexerXML : public QsciLexerHTML +{ + Q_OBJECT + +public: + //! Construct a QsciLexerXML with parent \a parent. \a parent is typically + //! the QsciScintilla instance. + QsciLexerXML(QObject *parent = 0); + + //! Destroys the QsciLexerXML instance. + virtual ~QsciLexerXML(); + + //! Returns the name of the language. + const char *language() const; + + //! Returns the name of the lexer. Some lexers support a number of + //! languages. + const char *lexer() const; + + //! Returns the foreground colour of the text for style number \a style. + //! + //! \sa defaultPaper() + QColor defaultColor(int style) const; + + //! Returns the end-of-line fill for style number \a style. + bool defaultEolFill(int style) const; + + //! Returns the font for style number \a style. + QFont defaultFont(int style) const; + + //! Returns the background colour of the text for style number \a style. + //! + //! \sa defaultColor() + QColor defaultPaper(int style) const; + + //! Returns the set of keywords for the keyword set \a set recognised + //! by the lexer as a space separated string. + const char *keywords(int set) const; + + //! Causes all properties to be refreshed by emitting the + //! propertyChanged() signal as required. + void refreshProperties(); + + //! If \a allowed is true then scripts are styled. The default is true. + //! + //! \sa scriptsStyled() + void setScriptsStyled(bool styled); + + //! Returns true if scripts are styled. + //! + //! \sa setScriptsStyled() + bool scriptsStyled() const; + +protected: + //! The lexer's properties are read from the settings \a qs. \a prefix + //! (which has a trailing '/') should be used as a prefix to the key of + //! each setting. true is returned if there is no error. + //! + bool readProperties(QSettings &qs, const QString &prefix); + + //! The lexer's properties are written to the settings \a qs. + //! \a prefix (which has a trailing '/') should be used as a prefix to + //! the key of each setting. true is returned if there is no error. + //! + bool writeProperties(QSettings &qs, const QString &prefix) const; + +private: + void setScriptsProp(); + + bool scripts; + + QsciLexerXML(const QsciLexerXML &); + QsciLexerXML &operator=(const QsciLexerXML &); +}; + +#endif diff --git a/libs/qscintilla/Qt4Qt5/qscilexercpp.cpp b/libs/qscintilla/Qt4Qt5/qscilexercpp.cpp new file mode 100644 index 00000000..6316018e --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/qscilexercpp.cpp @@ -0,0 +1,801 @@ +// This module implements the QsciLexerCPP class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#include "Qsci/qscilexercpp.h" + +#include +#include +#include + + +// The ctor. +QsciLexerCPP::QsciLexerCPP(QObject *parent, bool caseInsensitiveKeywords) + : QsciLexer(parent), + fold_atelse(false), fold_comments(false), fold_compact(true), + fold_preproc(true), style_preproc(false), dollars(true), + highlight_triple(false), highlight_hash(false), highlight_back(false), + highlight_escape(false), vs_escape(false), + nocase(caseInsensitiveKeywords) +{ +} + + +// The dtor. +QsciLexerCPP::~QsciLexerCPP() +{ +} + + +// Returns the language name. +const char *QsciLexerCPP::language() const +{ + return "C++"; +} + + +// Returns the lexer name. +const char *QsciLexerCPP::lexer() const +{ + return (nocase ? "cppnocase" : "cpp"); +} + + +// Return the set of character sequences that can separate auto-completion +// words. +QStringList QsciLexerCPP::autoCompletionWordSeparators() const +{ + QStringList wl; + + wl << "::" << "->" << "."; + + return wl; +} + + +// Return the list of keywords that can start a block. +const char *QsciLexerCPP::blockStartKeyword(int *style) const +{ + if (style) + *style = Keyword; + + return "case catch class default do else finally for if private " + "protected public struct try union while"; +} + + +// Return the list of characters that can start a block. +const char *QsciLexerCPP::blockStart(int *style) const +{ + if (style) + *style = Operator; + + return "{"; +} + + +// Return the list of characters that can end a block. +const char *QsciLexerCPP::blockEnd(int *style) const +{ + if (style) + *style = Operator; + + return "}"; +} + + +// Return the style used for braces. +int QsciLexerCPP::braceStyle() const +{ + return Operator; +} + + +// Return the string of characters that comprise a word. +const char *QsciLexerCPP::wordCharacters() const +{ + return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_#"; +} + + +// Returns the foreground colour of the text for a style. +QColor QsciLexerCPP::defaultColor(int style) const +{ + switch (style) + { + case Default: + return QColor(0x80, 0x80, 0x80); + + case Comment: + case CommentLine: + return QColor(0x00, 0x7f, 0x00); + + case CommentDoc: + case CommentLineDoc: + case PreProcessorCommentLineDoc: + return QColor(0x3f, 0x70, 0x3f); + + case Number: + return QColor(0x00, 0x7f, 0x7f); + + case Keyword: + return QColor(0x00, 0x00, 0x7f); + + case DoubleQuotedString: + case SingleQuotedString: + case RawString: + return QColor(0x7f, 0x00, 0x7f); + + case PreProcessor: + return QColor(0x7f, 0x7f, 0x00); + + case Operator: + case UnclosedString: + return QColor(0x00, 0x00, 0x00); + + case VerbatimString: + case TripleQuotedVerbatimString: + case HashQuotedString: + return QColor(0x00, 0x7f, 0x00); + + case Regex: + return QColor(0x3f, 0x7f, 0x3f); + + case CommentDocKeyword: + return QColor(0x30, 0x60, 0xa0); + + case CommentDocKeywordError: + return QColor(0x80, 0x40, 0x20); + + case PreProcessorComment: + return QColor(0x65, 0x99, 0x00); + + case InactiveDefault: + case InactiveUUID: + case InactiveCommentLineDoc: + case InactiveKeywordSet2: + case InactiveCommentDocKeyword: + case InactiveCommentDocKeywordError: + case InactivePreProcessorCommentLineDoc: + return QColor(0xc0, 0xc0, 0xc0); + + case InactiveComment: + case InactiveCommentLine: + case InactiveNumber: + case InactiveVerbatimString: + case InactiveTripleQuotedVerbatimString: + case InactiveHashQuotedString: + return QColor(0x90, 0xb0, 0x90); + + case InactiveCommentDoc: + return QColor(0xd0, 0xd0, 0xd0); + + case InactiveKeyword: + return QColor(0x90, 0x90, 0xb0); + + case InactiveDoubleQuotedString: + case InactiveSingleQuotedString: + case InactiveRawString: + return QColor(0xb0, 0x90, 0xb0); + + case InactivePreProcessor: + return QColor(0xb0, 0xb0, 0x90); + + case InactiveOperator: + case InactiveIdentifier: + case InactiveGlobalClass: + return QColor(0xb0, 0xb0, 0xb0); + + case InactiveUnclosedString: + return QColor(0x00, 0x00, 0x00); + + case InactiveRegex: + return QColor(0x7f, 0xaf, 0x7f); + + case InactivePreProcessorComment: + return QColor(0xa0, 0xc0, 0x90); + + case UserLiteral: + return QColor(0xc0, 0x60, 0x00); + + case InactiveUserLiteral: + return QColor(0xd7, 0xa0, 0x90); + + case TaskMarker: + return QColor(0xbe, 0x07, 0xff); + + case InactiveTaskMarker: + return QColor(0xc3, 0xa1, 0xcf); + } + + return QsciLexer::defaultColor(style); +} + + +// Returns the end-of-line fill for a style. +bool QsciLexerCPP::defaultEolFill(int style) const +{ + switch (style) + { + case UnclosedString: + case InactiveUnclosedString: + case VerbatimString: + case InactiveVerbatimString: + case Regex: + case InactiveRegex: + case TripleQuotedVerbatimString: + case InactiveTripleQuotedVerbatimString: + case HashQuotedString: + case InactiveHashQuotedString: + return true; + } + + return QsciLexer::defaultEolFill(style); +} + + +// Returns the font of the text for a style. +QFont QsciLexerCPP::defaultFont(int style) const +{ + QFont f; + + switch (style) + { + case Comment: + case InactiveComment: + case CommentLine: + case InactiveCommentLine: + case CommentDoc: + case InactiveCommentDoc: + case CommentLineDoc: + case InactiveCommentLineDoc: + case CommentDocKeyword: + case InactiveCommentDocKeyword: + case CommentDocKeywordError: + case InactiveCommentDocKeywordError: + case TaskMarker: + case InactiveTaskMarker: +#if defined(Q_OS_WIN) + f = QFont("Comic Sans MS",9); +#elif defined(Q_OS_MAC) + f = QFont("Comic Sans MS", 12); +#else + f = QFont("Bitstream Vera Serif",9); +#endif + break; + + case Keyword: + case InactiveKeyword: + case Operator: + case InactiveOperator: + f = QsciLexer::defaultFont(style); + f.setBold(true); + break; + + case DoubleQuotedString: + case InactiveDoubleQuotedString: + case SingleQuotedString: + case InactiveSingleQuotedString: + case UnclosedString: + case InactiveUnclosedString: + case VerbatimString: + case InactiveVerbatimString: + case Regex: + case InactiveRegex: + case TripleQuotedVerbatimString: + case InactiveTripleQuotedVerbatimString: + case HashQuotedString: + case InactiveHashQuotedString: +#if defined(Q_OS_WIN) + f = QFont("Courier New",10); +#elif defined(Q_OS_MAC) + f = QFont("Courier", 12); +#else + f = QFont("Bitstream Vera Sans Mono",9); +#endif + break; + + default: + f = QsciLexer::defaultFont(style); + } + + return f; +} + + +// Returns the set of keywords. +const char *QsciLexerCPP::keywords(int set) const +{ + if (set == 1) + return + "and and_eq asm auto bitand bitor bool break case " + "catch char class compl const const_cast continue " + "default delete do double dynamic_cast else enum " + "explicit export extern false float for friend goto if " + "inline int long mutable namespace new not not_eq " + "operator or or_eq private protected public register " + "reinterpret_cast return short signed sizeof static " + "static_cast struct switch template this throw true " + "try typedef typeid typename union unsigned using " + "virtual void volatile wchar_t while xor xor_eq"; + + if (set == 3) + return + "a addindex addtogroup anchor arg attention author b " + "brief bug c class code date def defgroup deprecated " + "dontinclude e em endcode endhtmlonly endif " + "endlatexonly endlink endverbatim enum example " + "exception f$ f[ f] file fn hideinitializer " + "htmlinclude htmlonly if image include ingroup " + "internal invariant interface latexonly li line link " + "mainpage name namespace nosubgrouping note overload " + "p page par param post pre ref relates remarks return " + "retval sa section see showinitializer since skip " + "skipline struct subsection test throw todo typedef " + "union until var verbatim verbinclude version warning " + "weakgroup $ @ \\ & < > # { }"; + + return 0; +} + + +// Returns the user name of a style. +QString QsciLexerCPP::description(int style) const +{ + switch (style) + { + case Default: + return tr("Default"); + + case InactiveDefault: + return tr("Inactive default"); + + case Comment: + return tr("C comment"); + + case InactiveComment: + return tr("Inactive C comment"); + + case CommentLine: + return tr("C++ comment"); + + case InactiveCommentLine: + return tr("Inactive C++ comment"); + + case CommentDoc: + return tr("JavaDoc style C comment"); + + case InactiveCommentDoc: + return tr("Inactive JavaDoc style C comment"); + + case Number: + return tr("Number"); + + case InactiveNumber: + return tr("Inactive number"); + + case Keyword: + return tr("Keyword"); + + case InactiveKeyword: + return tr("Inactive keyword"); + + case DoubleQuotedString: + return tr("Double-quoted string"); + + case InactiveDoubleQuotedString: + return tr("Inactive double-quoted string"); + + case SingleQuotedString: + return tr("Single-quoted string"); + + case InactiveSingleQuotedString: + return tr("Inactive single-quoted string"); + + case UUID: + return tr("IDL UUID"); + + case InactiveUUID: + return tr("Inactive IDL UUID"); + + case PreProcessor: + return tr("Pre-processor block"); + + case InactivePreProcessor: + return tr("Inactive pre-processor block"); + + case Operator: + return tr("Operator"); + + case InactiveOperator: + return tr("Inactive operator"); + + case Identifier: + return tr("Identifier"); + + case InactiveIdentifier: + return tr("Inactive identifier"); + + case UnclosedString: + return tr("Unclosed string"); + + case InactiveUnclosedString: + return tr("Inactive unclosed string"); + + case VerbatimString: + return tr("C# verbatim string"); + + case InactiveVerbatimString: + return tr("Inactive C# verbatim string"); + + case Regex: + return tr("JavaScript regular expression"); + + case InactiveRegex: + return tr("Inactive JavaScript regular expression"); + + case CommentLineDoc: + return tr("JavaDoc style C++ comment"); + + case InactiveCommentLineDoc: + return tr("Inactive JavaDoc style C++ comment"); + + case KeywordSet2: + return tr("Secondary keywords and identifiers"); + + case InactiveKeywordSet2: + return tr("Inactive secondary keywords and identifiers"); + + case CommentDocKeyword: + return tr("JavaDoc keyword"); + + case InactiveCommentDocKeyword: + return tr("Inactive JavaDoc keyword"); + + case CommentDocKeywordError: + return tr("JavaDoc keyword error"); + + case InactiveCommentDocKeywordError: + return tr("Inactive JavaDoc keyword error"); + + case GlobalClass: + return tr("Global classes and typedefs"); + + case InactiveGlobalClass: + return tr("Inactive global classes and typedefs"); + + case RawString: + return tr("C++ raw string"); + + case InactiveRawString: + return tr("Inactive C++ raw string"); + + case TripleQuotedVerbatimString: + return tr("Vala triple-quoted verbatim string"); + + case InactiveTripleQuotedVerbatimString: + return tr("Inactive Vala triple-quoted verbatim string"); + + case HashQuotedString: + return tr("Pike hash-quoted string"); + + case InactiveHashQuotedString: + return tr("Inactive Pike hash-quoted string"); + + case PreProcessorComment: + return tr("Pre-processor C comment"); + + case InactivePreProcessorComment: + return tr("Inactive pre-processor C comment"); + + case PreProcessorCommentLineDoc: + return tr("JavaDoc style pre-processor comment"); + + case InactivePreProcessorCommentLineDoc: + return tr("Inactive JavaDoc style pre-processor comment"); + + case UserLiteral: + return tr("User-defined literal"); + + case InactiveUserLiteral: + return tr("Inactive user-defined literal"); + + case TaskMarker: + return tr("Task marker"); + + case InactiveTaskMarker: + return tr("Inactive task marker"); + + case EscapeSequence: + return tr("Escape sequence"); + + case InactiveEscapeSequence: + return tr("Inactive escape sequence"); + } + + return QString(); +} + + +// Returns the background colour of the text for a style. +QColor QsciLexerCPP::defaultPaper(int style) const +{ + switch (style) + { + case UnclosedString: + case InactiveUnclosedString: + return QColor(0xe0,0xc0,0xe0); + + case VerbatimString: + case InactiveVerbatimString: + case TripleQuotedVerbatimString: + case InactiveTripleQuotedVerbatimString: + return QColor(0xe0,0xff,0xe0); + + case Regex: + case InactiveRegex: + return QColor(0xe0,0xf0,0xe0); + + case RawString: + case InactiveRawString: + return QColor(0xff,0xf3,0xff); + + case HashQuotedString: + case InactiveHashQuotedString: + return QColor(0xe7,0xff,0xd7); + } + + return QsciLexer::defaultPaper(style); +} + + +// Refresh all properties. +void QsciLexerCPP::refreshProperties() +{ + setAtElseProp(); + setCommentProp(); + setCompactProp(); + setPreprocProp(); + setStylePreprocProp(); + setDollarsProp(); + setHighlightTripleProp(); + setHighlightHashProp(); + setHighlightBackProp(); + setHighlightEscapeProp(); + setVerbatimStringEscapeProp(); +} + + +// Read properties from the settings. +bool QsciLexerCPP::readProperties(QSettings &qs,const QString &prefix) +{ + fold_atelse = qs.value(prefix + "foldatelse", false).toBool(); + fold_comments = qs.value(prefix + "foldcomments", false).toBool(); + fold_compact = qs.value(prefix + "foldcompact", true).toBool(); + fold_preproc = qs.value(prefix + "foldpreprocessor", true).toBool(); + style_preproc = qs.value(prefix + "stylepreprocessor", false).toBool(); + dollars = qs.value(prefix + "dollars", true).toBool(); + highlight_triple = qs.value(prefix + "highlighttriple", false).toBool(); + highlight_hash = qs.value(prefix + "highlighthash", false).toBool(); + highlight_back = qs.value(prefix + "highlightback", false).toBool(); + highlight_escape = qs.value(prefix + "highlightescape", false).toBool(); + vs_escape = qs.value(prefix + "verbatimstringescape", false).toBool(); + + return true; +} + + +// Write properties to the settings. +bool QsciLexerCPP::writeProperties(QSettings &qs,const QString &prefix) const +{ + qs.setValue(prefix + "foldatelse", fold_atelse); + qs.setValue(prefix + "foldcomments", fold_comments); + qs.setValue(prefix + "foldcompact", fold_compact); + qs.setValue(prefix + "foldpreprocessor", fold_preproc); + qs.setValue(prefix + "stylepreprocessor", style_preproc); + qs.setValue(prefix + "dollars", dollars); + qs.setValue(prefix + "highlighttriple", highlight_triple); + qs.setValue(prefix + "highlighthash", highlight_hash); + qs.setValue(prefix + "highlightback", highlight_back); + qs.setValue(prefix + "highlightescape", highlight_escape); + qs.setValue(prefix + "verbatimstringescape", vs_escape); + + return true; +} + + +// Set if else can be folded. +void QsciLexerCPP::setFoldAtElse(bool fold) +{ + fold_atelse = fold; + + setAtElseProp(); +} + + +// Set the "fold.at.else" property. +void QsciLexerCPP::setAtElseProp() +{ + emit propertyChanged("fold.at.else",(fold_atelse ? "1" : "0")); +} + + +// Set if comments can be folded. +void QsciLexerCPP::setFoldComments(bool fold) +{ + fold_comments = fold; + + setCommentProp(); +} + + +// Set the "fold.comment" property. +void QsciLexerCPP::setCommentProp() +{ + emit propertyChanged("fold.comment",(fold_comments ? "1" : "0")); +} + + +// Set if folds are compact +void QsciLexerCPP::setFoldCompact(bool fold) +{ + fold_compact = fold; + + setCompactProp(); +} + + +// Set the "fold.compact" property. +void QsciLexerCPP::setCompactProp() +{ + emit propertyChanged("fold.compact",(fold_compact ? "1" : "0")); +} + + +// Set if preprocessor blocks can be folded. +void QsciLexerCPP::setFoldPreprocessor(bool fold) +{ + fold_preproc = fold; + + setPreprocProp(); +} + + +// Set the "fold.preprocessor" property. +void QsciLexerCPP::setPreprocProp() +{ + emit propertyChanged("fold.preprocessor",(fold_preproc ? "1" : "0")); +} + + +// Set if preprocessor lines are styled. +void QsciLexerCPP::setStylePreprocessor(bool style) +{ + style_preproc = style; + + setStylePreprocProp(); +} + + +// Set the "styling.within.preprocessor" property. +void QsciLexerCPP::setStylePreprocProp() +{ + emit propertyChanged("styling.within.preprocessor",(style_preproc ? "1" : "0")); +} + + +// Set if '$' characters are allowed. +void QsciLexerCPP::setDollarsAllowed(bool allowed) +{ + dollars = allowed; + + setDollarsProp(); +} + + +// Set the "lexer.cpp.allow.dollars" property. +void QsciLexerCPP::setDollarsProp() +{ + emit propertyChanged("lexer.cpp.allow.dollars",(dollars ? "1" : "0")); +} + + +// Set if triple quoted strings are highlighted. +void QsciLexerCPP::setHighlightTripleQuotedStrings(bool enabled) +{ + highlight_triple = enabled; + + setHighlightTripleProp(); +} + + +// Set the "lexer.cpp.triplequoted.strings" property. +void QsciLexerCPP::setHighlightTripleProp() +{ + emit propertyChanged("lexer.cpp.triplequoted.strings", + (highlight_triple ? "1" : "0")); +} + + +// Set if hash quoted strings are highlighted. +void QsciLexerCPP::setHighlightHashQuotedStrings(bool enabled) +{ + highlight_hash = enabled; + + setHighlightHashProp(); +} + + +// Set the "lexer.cpp.hashquoted.strings" property. +void QsciLexerCPP::setHighlightHashProp() +{ + emit propertyChanged("lexer.cpp.hashquoted.strings", + (highlight_hash ? "1" : "0")); +} + + +// Set if back-quoted strings are highlighted. +void QsciLexerCPP::setHighlightBackQuotedStrings(bool enabled) +{ + highlight_back = enabled; + + setHighlightBackProp(); +} + + +// Set the "lexer.cpp.backquoted.strings" property. +void QsciLexerCPP::setHighlightBackProp() +{ + emit propertyChanged("lexer.cpp.backquoted.strings", + (highlight_back ? "1" : "0")); +} + + +// Set if escape sequences in strings are highlighted. +void QsciLexerCPP::setHighlightEscapeSequences(bool enabled) +{ + highlight_escape = enabled; + + setHighlightEscapeProp(); +} + + +// Set the "lexer.cpp.escape.sequence" property. +void QsciLexerCPP::setHighlightEscapeProp() +{ + emit propertyChanged("lexer.cpp.escape.sequence", + (highlight_escape ? "1" : "0")); +} + + +// Set if escape sequences in verbatim strings are allowed. +void QsciLexerCPP::setVerbatimStringEscapeSequencesAllowed(bool allowed) +{ + vs_escape = allowed; + + setVerbatimStringEscapeProp(); +} + + +// Set the "lexer.cpp.verbatim.strings.allow.escapes" property. +void QsciLexerCPP::setVerbatimStringEscapeProp() +{ + emit propertyChanged("lexer.cpp.verbatim.strings.allow.escapes", + (vs_escape ? "1" : "0")); +} diff --git a/libs/qscintilla/Qt4Qt5/qscilexerhtml.cpp b/libs/qscintilla/Qt4Qt5/qscilexerhtml.cpp new file mode 100644 index 00000000..0df3a6c8 --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/qscilexerhtml.cpp @@ -0,0 +1,1181 @@ +// This module implements the QsciLexerHTML class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#include "Qsci/qscilexerhtml.h" + +#include +#include +#include + +#include "Qsci/qscilexerjavascript.h" +#include "Qsci/qscilexerpython.h" + + +// The ctor. +QsciLexerHTML::QsciLexerHTML(QObject *parent) + : QsciLexer(parent), + fold_compact(true), fold_preproc(true), case_sens_tags(false), + fold_script_comments(false), fold_script_heredocs(false), + django_templates(false), mako_templates(false) +{ +} + + +// The dtor. +QsciLexerHTML::~QsciLexerHTML() +{ +} + + +// Returns the language name. +const char *QsciLexerHTML::language() const +{ + return "HTML"; +} + + +// Returns the lexer name. +const char *QsciLexerHTML::lexer() const +{ + return "hypertext"; +} + + +// Return the auto-completion fillup characters. +const char *QsciLexerHTML::autoCompletionFillups() const +{ + return "/>"; +} + + +// Return the string of characters that comprise a word. +const char *QsciLexerHTML::wordCharacters() const +{ + return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; +} + + +// Returns the foreground colour of the text for a style. +QColor QsciLexerHTML::defaultColor(int style) const +{ + switch (style) + { + case Default: + case JavaScriptDefault: + case JavaScriptWord: + case JavaScriptSymbol: + case ASPJavaScriptDefault: + case ASPJavaScriptWord: + case ASPJavaScriptSymbol: + case VBScriptDefault: + case ASPVBScriptDefault: + case PHPOperator: + return QColor(0x00,0x00,0x00); + + case Tag: + case XMLTagEnd: + case Script: + case SGMLDefault: + case SGMLCommand: + case VBScriptKeyword: + case VBScriptIdentifier: + case VBScriptUnclosedString: + case ASPVBScriptKeyword: + case ASPVBScriptIdentifier: + case ASPVBScriptUnclosedString: + return QColor(0x00,0x00,0x80); + + case UnknownTag: + case UnknownAttribute: + return QColor(0xff,0x00,0x00); + + case Attribute: + case VBScriptNumber: + case ASPVBScriptNumber: + return QColor(0x00,0x80,0x80); + + case HTMLNumber: + case JavaScriptNumber: + case ASPJavaScriptNumber: + case PythonNumber: + case PythonFunctionMethodName: + case ASPPythonNumber: + case ASPPythonFunctionMethodName: + return QColor(0x00,0x7f,0x7f); + + case HTMLDoubleQuotedString: + case HTMLSingleQuotedString: + case JavaScriptDoubleQuotedString: + case JavaScriptSingleQuotedString: + case ASPJavaScriptDoubleQuotedString: + case ASPJavaScriptSingleQuotedString: + case PythonDoubleQuotedString: + case PythonSingleQuotedString: + case ASPPythonDoubleQuotedString: + case ASPPythonSingleQuotedString: + case PHPKeyword: + return QColor(0x7f,0x00,0x7f); + + case OtherInTag: + case Entity: + case VBScriptString: + case ASPVBScriptString: + return QColor(0x80,0x00,0x80); + + case HTMLComment: + case SGMLComment: + return QColor(0x80,0x80,0x00); + + case XMLStart: + case XMLEnd: + case PHPStart: + case PythonClassName: + case ASPPythonClassName: + return QColor(0x00,0x00,0xff); + + case HTMLValue: + return QColor(0xff,0x00,0xff); + + case SGMLParameter: + return QColor(0x00,0x66,0x00); + + case SGMLDoubleQuotedString: + case SGMLError: + return QColor(0x80,0x00,0x00); + + case SGMLSingleQuotedString: + return QColor(0x99,0x33,0x00); + + case SGMLSpecial: + return QColor(0x33,0x66,0xff); + + case SGMLEntity: + return QColor(0x33,0x33,0x33); + + case SGMLBlockDefault: + return QColor(0x00,0x00,0x66); + + case JavaScriptStart: + case ASPJavaScriptStart: + return QColor(0x7f,0x7f,0x00); + + case JavaScriptComment: + case JavaScriptCommentLine: + case ASPJavaScriptComment: + case ASPJavaScriptCommentLine: + case PythonComment: + case ASPPythonComment: + case PHPDoubleQuotedString: + return QColor(0x00,0x7f,0x00); + + case JavaScriptCommentDoc: + return QColor(0x3f,0x70,0x3f); + + case JavaScriptKeyword: + case ASPJavaScriptKeyword: + case PythonKeyword: + case ASPPythonKeyword: + case PHPVariable: + case PHPDoubleQuotedVariable: + return QColor(0x00,0x00,0x7f); + + case ASPJavaScriptCommentDoc: + return QColor(0x7f,0x7f,0x7f); + + case VBScriptComment: + case ASPVBScriptComment: + return QColor(0x00,0x80,0x00); + + case PythonStart: + case PythonDefault: + case ASPPythonStart: + case ASPPythonDefault: + return QColor(0x80,0x80,0x80); + + case PythonTripleSingleQuotedString: + case PythonTripleDoubleQuotedString: + case ASPPythonTripleSingleQuotedString: + case ASPPythonTripleDoubleQuotedString: + return QColor(0x7f,0x00,0x00); + + case PHPDefault: + return QColor(0x00,0x00,0x33); + + case PHPSingleQuotedString: + return QColor(0x00,0x9f,0x00); + + case PHPNumber: + return QColor(0xcc,0x99,0x00); + + case PHPComment: + return QColor(0x99,0x99,0x99); + + case PHPCommentLine: + return QColor(0x66,0x66,0x66); + } + + return QsciLexer::defaultColor(style); +} + + +// Returns the end-of-line fill for a style. +bool QsciLexerHTML::defaultEolFill(int style) const +{ + switch (style) + { + case JavaScriptDefault: + case JavaScriptComment: + case JavaScriptCommentDoc: + case JavaScriptUnclosedString: + case ASPJavaScriptDefault: + case ASPJavaScriptComment: + case ASPJavaScriptCommentDoc: + case ASPJavaScriptUnclosedString: + case VBScriptDefault: + case VBScriptComment: + case VBScriptNumber: + case VBScriptKeyword: + case VBScriptString: + case VBScriptIdentifier: + case VBScriptUnclosedString: + case ASPVBScriptDefault: + case ASPVBScriptComment: + case ASPVBScriptNumber: + case ASPVBScriptKeyword: + case ASPVBScriptString: + case ASPVBScriptIdentifier: + case ASPVBScriptUnclosedString: + case PythonDefault: + case PythonComment: + case PythonNumber: + case PythonDoubleQuotedString: + case PythonSingleQuotedString: + case PythonKeyword: + case PythonTripleSingleQuotedString: + case PythonTripleDoubleQuotedString: + case PythonClassName: + case PythonFunctionMethodName: + case PythonOperator: + case PythonIdentifier: + case ASPPythonDefault: + case ASPPythonComment: + case ASPPythonNumber: + case ASPPythonDoubleQuotedString: + case ASPPythonSingleQuotedString: + case ASPPythonKeyword: + case ASPPythonTripleSingleQuotedString: + case ASPPythonTripleDoubleQuotedString: + case ASPPythonClassName: + case ASPPythonFunctionMethodName: + case ASPPythonOperator: + case ASPPythonIdentifier: + case PHPDefault: + return true; + } + + return QsciLexer::defaultEolFill(style); +} + + +// Returns the font of the text for a style. +QFont QsciLexerHTML::defaultFont(int style) const +{ + QFont f; + + switch (style) + { + case Default: + case Entity: +#if defined(Q_OS_WIN) + f = QFont("Times New Roman",11); +#elif defined(Q_OS_MAC) + f = QFont("Times New Roman", 12); +#else + f = QFont("Bitstream Charter",10); +#endif + break; + + case HTMLComment: +#if defined(Q_OS_WIN) + f = QFont("Verdana",9); +#elif defined(Q_OS_MAC) + f = QFont("Verdana", 12); +#else + f = QFont("Bitstream Vera Sans",8); +#endif + break; + + case SGMLCommand: + case PythonKeyword: + case PythonClassName: + case PythonFunctionMethodName: + case PythonOperator: + case ASPPythonKeyword: + case ASPPythonClassName: + case ASPPythonFunctionMethodName: + case ASPPythonOperator: + f = QsciLexer::defaultFont(style); + f.setBold(true); + break; + + case JavaScriptDefault: + case JavaScriptCommentDoc: + case JavaScriptKeyword: + case JavaScriptSymbol: + case ASPJavaScriptDefault: + case ASPJavaScriptCommentDoc: + case ASPJavaScriptKeyword: + case ASPJavaScriptSymbol: +#if defined(Q_OS_WIN) + f = QFont("Comic Sans MS",9); +#elif defined(Q_OS_MAC) + f = QFont("Comic Sans MS", 12); +#else + f = QFont("Bitstream Vera Serif",9); +#endif + f.setBold(true); + break; + + case JavaScriptComment: + case JavaScriptCommentLine: + case JavaScriptNumber: + case JavaScriptWord: + case JavaScriptDoubleQuotedString: + case JavaScriptSingleQuotedString: + case ASPJavaScriptComment: + case ASPJavaScriptCommentLine: + case ASPJavaScriptNumber: + case ASPJavaScriptWord: + case ASPJavaScriptDoubleQuotedString: + case ASPJavaScriptSingleQuotedString: + case VBScriptComment: + case ASPVBScriptComment: + case PythonComment: + case ASPPythonComment: + case PHPComment: +#if defined(Q_OS_WIN) + f = QFont("Comic Sans MS",9); +#elif defined(Q_OS_MAC) + f = QFont("Comic Sans MS", 12); +#else + f = QFont("Bitstream Vera Serif",9); +#endif + break; + + case VBScriptDefault: + case VBScriptNumber: + case VBScriptString: + case VBScriptIdentifier: + case VBScriptUnclosedString: + case ASPVBScriptDefault: + case ASPVBScriptNumber: + case ASPVBScriptString: + case ASPVBScriptIdentifier: + case ASPVBScriptUnclosedString: +#if defined(Q_OS_WIN) + f = QFont("Lucida Sans Unicode",9); +#elif defined(Q_OS_MAC) + f = QFont("Lucida Grande", 12); +#else + f = QFont("Bitstream Vera Serif",9); +#endif + break; + + case VBScriptKeyword: + case ASPVBScriptKeyword: +#if defined(Q_OS_WIN) + f = QFont("Lucida Sans Unicode",9); +#elif defined(Q_OS_MAC) + f = QFont("Lucida Grande", 12); +#else + f = QFont("Bitstream Vera Serif",9); +#endif + f.setBold(true); + break; + + case PythonDoubleQuotedString: + case PythonSingleQuotedString: + case ASPPythonDoubleQuotedString: + case ASPPythonSingleQuotedString: +#if defined(Q_OS_WIN) + f = QFont("Courier New",10); +#elif defined(Q_OS_MAC) + f = QFont("Courier New", 12); +#else + f = QFont("Bitstream Vera Sans Mono",9); +#endif + break; + + case PHPKeyword: + case PHPVariable: + case PHPDoubleQuotedVariable: + f = QsciLexer::defaultFont(style); + f.setItalic(true); + break; + + case PHPCommentLine: +#if defined(Q_OS_WIN) + f = QFont("Comic Sans MS",9); +#elif defined(Q_OS_MAC) + f = QFont("Comic Sans MS", 12); +#else + f = QFont("Bitstream Vera Serif",9); +#endif + f.setItalic(true); + break; + + default: + f = QsciLexer::defaultFont(style); + } + + return f; +} + + +// Returns the set of keywords. +const char *QsciLexerHTML::keywords(int set) const +{ + if (set == 1) + return + "a abbr acronym address applet area " + "b base basefont bdo big blockquote body br button " + "caption center cite code col colgroup " + "dd del dfn dir div dl dt " + "em " + "fieldset font form frame frameset " + "h1 h2 h3 h4 h5 h6 head hr html " + "i iframe img input ins isindex " + "kbd " + "label legend li link " + "map menu meta " + "noframes noscript " + "object ol optgroup option " + "p param pre " + "q " + "s samp script select small span strike strong style " + "sub sup " + "table tbody td textarea tfoot th thead title tr tt " + "u ul " + "var " + "xml xmlns " + "abbr accept-charset accept accesskey action align " + "alink alt archive axis " + "background bgcolor border " + "cellpadding cellspacing char charoff charset checked " + "cite class classid clear codebase codetype color " + "cols colspan compact content coords " + "data datafld dataformatas datapagesize datasrc " + "datetime declare defer dir disabled " + "enctype event " + "face for frame frameborder " + "headers height href hreflang hspace http-equiv " + "id ismap label lang language leftmargin link " + "longdesc " + "marginwidth marginheight maxlength media method " + "multiple " + "name nohref noresize noshade nowrap " + "object onblur onchange onclick ondblclick onfocus " + "onkeydown onkeypress onkeyup onload onmousedown " + "onmousemove onmouseover onmouseout onmouseup onreset " + "onselect onsubmit onunload " + "profile prompt " + "readonly rel rev rows rowspan rules " + "scheme scope selected shape size span src standby " + "start style summary " + "tabindex target text title topmargin type " + "usemap " + "valign value valuetype version vlink vspace " + "width " + "text password checkbox radio submit reset file " + "hidden image " + "public !doctype"; + + if (set == 2) + return QsciLexerJavaScript::keywordClass; + + if (set == 3) + return + // Move these to QsciLexerVisualBasic when we + // get round to implementing it. + "and begin case call continue do each else elseif end " + "erase error event exit false for function get gosub " + "goto if implement in load loop lset me mid new next " + "not nothing on or property raiseevent rem resume " + "return rset select set stop sub then to true unload " + "until wend while with withevents attribute alias as " + "boolean byref byte byval const compare currency date " + "declare dim double enum explicit friend global " + "integer let lib long module object option optional " + "preserve private property public redim single static " + "string type variant"; + + if (set == 4) + return QsciLexerPython::keywordClass; + + if (set == 5) + return + "and argv as argc break case cfunction class continue " + "declare default do die " + "echo else elseif empty enddeclare endfor endforeach " + "endif endswitch endwhile e_all e_parse e_error " + "e_warning eval exit extends " + "false for foreach function global " + "http_cookie_vars http_get_vars http_post_vars " + "http_post_files http_env_vars http_server_vars " + "if include include_once list new not null " + "old_function or " + "parent php_os php_self php_version print " + "require require_once return " + "static switch stdclass this true var xor virtual " + "while " + "__file__ __line__ __sleep __wakeup"; + + if (set == 6) + return "ELEMENT DOCTYPE ATTLIST ENTITY NOTATION"; + + return 0; +} + + +// Returns the user name of a style. +QString QsciLexerHTML::description(int style) const +{ + switch (style) + { + case Default: + return tr("HTML default"); + + case Tag: + return tr("Tag"); + + case UnknownTag: + return tr("Unknown tag"); + + case Attribute: + return tr("Attribute"); + + case UnknownAttribute: + return tr("Unknown attribute"); + + case HTMLNumber: + return tr("HTML number"); + + case HTMLDoubleQuotedString: + return tr("HTML double-quoted string"); + + case HTMLSingleQuotedString: + return tr("HTML single-quoted string"); + + case OtherInTag: + return tr("Other text in a tag"); + + case HTMLComment: + return tr("HTML comment"); + + case Entity: + return tr("Entity"); + + case XMLTagEnd: + return tr("End of a tag"); + + case XMLStart: + return tr("Start of an XML fragment"); + + case XMLEnd: + return tr("End of an XML fragment"); + + case Script: + return tr("Script tag"); + + case ASPAtStart: + return tr("Start of an ASP fragment with @"); + + case ASPStart: + return tr("Start of an ASP fragment"); + + case CDATA: + return tr("CDATA"); + + case PHPStart: + return tr("Start of a PHP fragment"); + + case HTMLValue: + return tr("Unquoted HTML value"); + + case ASPXCComment: + return tr("ASP X-Code comment"); + + case SGMLDefault: + return tr("SGML default"); + + case SGMLCommand: + return tr("SGML command"); + + case SGMLParameter: + return tr("First parameter of an SGML command"); + + case SGMLDoubleQuotedString: + return tr("SGML double-quoted string"); + + case SGMLSingleQuotedString: + return tr("SGML single-quoted string"); + + case SGMLError: + return tr("SGML error"); + + case SGMLSpecial: + return tr("SGML special entity"); + + case SGMLComment: + return tr("SGML comment"); + + case SGMLParameterComment: + return tr("First parameter comment of an SGML command"); + + case SGMLBlockDefault: + return tr("SGML block default"); + + case JavaScriptStart: + return tr("Start of a JavaScript fragment"); + + case JavaScriptDefault: + return tr("JavaScript default"); + + case JavaScriptComment: + return tr("JavaScript comment"); + + case JavaScriptCommentLine: + return tr("JavaScript line comment"); + + case JavaScriptCommentDoc: + return tr("JavaDoc style JavaScript comment"); + + case JavaScriptNumber: + return tr("JavaScript number"); + + case JavaScriptWord: + return tr("JavaScript word"); + + case JavaScriptKeyword: + return tr("JavaScript keyword"); + + case JavaScriptDoubleQuotedString: + return tr("JavaScript double-quoted string"); + + case JavaScriptSingleQuotedString: + return tr("JavaScript single-quoted string"); + + case JavaScriptSymbol: + return tr("JavaScript symbol"); + + case JavaScriptUnclosedString: + return tr("JavaScript unclosed string"); + + case JavaScriptRegex: + return tr("JavaScript regular expression"); + + case ASPJavaScriptStart: + return tr("Start of an ASP JavaScript fragment"); + + case ASPJavaScriptDefault: + return tr("ASP JavaScript default"); + + case ASPJavaScriptComment: + return tr("ASP JavaScript comment"); + + case ASPJavaScriptCommentLine: + return tr("ASP JavaScript line comment"); + + case ASPJavaScriptCommentDoc: + return tr("JavaDoc style ASP JavaScript comment"); + + case ASPJavaScriptNumber: + return tr("ASP JavaScript number"); + + case ASPJavaScriptWord: + return tr("ASP JavaScript word"); + + case ASPJavaScriptKeyword: + return tr("ASP JavaScript keyword"); + + case ASPJavaScriptDoubleQuotedString: + return tr("ASP JavaScript double-quoted string"); + + case ASPJavaScriptSingleQuotedString: + return tr("ASP JavaScript single-quoted string"); + + case ASPJavaScriptSymbol: + return tr("ASP JavaScript symbol"); + + case ASPJavaScriptUnclosedString: + return tr("ASP JavaScript unclosed string"); + + case ASPJavaScriptRegex: + return tr("ASP JavaScript regular expression"); + + case VBScriptStart: + return tr("Start of a VBScript fragment"); + + case VBScriptDefault: + return tr("VBScript default"); + + case VBScriptComment: + return tr("VBScript comment"); + + case VBScriptNumber: + return tr("VBScript number"); + + case VBScriptKeyword: + return tr("VBScript keyword"); + + case VBScriptString: + return tr("VBScript string"); + + case VBScriptIdentifier: + return tr("VBScript identifier"); + + case VBScriptUnclosedString: + return tr("VBScript unclosed string"); + + case ASPVBScriptStart: + return tr("Start of an ASP VBScript fragment"); + + case ASPVBScriptDefault: + return tr("ASP VBScript default"); + + case ASPVBScriptComment: + return tr("ASP VBScript comment"); + + case ASPVBScriptNumber: + return tr("ASP VBScript number"); + + case ASPVBScriptKeyword: + return tr("ASP VBScript keyword"); + + case ASPVBScriptString: + return tr("ASP VBScript string"); + + case ASPVBScriptIdentifier: + return tr("ASP VBScript identifier"); + + case ASPVBScriptUnclosedString: + return tr("ASP VBScript unclosed string"); + + case PythonStart: + return tr("Start of a Python fragment"); + + case PythonDefault: + return tr("Python default"); + + case PythonComment: + return tr("Python comment"); + + case PythonNumber: + return tr("Python number"); + + case PythonDoubleQuotedString: + return tr("Python double-quoted string"); + + case PythonSingleQuotedString: + return tr("Python single-quoted string"); + + case PythonKeyword: + return tr("Python keyword"); + + case PythonTripleDoubleQuotedString: + return tr("Python triple double-quoted string"); + + case PythonTripleSingleQuotedString: + return tr("Python triple single-quoted string"); + + case PythonClassName: + return tr("Python class name"); + + case PythonFunctionMethodName: + return tr("Python function or method name"); + + case PythonOperator: + return tr("Python operator"); + + case PythonIdentifier: + return tr("Python identifier"); + + case ASPPythonStart: + return tr("Start of an ASP Python fragment"); + + case ASPPythonDefault: + return tr("ASP Python default"); + + case ASPPythonComment: + return tr("ASP Python comment"); + + case ASPPythonNumber: + return tr("ASP Python number"); + + case ASPPythonDoubleQuotedString: + return tr("ASP Python double-quoted string"); + + case ASPPythonSingleQuotedString: + return tr("ASP Python single-quoted string"); + + case ASPPythonKeyword: + return tr("ASP Python keyword"); + + case ASPPythonTripleDoubleQuotedString: + return tr("ASP Python triple double-quoted string"); + + case ASPPythonTripleSingleQuotedString: + return tr("ASP Python triple single-quoted string"); + + case ASPPythonClassName: + return tr("ASP Python class name"); + + case ASPPythonFunctionMethodName: + return tr("ASP Python function or method name"); + + case ASPPythonOperator: + return tr("ASP Python operator"); + + case ASPPythonIdentifier: + return tr("ASP Python identifier"); + + case PHPDefault: + return tr("PHP default"); + + case PHPDoubleQuotedString: + return tr("PHP double-quoted string"); + + case PHPSingleQuotedString: + return tr("PHP single-quoted string"); + + case PHPKeyword: + return tr("PHP keyword"); + + case PHPNumber: + return tr("PHP number"); + + case PHPVariable: + return tr("PHP variable"); + + case PHPComment: + return tr("PHP comment"); + + case PHPCommentLine: + return tr("PHP line comment"); + + case PHPDoubleQuotedVariable: + return tr("PHP double-quoted variable"); + + case PHPOperator: + return tr("PHP operator"); + } + + return QString(); +} + + +// Returns the background colour of the text for a style. +QColor QsciLexerHTML::defaultPaper(int style) const +{ + switch (style) + { + case ASPAtStart: + return QColor(0xff,0xff,0x00); + + case ASPStart: + case CDATA: + return QColor(0xff,0xdf,0x00); + + case PHPStart: + return QColor(0xff,0xef,0xbf); + + case HTMLValue: + return QColor(0xff,0xef,0xff); + + case SGMLDefault: + case SGMLCommand: + case SGMLParameter: + case SGMLDoubleQuotedString: + case SGMLSingleQuotedString: + case SGMLSpecial: + case SGMLEntity: + case SGMLComment: + return QColor(0xef,0xef,0xff); + + case SGMLError: + return QColor(0xff,0x66,0x66); + + case SGMLBlockDefault: + return QColor(0xcc,0xcc,0xe0); + + case JavaScriptDefault: + case JavaScriptComment: + case JavaScriptCommentLine: + case JavaScriptCommentDoc: + case JavaScriptNumber: + case JavaScriptWord: + case JavaScriptKeyword: + case JavaScriptDoubleQuotedString: + case JavaScriptSingleQuotedString: + case JavaScriptSymbol: + return QColor(0xf0,0xf0,0xff); + + case JavaScriptUnclosedString: + case ASPJavaScriptUnclosedString: + return QColor(0xbf,0xbb,0xb0); + + case JavaScriptRegex: + case ASPJavaScriptRegex: + return QColor(0xff,0xbb,0xb0); + + case ASPJavaScriptDefault: + case ASPJavaScriptComment: + case ASPJavaScriptCommentLine: + case ASPJavaScriptCommentDoc: + case ASPJavaScriptNumber: + case ASPJavaScriptWord: + case ASPJavaScriptKeyword: + case ASPJavaScriptDoubleQuotedString: + case ASPJavaScriptSingleQuotedString: + case ASPJavaScriptSymbol: + return QColor(0xdf,0xdf,0x7f); + + case VBScriptDefault: + case VBScriptComment: + case VBScriptNumber: + case VBScriptKeyword: + case VBScriptString: + case VBScriptIdentifier: + return QColor(0xef,0xef,0xff); + + case VBScriptUnclosedString: + case ASPVBScriptUnclosedString: + return QColor(0x7f,0x7f,0xff); + + case ASPVBScriptDefault: + case ASPVBScriptComment: + case ASPVBScriptNumber: + case ASPVBScriptKeyword: + case ASPVBScriptString: + case ASPVBScriptIdentifier: + return QColor(0xcf,0xcf,0xef); + + case PythonDefault: + case PythonComment: + case PythonNumber: + case PythonDoubleQuotedString: + case PythonSingleQuotedString: + case PythonKeyword: + case PythonTripleSingleQuotedString: + case PythonTripleDoubleQuotedString: + case PythonClassName: + case PythonFunctionMethodName: + case PythonOperator: + case PythonIdentifier: + return QColor(0xef,0xff,0xef); + + case ASPPythonDefault: + case ASPPythonComment: + case ASPPythonNumber: + case ASPPythonDoubleQuotedString: + case ASPPythonSingleQuotedString: + case ASPPythonKeyword: + case ASPPythonTripleSingleQuotedString: + case ASPPythonTripleDoubleQuotedString: + case ASPPythonClassName: + case ASPPythonFunctionMethodName: + case ASPPythonOperator: + case ASPPythonIdentifier: + return QColor(0xcf,0xef,0xcf); + + case PHPDefault: + case PHPDoubleQuotedString: + case PHPSingleQuotedString: + case PHPKeyword: + case PHPNumber: + case PHPVariable: + case PHPComment: + case PHPCommentLine: + case PHPDoubleQuotedVariable: + case PHPOperator: + return QColor(0xff,0xf8,0xf8); + } + + return QsciLexer::defaultPaper(style); +} + + +// Refresh all properties. +void QsciLexerHTML::refreshProperties() +{ + setCompactProp(); + setPreprocProp(); + setCaseSensTagsProp(); + setScriptCommentsProp(); + setScriptHeredocsProp(); + setDjangoProp(); + setMakoProp(); +} + + +// Read properties from the settings. +bool QsciLexerHTML::readProperties(QSettings &qs,const QString &prefix) +{ + int rc = true; + + fold_compact = qs.value(prefix + "foldcompact", true).toBool(); + fold_preproc = qs.value(prefix + "foldpreprocessor", false).toBool(); + case_sens_tags = qs.value(prefix + "casesensitivetags", false).toBool(); + fold_script_comments = qs.value(prefix + "foldscriptcomments", false).toBool(); + fold_script_heredocs = qs.value(prefix + "foldscriptheredocs", false).toBool(); + django_templates = qs.value(prefix + "djangotemplates", false).toBool(); + mako_templates = qs.value(prefix + "makotemplates", false).toBool(); + + return rc; +} + + +// Write properties to the settings. +bool QsciLexerHTML::writeProperties(QSettings &qs,const QString &prefix) const +{ + int rc = true; + + qs.setValue(prefix + "foldcompact", fold_compact); + qs.setValue(prefix + "foldpreprocessor", fold_preproc); + qs.setValue(prefix + "casesensitivetags", case_sens_tags); + qs.setValue(prefix + "foldscriptcomments", fold_script_comments); + qs.setValue(prefix + "foldscriptheredocs", fold_script_heredocs); + qs.setValue(prefix + "djangotemplates", django_templates); + qs.setValue(prefix + "makotemplates", mako_templates); + + return rc; +} + + +// Set if tags are case sensitive. +void QsciLexerHTML::setCaseSensitiveTags(bool sens) +{ + case_sens_tags = sens; + + setCaseSensTagsProp(); +} + + +// Set the "html.tags.case.sensitive" property. +void QsciLexerHTML::setCaseSensTagsProp() +{ + emit propertyChanged("html.tags.case.sensitive",(case_sens_tags ? "1" : "0")); +} + + +// Set if folds are compact +void QsciLexerHTML::setFoldCompact(bool fold) +{ + fold_compact = fold; + + setCompactProp(); +} + + +// Set the "fold.compact" property. +void QsciLexerHTML::setCompactProp() +{ + emit propertyChanged("fold.compact",(fold_compact ? "1" : "0")); +} + + +// Set if preprocessor blocks can be folded. +void QsciLexerHTML::setFoldPreprocessor(bool fold) +{ + fold_preproc = fold; + + setPreprocProp(); +} + + +// Set the "fold.html.preprocessor" property. +void QsciLexerHTML::setPreprocProp() +{ + emit propertyChanged("fold.html.preprocessor",(fold_preproc ? "1" : "0")); +} + + +// Set if script comments can be folded. +void QsciLexerHTML::setFoldScriptComments(bool fold) +{ + fold_script_comments = fold; + + setScriptCommentsProp(); +} + + +// Set the "fold.hypertext.comment" property. +void QsciLexerHTML::setScriptCommentsProp() +{ + emit propertyChanged("fold.hypertext.comment",(fold_script_comments ? "1" : "0")); +} + + +// Set if script heredocs can be folded. +void QsciLexerHTML::setFoldScriptHeredocs(bool fold) +{ + fold_script_heredocs = fold; + + setScriptHeredocsProp(); +} + + +// Set the "fold.hypertext.heredoc" property. +void QsciLexerHTML::setScriptHeredocsProp() +{ + emit propertyChanged("fold.hypertext.heredoc",(fold_script_heredocs ? "1" : "0")); +} + + +// Set if Django templates are supported. +void QsciLexerHTML::setDjangoTemplates(bool enable) +{ + django_templates = enable; + + setDjangoProp(); +} + + +// Set the "lexer.html.django" property. +void QsciLexerHTML::setDjangoProp() +{ + emit propertyChanged("lexer.html.django", (django_templates ? "1" : "0")); +} + + +// Set if Mako templates are supported. +void QsciLexerHTML::setMakoTemplates(bool enable) +{ + mako_templates = enable; + + setMakoProp(); +} + + +// Set the "lexer.html.mako" property. +void QsciLexerHTML::setMakoProp() +{ + emit propertyChanged("lexer.html.mako", (mako_templates ? "1" : "0")); +} diff --git a/libs/qscintilla/Qt4Qt5/qscilexerjavascript.cpp b/libs/qscintilla/Qt4Qt5/qscilexerjavascript.cpp new file mode 100644 index 00000000..afa9c9bd --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/qscilexerjavascript.cpp @@ -0,0 +1,120 @@ +// This module implements the QsciLexerJavaScript class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#include "Qsci/qscilexerjavascript.h" + +#include +#include + + +// The list of JavaScript keywords that can be used by other friendly lexers. +const char *QsciLexerJavaScript::keywordClass = + "abstract boolean break byte case catch char class const continue " + "debugger default delete do double else enum export extends final " + "finally float for function goto if implements import in instanceof " + "int interface long native new package private protected public " + "return short static super switch synchronized this throw throws " + "transient try typeof var void volatile while with"; + + +// The ctor. +QsciLexerJavaScript::QsciLexerJavaScript(QObject *parent) + : QsciLexerCPP(parent) +{ +} + + +// The dtor. +QsciLexerJavaScript::~QsciLexerJavaScript() +{ +} + + +// Returns the language name. +const char *QsciLexerJavaScript::language() const +{ + return "JavaScript"; +} + + +// Returns the foreground colour of the text for a style. +QColor QsciLexerJavaScript::defaultColor(int style) const +{ + if (style == Regex) + return QColor(0x3f,0x7f,0x3f); + + return QsciLexerCPP::defaultColor(style); +} + + +// Returns the end-of-line fill for a style. +bool QsciLexerJavaScript::defaultEolFill(int style) const +{ + if (style == Regex) + return true; + + return QsciLexerCPP::defaultEolFill(style); +} + + +// Returns the font of the text for a style. +QFont QsciLexerJavaScript::defaultFont(int style) const +{ + if (style == Regex) +#if defined(Q_OS_WIN) + return QFont("Courier New",10); +#elif defined(Q_OS_MAC) + return QFont("Courier", 12); +#else + return QFont("Bitstream Vera Sans Mono",9); +#endif + + return QsciLexerCPP::defaultFont(style); +} + + +// Returns the set of keywords. +const char *QsciLexerJavaScript::keywords(int set) const +{ + if (set != 1) + return 0; + + return keywordClass; +} + + +// Returns the user name of a style. +QString QsciLexerJavaScript::description(int style) const +{ + if (style == Regex) + return tr("Regular expression"); + + return QsciLexerCPP::description(style); +} + + +// Returns the background colour of the text for a style. +QColor QsciLexerJavaScript::defaultPaper(int style) const +{ + if (style == Regex) + return QColor(0xe0,0xf0,0xff); + + return QsciLexer::defaultPaper(style); +} diff --git a/libs/qscintilla/Qt4Qt5/qscilexerpython.cpp b/libs/qscintilla/Qt4Qt5/qscilexerpython.cpp new file mode 100644 index 00000000..817d75fd --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/qscilexerpython.cpp @@ -0,0 +1,489 @@ +// This module implements the QsciLexerPython class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#include "Qsci/qscilexerpython.h" + +#include +#include +#include + + +// The list of Python keywords that can be used by other friendly lexers. +const char *QsciLexerPython::keywordClass = + "and as assert break class continue def del elif else except exec " + "finally for from global if import in is lambda None not or pass " + "print raise return try while with yield"; + + +// The ctor. +QsciLexerPython::QsciLexerPython(QObject *parent) + : QsciLexer(parent), + fold_comments(false), fold_compact(true), fold_quotes(false), + indent_warn(NoWarning), strings_over_newline(false), v2_unicode(true), + v3_binary_octal(true), v3_bytes(true), highlight_subids(true) +{ +} + + +// The dtor. +QsciLexerPython::~QsciLexerPython() +{ +} + + +// Returns the language name. +const char *QsciLexerPython::language() const +{ + return "Python"; +} + + +// Returns the lexer name. +const char *QsciLexerPython::lexer() const +{ + return "python"; +} + + +// Return the view used for indentation guides. +int QsciLexerPython::indentationGuideView() const +{ + return QsciScintillaBase::SC_IV_LOOKFORWARD; +} + + +// Return the set of character sequences that can separate auto-completion +// words. +QStringList QsciLexerPython::autoCompletionWordSeparators() const +{ + QStringList wl; + + wl << "."; + + return wl; +} + +// Return the list of characters that can start a block. +const char *QsciLexerPython::blockStart(int *style) const +{ + if (style) + *style = Operator; + + return ":"; +} + + +// Return the number of lines to look back when auto-indenting. +int QsciLexerPython::blockLookback() const +{ + // This must be 0 otherwise de-indenting a Python block gets very + // difficult. + return 0; +} + + +// Return the style used for braces. +int QsciLexerPython::braceStyle() const +{ + return Operator; +} + + +// Returns the foreground colour of the text for a style. +QColor QsciLexerPython::defaultColor(int style) const +{ + switch (style) + { + case Default: + return QColor(0x80,0x80,0x80); + + case Comment: + return QColor(0x00,0x7f,0x00); + + case Number: + return QColor(0x00,0x7f,0x7f); + + case DoubleQuotedString: + case SingleQuotedString: + return QColor(0x7f,0x00,0x7f); + + case Keyword: + return QColor(0x00,0x00,0x7f); + + case TripleSingleQuotedString: + case TripleDoubleQuotedString: + return QColor(0x7f,0x00,0x00); + + case ClassName: + return QColor(0x00,0x00,0xff); + + case FunctionMethodName: + return QColor(0x00,0x7f,0x7f); + + case Operator: + case Identifier: + break; + + case CommentBlock: + return QColor(0x7f,0x7f,0x7f); + + case UnclosedString: + return QColor(0x00,0x00,0x00); + + case HighlightedIdentifier: + return QColor(0x40,0x70,0x90); + + case Decorator: + return QColor(0x80,0x50,0x00); + } + + return QsciLexer::defaultColor(style); +} + + +// Returns the end-of-line fill for a style. +bool QsciLexerPython::defaultEolFill(int style) const +{ + if (style == UnclosedString) + return true; + + return QsciLexer::defaultEolFill(style); +} + + +// Returns the font of the text for a style. +QFont QsciLexerPython::defaultFont(int style) const +{ + QFont f; + + switch (style) + { + case Comment: +#if defined(Q_OS_WIN) + f = QFont("Comic Sans MS",9); +#elif defined(Q_OS_MAC) + f = QFont("Comic Sans MS", 12); +#else + f = QFont("Bitstream Vera Serif",9); +#endif + break; + + case DoubleQuotedString: + case SingleQuotedString: + case UnclosedString: +#if defined(Q_OS_WIN) + f = QFont("Courier New",10); +#elif defined(Q_OS_MAC) + f = QFont("Courier", 12); +#else + f = QFont("Bitstream Vera Sans Mono",9); +#endif + break; + + case Keyword: + case ClassName: + case FunctionMethodName: + case Operator: + f = QsciLexer::defaultFont(style); + f.setBold(true); + break; + + default: + f = QsciLexer::defaultFont(style); + } + + return f; +} + + +// Returns the set of keywords. +const char *QsciLexerPython::keywords(int set) const +{ + if (set != 1) + return 0; + + return keywordClass; +} + + +// Returns the user name of a style. +QString QsciLexerPython::description(int style) const +{ + switch (style) + { + case Default: + return tr("Default"); + + case Comment: + return tr("Comment"); + + case Number: + return tr("Number"); + + case DoubleQuotedString: + return tr("Double-quoted string"); + + case SingleQuotedString: + return tr("Single-quoted string"); + + case Keyword: + return tr("Keyword"); + + case TripleSingleQuotedString: + return tr("Triple single-quoted string"); + + case TripleDoubleQuotedString: + return tr("Triple double-quoted string"); + + case ClassName: + return tr("Class name"); + + case FunctionMethodName: + return tr("Function or method name"); + + case Operator: + return tr("Operator"); + + case Identifier: + return tr("Identifier"); + + case CommentBlock: + return tr("Comment block"); + + case UnclosedString: + return tr("Unclosed string"); + + case HighlightedIdentifier: + return tr("Highlighted identifier"); + + case Decorator: + return tr("Decorator"); + } + + return QString(); +} + + +// Returns the background colour of the text for a style. +QColor QsciLexerPython::defaultPaper(int style) const +{ + if (style == UnclosedString) + return QColor(0xe0,0xc0,0xe0); + + return QsciLexer::defaultPaper(style); +} + + +// Refresh all properties. +void QsciLexerPython::refreshProperties() +{ + setCommentProp(); + setCompactProp(); + setQuotesProp(); + setTabWhingeProp(); + setStringsOverNewlineProp(); + setV2UnicodeProp(); + setV3BinaryOctalProp(); + setV3BytesProp(); + setHighlightSubidsProp(); +} + + +// Read properties from the settings. +bool QsciLexerPython::readProperties(QSettings &qs,const QString &prefix) +{ + int rc = true, num; + + fold_comments = qs.value(prefix + "foldcomments", false).toBool(); + fold_compact = qs.value(prefix + "foldcompact", true).toBool(); + fold_quotes = qs.value(prefix + "foldquotes", false).toBool(); + indent_warn = (IndentationWarning)qs.value(prefix + "indentwarning", (int)NoWarning).toInt(); + strings_over_newline = qs.value(prefix + "stringsovernewline", false).toBool(); + v2_unicode = qs.value(prefix + "v2unicode", true).toBool(); + v3_binary_octal = qs.value(prefix + "v3binaryoctal", true).toBool(); + v3_bytes = qs.value(prefix + "v3bytes", true).toBool(); + highlight_subids = qs.value(prefix + "highlightsubids", true).toBool(); + + return rc; +} + + +// Write properties to the settings. +bool QsciLexerPython::writeProperties(QSettings &qs,const QString &prefix) const +{ + int rc = true; + + qs.setValue(prefix + "foldcomments", fold_comments); + qs.setValue(prefix + "foldcompact", fold_compact); + qs.setValue(prefix + "foldquotes", fold_quotes); + qs.setValue(prefix + "indentwarning", (int)indent_warn); + qs.setValue(prefix + "stringsovernewline", strings_over_newline); + qs.setValue(prefix + "v2unicode", v2_unicode); + qs.setValue(prefix + "v3binaryoctal", v3_binary_octal); + qs.setValue(prefix + "v3bytes", v3_bytes); + qs.setValue(prefix + "highlightsubids", highlight_subids); + + return rc; +} + + +// Set if comments can be folded. +void QsciLexerPython::setFoldComments(bool fold) +{ + fold_comments = fold; + + setCommentProp(); +} + + +// Set the "fold.comment.python" property. +void QsciLexerPython::setCommentProp() +{ + emit propertyChanged("fold.comment.python",(fold_comments ? "1" : "0")); +} + + +// Set if folds are compact. +void QsciLexerPython::setFoldCompact(bool fold) +{ + fold_compact = fold; + + setCompactProp(); +} + + +// Set the "fold.compact" property. +void QsciLexerPython::setCompactProp() +{ + emit propertyChanged("fold.compact",(fold_compact ? "1" : "0")); +} + + +// Set if quotes can be folded. +void QsciLexerPython::setFoldQuotes(bool fold) +{ + fold_quotes = fold; + + setQuotesProp(); +} + + +// Set the "fold.quotes.python" property. +void QsciLexerPython::setQuotesProp() +{ + emit propertyChanged("fold.quotes.python",(fold_quotes ? "1" : "0")); +} + + +// Set the indentation warning. +void QsciLexerPython::setIndentationWarning(QsciLexerPython::IndentationWarning warn) +{ + indent_warn = warn; + + setTabWhingeProp(); +} + + +// Set the "tab.timmy.whinge.level" property. +void QsciLexerPython::setTabWhingeProp() +{ + emit propertyChanged("tab.timmy.whinge.level", QByteArray::number(indent_warn)); +} + + +// Set if string literals can span newlines. +void QsciLexerPython::setStringsOverNewlineAllowed(bool allowed) +{ + strings_over_newline = allowed; + + setStringsOverNewlineProp(); +} + + +// Set the "lexer.python.strings.u" property. +void QsciLexerPython::setStringsOverNewlineProp() +{ + emit propertyChanged("lexer.python.strings.over.newline", (strings_over_newline ? "1" : "0")); +} + + +// Set if v2 unicode string literals are allowed. +void QsciLexerPython::setV2UnicodeAllowed(bool allowed) +{ + v2_unicode = allowed; + + setV2UnicodeProp(); +} + + +// Set the "lexer.python.strings.u" property. +void QsciLexerPython::setV2UnicodeProp() +{ + emit propertyChanged("lexer.python.strings.u", (v2_unicode ? "1" : "0")); +} + + +// Set if v3 binary and octal literals are allowed. +void QsciLexerPython::setV3BinaryOctalAllowed(bool allowed) +{ + v3_binary_octal = allowed; + + setV3BinaryOctalProp(); +} + + +// Set the "lexer.python.literals.binary" property. +void QsciLexerPython::setV3BinaryOctalProp() +{ + emit propertyChanged("lexer.python.literals.binary", (v3_binary_octal ? "1" : "0")); +} + + +// Set if v3 bytes string literals are allowed. +void QsciLexerPython::setV3BytesAllowed(bool allowed) +{ + v3_bytes = allowed; + + setV3BytesProp(); +} + + +// Set the "lexer.python.strings.b" property. +void QsciLexerPython::setV3BytesProp() +{ + emit propertyChanged("lexer.python.strings.b",(v3_bytes ? "1" : "0")); +} + + +// Set if sub-identifiers are highlighted. +void QsciLexerPython::setHighlightSubidentifiers(bool enabled) +{ + highlight_subids = enabled; + + setHighlightSubidsProp(); +} + + +// Set the "lexer.python.keywords2.no.sub.identifiers" property. +void QsciLexerPython::setHighlightSubidsProp() +{ + emit propertyChanged("lexer.python.keywords2.no.sub.identifiers", + (highlight_subids ? "0" : "1")); +} diff --git a/libs/qscintilla/Qt4Qt5/qscilexerxml.cpp b/libs/qscintilla/Qt4Qt5/qscilexerxml.cpp new file mode 100644 index 00000000..4394ef3d --- /dev/null +++ b/libs/qscintilla/Qt4Qt5/qscilexerxml.cpp @@ -0,0 +1,252 @@ +// This module implements the QsciLexerXML class. +// +// Copyright (c) 2017 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#include "Qsci/qscilexerxml.h" + +#include +#include +#include + + +// The ctor. +QsciLexerXML::QsciLexerXML(QObject *parent) + : QsciLexerHTML(parent), scripts(true) +{ +} + + +// The dtor. +QsciLexerXML::~QsciLexerXML() +{ +} + + +// Returns the language name. +const char *QsciLexerXML::language() const +{ + return "XML"; +} + + +// Returns the lexer name. +const char *QsciLexerXML::lexer() const +{ + return "xml"; +} + + +// Returns the foreground colour of the text for a style. +QColor QsciLexerXML::defaultColor(int style) const +{ + switch (style) + { + case Default: + return QColor(0x00,0x00,0x00); + + case Tag: + case UnknownTag: + case XMLTagEnd: + case SGMLDefault: + case SGMLCommand: + return QColor(0x00,0x00,0x80); + + case Attribute: + case UnknownAttribute: + return QColor(0x00,0x80,0x80); + + case HTMLNumber: + return QColor(0x00,0x7f,0x7f); + + case HTMLDoubleQuotedString: + case HTMLSingleQuotedString: + return QColor(0x7f,0x00,0x7f); + + case OtherInTag: + case Entity: + case XMLStart: + case XMLEnd: + return QColor(0x80,0x00,0x80); + + case HTMLComment: + case SGMLComment: + return QColor(0x80,0x80,0x00); + + case CDATA: + case PHPStart: + case SGMLDoubleQuotedString: + case SGMLError: + return QColor(0x80,0x00,0x00); + + case HTMLValue: + return QColor(0x60,0x80,0x60); + + case SGMLParameter: + return QColor(0x00,0x66,0x00); + + case SGMLSingleQuotedString: + return QColor(0x99,0x33,0x00); + + case SGMLSpecial: + return QColor(0x33,0x66,0xff); + + case SGMLEntity: + return QColor(0x33,0x33,0x33); + + case SGMLBlockDefault: + return QColor(0x00,0x00,0x66); + } + + return QsciLexerHTML::defaultColor(style); +} + + +// Returns the end-of-line fill for a style. +bool QsciLexerXML::defaultEolFill(int style) const +{ + if (style == CDATA) + return true; + + return QsciLexerHTML::defaultEolFill(style); +} + + +// Returns the font of the text for a style. +QFont QsciLexerXML::defaultFont(int style) const +{ + QFont f; + + switch (style) + { + case Default: + case Entity: + case CDATA: +#if defined(Q_OS_WIN) + f = QFont("Times New Roman",11); +#elif defined(Q_OS_MAC) + f = QFont("Times New Roman", 12); +#else + f = QFont("Bitstream Charter",10); +#endif + break; + + case XMLStart: + case XMLEnd: + case SGMLCommand: + f = QsciLexer::defaultFont(style); + f.setBold(true); + break; + + default: + f = QsciLexerHTML::defaultFont(style); + } + + return f; +} + + +// Returns the set of keywords. +const char *QsciLexerXML::keywords(int set) const +{ + if (set == 6) + return QsciLexerHTML::keywords(set); + + return 0; +} + + +// Returns the background colour of the text for a style. +QColor QsciLexerXML::defaultPaper(int style) const +{ + switch (style) + { + case CDATA: + return QColor(0xff,0xf0,0xf0); + + case SGMLDefault: + case SGMLCommand: + case SGMLParameter: + case SGMLDoubleQuotedString: + case SGMLSingleQuotedString: + case SGMLSpecial: + case SGMLEntity: + case SGMLComment: + return QColor(0xef,0xef,0xff); + + case SGMLError: + return QColor(0xff,0x66,0x66); + + case SGMLBlockDefault: + return QColor(0xcc,0xcc,0xe0); + } + + return QsciLexerHTML::defaultPaper(style); +} + + +// Refresh all properties. +void QsciLexerXML::refreshProperties() +{ + setScriptsProp(); +} + + +// Read properties from the settings. +bool QsciLexerXML::readProperties(QSettings &qs, const QString &prefix) +{ + int rc = QsciLexerHTML::readProperties(qs, prefix), num; + + scripts = qs.value(prefix + "scriptsstyled", true).toBool(); + + return rc; +} + + +// Write properties to the settings. +bool QsciLexerXML::writeProperties(QSettings &qs, const QString &prefix) const +{ + int rc = QsciLexerHTML::writeProperties(qs, prefix); + + qs.setValue(prefix + "scriptsstyled", scripts); + + return rc; +} + + +// Return true if scripts are styled. +bool QsciLexerXML::scriptsStyled() const +{ + return scripts; +} + + +// Set if scripts are styled. +void QsciLexerXML::setScriptsStyled(bool styled) +{ + scripts = styled; + + setScriptsProp(); +} + + +// Set the "lexer.xml.allow.scripts" property. +void QsciLexerXML::setScriptsProp() +{ + emit propertyChanged("lexer.xml.allow.scripts",(scripts ? "1" : "0")); +} diff --git a/libs/qscintilla/lexers/LexHTML.cpp b/libs/qscintilla/lexers/LexHTML.cpp new file mode 100644 index 00000000..bd14534d --- /dev/null +++ b/libs/qscintilla/lexers/LexHTML.cpp @@ -0,0 +1,2203 @@ +// Scintilla source code edit control +/** @file LexHTML.cxx + ** Lexer for HTML. + **/ +// Copyright 1998-2005 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include +#include +#include +#include +#include +#include + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "StringCopy.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START) +#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START) +#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START) + +enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment }; +enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc }; + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +inline bool IsOperator(int ch) { + if (IsASCII(ch) && isalnum(ch)) + return false; + // '.' left out as it is used to make up numbers + if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || + ch == '(' || ch == ')' || ch == '-' || ch == '+' || + ch == '=' || ch == '|' || ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ':' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || ch == '/' || + ch == '?' || ch == '!' || ch == '.' || ch == '~') + return true; + return false; +} + +static void GetTextSegment(Accessor &styler, Sci_PositionU start, Sci_PositionU end, char *s, size_t len) { + Sci_PositionU i = 0; + for (; (i < end - start + 1) && (i < len-1); i++) { + s[i] = static_cast(MakeLowerCase(styler[start + i])); + } + s[i] = '\0'; +} + +static const char *GetNextWord(Accessor &styler, Sci_PositionU start, char *s, size_t sLen) { + + Sci_PositionU i = 0; + for (; i < sLen-1; i++) { + char ch = static_cast(styler.SafeGetCharAt(start + i)); + if ((i == 0) && !IsAWordStart(ch)) + break; + if ((i > 0) && !IsAWordChar(ch)) + break; + s[i] = ch; + } + s[i] = '\0'; + + return s; +} + +static script_type segIsScriptingIndicator(Accessor &styler, Sci_PositionU start, Sci_PositionU end, script_type prevValue) { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + //Platform::DebugPrintf("Scripting indicator [%s]\n", s); + if (strstr(s, "src")) // External script + return eScriptNone; + if (strstr(s, "vbs")) + return eScriptVBS; + if (strstr(s, "pyth")) + return eScriptPython; + if (strstr(s, "javas")) + return eScriptJS; + if (strstr(s, "jscr")) + return eScriptJS; + if (strstr(s, "php")) + return eScriptPHP; + if (strstr(s, "xml")) { + const char *xml = strstr(s, "xml"); + for (const char *t=s; t= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + return eScriptPython; + } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { + return eScriptVBS; + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + return eScriptJS; + } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) { + return eScriptPHP; + } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) { + return eScriptSGML; + } else if (state == SCE_H_SGML_BLOCK_DEFAULT) { + return eScriptSGMLblock; + } else { + return eScriptNone; + } +} + +static int statePrintForState(int state, script_mode inScriptType) { + int StateToPrint = state; + + if (state >= SCE_HJ_START) { + if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON); + } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS); + } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) { + StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS); + } + } + + return StateToPrint; +} + +static int stateForPrintState(int StateToPrint) { + int state; + + if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) { + state = StateToPrint - SCE_HA_PYTHON; + } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) { + state = StateToPrint - SCE_HA_VBS; + } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) { + state = StateToPrint - SCE_HA_JS; + } else { + state = StateToPrint; + } + + return state; +} + +static inline bool IsNumber(Sci_PositionU start, Accessor &styler) { + return IsADigit(styler[start]) || (styler[start] == '.') || + (styler[start] == '-') || (styler[start] == '#'); +} + +static inline bool isStringState(int state) { + bool bResult; + + switch (state) { + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJA_DOUBLESTRING: + case SCE_HJA_SINGLESTRING: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_CHARACTER: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPA_STRING: + case SCE_HPA_CHARACTER: + case SCE_HPA_TRIPLE: + case SCE_HPA_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_HSTRING_VARIABLE: + case SCE_HPHP_COMPLEX_VARIABLE: + bResult = true; + break; + default : + bResult = false; + break; + } + return bResult; +} + +static inline bool stateAllowsTermination(int state) { + bool allowTermination = !isStringState(state); + if (allowTermination) { + switch (state) { + case SCE_HB_COMMENTLINE: + case SCE_HPHP_COMMENT: + case SCE_HP_COMMENTLINE: + case SCE_HPA_COMMENTLINE: + allowTermination = false; + } + } + return allowTermination; +} + +// not really well done, since it's only comments that should lex the %> and <% +static inline bool isCommentASPState(int state) { + bool bResult; + + switch (state) { + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTLINE: + case SCE_HJ_COMMENTDOC: + case SCE_HB_COMMENTLINE: + case SCE_HP_COMMENTLINE: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + bResult = true; + break; + default : + bResult = false; + break; + } + return bResult; +} + +static void classifyAttribHTML(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler) { + bool wordIsNumber = IsNumber(start, styler); + char chAttr = SCE_H_ATTRIBUTEUNKNOWN; + if (wordIsNumber) { + chAttr = SCE_H_NUMBER; + } else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) + chAttr = SCE_H_ATTRIBUTE; + } + if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords) + // No keywords -> all are known + chAttr = SCE_H_ATTRIBUTE; + styler.ColourTo(end, chAttr); +} + +static int classifyTagHTML(Sci_PositionU start, Sci_PositionU end, + WordList &keywords, Accessor &styler, bool &tagDontFold, + bool caseSensitive, bool isXml, bool allowScripts) { + char withSpace[30 + 2] = " "; + const char *s = withSpace + 1; + // Copy after the '<' + Sci_PositionU i = 1; + for (Sci_PositionU cPos = start; cPos <= end && i < 30; cPos++) { + char ch = styler[cPos]; + if ((ch != '<') && (ch != '/')) { + withSpace[i++] = caseSensitive ? ch : static_cast(MakeLowerCase(ch)); + } + } + + //The following is only a quick hack, to see if this whole thing would work + //we first need the tagname with a trailing space... + withSpace[i] = ' '; + withSpace[i+1] = '\0'; + + // if the current language is XML, I can fold any tag + // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.) + //...to find it in the list of no-container-tags + tagDontFold = (!isXml) && (NULL != strstr(" area base basefont br col command embed frame hr img input isindex keygen link meta param source track wbr ", withSpace)); + + //now we can remove the trailing space + withSpace[i] = '\0'; + + // No keywords -> all are known + char chAttr = SCE_H_TAGUNKNOWN; + if (s[0] == '!') { + chAttr = SCE_H_SGML_DEFAULT; + } else if (!keywords || keywords.InList(s)) { + chAttr = SCE_H_TAG; + } + styler.ColourTo(end, chAttr); + if (chAttr == SCE_H_TAG) { + if (allowScripts && 0 == strcmp(s, "script")) { + // check to see if this is a self-closing tag by sniffing ahead + bool isSelfClose = false; + for (Sci_PositionU cPos = end; cPos <= end + 200; cPos++) { + char ch = styler.SafeGetCharAt(cPos, '\0'); + if (ch == '\0' || ch == '>') + break; + else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') { + isSelfClose = true; + break; + } + } + + // do not enter a script state if the tag self-closed + if (!isSelfClose) + chAttr = SCE_H_SCRIPT; + } else if (!isXml && 0 == strcmp(s, "comment")) { + chAttr = SCE_H_COMMENT; + } + } + return chAttr; +} + +static void classifyWordHTJS(Sci_PositionU start, Sci_PositionU end, + WordList &keywords, Accessor &styler, script_mode inScriptType) { + char s[30 + 1]; + Sci_PositionU i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + + char chAttr = SCE_HJ_WORD; + bool wordIsNumber = IsADigit(s[0]) || ((s[0] == '.') && IsADigit(s[1])); + if (wordIsNumber) { + chAttr = SCE_HJ_NUMBER; + } else if (keywords.InList(s)) { + chAttr = SCE_HJ_KEYWORD; + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); +} + +static int classifyWordHTVB(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler, script_mode inScriptType) { + char chAttr = SCE_HB_IDENTIFIER; + bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); + if (wordIsNumber) { + chAttr = SCE_HB_NUMBER; + } else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) { + chAttr = SCE_HB_WORD; + if (strcmp(s, "rem") == 0) + chAttr = SCE_HB_COMMENTLINE; + } + } + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + if (chAttr == SCE_HB_COMMENTLINE) + return SCE_HB_COMMENTLINE; + else + return SCE_HB_DEFAULT; +} + +static void classifyWordHTPy(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType, bool isMako) { + bool wordIsNumber = IsADigit(styler[start]); + char s[30 + 1]; + Sci_PositionU i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + char chAttr = SCE_HP_IDENTIFIER; + if (0 == strcmp(prevWord, "class")) + chAttr = SCE_HP_CLASSNAME; + else if (0 == strcmp(prevWord, "def")) + chAttr = SCE_HP_DEFNAME; + else if (wordIsNumber) + chAttr = SCE_HP_NUMBER; + else if (keywords.InList(s)) + chAttr = SCE_HP_WORD; + else if (isMako && 0 == strcmp(s, "block")) + chAttr = SCE_HP_WORD; + styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); + strcpy(prevWord, s); +} + +// Update the word colour to default or keyword +// Called when in a PHP word +static void classifyWordHTPHP(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler) { + char chAttr = SCE_HPHP_DEFAULT; + bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1])); + if (wordIsNumber) { + chAttr = SCE_HPHP_NUMBER; + } else { + char s[100]; + GetTextSegment(styler, start, end, s, sizeof(s)); + if (keywords.InList(s)) + chAttr = SCE_HPHP_WORD; + } + styler.ColourTo(end, chAttr); +} + +static bool isWordHSGML(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler) { + char s[30 + 1]; + Sci_PositionU i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + return keywords.InList(s); +} + +static bool isWordCdata(Sci_PositionU start, Sci_PositionU end, Accessor &styler) { + char s[30 + 1]; + Sci_PositionU i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + return (0 == strcmp(s, "[CDATA[")); +} + +// Return the first state to reach when entering a scripting language +static int StateForScript(script_type scriptLanguage) { + int Result; + switch (scriptLanguage) { + case eScriptVBS: + Result = SCE_HB_START; + break; + case eScriptPython: + Result = SCE_HP_START; + break; + case eScriptPHP: + Result = SCE_HPHP_DEFAULT; + break; + case eScriptXML: + Result = SCE_H_TAGUNKNOWN; + break; + case eScriptSGML: + Result = SCE_H_SGML_DEFAULT; + break; + case eScriptComment: + Result = SCE_H_COMMENT; + break; + default : + Result = SCE_HJ_START; + break; + } + return Result; +} + +static inline bool issgmlwordchar(int ch) { + return !IsASCII(ch) || + (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '['); +} + +static inline bool IsPhpWordStart(int ch) { + return (IsASCII(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f); +} + +static inline bool IsPhpWordChar(int ch) { + return IsADigit(ch) || IsPhpWordStart(ch); +} + +static bool InTagState(int state) { + return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN || + state == SCE_H_SCRIPT || + state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN || + state == SCE_H_NUMBER || state == SCE_H_OTHER || + state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING; +} + +static bool IsCommentState(const int state) { + return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT; +} + +static bool IsScriptCommentState(const int state) { + return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT || + state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE; +} + +static bool isLineEnd(int ch) { + return ch == '\r' || ch == '\n'; +} + +static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) { + if (strlen(blockType) == 0) { + return ((ch == '%') && (chNext == '>')); + } else if ((0 == strcmp(blockType, "inherit")) || + (0 == strcmp(blockType, "namespace")) || + (0 == strcmp(blockType, "include")) || + (0 == strcmp(blockType, "page"))) { + return ((ch == '/') && (chNext == '>')); + } else if (0 == strcmp(blockType, "%")) { + if (ch == '/' && isLineEnd(chNext)) + return 1; + else + return isLineEnd(ch); + } else if (0 == strcmp(blockType, "{")) { + return ch == '}'; + } else { + return (ch == '>'); + } +} + +static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) { + if (strlen(blockType) == 0) { + return 0; + } else if (0 == strcmp(blockType, "%")) { + return ((ch == '%') && (chNext == '}')); + } else if (0 == strcmp(blockType, "{")) { + return ((ch == '}') && (chNext == '}')); + } else { + return 0; + } +} + +static bool isPHPStringState(int state) { + return + (state == SCE_HPHP_HSTRING) || + (state == SCE_HPHP_SIMPLESTRING) || + (state == SCE_HPHP_HSTRING_VARIABLE) || + (state == SCE_HPHP_COMPLEX_VARIABLE); +} + +static Sci_Position FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, Sci_Position i, const Sci_Position lengthDoc, Accessor &styler, bool &isSimpleString) { + Sci_Position j; + const Sci_Position beginning = i - 1; + bool isValidSimpleString = false; + + while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t')) + i++; + + char ch = styler.SafeGetCharAt(i); + const char chNext = styler.SafeGetCharAt(i + 1); + if (!IsPhpWordStart(ch)) { + if (ch == '\'' && IsPhpWordStart(chNext)) { + i++; + ch = chNext; + isSimpleString = true; + } else { + phpStringDelimiter[0] = '\0'; + return beginning; + } + } + phpStringDelimiter[0] = ch; + i++; + + for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) { + if (!IsPhpWordChar(styler[j])) { + if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) { + isValidSimpleString = true; + j++; + break; + } else { + phpStringDelimiter[0] = '\0'; + return beginning; + } + } + if (j - i < phpStringDelimiterSize - 2) + phpStringDelimiter[j-i+1] = styler[j]; + else + i++; + } + if (isSimpleString && !isValidSimpleString) { + phpStringDelimiter[0] = '\0'; + return beginning; + } + phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0'; + return j - 1; +} + +static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler, bool isXml) { + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords + + styler.StartAt(startPos); + char prevWord[200]; + prevWord[0] = '\0'; + char phpStringDelimiter[200]; // PHP is not limited in length, we are + phpStringDelimiter[0] = '\0'; + int StateToPrint = initStyle; + int state = stateForPrintState(StateToPrint); + char makoBlockType[200]; + makoBlockType[0] = '\0'; + int makoComment = 0; + char djangoBlockType[2]; + djangoBlockType[0] = '\0'; + + // If inside a tag, it may be a script tag, so reread from the start of line starting tag to ensure any language tags are seen + if (InTagState(state)) { + while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) { + Sci_Position backLineStart = styler.LineStart(styler.GetLine(startPos-1)); + length += startPos - backLineStart; + startPos = backLineStart; + } + state = SCE_H_DEFAULT; + } + // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState + if (isPHPStringState(state)) { + while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) { + startPos--; + length++; + state = styler.StyleAt(startPos); + } + if (startPos == 0) + state = SCE_H_DEFAULT; + } + styler.StartAt(startPos); + + /* Nothing handles getting out of these, so we need not start in any of them. + * As we're at line start and they can't span lines, we'll re-detect them anyway */ + switch (state) { + case SCE_H_QUESTION: + case SCE_H_XMLSTART: + case SCE_H_XMLEND: + case SCE_H_ASP: + state = SCE_H_DEFAULT; + break; + } + + Sci_Position lineCurrent = styler.GetLine(startPos); + int lineState; + if (lineCurrent > 0) { + lineState = styler.GetLineState(lineCurrent-1); + } else { + // Default client and ASP scripting language is JavaScript + lineState = eScriptJS << 8; + + // property asp.default.language + // Script in ASP code is initially assumed to be in JavaScript. + // To change this to VBScript set asp.default.language to 2. Python is 3. + lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; + } + script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode + bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag + bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag + bool tagDontFold = false; //some HTML tags should not be folded + script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name + script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name + int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state + + script_type scriptLanguage = ScriptOfState(state); + // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment + if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) { + scriptLanguage = eScriptComment; + } + script_type beforeLanguage = ScriptOfState(beforePreProc); + + // property fold.html + // Folding is turned on or off for HTML and XML files with this option. + // The fold option must also be on for folding to occur. + const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; + + const bool fold = foldHTML && styler.GetPropertyInt("fold", 0); + + // property fold.html.preprocessor + // Folding is turned on or off for scripts embedded in HTML files with this option. + // The default is on. + const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1); + + const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property fold.hypertext.comment + // Allow folding for comments in scripts embedded in HTML. + // The default is off. + const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0; + + // property fold.hypertext.heredoc + // Allow folding for heredocs in scripts embedded in HTML. + // The default is off. + const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0; + + // property html.tags.case.sensitive + // For XML and HTML, setting this property to 1 will make tags match in a case + // sensitive way which is the expected behaviour for XML and XHTML. + const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0; + + // property lexer.xml.allow.scripts + // Set to 0 to disable scripts in XML. + const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0; + + // property lexer.html.mako + // Set to 1 to enable the mako template language. + const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0; + + // property lexer.html.django + // Set to 1 to enable the django template language. + const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0; + + const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true); + const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true); + const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true); + // TODO: also handle + and - (except if they're part of ++ or --) and return keywords + const CharacterSet setOKBeforeJSRE(CharacterSet::setNone, "([{=,:;!%^&*|?~"); + + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + int visibleChars = 0; + int lineStartVisibleChars = 0; + + int chPrev = ' '; + int ch = ' '; + int chPrevNonWhite = ' '; + // look back to set chPrevNonWhite properly for better regex colouring + if (scriptLanguage == eScriptJS && startPos > 0) { + Sci_Position back = startPos; + int style = 0; + while (--back) { + style = styler.StyleAt(back); + if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC) + // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE + break; + } + if (style == SCE_HJ_SYMBOLS) { + chPrevNonWhite = static_cast(styler.SafeGetCharAt(back)); + } + } + + styler.StartSegment(startPos); + const Sci_Position lengthDoc = startPos + length; + for (Sci_Position i = startPos; i < lengthDoc; i++) { + const int chPrev2 = chPrev; + chPrev = ch; + if (!IsASpace(ch) && state != SCE_HJ_COMMENT && + state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC) + chPrevNonWhite = ch; + ch = static_cast(styler[i]); + int chNext = static_cast(styler.SafeGetCharAt(i + 1)); + const int chNext2 = static_cast(styler.SafeGetCharAt(i + 2)); + + // Handle DBCS codepages + if (styler.IsLeadByte(static_cast(ch))) { + chPrev = ' '; + i += 1; + continue; + } + + if ((!IsASpace(ch) || !foldCompact) && fold) + visibleChars++; + if (!IsASpace(ch)) + lineStartVisibleChars++; + + // decide what is the current state to print (depending of the script tag) + StateToPrint = statePrintForState(state, inScriptType); + + // handle script folding + if (fold) { + switch (scriptLanguage) { + case eScriptJS: + case eScriptPHP: + //not currently supported case eScriptVBS: + + if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) { + //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); + //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { + if (ch == '#') { + Sci_Position j = i + 1; + while ((j < lengthDoc) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelCurrent++; + } else if (styler.Match(j, "end")) { + levelCurrent--; + } + } else if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { + levelCurrent += (((ch == '{') || (ch == '/')) ? 1 : -1); + } + } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) { + levelCurrent--; + } + break; + case eScriptPython: + if (state != SCE_HP_COMMENTLINE && !isMako) { + if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) { + levelCurrent++; + } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) { + // check if the number of tabs is lower than the level + int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8; + for (Sci_Position j = 0; Findlevel > 0; j++) { + char chTmp = styler.SafeGetCharAt(i + j + 1); + if (chTmp == '\t') { + Findlevel -= 8; + } else if (chTmp == ' ') { + Findlevel--; + } else { + break; + } + } + + if (Findlevel > 0) { + levelCurrent -= Findlevel / 8; + if (Findlevel % 8) + levelCurrent--; + } + } + } + break; + default: + break; + } + } + + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) + // Avoid triggering two times on Dos/Win + // New line -> record any line state onto /next/ line + if (fold) { + int lev = levelPrev; + if (visibleChars == 0) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + + styler.SetLevel(lineCurrent, lev); + visibleChars = 0; + levelPrev = levelCurrent; + } + styler.SetLineState(lineCurrent, + ((inScriptType & 0x03) << 0) | + ((tagOpened ? 1 : 0) << 2) | + ((tagClosing ? 1 : 0) << 3) | + ((aspScript & 0x0F) << 4) | + ((clientScript & 0x0F) << 8) | + ((beforePreProc & 0xFF) << 12)); + lineCurrent++; + lineStartVisibleChars = 0; + } + + // handle start of Mako comment line + if (isMako && ch == '#' && chNext == '#') { + makoComment = 1; + state = SCE_HP_COMMENTLINE; + } + + // handle end of Mako comment line + else if (isMako && makoComment && (ch == '\r' || ch == '\n')) { + makoComment = 0; + styler.ColourTo(i - 1, StateToPrint); + if (scriptLanguage == eScriptPython) { + state = SCE_HP_DEFAULT; + } else { + state = SCE_H_DEFAULT; + } + } + + // Allow falling through to mako handling code if newline is going to end a block + if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && + (!isMako || (0 != strcmp(makoBlockType, "%")))) { + } + // Ignore everything in mako comment until the line ends + else if (isMako && makoComment) { + } + + // generic end of script processing + else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { + // Check if it's the end of the script tag (or any other HTML tag) + switch (state) { + // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!) + case SCE_H_DOUBLESTRING: + case SCE_H_SINGLESTRING: + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide + // the end of script marker from some JS interpreters. + case SCE_HB_COMMENTLINE: + case SCE_HBA_COMMENTLINE: + case SCE_HJ_DOUBLESTRING: + case SCE_HJ_SINGLESTRING: + case SCE_HJ_REGEX: + case SCE_HB_STRING: + case SCE_HBA_STRING: + case SCE_HP_STRING: + case SCE_HP_TRIPLE: + case SCE_HP_TRIPLEDOUBLE: + case SCE_HPHP_HSTRING: + case SCE_HPHP_SIMPLESTRING: + case SCE_HPHP_COMMENT: + case SCE_HPHP_COMMENTLINE: + break; + default : + // check if the closing tag is a script tag + if (const char *tag = + state == SCE_HJ_COMMENTLINE || isXml ? "script" : + state == SCE_H_COMMENT ? "comment" : 0) { + Sci_Position j = i + 2; + int chr; + do { + chr = static_cast(*tag++); + } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++))); + if (chr != 0) break; + } + // closing tag of the script (it's a closing HTML tag anyway) + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_TAGUNKNOWN; + inScriptType = eHtml; + scriptLanguage = eScriptNone; + clientScript = eScriptJS; + i += 2; + visibleChars += 2; + tagClosing = true; + continue; + } + } + + ///////////////////////////////////// + // handle the start of PHP pre-processor = Non-HTML + else if ((state != SCE_H_ASPAT) && + !isStringState(state) && + (state != SCE_HPHP_COMMENT) && + (state != SCE_HPHP_COMMENTLINE) && + (ch == '<') && + (chNext == '?') && + !IsScriptCommentState(state)) { + beforeLanguage = scriptLanguage; + scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, isXml ? eScriptXML : eScriptPHP); + if ((scriptLanguage != eScriptPHP) && (isStringState(state) || (state==SCE_H_COMMENT))) continue; + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + i++; + visibleChars++; + i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6); + if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLSTART); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = StateForScript(scriptLanguage); + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + // Fold whole script, but not if the XML first tag (all XML-like tags in this case) + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent++; + } + // should be better + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start Mako template Python code + else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || + (lineStartVisibleChars == 1 && ch == '%') || + (lineStartVisibleChars == 1 && ch == '/' && chNext == '%') || + (ch == '$' && chNext == '{') || + (ch == '<' && chNext == '/' && chNext2 == '%'))) { + if (ch == '%' || ch == '/') + StringCopy(makoBlockType, "%"); + else if (ch == '$') + StringCopy(makoBlockType, "{"); + else if (chNext == '/') + GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType)); + else + GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType)); + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + if (chNext == '/') { + i += 2; + visibleChars += 2; + } else if (ch != '%') { + i++; + visibleChars++; + } + state = SCE_HP_START; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + + if (ch != '%' && ch != '$' && ch != '/') { + i += static_cast(strlen(makoBlockType)); + visibleChars += static_cast(strlen(makoBlockType)); + if (keywords4.InList(makoBlockType)) + styler.ColourTo(i, SCE_HP_WORD); + else + styler.ColourTo(i, SCE_H_TAGUNKNOWN); + } + + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start/end of Django comment + else if (isDjango && state != SCE_H_COMMENT && (ch == '{' && chNext == '#')) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + beforeLanguage = scriptLanguage; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + i += 1; + visibleChars += 1; + scriptLanguage = eScriptComment; + state = SCE_H_COMMENT; + styler.ColourTo(i, SCE_H_ASP); + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } else if (isDjango && state == SCE_H_COMMENT && (ch == '#' && chNext == '}')) { + styler.ColourTo(i - 1, StateToPrint); + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + + // handle the start Django template code + else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' || chNext == '{'))) { + if (chNext == '%') + StringCopy(djangoBlockType, "%"); + else + StringCopy(djangoBlockType, "{"); + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + i += 1; + visibleChars += 1; + state = SCE_HP_START; + beforeLanguage = scriptLanguage; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + // handle the start of ASP pre-processor = Non-HTML + else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + if (chNext2 == '@') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + state = SCE_H_ASPAT; + } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) { + styler.ColourTo(i + 3, SCE_H_ASP); + state = SCE_H_XCCOMMENT; + scriptLanguage = eScriptVBS; + continue; + } else { + if (chNext2 == '=') { + i += 2; // place as if it was the second next char treated + visibleChars += 2; + } else { + i++; // place as if it was the next char treated + visibleChars++; + } + + state = StateForScript(aspScript); + } + scriptLanguage = eScriptVBS; + styler.ColourTo(i, SCE_H_ASP); + // fold whole script + if (foldHTMLPreprocessor) + levelCurrent++; + // should be better + ch = static_cast(styler.SafeGetCharAt(i)); + continue; + } + + ///////////////////////////////////// + // handle the start of SGML language (DTD) + else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) && + (chPrev == '<') && + (ch == '!') && + (StateToPrint != SCE_H_CDATA) && + (!IsCommentState(StateToPrint)) && + (!IsScriptCommentState(StateToPrint))) { + beforePreProc = state; + styler.ColourTo(i - 2, StateToPrint); + if ((chNext == '-') && (chNext2 == '-')) { + state = SCE_H_COMMENT; // wait for a pending command + styler.ColourTo(i + 2, SCE_H_COMMENT); + i += 2; // follow styling after the -- + } else if (isWordCdata(i + 1, i + 7, styler)) { + state = SCE_H_CDATA; + } else { + styler.ColourTo(i, SCE_H_SGML_DEFAULT); // ') { + i++; + visibleChars++; + } + else if (0 == strcmp(makoBlockType, "%") && ch == '/') { + i++; + visibleChars++; + } + if (0 != strcmp(makoBlockType, "%") || ch == '/') { + styler.ColourTo(i, SCE_H_ASP); + } + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = eScriptNone; + continue; + } + + // handle the end of Django template code + else if (isDjango && + ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && + isDjangoBlockEnd(ch, chNext, djangoBlockType)) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + if (state == SCE_HP_WORD) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + + // handle the end of a pre-processor = Non-HTML + else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) && + (((ch == '%') || (ch == '?')) && (chNext == '>'))) || + ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + // Bounce out of any ASP mode + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); + break; + case SCE_H_XCCOMMENT: + styler.ColourTo(i - 1, state); + break; + default : + styler.ColourTo(i - 1, StateToPrint); + break; + } + if (scriptLanguage != eScriptSGML) { + i++; + visibleChars++; + } + if (ch == '%') + styler.ColourTo(i, SCE_H_ASP); + else if (scriptLanguage == eScriptXML) + styler.ColourTo(i, SCE_H_XMLEND); + else if (scriptLanguage == eScriptSGML) + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + else + styler.ColourTo(i, SCE_H_QUESTION); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + // Unfold all scripting languages, except for XML tag + if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { + levelCurrent--; + } + scriptLanguage = beforeLanguage; + continue; + } + ///////////////////////////////////// + + switch (state) { + case SCE_H_DEFAULT: + if (ch == '<') { + // in HTML, fold on tag open and unfold on tag close + tagOpened = true; + tagClosing = (chNext == '/'); + styler.ColourTo(i - 1, StateToPrint); + if (chNext != '!') + state = SCE_H_TAGUNKNOWN; + } else if (ch == '&') { + styler.ColourTo(i - 1, SCE_H_DEFAULT); + state = SCE_H_ENTITY; + } + break; + case SCE_H_SGML_DEFAULT: + case SCE_H_SGML_BLOCK_DEFAULT: +// if (scriptLanguage == eScriptSGMLblock) +// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT; + + if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SIMPLESTRING; + } else if ((ch == '-') && (chPrev == '-')) { + if (static_cast(styler.GetStartSegment()) <= (i - 2)) { + styler.ColourTo(i - 2, StateToPrint); + } + state = SCE_H_SGML_COMMENT; + } else if (IsASCII(ch) && isalpha(ch) && (chPrev == '%')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_ENTITY; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_SPECIAL; + } else if (ch == '[') { + styler.ColourTo(i - 1, StateToPrint); + scriptLanguage = eScriptSGMLblock; + state = SCE_H_SGML_BLOCK_DEFAULT; + } else if (ch == ']') { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i, StateToPrint); + scriptLanguage = eScriptSGML; + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_ERROR); + } + state = SCE_H_SGML_DEFAULT; + } else if (scriptLanguage == eScriptSGMLblock) { + if ((ch == '!') && (chPrev == '<')) { + styler.ColourTo(i - 2, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + state = SCE_H_SGML_COMMAND; + } else if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_SGML_DEFAULT); + } + } + break; + case SCE_H_SGML_COMMAND: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } else if (!issgmlwordchar(ch)) { + if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SGML_1ST_PARAM; + } else { + state = SCE_H_SGML_ERROR; + } + } + break; + case SCE_H_SGML_1ST_PARAM: + // wait for the beginning of the word + if ((ch == '-') && (chPrev == '-')) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT); + } + state = SCE_H_SGML_1ST_PARAM_COMMENT; + } else if (issgmlwordchar(ch)) { + if (scriptLanguage == eScriptSGMLblock) { + styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT); + } else { + styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT); + } + // find the length of the word + int size = 1; + while (setHTMLWord.Contains(static_cast(styler.SafeGetCharAt(i + size)))) + size++; + styler.ColourTo(i + size - 1, StateToPrint); + i += size - 1; + visibleChars += size - 1; + ch = static_cast(styler.SafeGetCharAt(i)); + if (scriptLanguage == eScriptSGMLblock) { + state = SCE_H_SGML_BLOCK_DEFAULT; + } else { + state = SCE_H_SGML_DEFAULT; + } + continue; + } + break; + case SCE_H_SGML_ERROR: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i - 2, StateToPrint); + state = SCE_H_SGML_COMMENT; + } + break; + case SCE_H_SGML_DOUBLESTRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_SIMPLESTRING: + if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_SGML_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_CDATA: + if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_COMMENT: + if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + levelCurrent--; + } + break; + case SCE_H_SGML_1ST_PARAM_COMMENT: + if ((ch == '-') && (chPrev == '-')) { + styler.ColourTo(i, SCE_H_SGML_COMMENT); + state = SCE_H_SGML_1ST_PARAM; + } + break; + case SCE_H_SGML_SPECIAL: + if (!(IsASCII(ch) && isupper(ch))) { + styler.ColourTo(i - 1, StateToPrint); + if (isalnum(ch)) { + state = SCE_H_SGML_ERROR; + } else { + state = SCE_H_SGML_DEFAULT; + } + } + break; + case SCE_H_SGML_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_SGML_DEFAULT; + } else if (!(IsASCII(ch) && isalnum(ch)) && ch != '-' && ch != '.') { + styler.ColourTo(i, SCE_H_SGML_ERROR); + state = SCE_H_SGML_DEFAULT; + } + break; + case SCE_H_ENTITY: + if (ch == ';') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_DEFAULT; + } + if (ch != '#' && !(IsASCII(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway... + && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML + if (!IsASCII(ch)) // Possibly start of a multibyte character so don't allow this byte to be in entity style + styler.ColourTo(i-1, SCE_H_TAGUNKNOWN); + else + styler.ColourTo(i, SCE_H_TAGUNKNOWN); + state = SCE_H_DEFAULT; + } + break; + case SCE_H_TAGUNKNOWN: + if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) { + int eClass = classifyTagHTML(styler.GetStartSegment(), + i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts); + if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) { + if (!tagClosing) { + inScriptType = eNonHtmlScript; + scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment; + } else { + scriptLanguage = eScriptNone; + } + eClass = SCE_H_TAG; + } + if (ch == '>') { + styler.ColourTo(i, eClass); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '/' && chNext == '>') { + if (eClass == SCE_H_TAGUNKNOWN) { + styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN); + } else { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + } + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + } else { + if (eClass != SCE_H_TAGUNKNOWN) { + if (eClass == SCE_H_SGML_DEFAULT) { + state = SCE_H_SGML_DEFAULT; + } else { + state = SCE_H_OTHER; + } + } + } + } + break; + case SCE_H_ATTRIBUTE: + if (!setAttributeContinue.Contains(ch)) { + if (inScriptType == eNonHtmlScript) { + int scriptLanguagePrev = scriptLanguage; + clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage); + scriptLanguage = clientScript; + if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone)) + inScriptType = eHtml; + } + classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler); + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '=') { + styler.ColourTo(i, SCE_H_OTHER); + state = SCE_H_VALUE; + } else { + state = SCE_H_OTHER; + } + } + break; + case SCE_H_OTHER: + if (ch == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_SINGLESTRING; + } else if (ch == '=') { + styler.ColourTo(i, StateToPrint); + state = SCE_H_VALUE; + } else if (ch == '/' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_TAGEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + tagOpened = false; + } else if (ch == '?' && chNext == '>') { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i + 1, SCE_H_XMLEND); + i++; + ch = chNext; + state = SCE_H_DEFAULT; + } else if (setHTMLWord.Contains(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_H_ATTRIBUTE; + } + break; + case SCE_H_DOUBLESTRING: + if (ch == '\"') { + if (inScriptType == eNonHtmlScript) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + } + styler.ColourTo(i, SCE_H_DOUBLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_SINGLESTRING: + if (ch == '\'') { + if (inScriptType == eNonHtmlScript) { + scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage); + } + styler.ColourTo(i, SCE_H_SINGLESTRING); + state = SCE_H_OTHER; + } + break; + case SCE_H_VALUE: + if (!setHTMLWord.Contains(ch)) { + if (ch == '\"' && chPrev == '=') { + // Should really test for being first character + state = SCE_H_DOUBLESTRING; + } else if (ch == '\'' && chPrev == '=') { + state = SCE_H_SINGLESTRING; + } else { + if (IsNumber(styler.GetStartSegment(), styler)) { + styler.ColourTo(i - 1, SCE_H_NUMBER); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + if (ch == '>') { + styler.ColourTo(i, SCE_H_TAG); + if (inScriptType == eNonHtmlScript) { + state = StateForScript(scriptLanguage); + } else { + state = SCE_H_DEFAULT; + } + tagOpened = false; + if (!tagDontFold) { + if (tagClosing) { + levelCurrent--; + } else { + levelCurrent++; + } + } + tagClosing = false; + } else { + state = SCE_H_OTHER; + } + } + } + break; + case SCE_HJ_DEFAULT: + case SCE_HJ_START: + case SCE_HJ_SYMBOLS: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_WORD; + } else if (ch == '/' && chNext == '*') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + if (chNext2 == '/') { + // Eat the * so it isn't used for the end of the comment + i++; + } + } else if (ch == '/' && chNext == '/') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if (ch == '/' && setOKBeforeJSRE.Contains(chPrevNonWhite)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_REGEX; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HJ_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType); + //styler.ColourTo(i - 1, eHTJSKeyword); + state = SCE_HJ_DEFAULT; + if (ch == '/' && chNext == '*') { + if (chNext2 == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HJ_DOUBLESTRING; + } else if (ch == '\'') { + state = SCE_HJ_SINGLESTRING; + } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + state = SCE_HJ_DEFAULT; + } + } + break; + case SCE_HJ_COMMENT: + case SCE_HJ_COMMENTDOC: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType)); + state = SCE_HJ_DEFAULT; + ch = ' '; + } + break; + case SCE_HJ_DOUBLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\"') { + styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_STRINGEOL; + } + break; + case SCE_HJ_SINGLESTRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + } + } else if (ch == '\'') { + styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType)); + state = SCE_HJ_DEFAULT; + } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_COMMENTLINE; + i += 2; + } else if (isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + if (chPrev != '\\' && (chPrev2 != '\\' || chPrev != '\r' || ch != '\n')) { + state = SCE_HJ_STRINGEOL; + } + } + break; + case SCE_HJ_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } + break; + case SCE_HJ_REGEX: + if (ch == '\r' || ch == '\n' || ch == '/') { + if (ch == '/') { + while (IsASCII(chNext) && islower(chNext)) { // gobble regex flags + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } + styler.ColourTo(i, StateToPrint); + state = SCE_HJ_DEFAULT; + } else if (ch == '\\') { + // Gobble up the quoted character + if (chNext == '\\' || chNext == '/') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } + break; + case SCE_HB_DEFAULT: + case SCE_HB_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_WORD; + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRING; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HB_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + } + break; + case SCE_HB_WORD: + if (!IsAWordChar(ch)) { + state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); + if (state == SCE_HB_DEFAULT) { + if (ch == '\"') { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType)); + state = SCE_HB_DEFAULT; + } + } + } + break; + case SCE_HB_STRING: + if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_STRINGEOL; + } + break; + case SCE_HB_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HB_STRINGEOL: + if (!isLineEnd(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HB_DEFAULT; + } else if (!isLineEnd(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HB_DEFAULT; + } + break; + case SCE_HP_DEFAULT: + case SCE_HP_START: + if (IsAWordStart(ch)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_WORD; + } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') && + styler.SafeGetCharAt(i + 3) == '-') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '#') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + // state = statePrintForState(SCE_HP_STRING,inScriptType); + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + styler.ColourTo(i - 1, StateToPrint); + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i - 1, StateToPrint); + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } else if ((ch == ' ') || (ch == '\t')) { + if (state == SCE_HP_START) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + } + break; + case SCE_HP_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); + state = SCE_HP_DEFAULT; + if (ch == '#') { + state = SCE_HP_COMMENTLINE; + } else if (ch == '\"') { + if (chNext == '\"' && chNext2 == '\"') { + i += 2; + state = SCE_HP_TRIPLEDOUBLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_STRING; + } + } else if (ch == '\'') { + if (chNext == '\'' && chNext2 == '\'') { + i += 2; + state = SCE_HP_TRIPLE; + ch = ' '; + chPrev = ' '; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } else { + state = SCE_HP_CHARACTER; + } + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType)); + } + } + break; + case SCE_HP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_STRING: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } else if (ch == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_CHARACTER: + if (ch == '\\') { + if (chNext == '\"' || chNext == '\'' || chNext == '\\') { + i++; + ch = chNext; + chNext = static_cast(styler.SafeGetCharAt(i + 1)); + } + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLE: + if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + case SCE_HP_TRIPLEDOUBLE: + if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HP_DEFAULT; + } + break; + ///////////// start - PHP state handling + case SCE_HPHP_WORD: + if (!IsAWordChar(ch)) { + classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); + if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + StringCopy(phpStringDelimiter, "\""); + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); + if (strlen(phpStringDelimiter)) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + StringCopy(phpStringDelimiter, "\'"); + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else { + state = SCE_HPHP_DEFAULT; + } + } + break; + case SCE_HPHP_NUMBER: + // recognize bases 8,10 or 16 integers OR floating-point numbers + if (!IsADigit(ch) + && strchr(".xXabcdefABCDEF", ch) == NULL + && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) { + styler.ColourTo(i - 1, SCE_HPHP_NUMBER); + if (IsOperator(ch)) + state = SCE_HPHP_OPERATOR; + else + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, SCE_HPHP_VARIABLE); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENT: + if (ch == '/' && chPrev == '*') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_COMMENTLINE: + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + break; + case SCE_HPHP_HSTRING: + if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) { + // skip the next char + i++; + } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{')) + && IsPhpWordStart(chNext2)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_COMPLEX_VARIABLE; + } else if (ch == '$' && IsPhpWordStart(chNext)) { + styler.ColourTo(i - 1, StateToPrint); + state = SCE_HPHP_HSTRING_VARIABLE; + } else if (styler.Match(i, phpStringDelimiter)) { + if (phpStringDelimiter[0] == '\"') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } else if (isLineEnd(chPrev)) { + const int psdLength = static_cast(strlen(phpStringDelimiter)); + const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); + const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); + if (isLineEnd(chAfterPsd) || + (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + } + break; + case SCE_HPHP_SIMPLESTRING: + if (phpStringDelimiter[0] == '\'') { + if (ch == '\\') { + // skip the next char + i++; + } else if (ch == '\'') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + } + } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) { + const int psdLength = static_cast(strlen(phpStringDelimiter)); + const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); + const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); + if (isLineEnd(chAfterPsd) || + (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) { + i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1; + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_DEFAULT; + if (foldHeredoc) levelCurrent--; + } + } + break; + case SCE_HPHP_HSTRING_VARIABLE: + if (!IsPhpWordChar(chNext)) { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_COMPLEX_VARIABLE: + if (ch == '}') { + styler.ColourTo(i, StateToPrint); + state = SCE_HPHP_HSTRING; + } + break; + case SCE_HPHP_OPERATOR: + case SCE_HPHP_DEFAULT: + styler.ColourTo(i - 1, StateToPrint); + if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) { + state = SCE_HPHP_NUMBER; + } else if (IsAWordStart(ch)) { + state = SCE_HPHP_WORD; + } else if (ch == '/' && chNext == '*') { + i++; + state = SCE_HPHP_COMMENT; + } else if (ch == '/' && chNext == '/') { + i++; + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '#') { + state = SCE_HPHP_COMMENTLINE; + } else if (ch == '\"') { + state = SCE_HPHP_HSTRING; + StringCopy(phpStringDelimiter, "\""); + } else if (styler.Match(i, "<<<")) { + bool isSimpleString = false; + i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString); + if (strlen(phpStringDelimiter)) { + state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING); + if (foldHeredoc) levelCurrent++; + } + } else if (ch == '\'') { + state = SCE_HPHP_SIMPLESTRING; + StringCopy(phpStringDelimiter, "\'"); + } else if (ch == '$' && IsPhpWordStart(chNext)) { + state = SCE_HPHP_VARIABLE; + } else if (IsOperator(ch)) { + state = SCE_HPHP_OPERATOR; + } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) { + state = SCE_HPHP_DEFAULT; + } + break; + ///////////// end - PHP state handling + } + + // Some of the above terminated their lexeme but since the same character starts + // the same class again, only reenter if non empty segment. + + bool nonEmptySegment = i >= static_cast(styler.GetStartSegment()); + if (state == SCE_HB_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HB_STRING; + } else if (ch == '\'') { + state = SCE_HB_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HB_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HB_DEFAULT); + } + } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded + if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HBA_STRING; + } else if (ch == '\'') { + state = SCE_HBA_COMMENTLINE; + } else if (IsAWordStart(ch)) { + state = SCE_HBA_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, SCE_HBA_DEFAULT); + } + } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded + if (ch == '/' && chNext == '*') { + if (styler.SafeGetCharAt(i + 2) == '*') + state = SCE_HJ_COMMENTDOC; + else + state = SCE_HJ_COMMENT; + } else if (ch == '/' && chNext == '/') { + state = SCE_HJ_COMMENTLINE; + } else if ((ch == '\"') && (nonEmptySegment)) { + state = SCE_HJ_DOUBLESTRING; + } else if ((ch == '\'') && (nonEmptySegment)) { + state = SCE_HJ_SINGLESTRING; + } else if (IsAWordStart(ch)) { + state = SCE_HJ_WORD; + } else if (IsOperator(ch)) { + styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType)); + } + } + } + + switch (state) { + case SCE_HJ_WORD: + classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType); + break; + case SCE_HB_WORD: + classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType); + break; + case SCE_HP_WORD: + classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType, isMako); + break; + case SCE_HPHP_WORD: + classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler); + break; + default: + StateToPrint = statePrintForState(state, inScriptType); + if (static_cast(styler.GetStartSegment()) < lengthDoc) + styler.ColourTo(lengthDoc - 1, StateToPrint); + break; + } + + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + if (fold) { + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); + } +} + +static void ColouriseXMLDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + // Passing in true because we're lexing XML + ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true); +} + +static void ColouriseHTMLDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + // Passing in false because we're notlexing XML + ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false); +} + +static void ColourisePHPScriptDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + if (startPos == 0) + initStyle = SCE_HPHP_DEFAULT; + ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler); +} + +static const char * const htmlWordListDesc[] = { + "HTML elements and attributes", + "JavaScript keywords", + "VBScript keywords", + "Python keywords", + "PHP keywords", + "SGML and DTD keywords", + 0, +}; + +static const char * const phpscriptWordListDesc[] = { + "", //Unused + "", //Unused + "", //Unused + "", //Unused + "PHP keywords", + "", //Unused + 0, +}; + +LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc); +LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc); +LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc); diff --git a/libs/qscintilla/src/Catalogue.cpp b/libs/qscintilla/src/Catalogue.cpp index 375781d9..6dd4db2c 100644 --- a/libs/qscintilla/src/Catalogue.cpp +++ b/libs/qscintilla/src/Catalogue.cpp @@ -79,6 +79,8 @@ int Scintilla_LinkLexers() { //**\(\tLINK_LEXER(\*);\n\) LINK_LEXER(lmSQL); LINK_LEXER(lmJSON); + LINK_LEXER(lmHTML); + LINK_LEXER(lmXML); //--Autogenerated -- end of automatically generated section diff --git a/src/EditDialog.cpp b/src/EditDialog.cpp index 2a56b3ab..2def845d 100644 --- a/src/EditDialog.cpp +++ b/src/EditDialog.cpp @@ -3,6 +3,7 @@ #include "sqlitedb.h" #include "Settings.h" #include "src/qhexedit.h" +#include "docktextedit.h" #include "FileDialog.h" #include "Data.h" @@ -13,6 +14,7 @@ #include #include #include +#include #include EditDialog::EditDialog(QWidget* parent) @@ -21,7 +23,6 @@ EditDialog::EditDialog(QWidget* parent) currentIndex(QModelIndex()), dataSource(TextBuffer), dataType(Null), - textNullSet(false), isReadOnly(true) { ui->setupUi(this); @@ -34,17 +35,18 @@ EditDialog::EditDialog(QWidget* parent) hexLayout->addWidget(hexEdit); hexEdit->setOverwriteMode(false); - QHBoxLayout* jsonLayout = new QHBoxLayout(ui->editorJSON); - jsonEdit = new JsonTextEdit(this); - jsonLayout->addWidget(jsonEdit); + QHBoxLayout* sciLayout = new QHBoxLayout(ui->editorSci); + sciEdit = new DockTextEdit(this); + sciLayout->addWidget(sciEdit); QShortcut* ins = new QShortcut(QKeySequence(Qt::Key_Insert), this); connect(ins, SIGNAL(activated()), this, SLOT(toggleOverwriteMode())); connect(ui->editorText, SIGNAL(textChanged()), this, SLOT(updateApplyButton())); connect(hexEdit, SIGNAL(dataChanged()), this, SLOT(updateApplyButton())); - connect(jsonEdit, SIGNAL(textChanged()), this, SLOT(updateApplyButton())); - connect(jsonEdit, SIGNAL(textChanged()), this, SLOT(editTextChanged())); + + connect(sciEdit, SIGNAL(textChanged()), this, SLOT(updateApplyButton())); + connect(sciEdit, SIGNAL(textChanged()), this, SLOT(editTextChanged())); mustIndentAndCompact = Settings::getValue("databrowser", "indent_compact").toBool(); ui->buttonIndent->setChecked(mustIndentAndCompact); @@ -99,15 +101,15 @@ void EditDialog::loadData(const QByteArray& data) // Determine the data type, saving that info in the class variable dataType = checkDataType(data); - // Get the current editor mode (eg text, hex, or image mode) - int editMode = ui->editorStack->currentIndex(); + // Get the current editor mode (eg text, hex, image, json or xml mode) + int editMode = ui->comboMode->currentIndex(); // Data type specific handling switch (dataType) { case Null: // Set enabled any of the text widgets ui->editorText->setEnabled(true); - jsonEdit->setEnabled(true); + sciEdit->setEnabled(true); switch (editMode) { case TextEditor: // The text widget buffer is now the main data source @@ -119,15 +121,16 @@ void EditDialog::loadData(const QByteArray& data) break; case JsonEditor: + case XmlEditor: + // The JSON widget buffer is now the main data source - dataSource = JsonBuffer; + dataSource = SciBuffer; // Empty the text editor contents, then enable text editing - jsonEdit->clear(); + sciEdit->clear(); break; - case HexEditor: // The hex widget buffer is now the main data source dataSource = HexBuffer; @@ -153,78 +156,27 @@ void EditDialog::loadData(const QByteArray& data) case Text: case JSON: - // Set enabled any of the text widgets - ui->editorText->setEnabled(true); - jsonEdit->setEnabled(true); + // Can be stored in any widget, except the ImageViewer switch (editMode) { case TextEditor: - { - // The text widget buffer is now the main data source - dataSource = TextBuffer; - - // Load the text into the text editor, remove BOM first if there is one - QByteArray dataWithoutBom = data; - removedBom = removeBom(dataWithoutBom); - - textData = QString::fromUtf8(dataWithoutBom.constData(), dataWithoutBom.size()); - ui->editorText->setPlainText(textData); - - // Select all of the text by default - ui->editorText->selectAll(); - + setDataInBuffer(data, TextBuffer); break; - } case JsonEditor: - // The JSON widget buffer is now the main data source - dataSource = JsonBuffer; - { - QJsonParseError parseError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(data.constData(), data.size()), &parseError); - - if (mustIndentAndCompact && !jsonDoc.isNull()) { - // Load indented JSON into the JSON editor - textData = QString(jsonDoc.toJson(QJsonDocument::Indented)); - jsonEdit->setText(textData); - } else { - // Fallback case. The data is not yet valid JSON. - textData = QString::fromUtf8(data.constData(), data.size()); - jsonEdit->setText(textData); - } - - jsonEdit->clearErrorIndicators(); - if (parseError.error != QJsonParseError::NoError) - jsonEdit->setErrorIndicator(parseError.offset-1); - - } - + case XmlEditor: + setDataInBuffer(data, SciBuffer); break; - case HexEditor: - // The hex widget buffer is now the main data source - dataSource = HexBuffer; - - // Load the text into the hex editor - hexEdit->setData(data); - + setDataInBuffer(data, HexBuffer); break; - case ImageViewer: - // The text widget buffer is now the main data source - dataSource = TextBuffer; + // The image viewer cannot hold data nor display text. // Clear any image from the image viewing widget ui->editorImage->setPixmap(QPixmap(0,0)); // Load the text into the text editor - textData = QString::fromUtf8(data.constData(), data.size()); - ui->editorText->setPlainText(textData); - - // Enable text editing - ui->editorText->setEnabled(true); - - // Select all of the text by default - ui->editorText->selectAll(); + setDataInBuffer(data, TextBuffer); break; } @@ -235,10 +187,7 @@ void EditDialog::loadData(const QByteArray& data) // stored it in the editorImage widget instead, it would be a pixmap // and there's no good way to restore that back to the original // (pristine) image data. eg image metadata would be lost - hexEdit->setData(data); - - // The hex widget buffer is now the main data source - dataSource = HexBuffer; + setDataInBuffer(data, HexBuffer); // Update the display if in text edit or image viewer mode switch (editMode) { @@ -250,10 +199,12 @@ void EditDialog::loadData(const QByteArray& data) ui->editorText->setEnabled(false); break; + case XmlEditor: case JsonEditor: // Disable text editing, and use a warning message as the contents - jsonEdit->setText(tr("Image data can't be viewed with the JSON editor")); - jsonEdit->setEnabled(false); + sciEdit->setText(tr("Image data can't be viewed with this editor")); + sciEdit->setEnabled(false); + break; case ImageViewer: @@ -264,16 +215,44 @@ void EditDialog::loadData(const QByteArray& data) break; } break; + case SVG: + // Set the XML data in any buffer or update image in image viewer mode + switch (editMode) { + case TextEditor: + setDataInBuffer(data, TextBuffer); + break; + + case JsonEditor: + case XmlEditor: + + setDataInBuffer(data, SciBuffer); + break; + + case HexEditor: + + setDataInBuffer(data, HexBuffer); + break; + + case ImageViewer: + // Set data in the XML (Sci) Buffer and load the SVG Image + setDataInBuffer(data, SciBuffer); + sciEdit->setLanguage(DockTextEdit::XML); + + // Load the image into the image viewing widget + if (img.loadFromData(data)) { + ui->editorImage->setPixmap(QPixmap::fromImage(img)); + } + break; + } + break; default: - // The hex widget buffer is now the main data source - dataSource = HexBuffer; // The data seems to be general binary data, which is always loaded // into the hex widget (the only safe place for it) - // Load the data into the hex editor - hexEdit->setData(data); + // Load the data into the hex buffer + setDataInBuffer(data, HexBuffer); switch (editMode) { case TextEditor: @@ -285,9 +264,10 @@ void EditDialog::loadData(const QByteArray& data) break; case JsonEditor: + case XmlEditor: // Disable text editing, and use a warning message as the contents - jsonEdit->setText(QString(tr("Binary data can't be viewed with the JSON editor"))); - jsonEdit->setEnabled(false); + sciEdit->setText(QString(tr("Binary data can't be viewed with this editor"))); + sciEdit->setEnabled(false); break; case ImageViewer: @@ -310,7 +290,7 @@ void EditDialog::importData() this, tr("Choose a file to import") #ifndef Q_OS_MAC // Filters on OS X are buggy - , tr("Text files(*.txt);;Image files(%1);;JSON files(*.json);;All files(*)").arg(image_formats) + , tr("Text files (*.txt);;Image files (%1);;JSON files (*.json);;XML files (*.xml);;All files (*)").arg(image_formats) #endif ); if(QFile::exists(fileName)) @@ -361,11 +341,10 @@ void EditDialog::exportData() // Data source is the text buffer file.write(ui->editorText->toPlainText().toUtf8()); break; - case JsonBuffer: + case SciBuffer: // Data source is the JSON buffer - file.write(jsonEdit->text().toUtf8()); + file.write(sciEdit->text().toUtf8()); break; - } file.close(); } @@ -377,25 +356,17 @@ void EditDialog::setNull() ui->editorText->clear(); ui->editorImage->clear(); hexEdit->setData(QByteArray()); - jsonEdit->clear(); + sciEdit->clear(); dataType = Null; removedBom.clear(); - // Check if in text editor mode - int editMode = ui->editorStack->currentIndex(); - if (editMode == TextEditor || editMode == JsonEditor) { - // Setting NULL in the text editor switches the data source to it - dataSource = TextBuffer; + // The text editors don't know the difference between an empty string + // and a NULL, so we need to record NULL outside of that + dataType = Null; - // Ensure the text editor is enabled - ui->editorText->setEnabled(true); - // Ensure the JSON editor is enabled - jsonEdit->setEnabled(true); - - // The text editor doesn't know the difference between an empty string - // and a NULL, so we need to record NULL outside of that - textNullSet = true; - } + // Ensure the text (plain and Scintilla) editors are enabled + ui->editorText->setEnabled(true); + sciEdit->setEnabled(true); // Update the cell data info in the bottom left of the Edit Cell updateCellInfo(hexEdit->data()); @@ -424,47 +395,46 @@ void EditDialog::accept() if(!currentIndex.isValid()) return; + if (dataType == Null) { + emit recordTextUpdated(currentIndex, hexEdit->data(), true); + return; + } + switch (dataSource) { case TextBuffer: - // Check if a NULL is set in the text editor - if (textNullSet) { - emit recordTextUpdated(currentIndex, hexEdit->data(), true); - } else { - // It's not NULL, so proceed with normal text string checking - QString oldData = currentIndex.data(Qt::EditRole).toString(); - QString newData = removedBom + ui->editorText->toPlainText(); - if (oldData != newData) - // The data is different, so commit it back to the database - emit recordTextUpdated(currentIndex, removedBom + newData.toUtf8(), false); - } + { + QString oldData = currentIndex.data(Qt::EditRole).toString(); + QString newData = removedBom + ui->editorText->toPlainText(); + if (oldData != newData) + // The data is different, so commit it back to the database + emit recordTextUpdated(currentIndex, removedBom + newData.toUtf8(), false); break; - case JsonBuffer: - // Check if a NULL is set in the text editor - if (textNullSet) { - emit recordTextUpdated(currentIndex, hexEdit->data(), true); - } else { - // It's not NULL, so proceed with normal text string checking + } + case SciBuffer: + switch (sciEdit->language()) { + case DockTextEdit::JSON: + { QString oldData = currentIndex.data(Qt::EditRole).toString(); QString newData; QJsonParseError parseError; - QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonEdit->text().toUtf8(), &parseError); + QJsonDocument jsonDoc = QJsonDocument::fromJson(sciEdit->text().toUtf8(), &parseError); bool proceed; - jsonEdit->clearErrorIndicators(); + sciEdit->clearErrorIndicators(); if (parseError.error != QJsonParseError::NoError) - jsonEdit->setErrorIndicator(parseError.offset-1); + sciEdit->setErrorIndicator(parseError.offset-1); if (!jsonDoc.isNull()) { if (mustIndentAndCompact) // Compact the JSON data before storing newData = QString(jsonDoc.toJson(QJsonDocument::Compact)); else - newData = jsonEdit->text(); + newData = sciEdit->text(); proceed = (oldData != newData); } else { - newData = jsonEdit->text(); + newData = sciEdit->text(); proceed = (oldData != newData && promptInvalidData("JSON", parseError.errorString())); } if (proceed) @@ -472,7 +442,38 @@ void EditDialog::accept() emit recordTextUpdated(currentIndex, newData.toUtf8(), false); } break; + case DockTextEdit::XML: + { + QString oldData = currentIndex.data(Qt::EditRole).toString(); + QString newData; + QDomDocument xmlDoc; + QString errorMsg; + int errorLine, errorColumn; + + bool isValid = xmlDoc.setContent(sciEdit->text().toUtf8(), true, &errorMsg, &errorLine, &errorColumn); + bool proceed; + + sciEdit->clearErrorIndicators(); + if (!isValid) { + sciEdit->setErrorIndicator(errorLine-1, errorColumn-1, errorLine, 0); + newData = sciEdit->text(); + proceed = (oldData != newData && promptInvalidData("XML", errorMsg)); + } else { + if (mustIndentAndCompact) + // Compact the XML data before storing. If indent is -1, no whitespace at all is added. + newData = xmlDoc.toString(-1); + else + newData = sciEdit->text(); + proceed = (oldData != newData); + } + if (proceed) + // The data is different, so commit it back to the database + emit recordTextUpdated(currentIndex, newData.toUtf8(), false); + } + break; + } + break; case HexBuffer: // The data source is the hex widget buffer, thus binary data QByteArray oldData = currentIndex.data(Qt::EditRole).toByteArray(); @@ -483,10 +484,94 @@ void EditDialog::accept() } } +void EditDialog::setDataInBuffer(const QByteArray& data, DataSources source) +{ + dataSource = source; + QString textData; + + // 1) Perform validation and text formatting (if applicable). + // 2) Set the text in the corresponding editor widget (the text widget for the Image case). + // 3) Enable the widget. + switch (dataSource) { + case TextBuffer: + { + // Load the text into the text editor, remove BOM first if there is one + QByteArray dataWithoutBom = data; + removedBom = removeBom(dataWithoutBom); + + textData = QString::fromUtf8(dataWithoutBom.constData(), dataWithoutBom.size()); + ui->editorText->setPlainText(textData); + + // Select all of the text by default (this is useful for simple text data that we usually edit as a whole) + ui->editorText->selectAll(); + ui->editorText->setEnabled(true); + break; + } + case SciBuffer: + switch (sciEdit->language()) { + case DockTextEdit::JSON: + { + QJsonParseError parseError; + QJsonDocument jsonDoc = QJsonDocument::fromJson(QByteArray(data.constData(), data.size()), &parseError); + + if (mustIndentAndCompact && !jsonDoc.isNull()) { + // Load indented JSON into the JSON editor + textData = QString(jsonDoc.toJson(QJsonDocument::Indented)); + } else { + // Fallback case. The data is not yet valid JSON or no auto-formatting applied. + textData = QString::fromUtf8(data.constData(), data.size()); + } + sciEdit->setText(textData); + + sciEdit->clearErrorIndicators(); + if (parseError.error != QJsonParseError::NoError) + sciEdit->setErrorIndicator(parseError.offset-1); + sciEdit->setEnabled(true); + + } + + break; + + case DockTextEdit::XML: + { + QString errorMsg; + int errorLine, errorColumn; + QDomDocument xmlDoc; + bool isValid = xmlDoc.setContent(data, true, &errorMsg, &errorLine, &errorColumn); + + if (mustIndentAndCompact && isValid) { + // Load indented XML into the XML editor + textData = xmlDoc.toString(Settings::getValue("editor", "tabsize").toInt()); + } else { + // Fallback case. The data is not yet valid JSON or no auto-formatting applied. + textData = QString::fromUtf8(data.constData(), data.size()); + } + sciEdit->setText(textData); + + sciEdit->clearErrorIndicators(); + if (!isValid) + // Adjust line and column by one (Scintilla starts at 1 and QDomDocument at 0) + sciEdit->setErrorIndicator(errorLine-1, errorColumn-1, errorLine, 0); + sciEdit->setEnabled(true); + + } + break; + } + break; + case HexBuffer: + hexEdit->setData(data); + hexEdit->setEnabled(true); + + break; + } + +} + // Called when the user manually changes the "Mode" drop down combobox void EditDialog::editModeChanged(int newMode) { - ui->buttonIndent->setEnabled(newMode == JsonEditor); + ui->buttonIndent->setEnabled(newMode == JsonEditor || newMode == XmlEditor); + setStackCurrentIndex(newMode); // * If the dataSource is the text buffer, the data is always text * switch (dataSource) { @@ -496,30 +581,16 @@ void EditDialog::editModeChanged(int newMode) // Nothing to do, as the text is already in the text buffer break; - case JsonEditor: // Switching to the JSON editor + case JsonEditor: // Switching to one of the Scintilla editor modes + case XmlEditor: - // Convert the text widget buffer for the JSON widget - // * If the dataSource is the TextBuffer, the contents could - // be still compacted so we just pass it to our loadData() - // function to handle, for indenting if necessary * - // Switch to the selected editor first, as loadData() relies - // on it being current - ui->editorStack->setCurrentIndex(newMode); - - // Load the data into the appropriate widget, as done by loadData() - loadData(ui->editorText->toPlainText().toUtf8()); - // jsonEdit->setText(ui->editorText->toPlainText().toUtf8()); - - // The JSON widget buffer is now the main data source - dataSource = JsonBuffer; + setDataInBuffer(ui->editorText->toPlainText().toUtf8(), SciBuffer); break; case HexEditor: // Switching to the hex editor // Convert the text widget buffer for the hex widget - hexEdit->setData(removedBom + ui->editorText->toPlainText().toUtf8()); - // The hex widget buffer is now the main data source - dataSource = HexBuffer; + setDataInBuffer(removedBom + ui->editorText->toPlainText().toUtf8(), HexBuffer); break; case ImageViewer: @@ -527,72 +598,76 @@ void EditDialog::editModeChanged(int newMode) ui->editorImage->setPixmap(QPixmap(0,0)); break; } - - // Switch to the selected editor - ui->editorStack->setCurrentIndex(newMode); - return; break; case HexBuffer: // * If the dataSource is the hex buffer, the contents could be anything // so we just pass it to our loadData() function to handle * - // Switch to the selected editor first, as loadData() relies on it + // Note that we have already set the editor, as loadData() relies on it // being current - ui->editorStack->setCurrentIndex(newMode); // Load the data into the appropriate widget, as done by loadData() loadData(hexEdit->data()); break; - case JsonBuffer: + case SciBuffer: switch (newMode) { case TextEditor: // Switching to the text editor // Convert the text widget buffer for the JSON widget - ui->editorText->setText(jsonEdit->text()); - - // The Text widget buffer is now the main data source - dataSource = TextBuffer; + setDataInBuffer(sciEdit->text().toUtf8(), TextBuffer); break; - case JsonEditor: // Switching to the JSON editor - // Nothing to do, as the text is already in the JSON buffer - break; - - case HexEditor: // Switching to the hex editor // Convert the text widget buffer for the hex widget - hexEdit->setData(jsonEdit->text().toUtf8()); - - // The hex widget buffer is now the main data source - dataSource = HexBuffer; + setDataInBuffer(sciEdit->text().toUtf8(), HexBuffer); break; - case ImageViewer: - // Clear any image from the image viewing widget - ui->editorImage->setPixmap(QPixmap(0,0)); + { + // When SVG format, load the image, else clear it. + QByteArray data = sciEdit->text().toUtf8(); + dataType = checkDataType(data); + if (dataType == SVG) { + QImage img; + + if (img.loadFromData(data)) + ui->editorImage->setPixmap(QPixmap::fromImage(img)); + else + // Clear any image from the image viewing widget + ui->editorImage->setPixmap(QPixmap(0,0)); + } + } + break; + + case JsonEditor: // Switching to the JSON editor + case XmlEditor: // Switching to the XML editor + // The text is already in the Sci buffer but we need to perform the necessary formatting. + setDataInBuffer(sciEdit->text().toUtf8(), SciBuffer); + break; } - - // Switch to the selected editor - ui->editorStack->setCurrentIndex(newMode); - } + } } // Called for every keystroke in the text editor (only) void EditDialog::editTextChanged() { - if (dataSource == TextBuffer || dataSource == JsonBuffer) { + if (dataSource == TextBuffer || dataSource == SciBuffer) { // Data has been changed in the text editor, so it can't be a NULL - // any more - textNullSet = false; - + // any more. It hasn't been validated yet, so it cannot be JSON nor XML. + if (dataType == Null) { + dataType = Text; + ui->labelType->setText(tr("Type of data currently in cell: Text / Numeric")); + } // Update the cell info in the bottom left manually. This is because // updateCellInfo() only works with QByteArray's (for now) int dataLength; - if (dataSource == TextBuffer) + switch (dataSource) { + case TextBuffer: dataLength = ui->editorText->toPlainText().length(); - else - dataLength = jsonEdit->text().length(); - ui->labelType->setText(tr("Type of data currently in cell: Text / Numeric")); + break; + case SciBuffer: + dataLength = sciEdit->text().length(); + break; + } ui->labelSize->setText(tr("%n char(s)", "", dataLength)); } } @@ -601,12 +676,11 @@ void EditDialog::setMustIndentAndCompact(bool enable) { mustIndentAndCompact = enable; - // Indent or compact if necessary. If data has changed, reload from the widget, else from the table. - if (ui->buttonApply->isEnabled()) - loadData(jsonEdit->text().toUtf8()); - else + // Indent or compact if necessary. If data has changed (button Apply indicates so), reload from the widget, else from the table. + if (ui->buttonApply->isEnabled()) { + setDataInBuffer(sciEdit->text().toUtf8(), SciBuffer); + } else setCurrentIndex(currentIndex); - } // Determine the type of data in the cell @@ -623,13 +697,14 @@ int EditDialog::checkDataType(const QByteArray& data) // that returned true, do a more sophisticated test of the data. This way we get both, good performance and proper data checking. QBuffer imageBuffer(&cellData); QImageReader readerBuffer(&imageBuffer); + QString imageFormat = readerBuffer.format(); if(readerBuffer.canRead() && !readerBuffer.read().isNull()) - return Image; + return imageFormat == "svg" ? SVG : Image; // Check if it's text only if(isTextOnly(cellData)) { - QJsonDocument jsonDoc = QJsonDocument::fromJson(QString(cellData).toUtf8()); + QJsonDocument jsonDoc = QJsonDocument::fromJson(cellData); if (!jsonDoc.isNull()) return JSON; else @@ -647,7 +722,7 @@ void EditDialog::toggleOverwriteMode() hexEdit->setOverwriteMode(currentMode); ui->editorText->setOverwriteMode(currentMode); - jsonEdit->setOverwriteMode(currentMode); + sciEdit->setOverwriteMode(currentMode); } void EditDialog::setFocus() @@ -658,9 +733,25 @@ void EditDialog::setFocus() // to the dock itself doesn't make much sense as it's just a frame; you'd // have to tab to the editor which is what you most likely want to use. So // in order to save the user from doing this we explicitly set the focus - // to the editor. - ui->editorText->setFocus(); - ui->editorText->selectAll(); + // to the current editor. + int editMode = ui->editorStack->currentIndex(); + + switch (editMode) { + case TextEditor: + ui->editorText->setFocus(); + ui->editorText->selectAll(); + break; + case HexEditor: + hexEdit->setFocus(); + break; + case SciEditor: + sciEdit->setFocus(); + break; + case ImageViewer: + // Nothing to do + break; + } + } // Enables or disables the Apply, Null, & Import buttons in the Edit Cell dock @@ -677,7 +768,7 @@ void EditDialog::setReadOnly(bool ro) ui->editorText->setTextInteractionFlags(textFlags); ui->editorBinary->setEnabled(!ro); // We disable the entire hex editor here instead of setting it to read only because it doesn't have a setReadOnly() method - jsonEdit->setReadOnly(ro); + sciEdit->setReadOnly(ro); } // Update the information labels in the bottom left corner of the dialog @@ -686,7 +777,7 @@ void EditDialog::updateCellInfo(const QByteArray& data) QByteArray cellData = data; // Image data needs special treatment - if (dataType == Image) { + if (dataType == Image || dataType == SVG) { QBuffer imageBuffer(&cellData); QImageReader imageReader(&imageBuffer); @@ -776,6 +867,27 @@ void EditDialog::reloadSettings() hexFont.setPointSize(Settings::getValue("databrowser", "fontsize").toInt()); hexEdit->setFont(hexFont); - jsonEdit->reloadSettings(); - + sciEdit->reloadSettings(); +} + +void EditDialog::setStackCurrentIndex(int editMode) +{ + switch (editMode) { + case TextEditor: + case HexEditor: + case ImageViewer: + // General case: switch to the selected editor + ui->editorStack->setCurrentIndex(editMode); + break; + case JsonEditor: + // Scintilla case: switch to the single Scintilla editor and set language + ui->editorStack->setCurrentIndex(SciEditor); + sciEdit->setLanguage(DockTextEdit::JSON); + break; + case XmlEditor: + // Scintilla case: switch to the single Scintilla editor and set language + ui->editorStack->setCurrentIndex(SciEditor); + sciEdit->setLanguage(DockTextEdit::XML); + break; + } } diff --git a/src/EditDialog.h b/src/EditDialog.h index 490f3eae..40d62794 100644 --- a/src/EditDialog.h +++ b/src/EditDialog.h @@ -4,9 +4,8 @@ #include #include -#include "jsontextedit.h" - class QHexEdit; +class DockTextEdit; namespace Ui { class EditDialog; @@ -50,11 +49,10 @@ signals: private: Ui::EditDialog* ui; QHexEdit* hexEdit; - JsonTextEdit* jsonEdit; + DockTextEdit* sciEdit; QPersistentModelIndex currentIndex; int dataSource; int dataType; - bool textNullSet; bool isReadOnly; bool mustIndentAndCompact; QByteArray removedBom; @@ -62,27 +60,34 @@ private: enum DataSources { TextBuffer, HexBuffer, - JsonBuffer + SciBuffer }; + // SVG is both an Image and an XML document so it is treated separately enum DataTypes { Binary, Image, Null, Text, - JSON + JSON, + SVG }; + // Edit modes and editor stack (this must be aligned with the UI) + // Note that JSON and XML share the Scintilla widget. enum EditModes { TextEditor = 0, HexEditor = 1, - JsonEditor = 2, - ImageViewer = 3 + ImageViewer = 2, + JsonEditor, SciEditor = 3, + XmlEditor = 4 }; int checkDataType(const QByteArray& data); QString humanReadableSize(double byteCount) const; bool promptInvalidData(const QString& dataType, const QString& errorString); + void setDataInBuffer(const QByteArray& data, DataSources source); + void setStackCurrentIndex(int editMode); }; #endif diff --git a/src/EditDialog.ui b/src/EditDialog.ui index 05656913..ed9b2eb8 100644 --- a/src/EditDialog.ui +++ b/src/EditDialog.ui @@ -47,6 +47,11 @@ Binary + + + Image + + JSON @@ -54,7 +59,7 @@ - Image + XML @@ -182,13 +187,6 @@ - - - This editor mode lets you edit JSON data with syntax highlighting, automatic formatting and validation before saving. - -Errors are indicated with a red squiggle underline. - - true @@ -213,6 +211,13 @@ Errors are indicated with a red squiggle underline. + + + This editor mode lets you edit JSON or XML data with syntax highlighting, automatic formatting and validation before saving. + +Errors are indicated with a red squiggle underline. + + @@ -305,22 +310,6 @@ Errors are indicated with a red squiggle underline. - - editorStack - currentChanged(int) - comboMode - setCurrentIndex(int) - - - 185 - 169 - - - 149 - 39 - - - buttonApply clicked() diff --git a/src/ExtendedScintilla.cpp b/src/ExtendedScintilla.cpp index 266bddaf..4ca3de4b 100644 --- a/src/ExtendedScintilla.cpp +++ b/src/ExtendedScintilla.cpp @@ -87,16 +87,16 @@ void ExtendedScintilla::dropEvent(QDropEvent* e) f.close(); } -void ExtendedScintilla::setupSyntaxHighlightingFormat(const QString& settings_name, int style) +void ExtendedScintilla::setupSyntaxHighlightingFormat(QsciLexer *lexer, const QString& settings_name, int style) { - lexer()->setColor(QColor(Settings::getValue("syntaxhighlighter", settings_name + "_colour").toString()), style); + lexer->setColor(QColor(Settings::getValue("syntaxhighlighter", settings_name + "_colour").toString()), style); QFont font(Settings::getValue("editor", "font").toString()); font.setPointSize(Settings::getValue("editor", "fontsize").toInt()); font.setBold(Settings::getValue("syntaxhighlighter", settings_name + "_bold").toBool()); font.setItalic(Settings::getValue("syntaxhighlighter", settings_name + "_italic").toBool()); font.setUnderline(Settings::getValue("syntaxhighlighter", settings_name + "_underline").toBool()); - lexer()->setFont(font, style); + lexer->setFont(font, style); } void ExtendedScintilla::reloadKeywords() @@ -107,23 +107,16 @@ void ExtendedScintilla::reloadKeywords() void ExtendedScintilla::reloadSettings() { - // Enable auto completion if it hasn't been disabled - if(Settings::getValue("editor", "auto_completion").toBool()) - { - setAutoCompletionThreshold(3); - setAutoCompletionCaseSensitivity(false); - setAutoCompletionShowSingle(true); - setAutoCompletionSource(QsciScintilla::AcsAPIs); - } else { - setAutoCompletionThreshold(0); - } - + reloadLexerSettings(lexer()); +} +void ExtendedScintilla::reloadLexerSettings(QsciLexer *lexer) +{ // Set syntax highlighting settings QFont defaultfont(Settings::getValue("editor", "font").toString()); defaultfont.setStyleHint(QFont::TypeWriter); defaultfont.setPointSize(Settings::getValue("editor", "fontsize").toInt()); - lexer()->setDefaultColor(Qt::black); - lexer()->setFont(defaultfont); + lexer->setDefaultColor(Qt::black); + lexer->setFont(defaultfont); // Set font QFont font(Settings::getValue("editor", "font").toString()); @@ -145,7 +138,7 @@ void ExtendedScintilla::reloadSettings() // Set tab width setTabWidth(Settings::getValue("editor", "tabsize").toInt()); - lexer()->refreshProperties(); + lexer->refreshProperties(); // Check if error indicators are enabled and clear them if they just got disabled showErrorIndicators = Settings::getValue("editor", "error_indicators").toBool(); diff --git a/src/ExtendedScintilla.h b/src/ExtendedScintilla.h index 68f56b5d..9a7a1b37 100644 --- a/src/ExtendedScintilla.h +++ b/src/ExtendedScintilla.h @@ -32,7 +32,8 @@ public slots: protected: void dropEvent(QDropEvent* e); - void setupSyntaxHighlightingFormat(const QString& settings_name, int style); + void setupSyntaxHighlightingFormat(QsciLexer *lexer, const QString& settings_name, int style); + void reloadLexerSettings(QsciLexer *lexer); int errorIndicatorNumber; bool showErrorIndicators; diff --git a/src/Settings.cpp b/src/Settings.cpp index 796ba3ac..6aaeb35d 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -175,7 +175,7 @@ QVariant Settings::getDefaultValue(const QString& group, const QString& name) return 10; if(name == "symbol_limit") return 5000; - if(name == "compact_indent") + if(name == "indent_compact") return false; if(name == "null_text") return "NULL"; diff --git a/src/docktextedit.cpp b/src/docktextedit.cpp new file mode 100644 index 00000000..ae913134 --- /dev/null +++ b/src/docktextedit.cpp @@ -0,0 +1,79 @@ +#include "docktextedit.h" +#include "Settings.h" + +QsciLexerJSON* DockTextEdit::jsonLexer = nullptr; +QsciLexerXML* DockTextEdit::xmlLexer = nullptr; + +DockTextEdit::DockTextEdit(QWidget* parent) : + ExtendedScintilla(parent) +{ + // Create lexer objects if not done yet + if(jsonLexer == nullptr) + jsonLexer = new QsciLexerJSON(this); + if(xmlLexer == nullptr) + xmlLexer = new QsciLexerXML(this); + + // Set the JSON lexer as default + setLexer(jsonLexer); + + jsonLexer->setFoldCompact(false); + jsonLexer->setHighlightComments(true); + + // Do rest of initialisation + reloadSettings(); +} + +DockTextEdit::~DockTextEdit() +{ +} + +void DockTextEdit::reloadSettings() +{ + // Set the parent settings for both lexers + reloadLexerSettings(jsonLexer); + reloadLexerSettings(xmlLexer); + + setupSyntaxHighlightingFormat(jsonLexer, "comment", QsciLexerJSON::CommentLine); + setupSyntaxHighlightingFormat(jsonLexer, "comment", QsciLexerJSON::CommentBlock); + setupSyntaxHighlightingFormat(jsonLexer, "keyword", QsciLexerJSON::Keyword); + setupSyntaxHighlightingFormat(jsonLexer, "keyword", QsciLexerJSON::KeywordLD); + setupSyntaxHighlightingFormat(jsonLexer, "string", QsciLexerJSON::String); + setupSyntaxHighlightingFormat(jsonLexer, "table", QsciLexerJSON::Number); + setupSyntaxHighlightingFormat(jsonLexer, "identifier", QsciLexerJSON::Property); + + // The default style for invalid JSON or unclosed strings uses red + // background and white foreground, but the current line has + // precedence, so it is by default white over gray. We change the + // default to something more readable for the current line at + // invalid JSON. + QColor stringColor = QColor(Settings::getValue("syntaxhighlighter", "string_colour").toString()); + jsonLexer->setColor(stringColor, QsciLexerJSON::Error); + jsonLexer->setColor(stringColor, QsciLexerJSON::UnclosedString); + QFont errorFont(Settings::getValue("editor", "font").toString()); + errorFont.setPointSize(Settings::getValue("editor", "fontsize").toInt()); + errorFont.setItalic(true); + jsonLexer->setFont(errorFont, QsciLexerJSON::Error); + jsonLexer->setFont(errorFont, QsciLexerJSON::UnclosedString); + jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::Error); + jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::UnclosedString); + + setupSyntaxHighlightingFormat(xmlLexer, "comment", QsciLexerHTML::HTMLComment); + setupSyntaxHighlightingFormat(xmlLexer, "keyword", QsciLexerHTML::Tag); + setupSyntaxHighlightingFormat(xmlLexer, "string", QsciLexerHTML::HTMLDoubleQuotedString); + setupSyntaxHighlightingFormat(xmlLexer, "string", QsciLexerHTML::HTMLSingleQuotedString); + setupSyntaxHighlightingFormat(xmlLexer, "table", QsciLexerHTML::HTMLNumber); + setupSyntaxHighlightingFormat(xmlLexer, "identifier", QsciLexerHTML::Attribute); +} + +void DockTextEdit::setLanguage(Language lang) +{ + m_language = lang; + switch (lang) { + case JSON: + setLexer(jsonLexer); + break; + case XML: + setLexer(xmlLexer); + break; + } +} diff --git a/src/docktextedit.h b/src/docktextedit.h new file mode 100644 index 00000000..75f66b3e --- /dev/null +++ b/src/docktextedit.h @@ -0,0 +1,40 @@ +#ifndef DOCKTEXTEDIT_H +#define DOCKTEXTEDIT_H + +#include "ExtendedScintilla.h" +#include +#include + +/** + * @brief The DockTextEdit class + * This class is based on our Extended QScintilla widget + */ +class DockTextEdit : public ExtendedScintilla +{ + Q_OBJECT + +public: + explicit DockTextEdit(QWidget *parent = nullptr); + virtual ~DockTextEdit(); + + // Enumeration of supported languages + enum Language + { + JSON, + XML + }; + + void setLanguage(Language lang); + Language language() { return m_language; }; + +public slots: + void reloadSettings(); + +protected: + static QsciLexerJSON* jsonLexer; + static QsciLexerXML* xmlLexer; +private: + Language m_language; +}; + +#endif diff --git a/src/jsontextedit.cpp b/src/jsontextedit.cpp deleted file mode 100644 index 4d0bb1da..00000000 --- a/src/jsontextedit.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "jsontextedit.h" -#include "Settings.h" - -QsciLexerJSON* JsonTextEdit::jsonLexer = nullptr; - -JsonTextEdit::JsonTextEdit(QWidget* parent) : - ExtendedScintilla(parent) -{ - // Create lexer object if not done yet - if(jsonLexer == nullptr) - jsonLexer = new QsciLexerJSON(this); - - // Set the JSON lexer - setLexer(jsonLexer); - - jsonLexer->setFoldCompact(false); - - // Do rest of initialisation - reloadSettings(); -} - -JsonTextEdit::~JsonTextEdit() -{ -} - -void JsonTextEdit::reloadSettings() -{ - ExtendedScintilla::reloadSettings(); - - setupSyntaxHighlightingFormat("comment", QsciLexerJSON::CommentLine); - setupSyntaxHighlightingFormat("comment", QsciLexerJSON::CommentBlock); - setupSyntaxHighlightingFormat("keyword", QsciLexerJSON::Keyword); - setupSyntaxHighlightingFormat("keyword", QsciLexerJSON::KeywordLD); - setupSyntaxHighlightingFormat("string", QsciLexerJSON::String); - setupSyntaxHighlightingFormat("table", QsciLexerJSON::Number); - setupSyntaxHighlightingFormat("identifier", QsciLexerJSON::Property); - jsonLexer->setHighlightComments(true); - - // The default style for invalid JSON or unclosed strings uses red - // background and white foreground, but the current line has - // precedence, so it is by default white over gray. We change the - // default to something more readable for the current line at - // invalid JSON. - QColor stringColor = QColor(Settings::getValue("syntaxhighlighter", "string_colour").toString()); - jsonLexer->setColor(stringColor, QsciLexerJSON::Error); - jsonLexer->setColor(stringColor, QsciLexerJSON::UnclosedString); - QFont errorFont(Settings::getValue("editor", "font").toString()); - errorFont.setPointSize(Settings::getValue("editor", "fontsize").toInt()); - errorFont.setItalic(true); - jsonLexer->setFont(errorFont, QsciLexerJSON::Error); - jsonLexer->setFont(errorFont, QsciLexerJSON::UnclosedString); - jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::Error); - jsonLexer->setPaper(jsonLexer->defaultPaper(QsciLexerJSON::String), QsciLexerJSON::UnclosedString); -} diff --git a/src/jsontextedit.h b/src/jsontextedit.h deleted file mode 100644 index 4c81ebd2..00000000 --- a/src/jsontextedit.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef JSONTEXTEDIT_H -#define JSONTEXTEDIT_H - -#include "ExtendedScintilla.h" -#include - -/** - * @brief The JsonTextEdit class - * This class is based on our Extended QScintilla widget - */ -class JsonTextEdit : public ExtendedScintilla -{ - Q_OBJECT - -public: - explicit JsonTextEdit(QWidget *parent = nullptr); - virtual ~JsonTextEdit(); - - static QsciLexerJSON* jsonLexer; - -public slots: - void reloadSettings(); -}; - -#endif diff --git a/src/sqltextedit.cpp b/src/sqltextedit.cpp index 3f21e0ff..a8302d2a 100644 --- a/src/sqltextedit.cpp +++ b/src/sqltextedit.cpp @@ -30,16 +30,27 @@ SqlTextEdit::~SqlTextEdit() void SqlTextEdit::reloadSettings() { + // Enable auto completion if it hasn't been disabled + if(Settings::getValue("editor", "auto_completion").toBool()) + { + setAutoCompletionThreshold(3); + setAutoCompletionCaseSensitivity(true); + setAutoCompletionShowSingle(true); + setAutoCompletionSource(QsciScintilla::AcsAPIs); + } else { + setAutoCompletionThreshold(0); + } + ExtendedScintilla::reloadSettings(); - setupSyntaxHighlightingFormat("comment", QsciLexerSQL::Comment); - setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentLine); - setupSyntaxHighlightingFormat("comment", QsciLexerSQL::CommentDoc); - setupSyntaxHighlightingFormat("keyword", QsciLexerSQL::Keyword); - setupSyntaxHighlightingFormat("table", QsciLexerSQL::KeywordSet6); - setupSyntaxHighlightingFormat("function", QsciLexerSQL::KeywordSet7); - setupSyntaxHighlightingFormat("string", QsciLexerSQL::DoubleQuotedString); - setupSyntaxHighlightingFormat("string", QsciLexerSQL::SingleQuotedString); - setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::Identifier); - setupSyntaxHighlightingFormat("identifier", QsciLexerSQL::QuotedIdentifier); + setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::Comment); + setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::CommentLine); + setupSyntaxHighlightingFormat(sqlLexer, "comment", QsciLexerSQL::CommentDoc); + setupSyntaxHighlightingFormat(sqlLexer, "keyword", QsciLexerSQL::Keyword); + setupSyntaxHighlightingFormat(sqlLexer, "table", QsciLexerSQL::KeywordSet6); + setupSyntaxHighlightingFormat(sqlLexer, "function", QsciLexerSQL::KeywordSet7); + setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::DoubleQuotedString); + setupSyntaxHighlightingFormat(sqlLexer, "string", QsciLexerSQL::SingleQuotedString); + setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::Identifier); + setupSyntaxHighlightingFormat(sqlLexer, "identifier", QsciLexerSQL::QuotedIdentifier); } diff --git a/src/src.pro b/src/src.pro index 44f6e33b..b6b6f934 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,6 +1,6 @@ TEMPLATE = app -QT += core gui network widgets printsupport concurrent +QT += core gui network widgets printsupport concurrent xml macx: QT += opengl TARGET = sqlitebrowser @@ -59,7 +59,7 @@ HEADERS += \ RemoteDock.h \ RemoteModel.h \ RemotePushDialog.h \ - jsontextedit.h \ + docktextedit.h \ FindReplaceDialog.h \ ExtendedScintilla.h \ FileExtensionManager.h \ @@ -100,7 +100,7 @@ SOURCES += \ RemoteDock.cpp \ RemoteModel.cpp \ RemotePushDialog.cpp \ - jsontextedit.cpp \ + docktextedit.cpp \ FindReplaceDialog.cpp \ ExtendedScintilla.cpp \ FileExtensionManager.cpp \