1 skipped line |
2 | | 2 | | /** @file LexHTML.cxx |
|
|
|
5 | | // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> | | 5 | | // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> |
6 | | 6 | | // The License.txt file describes the conditions under which this software may be distributed. |
|
|
|
26 skipped lines |
35 | | 35 | | return (ch < 0x80) && (isalnum(ch) || ch == '_'); |
|
|
|
| | 38 | | static inline int MakeLowerCase(int ch) { |
| | 39 | | if (ch < 'A' || ch > 'Z') |
| | 40 | | return ch; |
| | 41 | | else |
| | 42 | | return ch - 'A' + 'a'; |
| | 43 | | } |
| | 44 | | |
38 | | static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) { | | 45 | | static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) { |
39 | | char s[30 + 1]; | | |
40 | | unsigned int i = 0; | | 46 | | size_t i = 0; |
41 | | for (; i < end - start + 1 && i < 30; i++) { | | 47 | | for (; (i < end - start + 1) && (i < len-1); i++) { |
42 | | s[i] = static_cast<char>(tolower(styler[start + i])); | | 48 | | s[i] = static_cast<char>(MakeLowerCase(styler[start + i])); |
|
|
| | 51 | | } |
| | 52 | | |
| | 53 | | static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) { |
| | 54 | | char s[100]; |
| | 55 | | GetTextSegment(styler, start, end, s, sizeof(s)); |
45 | | 56 | | //Platform::DebugPrintf("Scripting indicator [%s]\n", s); |
|
46 | | 57 | | if (strstr(s, "src")) // External script |
|
47 | | 58 | | return eScriptNone; |
|
15 skipped lines |
|
64 | | 75 | | static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, unsigned int end) { |
|
|
66 | | char s[30 + 1]; | | 77 | | char s[100]; |
67 | | unsigned int i = 0; | | |
68 | | for (; i < end - start + 1 && i < 30; i++) { | | 78 | | GetTextSegment(styler, start, end, s, sizeof(s)); |
69 | | s[i] = static_cast<char>(tolower(styler[start + i])); | | |
70 | | } | | |
71 | | s[i] = '\0'; | | |
72 | | 79 | | if (0 == strncmp(s, "php", 3)) { |
|
|
|
108 skipped lines |
183 | | 190 | | if (wordIsNumber) { |
|
184 | | 191 | | chAttr = SCE_H_NUMBER; |
|
|
186 | | char s[30 + 1]; | | 193 | | char s[100]; |
187 | | unsigned int i = 0; | | |
188 | | for (; i < end - start + 1 && i < 30; i++) { | | 194 | | GetTextSegment(styler, start, end, s, sizeof(s)); |
189 | | s[i] = static_cast<char>(tolower(styler[start + i])); | | |
190 | | } | | |
191 | | s[i] = '\0'; | | |
192 | | 195 | | if (keywords.InList(s)) |
|
193 | | 196 | | chAttr = SCE_H_ATTRIBUTE; |
|
|
12 skipped lines |
207 | | 210 | | for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) { |
|
208 | | 211 | | char ch = styler[cPos]; |
|
209 | | 212 | | if ((ch != '<') && (ch != '/')) { |
|
210 | | s[i++] = caseSensitive ? ch : static_cast<char>(tolower(ch)); | | 213 | | s[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch)); |
|
|
|
56 skipped lines |
270 | | 273 | | if (wordIsNumber) |
|
271 | | 274 | | chAttr = SCE_HB_NUMBER; |
|
|
273 | | char s[30 + 1]; | | 276 | | char s[100]; |
274 | | unsigned int i = 0; | | |
275 | | for (; i < end - start + 1 && i < 30; i++) { | | 277 | | GetTextSegment(styler, start, end, s, sizeof(s)); |
276 | | s[i] = static_cast<char>(tolower(styler[start + i])); | | |
277 | | } | | |
278 | | s[i] = '\0'; | | |
279 | | 278 | | if (keywords.InList(s)) { |
|
280 | | 279 | | chAttr = SCE_HB_WORD; |
|
281 | | 280 | | if (strcmp(s, "rem") == 0) |
|
36 skipped lines |
318 | | 317 | | if (wordIsNumber) |
|
319 | | 318 | | chAttr = SCE_HPHP_NUMBER; |
|
|
321 | | char s[100 + 1]; | | 320 | | char s[100]; |
322 | | unsigned int i = 0; | | |
323 | | for (; i < end - start + 1 && i < 100; i++) { | | 321 | | GetTextSegment(styler, start, end, s, sizeof(s)); |
324 | | s[i] = static_cast<char>(tolower(styler[start + i])); | | |
325 | | } | | |
326 | | s[i] = '\0'; | | |
327 | | 322 | | if (keywords.InList(s)) |
|
328 | | 323 | | chAttr = SCE_HPHP_WORD; |
|
|
76 skipped lines |
406 | | 401 | | return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT; |
|
|
|
| | 404 | | static bool IsScriptCommentState(const int state) { |
| | 405 | | return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT || |
| | 406 | | state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE; |
| | 407 | | } |
| | 408 | | |
409 | | 409 | | static bool isLineEnd(char ch) { |
|
410 | | 410 | | return ch == '\r' || ch == '\n'; |
|
|
12 skipped lines |
|
425 | | 425 | | static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler) { |
|
|
| | 427 | | while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t')) |
| | 428 | | i++; |
427 | | 429 | | phpStringDelimiter[0] = '\n'; |
|
428 | | 430 | | for (j = i; j < lengthDoc && styler[j] != '\n' && styler[j] != '\r'; j++) { |
|
429 | | 431 | | if (j - i < phpStringDelimiterSize - 2) |
|
71 skipped lines |
501 | | 503 | | char chPrev = ' '; |
|
|
503 | | 505 | | char chPrevNonWhite = ' '; |
|
| | 506 | | // look back to set chPrevNonWhite properly for better regex colouring |
| | 507 | | if (scriptLanguage == eScriptJS && startPos > 0) { |
| | 508 | | int back = startPos; |
| | 509 | | int style = 0; |
| | 510 | | while (--back) { |
5 skipped lines |
| | 516 | | if (style == SCE_HJ_SYMBOLS) { |
| | 517 | | chPrevNonWhite = styler.SafeGetCharAt(back); |
| | 518 | | } |
| | 519 | | } |
| | 520 | | |
504 | | 521 | | styler.StartSegment(startPos); |
|
505 | | 522 | | const int lengthDoc = startPos + length; |
|
506 | | 523 | | for (int i = startPos; i < lengthDoc; i++) { |
|
507 | | 524 | | const char chPrev2 = chPrev; |
|
|
509 | | if (ch != ' ' && ch != '\t') | | 526 | | if (!isspacechar(ch) && state != SCE_HJ_COMMENT && |
| | 527 | | state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC) |
510 | | 528 | | chPrevNonWhite = ch; |
|
|
512 | | 530 | | char chNext = styler.SafeGetCharAt(i + 1); |
|
92 skipped lines |
605 | | 623 | | case SCE_H_SINGLESTRING: |
|
606 | | 624 | | case SCE_HJ_COMMENT: |
|
607 | | 625 | | case SCE_HJ_COMMENTDOC: |
|
608 | | // SCE_HJ_COMMENTLINE removed as this is a common thing done to hide | | 626 | | //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide |
609 | | // the end of script marker from some JS interpreters. | | 627 | | // the end of script marker from some JS interpreters. |
610 | | //case SCE_HJ_COMMENTLINE: | | |
611 | | 628 | | case SCE_HJ_DOUBLESTRING: |
|
612 | | 629 | | case SCE_HJ_SINGLESTRING: |
|
613 | | 630 | | case SCE_HJ_REGEX: |
|
3 skipped lines |
617 | | 634 | | case SCE_HP_TRIPLEDOUBLE: |
|
|
|
| | 637 | | // check if the closing tag is a script tag |
| | 638 | | if (state == SCE_HJ_COMMENTLINE) { |
| | 639 | | char tag[7]; // room for the <script> tag |
| | 640 | | char chr; // current char |
| | 641 | | int j=0; |
3 skipped lines |
| | 645 | | chr = styler.SafeGetCharAt(i+2+j); |
| | 646 | | } |
| | 647 | | tag[j] = '\0'; |
| | 648 | | if (strcmp(tag, "script") != 0) break; |
| | 649 | | } |
620 | | 650 | | // closing tag of the script (it's a closing HTML tag anyway) |
|
621 | | 651 | | styler.ColourTo(i - 1, StateToPrint); |
|
622 | | 652 | | state = SCE_H_TAGUNKNOWN; |
|
13 skipped lines |
636 | | 666 | | !isPHPStringState(state) && |
|
637 | | 667 | | (state != SCE_HPHP_COMMENT) && |
|
|
639 | | (chNext == '?')) { | | 669 | | (chNext == '?') && |
| | 670 | | !IsScriptCommentState(state) ) { |
640 | | 671 | | scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment() + 2, i + 10, eScriptPHP); |
|
641 | | 672 | | if (scriptLanguage != eScriptPHP && isStringState(state)) continue; |
|
642 | | 673 | | styler.ColourTo(i - 1, StateToPrint); |
|
10 skipped lines |
653 | | 684 | | inScriptType = eNonHtmlScriptPreProc; |
|
|
655 | | 686 | | inScriptType = eNonHtmlPreProc; |
|
656 | | // fold whole script | | 687 | | // Fold whole script, but not if the XML first tag (all XML-like tags in this case) |
657 | | if (foldHTMLPreprocessor){ | | 688 | | if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { |
|
659 | | if (scriptLanguage == eScriptXML) | | |
660 | | levelCurrent--; // no folding of the XML first tag (all XML-like tags in this case) | | |
|
662 | | 691 | | // should be better |
|
663 | | 692 | | ch = styler.SafeGetCharAt(i); |
|
1 skipped line |
|
|
667 | | 696 | | // handle the start of ASP pre-processor = Non-HTML |
|
668 | | else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%')) { | | 697 | | else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { |
669 | | 698 | | styler.ColourTo(i - 1, StateToPrint); |
|
670 | | 699 | | beforePreProc = state; |
|
671 | | 700 | | if (inScriptType == eNonHtmlScript) |
|
34 skipped lines |
706 | | 735 | | ///////////////////////////////////// |
|
707 | | 736 | | // handle the start of SGML language (DTD) |
|
708 | | 737 | | else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) && |
|
709 | | (chPrev == '<') && | | 738 | | (chPrev == '<') && |
710 | | (ch == '!') && | | 739 | | (ch == '!') && |
711 | | (StateToPrint != SCE_H_CDATA) && (!IsCommentState(StateToPrint))) { | | 740 | | (StateToPrint != SCE_H_CDATA) && |
| | 741 | | (!IsCommentState(StateToPrint)) && |
| | 742 | | (!IsScriptCommentState(StateToPrint)) ) { |
712 | | 743 | | beforePreProc = state; |
|
713 | | 744 | | styler.ColourTo(i - 2, StateToPrint); |
|
714 | | 745 | | if ((chNext == '-') && (chNext2 == '-')) { |
|
715 | | 746 | | state = SCE_H_COMMENT; // wait for a pending command |
|
716 | | } | | 747 | | styler.ColourTo(i + 2, SCE_H_COMMENT); |
| | 748 | | i += 2; // follow styling after the -- |
717 | | else if (isWordCdata(i + 1, i + 7, styler)) { | | 749 | | } else if (isWordCdata(i + 1, i + 7, styler)) { |
718 | | 750 | | state = SCE_H_CDATA; |
|
|
720 | | 752 | | styler.ColourTo(i, SCE_H_SGML_DEFAULT); // <! is default |
|
12 skipped lines |
733 | | 765 | | || (inScriptType == eNonHtmlScriptPreProc)) && ( |
|
734 | | 766 | | ((scriptLanguage == eScriptPHP) && (ch == '?') && !isPHPStringState(state) && (state != SCE_HPHP_COMMENT)) || |
|
735 | | 767 | | ((scriptLanguage != eScriptNone) && !isStringState(state) && |
|
736 | | (ch == '%')) | | 768 | | ((ch == '%') || (ch == '?'))) |
737 | | 769 | | ) && (chNext == '>')) || |
|
738 | | 770 | | ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { |
|
739 | | 771 | | if (state == SCE_H_ASPAT) { |
|
38 skipped lines |
778 | | 810 | | inScriptType = eNonHtmlScript; |
|
|
780 | | 812 | | inScriptType = eHtml; |
|
781 | | scriptLanguage = eScriptNone; | | |
782 | | // unfold all scripting languages | | 813 | | // Unfold all scripting languages, except for XML tag |
783 | | if (foldHTMLPreprocessor) | | 814 | | if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { |
|
| | 816 | | } |
| | 817 | | scriptLanguage = eScriptNone; |
|
|
787 | | 820 | | ///////////////////////////////////// |
|
431 skipped lines |
1219 | | 1252 | | if (ch == '/' && chPrev == '*') { |
|
1220 | | 1253 | | styler.ColourTo(i, StateToPrint); |
|
1221 | | 1254 | | state = SCE_HJ_DEFAULT; |
|
| | 1255 | | ch = ' '; |
|
|
1224 | | 1258 | | case SCE_HJ_COMMENTLINE: |
|
1225 | | 1259 | | if (ch == '\r' || ch == '\n') { |
|
1226 | | 1260 | | styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType)); |
|
1227 | | 1261 | | state = SCE_HJ_DEFAULT; |
|
| | 1262 | | ch = ' '; |
|
|
1230 | | 1265 | | case SCE_HJ_DOUBLESTRING: |
|
41 skipped lines |
|
1273 | | 1308 | | case SCE_HJ_REGEX: |
|
1274 | | 1309 | | if (ch == '\r' || ch == '\n' || ch == '/') { |
|
| | 1310 | | if (ch == '/') { |
| | 1311 | | while (isascii(chNext) && islower(chNext)) { // gobble regex flags |
| | 1312 | | i++; |
| | 1313 | | ch = chNext; |
| | 1314 | | chNext = styler.SafeGetCharAt(i + 1); |
| | 1315 | | } |
| | 1316 | | } |
1275 | | 1317 | | styler.ColourTo(i, StateToPrint); |
|
1276 | | 1318 | | state = SCE_HJ_DEFAULT; |
|
1277 | | 1319 | | } else if (ch == '\\') { |
|
218 skipped lines |
|
|
1498 | | 1540 | | case SCE_HPHP_NUMBER: |
|
| | 1541 | | // recognize bases 8,10 or 16 integers OR floating-point numbers |
| | 1542 | | if (!IsADigit(ch) |
| | 1543 | | && strchr(".xXabcdefABCDEF", ch) == NULL |
1499 | | if (!IsADigit(ch) && ch != '.' && ch != 'e' && ch != 'E' && (ch != '-' || (chPrev != 'e' && chPrev != 'E'))) { | | 1544 | | && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) { |
1500 | | 1545 | | styler.ColourTo(i - 1, SCE_HPHP_NUMBER); |
|
1501 | | 1546 | | if (isoperator(ch)) |
|
1502 | | 1547 | | state = SCE_HPHP_OPERATOR; |
|
443 skipped lines |
|
|
|
| | 1994 | | static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], |
| | 1995 | | Accessor &styler) { |
| | 1996 | | if(startPos == 0) initStyle = SCE_HPHP_DEFAULT; |
| | 1997 | | ColouriseHyperTextDoc(startPos,length,initStyle,keywordlists,styler); |
| | 1998 | | } |
| | 1999 | | |
1949 | | 2000 | | static const char * const htmlWordListDesc[] = { |
|
1950 | | 2001 | | "HTML elements and attributes", |
|
1951 | | 2002 | | "JavaScript keywords", |
|
4 skipped lines |
|
|
|
| | 2010 | | static const char * const phpscriptWordListDesc[] = { |
| | 2011 | | "", //Unused |
| | 2012 | | "", //Unused |
| | 2013 | | "", //Unused |
| | 2014 | | "", //Unused |
| | 2015 | | "PHP keywords", |
| | 2016 | | "", //Unused |
| | 2017 | | 0, |
| | 2018 | | }; |
| | 2019 | | |
1959 | | LexerModule lmHTML(SCLEX_HTML, ColouriseHyperTextDoc, "hypertext", 0, htmlWordListDesc); | | 2020 | | LexerModule lmHTML(SCLEX_HTML, ColouriseHyperTextDoc, "hypertext", 0, htmlWordListDesc, 7); |
1960 | | LexerModule lmXML(SCLEX_XML, ColouriseHyperTextDoc, "xml", 0, htmlWordListDesc); | | 2021 | | LexerModule lmXML(SCLEX_XML, ColouriseHyperTextDoc, "xml", 0, htmlWordListDesc, 7); |
| | 2022 | | // SCLEX_ASP and SCLEX_PHP should not be used in new code: use SCLEX_HTML instead. |
1961 | | LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc); | | 2023 | | LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc, 7); |
1962 | | LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc); | | 2024 | | LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc, 7); |
| | 2025 | | LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 7); |
|