489
626
int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state
491
628
script_type scriptLanguage = ScriptOfState(state);
629
// If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment
630
if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) {
631
scriptLanguage = eScriptComment;
634
// property fold.html
635
// Folding is turned on or off for HTML and XML files with this option.
636
// The fold option must also be on for folding to occur.
493
637
const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0;
494
639
const bool fold = foldHTML && styler.GetPropertyInt("fold", 0);
641
// property fold.html.preprocessor
642
// Folding is turned on or off for scripts embedded in HTML files with this option.
643
// The default is on.
495
644
const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1);
496
646
const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
648
// property fold.hypertext.comment
649
// Allow folding for comments in scripts embedded in HTML.
650
// The default is off.
651
const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0;
653
// property fold.hypertext.heredoc
654
// Allow folding for heredocs in scripts embedded in HTML.
655
// The default is off.
656
const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0;
658
// property html.tags.case.sensitive
659
// For XML and HTML, setting this property to 1 will make tags match in a case
660
// sensitive way which is the expected behaviour for XML and XHTML.
497
661
const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
663
// property lexer.xml.allow.scripts
664
// Set to 0 to disable scripts in XML.
665
const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0;
667
// property lexer.html.mako
668
// Set to 1 to enable the mako template language.
669
const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0;
671
const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
672
const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true);
673
const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true);
499
675
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
500
676
int levelCurrent = levelPrev;
501
677
int visibleChars = 0;
678
int lineStartVisibleChars = 0;
505
char chPrevNonWhite = ' ';
682
int chPrevNonWhite = ' ';
506
683
// look back to set chPrevNonWhite properly for better regex colouring
507
684
if (scriptLanguage == eScriptJS && startPos > 0) {
508
685
int back = startPos;
754
992
state = SCE_H_SGML_COMMAND; // wait for a pending command
756
994
// fold whole tag (-- when closing the tag)
757
if (foldHTMLPreprocessor)
995
if (foldHTMLPreprocessor || (state == SCE_H_COMMENT))
1000
// handle the end of Mako Python code
1002
((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
1003
(scriptLanguage != eScriptNone) && stateAllowsTermination(state) &&
1004
isMakoBlockEnd(ch, chNext, makoBlockType)) {
1005
if (state == SCE_H_ASPAT) {
1006
aspScript = segIsScriptingIndicator(styler,
1007
styler.GetStartSegment(), i - 1, aspScript);
1009
if (state == SCE_HP_WORD) {
1010
classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
1012
styler.ColourTo(i - 1, StateToPrint);
1014
if (0 != strcmp(makoBlockType, "%") && (0 != strcmp(makoBlockType, "{")) && ch != '>') {
1018
if (0 != strcmp(makoBlockType, "%")) {
1019
styler.ColourTo(i, SCE_H_ASP);
1021
state = beforePreProc;
1022
if (inScriptType == eNonHtmlScriptPreProc)
1023
inScriptType = eNonHtmlScript;
1025
inScriptType = eHtml;
1026
if (foldHTMLPreprocessor && ch != '\n' && ch != '\r') {
1029
scriptLanguage = eScriptNone;
762
1033
// handle the end of a pre-processor = Non-HTML
764
((inScriptType == eNonHtmlPreProc)
765
|| (inScriptType == eNonHtmlScriptPreProc)) && (
766
((scriptLanguage == eScriptPHP) && (ch == '?') && !isPHPStringState(state) && (state != SCE_HPHP_COMMENT)) ||
767
((scriptLanguage != eScriptNone) && !isStringState(state) &&
768
((ch == '%') || (ch == '?')))
769
) && (chNext == '>')) ||
1034
else if ((!isMako && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) &&
1035
(((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) &&
1036
(((ch == '%') || (ch == '?')) && (chNext == '>'))) ||
770
1037
((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) {
771
1038
if (state == SCE_H_ASPAT) {
772
1039
aspScript = segIsScriptingIndicator(styler,
1582
1855
styler.ColourTo(i - 1, StateToPrint);
1583
1856
state = SCE_HPHP_HSTRING_VARIABLE;
1584
1857
} else if (styler.Match(i, phpStringDelimiter)) {
1585
if (strlen(phpStringDelimiter) > 1)
1586
i += strlen(phpStringDelimiter) - 1;
1587
styler.ColourTo(i, StateToPrint);
1588
state = SCE_HPHP_DEFAULT;
1858
if (phpStringDelimiter[0] == '\"') {
1859
styler.ColourTo(i, StateToPrint);
1860
state = SCE_HPHP_DEFAULT;
1861
} else if (isLineEnd(chPrev)) {
1862
const int psdLength = strlen(phpStringDelimiter);
1863
const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
1864
const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
1865
if (isLineEnd(chAfterPsd) ||
1866
(chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
1867
i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
1868
styler.ColourTo(i, StateToPrint);
1869
state = SCE_HPHP_DEFAULT;
1870
if (foldHeredoc) levelCurrent--;
1591
1875
case SCE_HPHP_SIMPLESTRING:
1593
// skip the next char
1595
} else if (ch == '\'') {
1596
styler.ColourTo(i, StateToPrint);
1597
state = SCE_HPHP_DEFAULT;
1876
if (phpStringDelimiter[0] == '\'') {
1878
// skip the next char
1880
} else if (ch == '\'') {
1881
styler.ColourTo(i, StateToPrint);
1882
state = SCE_HPHP_DEFAULT;
1884
} else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) {
1885
const int psdLength = strlen(phpStringDelimiter);
1886
const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
1887
const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
1888
if (isLineEnd(chAfterPsd) ||
1889
(chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
1890
i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
1891
styler.ColourTo(i, StateToPrint);
1892
state = SCE_HPHP_DEFAULT;
1893
if (foldHeredoc) levelCurrent--;
1600
1897
case SCE_HPHP_HSTRING_VARIABLE:
1601
if (!IsPhpWordChar(ch)) {
1602
styler.ColourTo(i - 1, StateToPrint);
1603
i--; // strange but it works
1898
if (!IsPhpWordChar(chNext)) {
1899
styler.ColourTo(i, StateToPrint);
1604
1900
state = SCE_HPHP_HSTRING;
1701
static bool isASPScript(int state) {
1703
(state >= SCE_HJA_START && state <= SCE_HJA_REGEX) ||
1704
(state >= SCE_HBA_START && state <= SCE_HBA_STRINGEOL) ||
1705
(state >= SCE_HPA_DEFAULT && state <= SCE_HPA_IDENTIFIER);
1708
static void ColouriseHBAPiece(StyleContext &sc, WordList *keywordlists[]) {
1709
WordList &keywordsVBS = *keywordlists[2];
1710
if (sc.state == SCE_HBA_WORD) {
1711
if (!IsAWordChar(sc.ch)) {
1713
sc.GetCurrentLowered(s, sizeof(s));
1714
if (keywordsVBS.InList(s)) {
1715
if (strcmp(s, "rem") == 0) {
1716
sc.ChangeState(SCE_HBA_COMMENTLINE);
1718
sc.SetState(SCE_HBA_DEFAULT);
1721
sc.SetState(SCE_HBA_DEFAULT);
1724
sc.ChangeState(SCE_HBA_IDENTIFIER);
1725
sc.SetState(SCE_HBA_DEFAULT);
1728
} else if (sc.state == SCE_HBA_NUMBER) {
1729
if (!IsAWordChar(sc.ch)) {
1730
sc.SetState(SCE_HBA_DEFAULT);
1732
} else if (sc.state == SCE_HBA_STRING) {
1733
if (sc.ch == '\"') {
1734
sc.ForwardSetState(SCE_HBA_DEFAULT);
1735
} else if (sc.ch == '\r' || sc.ch == '\n') {
1736
sc.ChangeState(SCE_HBA_STRINGEOL);
1737
sc.ForwardSetState(SCE_HBA_DEFAULT);
1739
} else if (sc.state == SCE_HBA_COMMENTLINE) {
1740
if (sc.ch == '\r' || sc.ch == '\n') {
1741
sc.SetState(SCE_HBA_DEFAULT);
1745
if (sc.state == SCE_HBA_DEFAULT) {
1746
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
1747
sc.SetState(SCE_HBA_NUMBER);
1748
} else if (IsAWordStart(sc.ch)) {
1749
sc.SetState(SCE_HBA_WORD);
1750
} else if (sc.ch == '\'') {
1751
sc.SetState(SCE_HBA_COMMENTLINE);
1752
} else if (sc.ch == '\"') {
1753
sc.SetState(SCE_HBA_STRING);
1758
static void ColouriseHTMLPiece(StyleContext &sc, WordList *keywordlists[]) {
1759
WordList &keywordsTags = *keywordlists[0];
1760
if (sc.state == SCE_H_COMMENT) {
1761
if (sc.Match("-->")) {
1764
sc.ForwardSetState(SCE_H_DEFAULT);
1766
} else if (sc.state == SCE_H_ENTITY) {
1768
sc.ForwardSetState(SCE_H_DEFAULT);
1769
} else if (sc.ch != '#' && (sc.ch < 0x80) && !isalnum(sc.ch) // Should check that '#' follows '&', but it is unlikely anyway...
1770
&& sc.ch != '.' && sc.ch != '-' && sc.ch != '_' && sc.ch != ':') { // valid in XML
1771
sc.ChangeState(SCE_H_TAGUNKNOWN);
1772
sc.SetState(SCE_H_DEFAULT);
1774
} else if (sc.state == SCE_H_TAGUNKNOWN) {
1775
if (!ishtmlwordchar(static_cast<char>(sc.ch)) && !((sc.ch == '/') && (sc.chPrev == '<')) && sc.ch != '[') {
1777
sc.GetCurrentLowered(s, sizeof(s));
1779
if (keywordsTags.InList(s + 2)) {
1780
sc.ChangeState(SCE_H_TAG);
1783
if (keywordsTags.InList(s + 1)) {
1784
sc.ChangeState(SCE_H_TAG);
1788
sc.ForwardSetState(SCE_H_DEFAULT);
1789
} else if (sc.Match('/', '>')) {
1790
sc.SetState(SCE_H_TAGEND);
1792
sc.ForwardSetState(SCE_H_DEFAULT);
1794
sc.SetState(SCE_H_OTHER);
1797
} else if (sc.state == SCE_H_ATTRIBUTE) {
1798
if (!ishtmlwordchar(static_cast<char>(sc.ch))) {
1800
sc.GetCurrentLowered(s, sizeof(s));
1801
if (!keywordsTags.InList(s)) {
1802
sc.ChangeState(SCE_H_ATTRIBUTEUNKNOWN);
1804
sc.SetState(SCE_H_OTHER);
1806
} else if (sc.state == SCE_H_OTHER) {
1808
sc.SetState(SCE_H_TAG);
1809
sc.ForwardSetState(SCE_H_DEFAULT);
1810
} else if (sc.Match('/', '>')) {
1811
sc.SetState(SCE_H_TAG);
1813
sc.ForwardSetState(SCE_H_DEFAULT);
1814
} else if (sc.chPrev == '=') {
1815
sc.SetState(SCE_H_VALUE);
1817
} else if (sc.state == SCE_H_DOUBLESTRING) {
1818
if (sc.ch == '\"') {
1819
sc.ForwardSetState(SCE_H_OTHER);
1821
} else if (sc.state == SCE_H_SINGLESTRING) {
1822
if (sc.ch == '\'') {
1823
sc.ForwardSetState(SCE_H_OTHER);
1825
} else if (sc.state == SCE_H_NUMBER) {
1826
if (!IsADigit(sc.ch)) {
1827
sc.SetState(SCE_H_OTHER);
1831
if (sc.state == SCE_H_DEFAULT) {
1833
if (sc.Match("<!--"))
1834
sc.SetState(SCE_H_COMMENT);
1836
sc.SetState(SCE_H_TAGUNKNOWN);
1837
} else if (sc.ch == '&') {
1838
sc.SetState(SCE_H_ENTITY);
1840
} else if ((sc.state == SCE_H_OTHER) || (sc.state == SCE_H_VALUE)) {
1841
if (sc.ch == '\"' && sc.chPrev == '=') {
1842
sc.SetState(SCE_H_DOUBLESTRING);
1843
} else if (sc.ch == '\'' && sc.chPrev == '=') {
1844
sc.SetState(SCE_H_SINGLESTRING);
1845
} else if (IsADigit(sc.ch)) {
1846
sc.SetState(SCE_H_NUMBER);
1847
} else if (sc.ch == '>') {
1848
sc.SetState(SCE_H_TAG);
1849
sc.ForwardSetState(SCE_H_DEFAULT);
1850
} else if (ishtmlwordchar(static_cast<char>(sc.ch))) {
1851
sc.SetState(SCE_H_ATTRIBUTE);
1856
static void ColouriseASPPiece(StyleContext &sc, WordList *keywordlists[]) {
1857
// Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1858
if ((sc.state == SCE_H_ASPAT || isASPScript(sc.state)) && sc.Match('%', '>')) {
1859
sc.SetState(SCE_H_ASP);
1861
sc.ForwardSetState(SCE_H_DEFAULT);
1864
// Handle some ASP script
1865
if (sc.state >= SCE_HBA_START && sc.state <= SCE_HBA_STRINGEOL) {
1866
ColouriseHBAPiece(sc, keywordlists);
1867
} else if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
1868
ColouriseHTMLPiece(sc, keywordlists);
1871
// Enter new sc.state
1872
if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
1873
if (sc.Match('<', '%')) {
1874
if (sc.state == SCE_H_TAGUNKNOWN)
1875
sc.ChangeState(SCE_H_ASP);
1877
sc.SetState(SCE_H_ASP);
1881
sc.ForwardSetState(SCE_H_ASPAT);
1886
sc.SetState(SCE_HBA_DEFAULT);
1892
static void ColouriseASPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
1894
// Lexer for HTML requires more lexical states (7 bits worth) than most lexers
1895
StyleContext sc(startPos, length, initStyle, styler, 0x7f);
1896
for (; sc.More(); sc.Forward()) {
1897
ColouriseASPPiece(sc, keywordlists);
1902
static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {
1903
// Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1904
if (sc.state >= SCE_HPHP_DEFAULT && sc.state <= SCE_HPHP_OPERATOR) {
1905
if (!isPHPStringState(sc.state) &&
1906
(sc.state != SCE_HPHP_COMMENT) &&
1907
(sc.Match('?', '>'))) {
1908
sc.SetState(SCE_H_QUESTION);
1910
sc.ForwardSetState(SCE_H_DEFAULT);
1914
if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
1915
ColouriseHTMLPiece(sc, keywordlists);
1918
// Handle some PHP script
1919
if (sc.state == SCE_HPHP_WORD) {
1920
if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
1921
sc.SetState(SCE_HPHP_DEFAULT);
1923
} else if (sc.state == SCE_HPHP_COMMENTLINE) {
1924
if (sc.ch == '\r' || sc.ch == '\n') {
1925
sc.SetState(SCE_HPHP_DEFAULT);
1927
} else if (sc.state == SCE_HPHP_COMMENT) {
1928
if (sc.Match('*', '/')) {
1931
sc.SetState(SCE_HPHP_DEFAULT);
1933
} else if (sc.state == SCE_HPHP_HSTRING) {
1934
if (sc.ch == '\"') {
1935
sc.ForwardSetState(SCE_HPHP_DEFAULT);
1937
} else if (sc.state == SCE_HPHP_SIMPLESTRING) {
1938
if (sc.ch == '\'') {
1939
sc.ForwardSetState(SCE_HPHP_DEFAULT);
1941
} else if (sc.state == SCE_HPHP_VARIABLE) {
1942
if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
1943
sc.SetState(SCE_HPHP_DEFAULT);
1945
} else if (sc.state == SCE_HPHP_OPERATOR) {
1946
sc.SetState(SCE_HPHP_DEFAULT);
1949
// Enter new sc.state
1950
if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
1951
if (sc.Match("<?php")) {
1952
sc.SetState(SCE_H_QUESTION);
1958
sc.SetState(SCE_HPHP_DEFAULT);
1961
if (sc.state == SCE_HPHP_DEFAULT) {
1962
if (IsPhpWordStart(static_cast<char>(sc.ch))) {
1963
sc.SetState(SCE_HPHP_WORD);
1964
} else if (sc.ch == '#') {
1965
sc.SetState(SCE_HPHP_COMMENTLINE);
1966
} else if (sc.Match("<!--")) {
1967
sc.SetState(SCE_HPHP_COMMENTLINE);
1968
} else if (sc.Match('/', '/')) {
1969
sc.SetState(SCE_HPHP_COMMENTLINE);
1970
} else if (sc.Match('/', '*')) {
1971
sc.SetState(SCE_HPHP_COMMENT);
1972
} else if (sc.ch == '\"') {
1973
sc.SetState(SCE_HPHP_HSTRING);
1974
} else if (sc.ch == '\'') {
1975
sc.SetState(SCE_HPHP_SIMPLESTRING);
1976
} else if (sc.ch == '$' && IsPhpWordStart(static_cast<char>(sc.chNext))) {
1977
sc.SetState(SCE_HPHP_VARIABLE);
1978
} else if (isoperator(static_cast<char>(sc.ch))) {
1979
sc.SetState(SCE_HPHP_OPERATOR);
1984
static void ColourisePHPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
1986
// Lexer for HTML requires more lexical states (7 bits worth) than most lexers
1987
StyleContext sc(startPos, length, initStyle, styler, 0x7f);
1988
for (; sc.More(); sc.Forward()) {
1989
ColourisePHPPiece(sc, keywordlists);
2018
static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
2020
// Passing in true because we're lexing XML
2021
ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true);
2024
static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
2026
// Passing in false because we're notlexing XML
2027
ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false);
1994
2030
static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
1996
if(startPos == 0) initStyle = SCE_HPHP_DEFAULT;
1997
ColouriseHyperTextDoc(startPos,length,initStyle,keywordlists,styler);
2033
initStyle = SCE_HPHP_DEFAULT;
2034
ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler);
2000
2037
static const char * const htmlWordListDesc[] = {