aboutsummaryrefslogtreecommitdiffhomepage
path: root/lexers/LexHTML.cxx
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2018-05-23 13:19:22 +1000
committerNeil <nyamatongwe@gmail.com>2018-05-23 13:19:22 +1000
commit5f1862320f98093e1e0372914b1c74b2bf53b8c7 (patch)
tree7a86b060bc7af32813a0d509b55d097dab775569 /lexers/LexHTML.cxx
parent18e8facccc354accf959e4921c5127aac3c3a8ac (diff)
downloadscintilla-mirror-5f1862320f98093e1e0372914b1c74b2bf53b8c7.tar.gz
Change from function to object lexer. Use string and set types to simplify code.
Diffstat (limited to 'lexers/LexHTML.cxx')
-rw-r--r--lexers/LexHTML.cxx519
1 files changed, 307 insertions, 212 deletions
diff --git a/lexers/LexHTML.cxx b/lexers/LexHTML.cxx
index 5551277e5..9567ecaa6 100644
--- a/lexers/LexHTML.cxx
+++ b/lexers/LexHTML.cxx
@@ -11,18 +11,21 @@
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
+#include <string>
+#include <map>
+#include <set>
#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"
+#include "OptionSet.h"
+#include "DefaultLexer.h"
using namespace Scintilla;
@@ -65,20 +68,27 @@ void GetTextSegment(Accessor &styler, Sci_PositionU start, Sci_PositionU end, ch
s[i] = '\0';
}
-const char *GetNextWord(Accessor &styler, Sci_PositionU start, char *s, size_t sLen) {
+std::string GetStringSegment(Accessor &styler, Sci_PositionU start, Sci_PositionU end) {
+ std::string s;
+ Sci_PositionU i = 0;
+ for (; (i < end - start + 1); i++) {
+ s.push_back(MakeLowerCase(styler[start + i]));
+ }
+ return s;
+}
+std::string GetNextWord(Accessor &styler, Sci_PositionU start) {
+ std::string ret;
Sci_PositionU i = 0;
- for (; i < sLen-1; i++) {
- char ch = static_cast<char>(styler.SafeGetCharAt(start + i));
+ for (; i < 200; i++) { // Put an upper limit to bound time taken for unexpected text.
+ const char ch = styler.SafeGetCharAt(start + i);
if ((i == 0) && !IsAWordStart(ch))
break;
if ((i > 0) && !IsAWordChar(ch))
break;
- s[i] = ch;
+ ret.push_back(ch);
}
- s[i] = '\0';
-
- return s;
+ return ret;
}
script_type segIsScriptingIndicator(Accessor &styler, Sci_PositionU start, Sci_PositionU end, script_type prevValue) {
@@ -112,12 +122,10 @@ script_type segIsScriptingIndicator(Accessor &styler, Sci_PositionU start, Sci_P
int PrintScriptingIndicatorOffset(Accessor &styler, Sci_PositionU start, Sci_PositionU end) {
int iResult = 0;
- char s[100];
- GetTextSegment(styler, start, end, s, sizeof(s));
- if (0 == strncmp(s, "php", 3)) {
+ std::string s = GetStringSegment(styler, start, end);
+ if (0 == strncmp(s.c_str(), "php", 3)) {
iResult = 3;
}
-
return iResult;
}
@@ -248,9 +256,8 @@ void classifyAttribHTML(Sci_PositionU start, Sci_PositionU end, WordList &keywor
if (wordIsNumber) {
chAttr = SCE_H_NUMBER;
} else {
- char s[100];
- GetTextSegment(styler, start, end, s, sizeof(s));
- if (keywords.InList(s))
+ std::string s = GetStringSegment(styler, start, end);
+ if (keywords.InList(s.c_str()))
chAttr = SCE_H_ATTRIBUTE;
}
if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords)
@@ -261,45 +268,34 @@ void classifyAttribHTML(Sci_PositionU start, Sci_PositionU end, WordList &keywor
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;
+ bool caseSensitive, bool isXml, bool allowScripts,
+ const std::set<std::string> &nonFoldingTags) {
+ std::string tag;
// Copy after the '<'
- Sci_PositionU i = 1;
- for (Sci_PositionU cPos = start; cPos <= end && i < 30; cPos++) {
- char ch = styler[cPos];
+ for (Sci_PositionU cPos = start; cPos <= end; cPos++) {
+ const char ch = styler[cPos];
if ((ch != '<') && (ch != '/')) {
- withSpace[i++] = caseSensitive ? ch : MakeLowerCase(ch);
+ tag.push_back(caseSensitive ? ch : 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';
-
+ tagDontFold = (!isXml) && (nonFoldingTags.count(tag) > 0);
// No keywords -> all are known
char chAttr = SCE_H_TAGUNKNOWN;
- if (s[0] == '!') {
+ if (!tag.empty() && (tag[0] == '!')) {
chAttr = SCE_H_SGML_DEFAULT;
- } else if (!keywords || keywords.InList(s)) {
+ } else if (!keywords || keywords.InList(tag.c_str())) {
chAttr = SCE_H_TAG;
}
styler.ColourTo(end, chAttr);
if (chAttr == SCE_H_TAG) {
- if (allowScripts && 0 == strcmp(s, "script")) {
+ if (allowScripts && (tag == "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');
+ const char ch = styler.SafeGetCharAt(cPos, '\0');
if (ch == '\0' || ch == '>')
break;
else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') {
@@ -311,7 +307,7 @@ int classifyTagHTML(Sci_PositionU start, Sci_PositionU end,
// do not enter a script state if the tag self-closed
if (!isSelfClose)
chAttr = SCE_H_SCRIPT;
- } else if (!isXml && 0 == strcmp(s, "comment")) {
+ } else if (!isXml && (tag == "comment")) {
chAttr = SCE_H_COMMENT;
}
}
@@ -343,11 +339,10 @@ int classifyWordHTVB(Sci_PositionU start, Sci_PositionU end, WordList &keywords,
if (wordIsNumber) {
chAttr = SCE_HB_NUMBER;
} else {
- char s[100];
- GetTextSegment(styler, start, end, s, sizeof(s));
- if (keywords.InList(s)) {
+ std::string s = GetStringSegment(styler, start, end);
+ if (keywords.InList(s.c_str())) {
chAttr = SCE_HB_WORD;
- if (strcmp(s, "rem") == 0)
+ if (s == "rem")
chAttr = SCE_HB_COMMENTLINE;
}
}
@@ -358,27 +353,25 @@ int classifyWordHTVB(Sci_PositionU start, Sci_PositionU end, WordList &keywords,
return SCE_HB_DEFAULT;
}
-void classifyWordHTPy(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType, bool isMako) {
+void classifyWordHTPy(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler, std::string &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];
+ std::string s;
+ for (Sci_PositionU i = 0; i < end - start + 1 && i < 30; i++) {
+ s.push_back(styler[start + i]);
}
- s[i] = '\0';
char chAttr = SCE_HP_IDENTIFIER;
- if (0 == strcmp(prevWord, "class"))
+ if (prevWord == "class")
chAttr = SCE_HP_CLASSNAME;
- else if (0 == strcmp(prevWord, "def"))
+ else if (prevWord == "def")
chAttr = SCE_HP_DEFNAME;
else if (wordIsNumber)
chAttr = SCE_HP_NUMBER;
- else if (keywords.InList(s))
+ else if (keywords.InList(s.c_str()))
chAttr = SCE_HP_WORD;
- else if (isMako && 0 == strcmp(s, "block"))
+ else if (isMako && (s == "block"))
chAttr = SCE_HP_WORD;
styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
- strcpy(prevWord, s);
+ prevWord = s;
}
// Update the word colour to default or keyword
@@ -389,32 +382,27 @@ void classifyWordHTPHP(Sci_PositionU start, Sci_PositionU end, WordList &keyword
if (wordIsNumber) {
chAttr = SCE_HPHP_NUMBER;
} else {
- char s[100];
- GetTextSegment(styler, start, end, s, sizeof(s));
- if (keywords.InList(s))
+ std::string s = GetStringSegment(styler, start, end);
+ if (keywords.InList(s.c_str()))
chAttr = SCE_HPHP_WORD;
}
styler.ColourTo(end, chAttr);
}
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];
+ std::string s;
+ for (Sci_PositionU i = 0; i < end - start + 1 && i < 30; i++) {
+ s.push_back(styler[start + i]);
}
- s[i] = '\0';
- return keywords.InList(s);
+ return keywords.InList(s.c_str());
}
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];
+ std::string s;
+ for (Sci_PositionU i = 0; i < end - start + 1 && i < 30; i++) {
+ s.push_back(styler[start + i]);
}
- s[i] = '\0';
- return (0 == strcmp(s, "[CDATA["));
+ return s == "[CDATA[";
}
// Return the first state to reach when entering a scripting language
@@ -480,32 +468,32 @@ bool isLineEnd(int ch) {
return ch == '\r' || ch == '\n';
}
-bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) {
- if (strlen(blockType) == 0) {
+bool isMakoBlockEnd(const int ch, const int chNext, const std::string &blockType) {
+ if (blockType.empty()) {
return ((ch == '%') && (chNext == '>'));
- } else if ((0 == strcmp(blockType, "inherit")) ||
- (0 == strcmp(blockType, "namespace")) ||
- (0 == strcmp(blockType, "include")) ||
- (0 == strcmp(blockType, "page"))) {
+ } else if ((blockType == "inherit") ||
+ (blockType == "namespace") ||
+ (blockType == "include") ||
+ (blockType == "page")) {
return ((ch == '/') && (chNext == '>'));
- } else if (0 == strcmp(blockType, "%")) {
+ } else if (blockType == "%") {
if (ch == '/' && isLineEnd(chNext))
return true;
else
return isLineEnd(ch);
- } else if (0 == strcmp(blockType, "{")) {
+ } else if (blockType == "{") {
return ch == '}';
} else {
return (ch == '>');
}
}
-bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) {
- if (strlen(blockType) == 0) {
+bool isDjangoBlockEnd(const int ch, const int chNext, const std::string &blockType) {
+ if (blockType.empty()) {
return false;
- } else if (0 == strcmp(blockType, "%")) {
+ } else if (blockType == "%") {
return ((ch == '%') && (chNext == '}'));
- } else if (0 == strcmp(blockType, "{")) {
+ } else if (blockType == "{") {
return ((ch == '}') && (chNext == '}'));
} else {
return false;
@@ -520,29 +508,27 @@ bool isPHPStringState(int state) {
(state == SCE_HPHP_COMPLEX_VARIABLE);
}
-Sci_Position FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, Sci_Position i, const Sci_Position lengthDoc, Accessor &styler, bool &isSimpleString) {
+Sci_Position FindPhpStringDelimiter(std::string &phpStringDelimiter, 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);
+ phpStringDelimiter.clear();
if (!IsPhpWordStart(ch)) {
if (ch == '\'' && IsPhpWordStart(chNext)) {
i++;
ch = chNext;
isSimpleString = true;
} else {
- phpStringDelimiter[0] = '\0';
return beginning;
}
}
- phpStringDelimiter[0] = ch;
+ phpStringDelimiter.push_back(ch);
i++;
-
for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) {
if (!IsPhpWordChar(styler[j])) {
if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) {
@@ -550,24 +536,37 @@ Sci_Position FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStrin
j++;
break;
} else {
- phpStringDelimiter[0] = '\0';
+ phpStringDelimiter.clear();
return beginning;
}
}
- if (j - i < phpStringDelimiterSize - 2)
- phpStringDelimiter[j-i+1] = styler[j];
- else
- i++;
+ phpStringDelimiter.push_back(styler[j]);
}
if (isSimpleString && !isValidSimpleString) {
- phpStringDelimiter[0] = '\0';
+ phpStringDelimiter.clear();
return beginning;
}
- phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0';
return j - 1;
}
-static const char * const htmlWordListDesc[] = {
+// Options used for LexerHTML
+struct OptionsHTML {
+ int aspDefaultLanguage = eScriptJS;
+ bool caseSensitive = false;
+ bool allowScripts = true;
+ bool isMako = false;
+ bool isDjango = false;
+ bool fold = false;
+ bool foldHTML = false;
+ bool foldHTMLPreprocessor = true;
+ bool foldCompact = true;
+ bool foldComment = false;
+ bool foldHeredoc = false;
+ OptionsHTML() noexcept{
+ }
+};
+
+const char * const htmlWordListDesc[] = {
"HTML elements and attributes",
"JavaScript keywords",
"VBScript keywords",
@@ -577,7 +576,7 @@ static const char * const htmlWordListDesc[] = {
0,
};
-static const char * const phpscriptWordListDesc[] = {
+const char * const phpscriptWordListDesc[] = {
"", //Unused
"", //Unused
"", //Unused
@@ -587,6 +586,50 @@ static const char * const phpscriptWordListDesc[] = {
0,
};
+struct OptionSetHTML : public OptionSet<OptionsHTML> {
+ OptionSetHTML(bool isPHPScript_) {
+
+ DefineProperty("asp.default.language", &OptionsHTML::aspDefaultLanguage,
+ "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.");
+
+ DefineProperty("html.tags.case.sensitive", &OptionsHTML::caseSensitive,
+ "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.");
+
+ DefineProperty("lexer.xml.allow.scripts", &OptionsHTML::allowScripts,
+ "Set to 0 to disable scripts in XML.");
+
+ DefineProperty("lexer.html.mako", &OptionsHTML::isMako,
+ "Set to 1 to enable the mako template language.");
+
+ DefineProperty("lexer.html.django", &OptionsHTML::isDjango,
+ "Set to 1 to enable the django template language.");
+
+ DefineProperty("fold", &OptionsHTML::fold);
+
+ DefineProperty("fold.html", &OptionsHTML::foldHTML,
+ "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.");
+
+ DefineProperty("fold.html.preprocessor", &OptionsHTML::foldHTMLPreprocessor,
+ "Folding is turned on or off for scripts embedded in HTML files with this option. "
+ "The default is on.");
+
+ DefineProperty("fold.compact", &OptionsHTML::foldCompact);
+
+ DefineProperty("fold.hypertext.comment", &OptionsHTML::foldComment,
+ "Allow folding for comments in scripts embedded in HTML. "
+ "The default is off.");
+
+ DefineProperty("fold.hypertext.heredoc", &OptionsHTML::foldHeredoc,
+ "Allow folding for heredocs in scripts embedded in HTML. "
+ "The default is off.");
+
+ DefineWordListSets(isPHPScript_ ? phpscriptWordListDesc : htmlWordListDesc);
+ }
+};
+
LexicalClass lexicalClassesHTML[] = {
// Lexer HTML SCLEX_HTML SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_:
0, "SCE_H_DEFAULT", "default", "Text",
@@ -755,30 +798,137 @@ LexicalClass lexicalClassesXML[] = {
31, "SCE_H_SGML_BLOCK_DEFAULT", "default", "SGML block",
};
+const char *tagsThatDoNotFold[] = {
+ "area",
+ "base",
+ "basefont",
+ "br",
+ "col",
+ "command",
+ "embed",
+ "frame",
+ "hr",
+ "img",
+ "input",
+ "isindex",
+ "keygen",
+ "link",
+ "meta",
+ "param",
+ "source",
+ "track",
+ "wbr"
+};
+
+}
+class LexerHTML : public DefaultLexer {
+ bool isXml;
+ bool isPHPScript;
+ WordList keywords;
+ WordList keywords2;
+ WordList keywords3;
+ WordList keywords4;
+ WordList keywords5;
+ WordList keywords6; // SGML (DTD) keywords
+ OptionsHTML options;
+ OptionSetHTML osHTML;
+ std::set<std::string> nonFoldingTags;
+public:
+ explicit LexerHTML(bool isXml_, bool isPHPScript_) :
+ DefaultLexer(isXml_ ? lexicalClassesHTML : lexicalClassesXML,
+ isXml_ ? std::size(lexicalClassesHTML) : std::size(lexicalClassesXML)),
+ isXml(isXml_),
+ isPHPScript(isPHPScript_),
+ osHTML(isPHPScript_),
+ nonFoldingTags(std::begin(tagsThatDoNotFold), std::end(tagsThatDoNotFold)) {
+ }
+ ~LexerHTML() override {
+ }
+ void SCI_METHOD Release() override {
+ delete this;
+ }
+ const char *SCI_METHOD PropertyNames() override {
+ return osHTML.PropertyNames();
+ }
+ int SCI_METHOD PropertyType(const char *name) override {
+ return osHTML.PropertyType(name);
+ }
+ const char *SCI_METHOD DescribeProperty(const char *name) override {
+ return osHTML.DescribeProperty(name);
+ }
+ Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
+ const char *SCI_METHOD DescribeWordListSets() override {
+ return osHTML.DescribeWordListSets();
+ }
+ Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
+ void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
+ // No Fold as all folding performs in Lex.
+
+ static ILexer4 *LexerFactoryHTML() {
+ return new LexerHTML(false, false);
+ }
+ static ILexer4 *LexerFactoryXML() {
+ return new LexerHTML(true, false);
+ }
+ static ILexer4 *LexerFactoryPHPScript() {
+ return new LexerHTML(false, true);
+ }
+};
+
+Sci_Position SCI_METHOD LexerHTML::PropertySet(const char *key, const char *val) {
+ if (osHTML.PropertySet(&options, key, val)) {
+ return 0;
+ }
+ return -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
+Sci_Position SCI_METHOD LexerHTML::WordListSet(int n, const char *wl) {
+ WordList *wordListN = 0;
+ switch (n) {
+ case 0:
+ wordListN = &keywords;
+ break;
+ case 1:
+ wordListN = &keywords2;
+ break;
+ case 2:
+ wordListN = &keywords3;
+ break;
+ case 3:
+ wordListN = &keywords4;
+ break;
+ case 4:
+ wordListN = &keywords5;
+ break;
+ case 5:
+ wordListN = &keywords6;
+ break;
+ }
+ Sci_Position firstModification = -1;
+ if (wordListN) {
+ WordList wlNew;
+ wlNew.Set(wl);
+ if (*wordListN != wlNew) {
+ wordListN->Set(wl);
+ firstModification = 0;
+ }
+ }
+ return firstModification;
+}
+void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
+ Accessor styler(pAccess, nullptr);
+ if (isPHPScript && (startPos == 0)) {
+ initStyle = SCE_HPHP_DEFAULT;
+ }
styler.StartAt(startPos);
- char prevWord[200];
- prevWord[0] = '\0';
- char phpStringDelimiter[200]; // PHP is not limited in length, we are
- phpStringDelimiter[0] = '\0';
+ std::string prevWord;
+ std::string phpStringDelimiter;
int StateToPrint = initStyle;
int state = stateForPrintState(StateToPrint);
- char makoBlockType[200];
- makoBlockType[0] = '\0';
+ std::string makoBlockType;
int makoComment = 0;
- char djangoBlockType[2];
- djangoBlockType[0] = '\0';
-
+ std::string djangoBlockType;
// 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)))) {
@@ -818,13 +968,10 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
} 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;
+ lineState |= options.aspDefaultLanguage << 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
@@ -838,48 +985,16 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
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 bool foldHTML = options.foldHTML;
+ const bool fold = foldHTML && options.fold;
+ const bool foldHTMLPreprocessor = foldHTML && options.foldHTMLPreprocessor;
+ const bool foldCompact = options.foldCompact;
+ const bool foldComment = fold && options.foldComment;
+ const bool foldHeredoc = fold && options.foldHeredoc;
+ const bool caseSensitive = options.caseSensitive;
+ const bool allowScripts = options.allowScripts;
+ const bool isMako = options.isMako;
+ const bool isDjango = options.isDjango;
const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true);
const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true);
@@ -1036,10 +1151,9 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
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, "%")))) {
+ (!isMako || (makoBlockType != "%"))) {
}
// Ignore everything in mako comment until the line ends
else if (isMako && makoComment) {
@@ -1138,13 +1252,13 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
(ch == '$' && chNext == '{') ||
(ch == '<' && chNext == '/' && chNext2 == '%'))) {
if (ch == '%' || ch == '/')
- StringCopy(makoBlockType, "%");
+ makoBlockType = "%";
else if (ch == '$')
- StringCopy(makoBlockType, "{");
+ makoBlockType = "{";
else if (chNext == '/')
- GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType));
+ makoBlockType = GetNextWord(styler, i+3);
else
- GetNextWord(styler, i+2, makoBlockType, sizeof(makoBlockType));
+ makoBlockType = GetNextWord(styler, i+2);
styler.ColourTo(i - 1, StateToPrint);
beforePreProc = state;
if (inScriptType == eNonHtmlScript)
@@ -1162,11 +1276,10 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
state = SCE_HP_START;
scriptLanguage = eScriptPython;
styler.ColourTo(i, SCE_H_ASP);
-
if (ch != '%' && ch != '$' && ch != '/') {
- i += static_cast<int>(strlen(makoBlockType));
- visibleChars += static_cast<int>(strlen(makoBlockType));
- if (keywords4.InList(makoBlockType))
+ i += makoBlockType.length();
+ visibleChars += static_cast<int>(makoBlockType.length());
+ if (keywords4.InList(makoBlockType.c_str()))
styler.ColourTo(i, SCE_HP_WORD);
else
styler.ColourTo(i, SCE_H_TAGUNKNOWN);
@@ -1209,9 +1322,9 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
// handle the start Django template code
else if (isDjango && scriptLanguage != eScriptPython && scriptLanguage != eScriptComment && (ch == '{' && (chNext == '%' || chNext == '{'))) {
if (chNext == '%')
- StringCopy(djangoBlockType, "%");
+ djangoBlockType = "%";
else
- StringCopy(djangoBlockType, "{");
+ djangoBlockType = "{";
styler.ColourTo(i - 1, StateToPrint);
beforePreProc = state;
if (inScriptType == eNonHtmlScript)
@@ -1310,15 +1423,15 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
} else {
styler.ColourTo(i - 1, StateToPrint);
}
- if (0 != strcmp(makoBlockType, "%") && (0 != strcmp(makoBlockType, "{")) && ch != '>') {
+ if ((makoBlockType != "%") && (makoBlockType != "{") && ch != '>') {
i++;
visibleChars++;
}
- else if (0 == strcmp(makoBlockType, "%") && ch == '/') {
+ else if ((makoBlockType == "%") && ch == '/') {
i++;
visibleChars++;
}
- if (0 != strcmp(makoBlockType, "%") || ch == '/') {
+ if ((makoBlockType != "%") || ch == '/') {
styler.ColourTo(i, SCE_H_ASP);
}
state = beforePreProc;
@@ -1596,7 +1709,7 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
case SCE_H_TAGUNKNOWN:
if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) {
int eClass = classifyTagHTML(styler.GetStartSegment(),
- i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts);
+ i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts, nonFoldingTags);
if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) {
if (!tagClosing) {
inScriptType = eNonHtmlScript;
@@ -2126,17 +2239,17 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
state = SCE_HPHP_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_HPHP_HSTRING;
- StringCopy(phpStringDelimiter, "\"");
+ phpStringDelimiter = "\"";
} else if (styler.Match(i, "<<<")) {
bool isSimpleString = false;
- i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
- if (strlen(phpStringDelimiter)) {
+ i = FindPhpStringDelimiter(phpStringDelimiter, i + 3, lengthDoc, styler, isSimpleString);
+ if (!phpStringDelimiter.empty()) {
state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
if (foldHeredoc) levelCurrent++;
}
} else if (ch == '\'') {
state = SCE_HPHP_SIMPLESTRING;
- StringCopy(phpStringDelimiter, "\'");
+ phpStringDelimiter = "\'";
} else if (ch == '$' && IsPhpWordStart(chNext)) {
state = SCE_HPHP_VARIABLE;
} else if (IsOperator(ch)) {
@@ -2177,7 +2290,7 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
}
break;
case SCE_HPHP_HSTRING:
- if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) {
+ if (ch == '\\' && ((phpStringDelimiter == "\"") || chNext == '$' || chNext == '{')) {
// skip the next char
i++;
} else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{'))
@@ -2187,12 +2300,12 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
} else if (ch == '$' && IsPhpWordStart(chNext)) {
styler.ColourTo(i - 1, StateToPrint);
state = SCE_HPHP_HSTRING_VARIABLE;
- } else if (styler.Match(i, phpStringDelimiter)) {
- if (phpStringDelimiter[0] == '\"') {
+ } else if (styler.Match(i, phpStringDelimiter.c_str())) {
+ if (phpStringDelimiter == "\"") {
styler.ColourTo(i, StateToPrint);
state = SCE_HPHP_DEFAULT;
} else if (isLineEnd(chPrev)) {
- const int psdLength = static_cast<int>(strlen(phpStringDelimiter));
+ const int psdLength = static_cast<int>(phpStringDelimiter.length());
const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
if (isLineEnd(chAfterPsd) ||
@@ -2206,7 +2319,7 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
}
break;
case SCE_HPHP_SIMPLESTRING:
- if (phpStringDelimiter[0] == '\'') {
+ if (phpStringDelimiter == "\'") {
if (ch == '\\') {
// skip the next char
i++;
@@ -2214,8 +2327,8 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
styler.ColourTo(i, StateToPrint);
state = SCE_HPHP_DEFAULT;
}
- } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) {
- const int psdLength = static_cast<int>(strlen(phpStringDelimiter));
+ } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter.c_str())) {
+ const int psdLength = static_cast<int>(phpStringDelimiter.length());
const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
if (isLineEnd(chAfterPsd) ||
@@ -2256,17 +2369,17 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
state = SCE_HPHP_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_HPHP_HSTRING;
- StringCopy(phpStringDelimiter, "\"");
+ phpStringDelimiter = "\"";
} else if (styler.Match(i, "<<<")) {
bool isSimpleString = false;
- i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
- if (strlen(phpStringDelimiter)) {
+ i = FindPhpStringDelimiter(phpStringDelimiter, i + 3, lengthDoc, styler, isSimpleString);
+ if (!phpStringDelimiter.empty()) {
state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
if (foldHeredoc) levelCurrent++;
}
} else if (ch == '\'') {
state = SCE_HPHP_SIMPLESTRING;
- StringCopy(phpStringDelimiter, "\'");
+ phpStringDelimiter = "\'";
} else if (ch == '$' && IsPhpWordStart(chNext)) {
state = SCE_HPHP_VARIABLE;
} else if (IsOperator(ch)) {
@@ -2347,27 +2460,9 @@ static void ColouriseHyperTextDoc(Sci_PositionU startPos, Sci_Position length, i
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
+ styler.Flush();
}
-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);
-}
-
-LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, lexicalClassesHTML, ELEMENTS(lexicalClassesHTML));
-LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, lexicalClassesXML, ELEMENTS(lexicalClassesXML));
-LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc);
+LexerModule lmHTML(SCLEX_HTML, LexerHTML::LexerFactoryHTML, "hypertext", htmlWordListDesc);
+LexerModule lmXML(SCLEX_XML, LexerHTML::LexerFactoryXML, "xml", htmlWordListDesc);
+LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, LexerHTML::LexerFactoryPHPScript, "phpscript", phpscriptWordListDesc);