1 // Scintilla source code edit control
5 // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
18 #include "StyleContext.h"
20 #include "Scintilla.h"
23 #define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START)
24 #define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START)
25 #define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START)
27 enum script_type
{ eScriptNone
= 0, eScriptJS
, eScriptVBS
, eScriptPython
, eScriptPHP
, eScriptXML
, eScriptSGML
, eScriptSGMLblock
};
28 enum script_mode
{ eHtml
= 0, eNonHtmlScript
, eNonHtmlPreProc
, eNonHtmlScriptPreProc
};
30 static inline bool IsAWordChar(const int ch
) {
31 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
34 static inline bool IsAWordStart(const int ch
) {
35 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
38 static inline int MakeLowerCase(int ch
) {
39 if (ch
< 'A' || ch
> 'Z')
42 return ch
- 'A' + 'a';
45 static void GetTextSegment(Accessor
&styler
, unsigned int start
, unsigned int end
, char *s
, size_t len
) {
47 for (; (i
< end
- start
+ 1) && (i
< len
-1); i
++) {
48 s
[i
] = static_cast<char>(MakeLowerCase(styler
[start
+ i
]));
53 static script_type
segIsScriptingIndicator(Accessor
&styler
, unsigned int start
, unsigned int end
, script_type prevValue
) {
55 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
56 //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
57 if (strstr(s
, "src")) // External script
61 if (strstr(s
, "pyth"))
63 if (strstr(s
, "javas"))
65 if (strstr(s
, "jscr"))
75 static int PrintScriptingIndicatorOffset(Accessor
&styler
, unsigned int start
, unsigned int end
) {
78 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
79 if (0 == strncmp(s
, "php", 3)) {
86 static script_type
ScriptOfState(int state
) {
87 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
89 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
91 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
93 } else if ((state
>= SCE_HPHP_DEFAULT
) && (state
<= SCE_HPHP_COMMENTLINE
)) {
95 } else if ((state
>= SCE_H_SGML_DEFAULT
) && (state
< SCE_H_SGML_BLOCK_DEFAULT
)) {
97 } else if (state
== SCE_H_SGML_BLOCK_DEFAULT
) {
98 return eScriptSGMLblock
;
104 static int statePrintForState(int state
, script_mode inScriptType
) {
107 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
108 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_PYTHON
);
109 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
110 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_VBS
);
111 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
112 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_JS
);
114 StateToPrint
= state
;
120 static int stateForPrintState(int StateToPrint
) {
123 if ((StateToPrint
>= SCE_HPA_START
) && (StateToPrint
<= SCE_HPA_IDENTIFIER
)) {
124 state
= StateToPrint
- SCE_HA_PYTHON
;
125 } else if ((StateToPrint
>= SCE_HBA_START
) && (StateToPrint
<= SCE_HBA_STRINGEOL
)) {
126 state
= StateToPrint
- SCE_HA_VBS
;
127 } else if ((StateToPrint
>= SCE_HJA_START
) && (StateToPrint
<= SCE_HJA_REGEX
)) {
128 state
= StateToPrint
- SCE_HA_JS
;
130 state
= StateToPrint
;
136 static inline bool IsNumber(unsigned int start
, Accessor
&styler
) {
137 return IsADigit(styler
[start
]) || (styler
[start
] == '.') ||
138 (styler
[start
] == '-') || (styler
[start
] == '#');
141 static inline bool isStringState(int state
) {
145 case SCE_HJ_DOUBLESTRING
:
146 case SCE_HJ_SINGLESTRING
:
147 case SCE_HJA_DOUBLESTRING
:
148 case SCE_HJA_SINGLESTRING
:
153 case SCE_HPHP_HSTRING
:
154 case SCE_HPHP_SIMPLESTRING
:
155 case SCE_HPHP_HSTRING_VARIABLE
:
156 case SCE_HPHP_COMPLEX_VARIABLE
:
166 // not really well done, since it's only comments that should lex the %> and <%
167 static inline bool isCommentASPState(int state
) {
172 case SCE_HJ_COMMENTLINE
:
173 case SCE_HJ_COMMENTDOC
:
174 case SCE_HB_COMMENTLINE
:
175 case SCE_HP_COMMENTLINE
:
176 case SCE_HPHP_COMMENT
:
177 case SCE_HPHP_COMMENTLINE
:
187 static void classifyAttribHTML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
188 bool wordIsNumber
= IsNumber(start
, styler
);
189 char chAttr
= SCE_H_ATTRIBUTEUNKNOWN
;
191 chAttr
= SCE_H_NUMBER
;
194 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
195 if (keywords
.InList(s
))
196 chAttr
= SCE_H_ATTRIBUTE
;
198 if ((chAttr
== SCE_H_ATTRIBUTEUNKNOWN
) && !keywords
)
199 // No keywords -> all are known
200 chAttr
= SCE_H_ATTRIBUTE
;
201 styler
.ColourTo(end
, chAttr
);
204 static int classifyTagHTML(unsigned int start
, unsigned int end
,
205 WordList
&keywords
, Accessor
&styler
, bool &tagDontFold
,
206 bool caseSensitive
) {
208 // Copy after the '<'
210 for (unsigned int cPos
= start
; cPos
<= end
&& i
< 30; cPos
++) {
211 char ch
= styler
[cPos
];
212 if ((ch
!= '<') && (ch
!= '/')) {
213 s
[i
++] = caseSensitive
? ch
: static_cast<char>(MakeLowerCase(ch
));
217 //The following is only a quick hack, to see if this whole thing would work
218 //we first need the tagname with a trailing space...
222 //...to find it in the list of no-container-tags
223 // (There are many more. We will need a keywordlist in the property file for this)
224 tagDontFold
= (NULL
!= strstr("meta link img area br hr input ",s
));
226 //now we can remove the trailing space
229 bool isScript
= false;
230 char chAttr
= SCE_H_TAGUNKNOWN
;
232 chAttr
= SCE_H_SGML_DEFAULT
;
233 } else if (s
[0] == '/') { // Closing tag
234 if (keywords
.InList(s
+ 1))
237 if (keywords
.InList(s
)) {
239 isScript
= 0 == strcmp(s
, "script");
242 if ((chAttr
== SCE_H_TAGUNKNOWN
) && !keywords
) {
243 // No keywords -> all are known
245 isScript
= 0 == strcmp(s
, "script");
247 styler
.ColourTo(end
, chAttr
);
248 return isScript
? SCE_H_SCRIPT
: chAttr
;
251 static void classifyWordHTJS(unsigned int start
, unsigned int end
,
252 WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
253 char chAttr
= SCE_HJ_WORD
;
254 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.');
256 chAttr
= SCE_HJ_NUMBER
;
260 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
261 s
[i
] = styler
[start
+ i
];
264 if (keywords
.InList(s
))
265 chAttr
= SCE_HJ_KEYWORD
;
267 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
270 static int classifyWordHTVB(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
271 char chAttr
= SCE_HB_IDENTIFIER
;
272 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.');
274 chAttr
= SCE_HB_NUMBER
;
277 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
278 if (keywords
.InList(s
)) {
279 chAttr
= SCE_HB_WORD
;
280 if (strcmp(s
, "rem") == 0)
281 chAttr
= SCE_HB_COMMENTLINE
;
284 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
285 if (chAttr
== SCE_HB_COMMENTLINE
)
286 return SCE_HB_COMMENTLINE
;
288 return SCE_HB_DEFAULT
;
291 static void classifyWordHTPy(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, char *prevWord
, script_mode inScriptType
) {
292 bool wordIsNumber
= IsADigit(styler
[start
]);
295 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
296 s
[i
] = styler
[start
+ i
];
299 char chAttr
= SCE_HP_IDENTIFIER
;
300 if (0 == strcmp(prevWord
, "class"))
301 chAttr
= SCE_HP_CLASSNAME
;
302 else if (0 == strcmp(prevWord
, "def"))
303 chAttr
= SCE_HP_DEFNAME
;
304 else if (wordIsNumber
)
305 chAttr
= SCE_HP_NUMBER
;
306 else if (keywords
.InList(s
))
307 chAttr
= SCE_HP_WORD
;
308 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
312 // Update the word colour to default or keyword
313 // Called when in a PHP word
314 static void classifyWordHTPHP(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
315 char chAttr
= SCE_HPHP_DEFAULT
;
316 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.' && start
+1 <= end
&& IsADigit(styler
[start
+1]));
318 chAttr
= SCE_HPHP_NUMBER
;
321 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
322 if (keywords
.InList(s
))
323 chAttr
= SCE_HPHP_WORD
;
325 styler
.ColourTo(end
, chAttr
);
328 static bool isWordHSGML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
331 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
332 s
[i
] = styler
[start
+ i
];
335 return keywords
.InList(s
);
338 static bool isWordCdata(unsigned int start
, unsigned int end
, Accessor
&styler
) {
341 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
342 s
[i
] = styler
[start
+ i
];
345 return (0 == strcmp(s
, "[CDATA["));
348 // Return the first state to reach when entering a scripting language
349 static int StateForScript(script_type scriptLanguage
) {
351 switch (scriptLanguage
) {
353 Result
= SCE_HB_START
;
356 Result
= SCE_HP_START
;
359 Result
= SCE_HPHP_DEFAULT
;
362 Result
= SCE_H_TAGUNKNOWN
;
365 Result
= SCE_H_SGML_DEFAULT
;
368 Result
= SCE_HJ_START
;
374 static inline bool ishtmlwordchar(char ch
) {
375 return !isascii(ch
) ||
376 (isalnum(ch
) || ch
== '.' || ch
== '-' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#');
379 static inline bool issgmlwordchar(char ch
) {
380 return !isascii(ch
) ||
381 (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#' || ch
== '[');
384 static inline bool IsPhpWordStart(const unsigned char ch
) {
385 return (isascii(ch
) && (isalpha(ch
) || (ch
== '_'))) || (ch
>= 0x7f);
388 static inline bool IsPhpWordChar(char ch
) {
389 return IsADigit(ch
) || IsPhpWordStart(ch
);
392 static bool InTagState(int state
) {
393 return state
== SCE_H_TAG
|| state
== SCE_H_TAGUNKNOWN
||
394 state
== SCE_H_SCRIPT
||
395 state
== SCE_H_ATTRIBUTE
|| state
== SCE_H_ATTRIBUTEUNKNOWN
||
396 state
== SCE_H_NUMBER
|| state
== SCE_H_OTHER
||
397 state
== SCE_H_DOUBLESTRING
|| state
== SCE_H_SINGLESTRING
;
400 static bool IsCommentState(const int state
) {
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
;
409 static bool isLineEnd(char ch
) {
410 return ch
== '\r' || ch
== '\n';
413 static bool isOKBeforeRE(char ch
) {
414 return (ch
== '(') || (ch
== '=') || (ch
== ',');
417 static bool isPHPStringState(int state
) {
419 (state
== SCE_HPHP_HSTRING
) ||
420 (state
== SCE_HPHP_SIMPLESTRING
) ||
421 (state
== SCE_HPHP_HSTRING_VARIABLE
) ||
422 (state
== SCE_HPHP_COMPLEX_VARIABLE
);
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'))
429 phpStringDelimiter
[0] = '\n';
430 for (j
= i
; j
< lengthDoc
&& styler
[j
] != '\n' && styler
[j
] != '\r'; j
++) {
431 if (j
- i
< phpStringDelimiterSize
- 2)
432 phpStringDelimiter
[j
-i
+1] = styler
[j
];
436 phpStringDelimiter
[j
-i
+1] = '\0';
440 static void ColouriseHyperTextDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
442 WordList
&keywords
= *keywordlists
[0];
443 WordList
&keywords2
= *keywordlists
[1];
444 WordList
&keywords3
= *keywordlists
[2];
445 WordList
&keywords4
= *keywordlists
[3];
446 WordList
&keywords5
= *keywordlists
[4];
447 WordList
&keywords6
= *keywordlists
[5]; // SGML (DTD) keywords
449 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
450 styler
.StartAt(startPos
, STYLE_MAX
);
453 char phpStringDelimiter
[200]; // PHP is not limited in length, we are
454 phpStringDelimiter
[0] = '\0';
455 int StateToPrint
= initStyle
;
456 int state
= stateForPrintState(StateToPrint
);
458 // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen
459 if (InTagState(state
)) {
460 while ((startPos
> 0) && (InTagState(styler
.StyleAt(startPos
- 1)))) {
464 state
= SCE_H_DEFAULT
;
466 // String can be heredoc, must find a delimiter first
467 while (startPos
> 0 && isPHPStringState(state
) && state
!= SCE_HPHP_SIMPLESTRING
) {
470 state
= styler
.StyleAt(startPos
);
472 styler
.StartAt(startPos
, STYLE_MAX
);
474 int lineCurrent
= styler
.GetLine(startPos
);
476 if (lineCurrent
> 0) {
477 lineState
= styler
.GetLineState(lineCurrent
);
479 // Default client and ASP scripting language is JavaScript
480 lineState
= eScriptJS
<< 8;
481 lineState
|= styler
.GetPropertyInt("asp.default.language", eScriptJS
) << 4;
483 script_mode inScriptType
= script_mode((lineState
>> 0) & 0x03); // 2 bits of scripting mode
484 bool tagOpened
= (lineState
>> 2) & 0x01; // 1 bit to know if we are in an opened tag
485 bool tagClosing
= (lineState
>> 3) & 0x01; // 1 bit to know if we are in a closing tag
486 bool tagDontFold
= false; //some HTML tags should not be folded
487 script_type aspScript
= script_type((lineState
>> 4) & 0x0F); // 4 bits of script name
488 script_type clientScript
= script_type((lineState
>> 8) & 0x0F); // 4 bits of script name
489 int beforePreProc
= (lineState
>> 12) & 0xFF; // 8 bits of state
491 script_type scriptLanguage
= ScriptOfState(state
);
493 const bool foldHTML
= styler
.GetPropertyInt("fold.html", 0) != 0;
494 const bool fold
= foldHTML
&& styler
.GetPropertyInt("fold", 0);
495 const bool foldHTMLPreprocessor
= foldHTML
&& styler
.GetPropertyInt("fold.html.preprocessor", 1);
496 const bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
497 const bool caseSensitive
= styler
.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
499 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
500 int levelCurrent
= levelPrev
;
501 int visibleChars
= 0;
505 char chPrevNonWhite
= ' ';
506 // look back to set chPrevNonWhite properly for better regex colouring
507 if (scriptLanguage
== eScriptJS
&& startPos
> 0) {
511 style
= styler
.StyleAt(back
);
512 if (style
< SCE_HJ_DEFAULT
|| style
> SCE_HJ_COMMENTDOC
)
513 // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
516 if (style
== SCE_HJ_SYMBOLS
) {
517 chPrevNonWhite
= styler
.SafeGetCharAt(back
);
521 styler
.StartSegment(startPos
);
522 const int lengthDoc
= startPos
+ length
;
523 for (int i
= startPos
; i
< lengthDoc
; i
++) {
524 const char chPrev2
= chPrev
;
526 if (!isspacechar(ch
) && state
!= SCE_HJ_COMMENT
&&
527 state
!= SCE_HJ_COMMENTLINE
&& state
!= SCE_HJ_COMMENTDOC
)
530 char chNext
= styler
.SafeGetCharAt(i
+ 1);
531 const char chNext2
= styler
.SafeGetCharAt(i
+ 2);
533 // Handle DBCS codepages
534 if (styler
.IsLeadByte(ch
)) {
540 if ((!isspacechar(ch
) || !foldCompact
) && fold
)
543 // decide what is the current state to print (depending of the script tag)
544 StateToPrint
= statePrintForState(state
, inScriptType
);
546 // handle script folding
548 switch (scriptLanguage
) {
551 //not currently supported case eScriptVBS:
553 if ((state
!= SCE_HPHP_COMMENT
) && (state
!= SCE_HPHP_COMMENTLINE
) && (state
!= SCE_HJ_COMMENT
) && (state
!= SCE_HJ_COMMENTLINE
) && (state
!= SCE_HJ_COMMENTDOC
) && (!isStringState(state
))) {
554 //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle);
555 //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {
556 if ((ch
== '{') || (ch
== '}')) {
557 levelCurrent
+= (ch
== '{') ? 1 : -1;
562 if (state
!= SCE_HP_COMMENTLINE
) {
563 if ((ch
== ':') && ((chNext
== '\n') || (chNext
== '\r' && chNext2
== '\n'))) {
565 } else if ((ch
== '\n') && !((chNext
== '\r') && (chNext2
== '\n')) && (chNext
!= '\n')) {
566 // check if the number of tabs is lower than the level
567 int Findlevel
= (levelCurrent
& ~SC_FOLDLEVELBASE
) * 8;
568 for (int j
= 0; Findlevel
> 0; j
++) {
569 char chTmp
= styler
.SafeGetCharAt(i
+ j
+ 1);
572 } else if (chTmp
== ' ') {
580 levelCurrent
-= Findlevel
/ 8;
592 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) {
593 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
594 // Avoid triggering two times on Dos/Win
595 // New line -> record any line state onto /next/ line
598 if (visibleChars
== 0)
599 lev
|= SC_FOLDLEVELWHITEFLAG
;
600 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
601 lev
|= SC_FOLDLEVELHEADERFLAG
;
603 styler
.SetLevel(lineCurrent
, lev
);
605 levelPrev
= levelCurrent
;
608 styler
.SetLineState(lineCurrent
,
609 ((inScriptType
& 0x03) << 0) |
610 ((tagOpened
& 0x01) << 2) |
611 ((tagClosing
& 0x01) << 3) |
612 ((aspScript
& 0x0F) << 4) |
613 ((clientScript
& 0x0F) << 8) |
614 ((beforePreProc
& 0xFF) << 12));
617 // generic end of script processing
618 else if ((inScriptType
== eNonHtmlScript
) && (ch
== '<') && (chNext
== '/')) {
619 // Check if it's the end of the script tag (or any other HTML tag)
621 // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
622 case SCE_H_DOUBLESTRING
:
623 case SCE_H_SINGLESTRING
:
625 case SCE_HJ_COMMENTDOC
:
626 //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
627 // the end of script marker from some JS interpreters.
628 case SCE_HJ_DOUBLESTRING
:
629 case SCE_HJ_SINGLESTRING
:
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
642 chr
= styler
.SafeGetCharAt(i
+2);
643 while (j
< 6 && !isspacechar(chr
)) {
644 tag
[j
++] = static_cast<char>(MakeLowerCase(chr
));
645 chr
= styler
.SafeGetCharAt(i
+2+j
);
648 if (strcmp(tag
, "script") != 0) break;
650 // closing tag of the script (it's a closing HTML tag anyway)
651 styler
.ColourTo(i
- 1, StateToPrint
);
652 state
= SCE_H_TAGUNKNOWN
;
653 inScriptType
= eHtml
;
654 scriptLanguage
= eScriptNone
;
655 clientScript
= eScriptJS
;
663 /////////////////////////////////////
664 // handle the start of PHP pre-processor = Non-HTML
665 else if ((state
!= SCE_H_ASPAT
) &&
666 !isPHPStringState(state
) &&
667 (state
!= SCE_HPHP_COMMENT
) &&
670 !IsScriptCommentState(state
) ) {
671 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment() + 2, i
+ 10, eScriptPHP
);
672 if (scriptLanguage
!= eScriptPHP
&& isStringState(state
)) continue;
673 styler
.ColourTo(i
- 1, StateToPrint
);
674 beforePreProc
= state
;
677 i
+= PrintScriptingIndicatorOffset(styler
, styler
.GetStartSegment() + 2, i
+ 10);
678 if (scriptLanguage
== eScriptXML
)
679 styler
.ColourTo(i
, SCE_H_XMLSTART
);
681 styler
.ColourTo(i
, SCE_H_QUESTION
);
682 state
= StateForScript(scriptLanguage
);
683 if (inScriptType
== eNonHtmlScript
)
684 inScriptType
= eNonHtmlScriptPreProc
;
686 inScriptType
= eNonHtmlPreProc
;
687 // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
688 if (foldHTMLPreprocessor
&& (scriptLanguage
!= eScriptXML
)) {
692 ch
= styler
.SafeGetCharAt(i
);
696 // handle the start of ASP pre-processor = Non-HTML
697 else if (!isCommentASPState(state
) && (ch
== '<') && (chNext
== '%') && !isPHPStringState(state
)) {
698 styler
.ColourTo(i
- 1, StateToPrint
);
699 beforePreProc
= state
;
700 if (inScriptType
== eNonHtmlScript
)
701 inScriptType
= eNonHtmlScriptPreProc
;
703 inScriptType
= eNonHtmlPreProc
;
705 if (chNext2
== '@') {
706 i
+= 2; // place as if it was the second next char treated
709 } else if ((chNext2
== '-') && (styler
.SafeGetCharAt(i
+ 3) == '-')) {
710 styler
.ColourTo(i
+ 3, SCE_H_ASP
);
711 state
= SCE_H_XCCOMMENT
;
712 scriptLanguage
= eScriptVBS
;
715 if (chNext2
== '=') {
716 i
+= 2; // place as if it was the second next char treated
719 i
++; // place as if it was the next char treated
723 state
= StateForScript(aspScript
);
725 scriptLanguage
= eScriptVBS
;
726 styler
.ColourTo(i
, SCE_H_ASP
);
728 if (foldHTMLPreprocessor
)
731 ch
= styler
.SafeGetCharAt(i
);
735 /////////////////////////////////////
736 // handle the start of SGML language (DTD)
737 else if (((scriptLanguage
== eScriptNone
) || (scriptLanguage
== eScriptXML
)) &&
740 (StateToPrint
!= SCE_H_CDATA
) &&
741 (!IsCommentState(StateToPrint
)) &&
742 (!IsScriptCommentState(StateToPrint
)) ) {
743 beforePreProc
= state
;
744 styler
.ColourTo(i
- 2, StateToPrint
);
745 if ((chNext
== '-') && (chNext2
== '-')) {
746 state
= SCE_H_COMMENT
; // wait for a pending command
747 styler
.ColourTo(i
+ 2, SCE_H_COMMENT
);
748 i
+= 2; // follow styling after the --
749 } else if (isWordCdata(i
+ 1, i
+ 7, styler
)) {
752 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
); // <! is default
753 scriptLanguage
= eScriptSGML
;
754 state
= SCE_H_SGML_COMMAND
; // wait for a pending command
756 // fold whole tag (-- when closing the tag)
757 if (foldHTMLPreprocessor
)
762 // 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
== '>')) ||
770 ((scriptLanguage
== eScriptSGML
) && (ch
== '>') && (state
!= SCE_H_SGML_COMMENT
))) {
771 if (state
== SCE_H_ASPAT
) {
772 aspScript
= segIsScriptingIndicator(styler
,
773 styler
.GetStartSegment(), i
- 1, aspScript
);
775 // Bounce out of any ASP mode
778 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
781 classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
784 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
787 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
789 case SCE_H_XCCOMMENT
:
790 styler
.ColourTo(i
- 1, state
);
793 styler
.ColourTo(i
- 1, StateToPrint
);
796 if (scriptLanguage
!= eScriptSGML
) {
801 styler
.ColourTo(i
, SCE_H_ASP
);
802 else if (scriptLanguage
== eScriptXML
)
803 styler
.ColourTo(i
, SCE_H_XMLEND
);
804 else if (scriptLanguage
== eScriptSGML
)
805 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
807 styler
.ColourTo(i
, SCE_H_QUESTION
);
808 state
= beforePreProc
;
809 if (inScriptType
== eNonHtmlScriptPreProc
)
810 inScriptType
= eNonHtmlScript
;
812 inScriptType
= eHtml
;
813 // Unfold all scripting languages, except for XML tag
814 if (foldHTMLPreprocessor
&& (scriptLanguage
!= eScriptXML
)) {
817 scriptLanguage
= eScriptNone
;
820 /////////////////////////////////////
825 // in HTML, fold on tag open and unfold on tag close
827 tagClosing
= (chNext
== '/');
828 styler
.ColourTo(i
- 1, StateToPrint
);
830 state
= SCE_H_TAGUNKNOWN
;
831 } else if (ch
== '&') {
832 styler
.ColourTo(i
- 1, SCE_H_DEFAULT
);
833 state
= SCE_H_ENTITY
;
836 case SCE_H_SGML_DEFAULT
:
837 case SCE_H_SGML_BLOCK_DEFAULT
:
838 // if (scriptLanguage == eScriptSGMLblock)
839 // StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
842 styler
.ColourTo(i
- 1, StateToPrint
);
843 state
= SCE_H_SGML_DOUBLESTRING
;
844 } else if (ch
== '\'') {
845 styler
.ColourTo(i
- 1, StateToPrint
);
846 state
= SCE_H_SGML_SIMPLESTRING
;
847 } else if ((ch
== '-') && (chPrev
== '-')) {
848 styler
.ColourTo(i
- 2, StateToPrint
);
849 state
= SCE_H_SGML_COMMENT
;
850 } else if (isascii(ch
) && isalpha(ch
) && (chPrev
== '%')) {
851 styler
.ColourTo(i
- 2, StateToPrint
);
852 state
= SCE_H_SGML_ENTITY
;
853 } else if (ch
== '#') {
854 styler
.ColourTo(i
- 1, StateToPrint
);
855 state
= SCE_H_SGML_SPECIAL
;
856 } else if (ch
== '[') {
857 styler
.ColourTo(i
- 1, StateToPrint
);
858 scriptLanguage
= eScriptSGMLblock
;
859 state
= SCE_H_SGML_BLOCK_DEFAULT
;
860 } else if (ch
== ']') {
861 if (scriptLanguage
== eScriptSGMLblock
) {
862 styler
.ColourTo(i
, StateToPrint
);
863 scriptLanguage
= eScriptSGML
;
865 styler
.ColourTo(i
- 1, StateToPrint
);
866 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
868 state
= SCE_H_SGML_DEFAULT
;
869 } else if (scriptLanguage
== eScriptSGMLblock
) {
870 if ((ch
== '!') && (chPrev
== '<')) {
871 styler
.ColourTo(i
- 2, StateToPrint
);
872 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
873 state
= SCE_H_SGML_COMMAND
;
874 } else if (ch
== '>') {
875 styler
.ColourTo(i
- 1, StateToPrint
);
876 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
880 case SCE_H_SGML_COMMAND
:
881 if ((ch
== '-') && (chPrev
== '-')) {
882 styler
.ColourTo(i
- 2, StateToPrint
);
883 state
= SCE_H_SGML_COMMENT
;
884 } else if (!issgmlwordchar(ch
)) {
885 if (isWordHSGML(styler
.GetStartSegment(), i
- 1, keywords6
, styler
)) {
886 styler
.ColourTo(i
- 1, StateToPrint
);
887 state
= SCE_H_SGML_1ST_PARAM
;
889 state
= SCE_H_SGML_ERROR
;
893 case SCE_H_SGML_1ST_PARAM
:
894 // wait for the beginning of the word
895 if ((ch
== '-') && (chPrev
== '-')) {
896 if (scriptLanguage
== eScriptSGMLblock
) {
897 styler
.ColourTo(i
- 2, SCE_H_SGML_BLOCK_DEFAULT
);
899 styler
.ColourTo(i
- 2, SCE_H_SGML_DEFAULT
);
901 state
= SCE_H_SGML_1ST_PARAM_COMMENT
;
902 } else if (issgmlwordchar(ch
)) {
903 if (scriptLanguage
== eScriptSGMLblock
) {
904 styler
.ColourTo(i
- 1, SCE_H_SGML_BLOCK_DEFAULT
);
906 styler
.ColourTo(i
- 1, SCE_H_SGML_DEFAULT
);
908 // find the length of the word
910 while (ishtmlwordchar(styler
.SafeGetCharAt(i
+ size
)))
912 styler
.ColourTo(i
+ size
- 1, StateToPrint
);
914 visibleChars
+= size
- 1;
915 ch
= styler
.SafeGetCharAt(i
);
916 if (scriptLanguage
== eScriptSGMLblock
) {
917 state
= SCE_H_SGML_BLOCK_DEFAULT
;
919 state
= SCE_H_SGML_DEFAULT
;
924 case SCE_H_SGML_ERROR
:
925 if ((ch
== '-') && (chPrev
== '-')) {
926 styler
.ColourTo(i
- 2, StateToPrint
);
927 state
= SCE_H_SGML_COMMENT
;
929 case SCE_H_SGML_DOUBLESTRING
:
931 styler
.ColourTo(i
, StateToPrint
);
932 state
= SCE_H_SGML_DEFAULT
;
935 case SCE_H_SGML_SIMPLESTRING
:
937 styler
.ColourTo(i
, StateToPrint
);
938 state
= SCE_H_SGML_DEFAULT
;
941 case SCE_H_SGML_COMMENT
:
942 if ((ch
== '-') && (chPrev
== '-')) {
943 styler
.ColourTo(i
, StateToPrint
);
944 state
= SCE_H_SGML_DEFAULT
;
948 if ((chPrev2
== ']') && (chPrev
== ']') && (ch
== '>')) {
949 styler
.ColourTo(i
, StateToPrint
);
950 state
= SCE_H_DEFAULT
;
955 if ((chPrev2
== '-') && (chPrev
== '-') && (ch
== '>')) {
956 styler
.ColourTo(i
, StateToPrint
);
957 state
= SCE_H_DEFAULT
;
961 case SCE_H_SGML_1ST_PARAM_COMMENT
:
962 if ((ch
== '-') && (chPrev
== '-')) {
963 styler
.ColourTo(i
, SCE_H_SGML_COMMENT
);
964 state
= SCE_H_SGML_1ST_PARAM
;
967 case SCE_H_SGML_SPECIAL
:
968 if (!(isascii(ch
) && isupper(ch
))) {
969 styler
.ColourTo(i
- 1, StateToPrint
);
971 state
= SCE_H_SGML_ERROR
;
973 state
= SCE_H_SGML_DEFAULT
;
977 case SCE_H_SGML_ENTITY
:
979 styler
.ColourTo(i
, StateToPrint
);
980 state
= SCE_H_SGML_DEFAULT
;
981 } else if (!(isascii(ch
) && isalnum(ch
)) && ch
!= '-' && ch
!= '.') {
982 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
983 state
= SCE_H_SGML_DEFAULT
;
988 styler
.ColourTo(i
, StateToPrint
);
989 state
= SCE_H_DEFAULT
;
991 if (ch
!= '#' && !(isascii(ch
) && isalnum(ch
)) // Should check that '#' follows '&', but it is unlikely anyway...
992 && ch
!= '.' && ch
!= '-' && ch
!= '_' && ch
!= ':') { // valid in XML
993 styler
.ColourTo(i
, SCE_H_TAGUNKNOWN
);
994 state
= SCE_H_DEFAULT
;
997 case SCE_H_TAGUNKNOWN
:
998 if (!ishtmlwordchar(ch
) && !((ch
== '/') && (chPrev
== '<')) && ch
!= '[') {
999 int eClass
= classifyTagHTML(styler
.GetStartSegment(),
1000 i
- 1, keywords
, styler
, tagDontFold
, caseSensitive
);
1001 if (eClass
== SCE_H_SCRIPT
) {
1003 inScriptType
= eNonHtmlScript
;
1004 scriptLanguage
= clientScript
;
1007 scriptLanguage
= eScriptNone
;
1012 styler
.ColourTo(i
, eClass
);
1013 if (inScriptType
== eNonHtmlScript
) {
1014 state
= StateForScript(scriptLanguage
);
1016 state
= SCE_H_DEFAULT
;
1027 } else if (ch
== '/' && chNext
== '>') {
1028 if (eClass
== SCE_H_TAGUNKNOWN
) {
1029 styler
.ColourTo(i
+ 1, SCE_H_TAGUNKNOWN
);
1031 styler
.ColourTo(i
- 1, StateToPrint
);
1032 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1036 state
= SCE_H_DEFAULT
;
1039 if (eClass
!= SCE_H_TAGUNKNOWN
) {
1040 if (eClass
== SCE_H_SGML_DEFAULT
) {
1041 state
= SCE_H_SGML_DEFAULT
;
1043 state
= SCE_H_OTHER
;
1049 case SCE_H_ATTRIBUTE
:
1050 if (!ishtmlwordchar(ch
) && ch
!= '/' && ch
!= '-') {
1051 if (inScriptType
== eNonHtmlScript
) {
1052 int scriptLanguagePrev
= scriptLanguage
;
1053 clientScript
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
- 1, scriptLanguage
);
1054 scriptLanguage
= clientScript
;
1055 if ((scriptLanguagePrev
!= scriptLanguage
) && (scriptLanguage
== eScriptNone
))
1056 inScriptType
= eHtml
;
1058 classifyAttribHTML(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
1060 styler
.ColourTo(i
, SCE_H_TAG
);
1061 if (inScriptType
== eNonHtmlScript
) {
1062 state
= StateForScript(scriptLanguage
);
1064 state
= SCE_H_DEFAULT
;
1075 } else if (ch
== '=') {
1076 styler
.ColourTo(i
, SCE_H_OTHER
);
1077 state
= SCE_H_VALUE
;
1079 state
= SCE_H_OTHER
;
1085 styler
.ColourTo(i
- 1, StateToPrint
);
1086 styler
.ColourTo(i
, SCE_H_TAG
);
1087 if (inScriptType
== eNonHtmlScript
) {
1088 state
= StateForScript(scriptLanguage
);
1090 state
= SCE_H_DEFAULT
;
1101 } else if (ch
== '\"') {
1102 styler
.ColourTo(i
- 1, StateToPrint
);
1103 state
= SCE_H_DOUBLESTRING
;
1104 } else if (ch
== '\'') {
1105 styler
.ColourTo(i
- 1, StateToPrint
);
1106 state
= SCE_H_SINGLESTRING
;
1107 } else if (ch
== '=') {
1108 styler
.ColourTo(i
, StateToPrint
);
1109 state
= SCE_H_VALUE
;
1110 } else if (ch
== '/' && chNext
== '>') {
1111 styler
.ColourTo(i
- 1, StateToPrint
);
1112 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1115 state
= SCE_H_DEFAULT
;
1117 } else if (ch
== '?' && chNext
== '>') {
1118 styler
.ColourTo(i
- 1, StateToPrint
);
1119 styler
.ColourTo(i
+ 1, SCE_H_XMLEND
);
1122 state
= SCE_H_DEFAULT
;
1123 } else if (ishtmlwordchar(ch
)) {
1124 styler
.ColourTo(i
- 1, StateToPrint
);
1125 state
= SCE_H_ATTRIBUTE
;
1128 case SCE_H_DOUBLESTRING
:
1130 if (inScriptType
== eNonHtmlScript
) {
1131 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1133 styler
.ColourTo(i
, SCE_H_DOUBLESTRING
);
1134 state
= SCE_H_OTHER
;
1137 case SCE_H_SINGLESTRING
:
1139 if (inScriptType
== eNonHtmlScript
) {
1140 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1142 styler
.ColourTo(i
, SCE_H_SINGLESTRING
);
1143 state
= SCE_H_OTHER
;
1147 if (!ishtmlwordchar(ch
)) {
1148 if (ch
== '\"' && chPrev
== '=') {
1149 // Should really test for being first character
1150 state
= SCE_H_DOUBLESTRING
;
1151 } else if (ch
== '\'' && chPrev
== '=') {
1152 state
= SCE_H_SINGLESTRING
;
1154 if (IsNumber(styler
.GetStartSegment(), styler
)) {
1155 styler
.ColourTo(i
- 1, SCE_H_NUMBER
);
1157 styler
.ColourTo(i
- 1, StateToPrint
);
1160 styler
.ColourTo(i
, SCE_H_TAG
);
1161 if (inScriptType
== eNonHtmlScript
) {
1162 state
= StateForScript(scriptLanguage
);
1164 state
= SCE_H_DEFAULT
;
1176 state
= SCE_H_OTHER
;
1181 case SCE_HJ_DEFAULT
:
1183 case SCE_HJ_SYMBOLS
:
1184 if (iswordstart(ch
)) {
1185 styler
.ColourTo(i
- 1, StateToPrint
);
1186 state
= SCE_HJ_WORD
;
1187 } else if (ch
== '/' && chNext
== '*') {
1188 styler
.ColourTo(i
- 1, StateToPrint
);
1190 state
= SCE_HJ_COMMENTDOC
;
1192 state
= SCE_HJ_COMMENT
;
1193 } else if (ch
== '/' && chNext
== '/') {
1194 styler
.ColourTo(i
- 1, StateToPrint
);
1195 state
= SCE_HJ_COMMENTLINE
;
1196 } else if (ch
== '/' && isOKBeforeRE(chPrevNonWhite
)) {
1197 styler
.ColourTo(i
- 1, StateToPrint
);
1198 state
= SCE_HJ_REGEX
;
1199 } else if (ch
== '\"') {
1200 styler
.ColourTo(i
- 1, StateToPrint
);
1201 state
= SCE_HJ_DOUBLESTRING
;
1202 } else if (ch
== '\'') {
1203 styler
.ColourTo(i
- 1, StateToPrint
);
1204 state
= SCE_HJ_SINGLESTRING
;
1205 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1206 styler
.SafeGetCharAt(i
+ 3) == '-') {
1207 styler
.ColourTo(i
- 1, StateToPrint
);
1208 state
= SCE_HJ_COMMENTLINE
;
1209 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1210 styler
.ColourTo(i
- 1, StateToPrint
);
1211 state
= SCE_HJ_COMMENTLINE
;
1213 } else if (isoperator(ch
)) {
1214 styler
.ColourTo(i
- 1, StateToPrint
);
1215 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1216 state
= SCE_HJ_DEFAULT
;
1217 } else if ((ch
== ' ') || (ch
== '\t')) {
1218 if (state
== SCE_HJ_START
) {
1219 styler
.ColourTo(i
- 1, StateToPrint
);
1220 state
= SCE_HJ_DEFAULT
;
1225 if (!iswordchar(ch
)) {
1226 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
1227 //styler.ColourTo(i - 1, eHTJSKeyword);
1228 state
= SCE_HJ_DEFAULT
;
1229 if (ch
== '/' && chNext
== '*') {
1231 state
= SCE_HJ_COMMENTDOC
;
1233 state
= SCE_HJ_COMMENT
;
1234 } else if (ch
== '/' && chNext
== '/') {
1235 state
= SCE_HJ_COMMENTLINE
;
1236 } else if (ch
== '\"') {
1237 state
= SCE_HJ_DOUBLESTRING
;
1238 } else if (ch
== '\'') {
1239 state
= SCE_HJ_SINGLESTRING
;
1240 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1241 styler
.ColourTo(i
- 1, StateToPrint
);
1242 state
= SCE_HJ_COMMENTLINE
;
1244 } else if (isoperator(ch
)) {
1245 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1246 state
= SCE_HJ_DEFAULT
;
1250 case SCE_HJ_COMMENT
:
1251 case SCE_HJ_COMMENTDOC
:
1252 if (ch
== '/' && chPrev
== '*') {
1253 styler
.ColourTo(i
, StateToPrint
);
1254 state
= SCE_HJ_DEFAULT
;
1258 case SCE_HJ_COMMENTLINE
:
1259 if (ch
== '\r' || ch
== '\n') {
1260 styler
.ColourTo(i
- 1, statePrintForState(SCE_HJ_COMMENTLINE
, inScriptType
));
1261 state
= SCE_HJ_DEFAULT
;
1265 case SCE_HJ_DOUBLESTRING
:
1267 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1270 } else if (ch
== '\"') {
1271 styler
.ColourTo(i
, statePrintForState(SCE_HJ_DOUBLESTRING
, inScriptType
));
1272 state
= SCE_HJ_DEFAULT
;
1273 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1274 styler
.ColourTo(i
- 1, StateToPrint
);
1275 state
= SCE_HJ_COMMENTLINE
;
1277 } else if (isLineEnd(ch
)) {
1278 styler
.ColourTo(i
- 1, StateToPrint
);
1279 state
= SCE_HJ_STRINGEOL
;
1282 case SCE_HJ_SINGLESTRING
:
1284 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1287 } else if (ch
== '\'') {
1288 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SINGLESTRING
, inScriptType
));
1289 state
= SCE_HJ_DEFAULT
;
1290 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1291 styler
.ColourTo(i
- 1, StateToPrint
);
1292 state
= SCE_HJ_COMMENTLINE
;
1294 } else if (isLineEnd(ch
)) {
1295 styler
.ColourTo(i
- 1, StateToPrint
);
1296 state
= SCE_HJ_STRINGEOL
;
1299 case SCE_HJ_STRINGEOL
:
1300 if (!isLineEnd(ch
)) {
1301 styler
.ColourTo(i
- 1, StateToPrint
);
1302 state
= SCE_HJ_DEFAULT
;
1303 } else if (!isLineEnd(chNext
)) {
1304 styler
.ColourTo(i
, StateToPrint
);
1305 state
= SCE_HJ_DEFAULT
;
1309 if (ch
== '\r' || ch
== '\n' || ch
== '/') {
1311 while (isascii(chNext
) && islower(chNext
)) { // gobble regex flags
1314 chNext
= styler
.SafeGetCharAt(i
+ 1);
1317 styler
.ColourTo(i
, StateToPrint
);
1318 state
= SCE_HJ_DEFAULT
;
1319 } else if (ch
== '\\') {
1320 // Gobble up the quoted character
1321 if (chNext
== '\\' || chNext
== '/') {
1324 chNext
= styler
.SafeGetCharAt(i
+ 1);
1328 case SCE_HB_DEFAULT
:
1330 if (iswordstart(ch
)) {
1331 styler
.ColourTo(i
- 1, StateToPrint
);
1332 state
= SCE_HB_WORD
;
1333 } else if (ch
== '\'') {
1334 styler
.ColourTo(i
- 1, StateToPrint
);
1335 state
= SCE_HB_COMMENTLINE
;
1336 } else if (ch
== '\"') {
1337 styler
.ColourTo(i
- 1, StateToPrint
);
1338 state
= SCE_HB_STRING
;
1339 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1340 styler
.SafeGetCharAt(i
+ 3) == '-') {
1341 styler
.ColourTo(i
- 1, StateToPrint
);
1342 state
= SCE_HB_COMMENTLINE
;
1343 } else if (isoperator(ch
)) {
1344 styler
.ColourTo(i
- 1, StateToPrint
);
1345 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1346 state
= SCE_HB_DEFAULT
;
1347 } else if ((ch
== ' ') || (ch
== '\t')) {
1348 if (state
== SCE_HB_START
) {
1349 styler
.ColourTo(i
- 1, StateToPrint
);
1350 state
= SCE_HB_DEFAULT
;
1355 if (!iswordchar(ch
)) {
1356 state
= classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
1357 if (state
== SCE_HB_DEFAULT
) {
1359 state
= SCE_HB_STRING
;
1360 } else if (ch
== '\'') {
1361 state
= SCE_HB_COMMENTLINE
;
1362 } else if (isoperator(ch
)) {
1363 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1364 state
= SCE_HB_DEFAULT
;
1371 styler
.ColourTo(i
, StateToPrint
);
1372 state
= SCE_HB_DEFAULT
;
1373 } else if (ch
== '\r' || ch
== '\n') {
1374 styler
.ColourTo(i
- 1, StateToPrint
);
1375 state
= SCE_HB_STRINGEOL
;
1378 case SCE_HB_COMMENTLINE
:
1379 if (ch
== '\r' || ch
== '\n') {
1380 styler
.ColourTo(i
- 1, StateToPrint
);
1381 state
= SCE_HB_DEFAULT
;
1384 case SCE_HB_STRINGEOL
:
1385 if (!isLineEnd(ch
)) {
1386 styler
.ColourTo(i
- 1, StateToPrint
);
1387 state
= SCE_HB_DEFAULT
;
1388 } else if (!isLineEnd(chNext
)) {
1389 styler
.ColourTo(i
, StateToPrint
);
1390 state
= SCE_HB_DEFAULT
;
1393 case SCE_HP_DEFAULT
:
1395 if (iswordstart(ch
)) {
1396 styler
.ColourTo(i
- 1, StateToPrint
);
1397 state
= SCE_HP_WORD
;
1398 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1399 styler
.SafeGetCharAt(i
+ 3) == '-') {
1400 styler
.ColourTo(i
- 1, StateToPrint
);
1401 state
= SCE_HP_COMMENTLINE
;
1402 } else if (ch
== '#') {
1403 styler
.ColourTo(i
- 1, StateToPrint
);
1404 state
= SCE_HP_COMMENTLINE
;
1405 } else if (ch
== '\"') {
1406 styler
.ColourTo(i
- 1, StateToPrint
);
1407 if (chNext
== '\"' && chNext2
== '\"') {
1409 state
= SCE_HP_TRIPLEDOUBLE
;
1412 chNext
= styler
.SafeGetCharAt(i
+ 1);
1414 // state = statePrintForState(SCE_HP_STRING,inScriptType);
1415 state
= SCE_HP_STRING
;
1417 } else if (ch
== '\'') {
1418 styler
.ColourTo(i
- 1, StateToPrint
);
1419 if (chNext
== '\'' && chNext2
== '\'') {
1421 state
= SCE_HP_TRIPLE
;
1424 chNext
= styler
.SafeGetCharAt(i
+ 1);
1426 state
= SCE_HP_CHARACTER
;
1428 } else if (isoperator(ch
)) {
1429 styler
.ColourTo(i
- 1, StateToPrint
);
1430 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1431 } else if ((ch
== ' ') || (ch
== '\t')) {
1432 if (state
== SCE_HP_START
) {
1433 styler
.ColourTo(i
- 1, StateToPrint
);
1434 state
= SCE_HP_DEFAULT
;
1439 if (!iswordchar(ch
)) {
1440 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
1441 state
= SCE_HP_DEFAULT
;
1443 state
= SCE_HP_COMMENTLINE
;
1444 } else if (ch
== '\"') {
1445 if (chNext
== '\"' && chNext2
== '\"') {
1447 state
= SCE_HP_TRIPLEDOUBLE
;
1450 chNext
= styler
.SafeGetCharAt(i
+ 1);
1452 state
= SCE_HP_STRING
;
1454 } else if (ch
== '\'') {
1455 if (chNext
== '\'' && chNext2
== '\'') {
1457 state
= SCE_HP_TRIPLE
;
1460 chNext
= styler
.SafeGetCharAt(i
+ 1);
1462 state
= SCE_HP_CHARACTER
;
1464 } else if (isoperator(ch
)) {
1465 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1469 case SCE_HP_COMMENTLINE
:
1470 if (ch
== '\r' || ch
== '\n') {
1471 styler
.ColourTo(i
- 1, StateToPrint
);
1472 state
= SCE_HP_DEFAULT
;
1477 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1480 chNext
= styler
.SafeGetCharAt(i
+ 1);
1482 } else if (ch
== '\"') {
1483 styler
.ColourTo(i
, StateToPrint
);
1484 state
= SCE_HP_DEFAULT
;
1487 case SCE_HP_CHARACTER
:
1489 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1492 chNext
= styler
.SafeGetCharAt(i
+ 1);
1494 } else if (ch
== '\'') {
1495 styler
.ColourTo(i
, StateToPrint
);
1496 state
= SCE_HP_DEFAULT
;
1500 if (ch
== '\'' && chPrev
== '\'' && chPrev2
== '\'') {
1501 styler
.ColourTo(i
, StateToPrint
);
1502 state
= SCE_HP_DEFAULT
;
1505 case SCE_HP_TRIPLEDOUBLE
:
1506 if (ch
== '\"' && chPrev
== '\"' && chPrev2
== '\"') {
1507 styler
.ColourTo(i
, StateToPrint
);
1508 state
= SCE_HP_DEFAULT
;
1511 ///////////// start - PHP state handling
1513 if (!iswordchar(ch
)) {
1514 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
1515 if (ch
== '/' && chNext
== '*') {
1517 state
= SCE_HPHP_COMMENT
;
1518 } else if (ch
== '/' && chNext
== '/') {
1520 state
= SCE_HPHP_COMMENTLINE
;
1521 } else if (ch
== '#') {
1522 state
= SCE_HPHP_COMMENTLINE
;
1523 } else if (ch
== '\"') {
1524 state
= SCE_HPHP_HSTRING
;
1525 strcpy(phpStringDelimiter
, "\"");
1526 } else if (styler
.Match(i
, "<<<")) {
1527 state
= SCE_HPHP_HSTRING
;
1528 i
= FindPhpStringDelimiter(phpStringDelimiter
, sizeof(phpStringDelimiter
), i
+ 3, lengthDoc
, styler
);
1529 } else if (ch
== '\'') {
1530 state
= SCE_HPHP_SIMPLESTRING
;
1531 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1532 state
= SCE_HPHP_VARIABLE
;
1533 } else if (isoperator(ch
)) {
1534 state
= SCE_HPHP_OPERATOR
;
1536 state
= SCE_HPHP_DEFAULT
;
1540 case SCE_HPHP_NUMBER
:
1541 // recognize bases 8,10 or 16 integers OR floating-point numbers
1543 && strchr(".xXabcdefABCDEF", ch
) == NULL
1544 && ((ch
!= '-' && ch
!= '+') || (chPrev
!= 'e' && chPrev
!= 'E'))) {
1545 styler
.ColourTo(i
- 1, SCE_HPHP_NUMBER
);
1547 state
= SCE_HPHP_OPERATOR
;
1549 state
= SCE_HPHP_DEFAULT
;
1552 case SCE_HPHP_VARIABLE
:
1553 if (!IsPhpWordChar(ch
)) {
1554 styler
.ColourTo(i
- 1, SCE_HPHP_VARIABLE
);
1556 state
= SCE_HPHP_OPERATOR
;
1558 state
= SCE_HPHP_DEFAULT
;
1561 case SCE_HPHP_COMMENT
:
1562 if (ch
== '/' && chPrev
== '*') {
1563 styler
.ColourTo(i
, StateToPrint
);
1564 state
= SCE_HPHP_DEFAULT
;
1567 case SCE_HPHP_COMMENTLINE
:
1568 if (ch
== '\r' || ch
== '\n') {
1569 styler
.ColourTo(i
- 1, StateToPrint
);
1570 state
= SCE_HPHP_DEFAULT
;
1573 case SCE_HPHP_HSTRING
:
1574 if (ch
== '\\' && (phpStringDelimiter
[0] == '\"' || chNext
== '$' || chNext
== '{')) {
1575 // skip the next char
1577 } else if (((ch
== '{' && chNext
== '$') || (ch
== '$' && chNext
== '{'))
1578 && IsPhpWordStart(chNext2
)) {
1579 styler
.ColourTo(i
- 1, StateToPrint
);
1580 state
= SCE_HPHP_COMPLEX_VARIABLE
;
1581 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1582 styler
.ColourTo(i
- 1, StateToPrint
);
1583 state
= SCE_HPHP_HSTRING_VARIABLE
;
1584 } 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
;
1591 case SCE_HPHP_SIMPLESTRING
:
1593 // skip the next char
1595 } else if (ch
== '\'') {
1596 styler
.ColourTo(i
, StateToPrint
);
1597 state
= SCE_HPHP_DEFAULT
;
1600 case SCE_HPHP_HSTRING_VARIABLE
:
1601 if (!IsPhpWordChar(ch
)) {
1602 styler
.ColourTo(i
- 1, StateToPrint
);
1603 i
--; // strange but it works
1604 state
= SCE_HPHP_HSTRING
;
1607 case SCE_HPHP_COMPLEX_VARIABLE
:
1609 styler
.ColourTo(i
, StateToPrint
);
1610 state
= SCE_HPHP_HSTRING
;
1613 case SCE_HPHP_OPERATOR
:
1614 case SCE_HPHP_DEFAULT
:
1615 styler
.ColourTo(i
- 1, StateToPrint
);
1616 if (IsADigit(ch
) || (ch
== '.' && IsADigit(chNext
))) {
1617 state
= SCE_HPHP_NUMBER
;
1618 } else if (iswordstart(ch
)) {
1619 state
= SCE_HPHP_WORD
;
1620 } else if (ch
== '/' && chNext
== '*') {
1622 state
= SCE_HPHP_COMMENT
;
1623 } else if (ch
== '/' && chNext
== '/') {
1625 state
= SCE_HPHP_COMMENTLINE
;
1626 } else if (ch
== '#') {
1627 state
= SCE_HPHP_COMMENTLINE
;
1628 } else if (ch
== '\"') {
1629 state
= SCE_HPHP_HSTRING
;
1630 strcpy(phpStringDelimiter
, "\"");
1631 } else if (styler
.Match(i
, "<<<")) {
1632 state
= SCE_HPHP_HSTRING
;
1633 i
= FindPhpStringDelimiter(phpStringDelimiter
, sizeof(phpStringDelimiter
), i
+ 3, lengthDoc
, styler
);
1634 } else if (ch
== '\'') {
1635 state
= SCE_HPHP_SIMPLESTRING
;
1636 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1637 state
= SCE_HPHP_VARIABLE
;
1638 } else if (isoperator(ch
)) {
1639 state
= SCE_HPHP_OPERATOR
;
1640 } else if ((state
== SCE_HPHP_OPERATOR
) && (isspacechar(ch
))) {
1641 state
= SCE_HPHP_DEFAULT
;
1644 ///////////// end - PHP state handling
1647 // Some of the above terminated their lexeme but since the same character starts
1648 // the same class again, only reenter if non empty segment.
1650 bool nonEmptySegment
= i
>= static_cast<int>(styler
.GetStartSegment());
1651 if (state
== SCE_HB_DEFAULT
) { // One of the above succeeded
1652 if ((ch
== '\"') && (nonEmptySegment
)) {
1653 state
= SCE_HB_STRING
;
1654 } else if (ch
== '\'') {
1655 state
= SCE_HB_COMMENTLINE
;
1656 } else if (iswordstart(ch
)) {
1657 state
= SCE_HB_WORD
;
1658 } else if (isoperator(ch
)) {
1659 styler
.ColourTo(i
, SCE_HB_DEFAULT
);
1661 } else if (state
== SCE_HBA_DEFAULT
) { // One of the above succeeded
1662 if ((ch
== '\"') && (nonEmptySegment
)) {
1663 state
= SCE_HBA_STRING
;
1664 } else if (ch
== '\'') {
1665 state
= SCE_HBA_COMMENTLINE
;
1666 } else if (iswordstart(ch
)) {
1667 state
= SCE_HBA_WORD
;
1668 } else if (isoperator(ch
)) {
1669 styler
.ColourTo(i
, SCE_HBA_DEFAULT
);
1671 } else if (state
== SCE_HJ_DEFAULT
) { // One of the above succeeded
1672 if (ch
== '/' && chNext
== '*') {
1673 if (styler
.SafeGetCharAt(i
+ 2) == '*')
1674 state
= SCE_HJ_COMMENTDOC
;
1676 state
= SCE_HJ_COMMENT
;
1677 } else if (ch
== '/' && chNext
== '/') {
1678 state
= SCE_HJ_COMMENTLINE
;
1679 } else if ((ch
== '\"') && (nonEmptySegment
)) {
1680 state
= SCE_HJ_DOUBLESTRING
;
1681 } else if ((ch
== '\'') && (nonEmptySegment
)) {
1682 state
= SCE_HJ_SINGLESTRING
;
1683 } else if (iswordstart(ch
)) {
1684 state
= SCE_HJ_WORD
;
1685 } else if (isoperator(ch
)) {
1686 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1691 StateToPrint
= statePrintForState(state
, inScriptType
);
1692 styler
.ColourTo(lengthDoc
- 1, StateToPrint
);
1694 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
1696 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
1697 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
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
);
1994 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
);
2000 static const char * const htmlWordListDesc
[] = {
2001 "HTML elements and attributes",
2002 "JavaScript keywords",
2003 "VBScript keywords",
2006 "SGML and DTD keywords",
2010 static const char * const phpscriptWordListDesc
[] = {
2020 LexerModule
lmHTML(SCLEX_HTML
, ColouriseHyperTextDoc
, "hypertext", 0, htmlWordListDesc
, 7);
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.
2023 LexerModule
lmASP(SCLEX_ASP
, ColouriseASPDoc
, "asp", 0, htmlWordListDesc
, 7);
2024 LexerModule
lmPHP(SCLEX_PHP
, ColourisePHPDoc
, "php", 0, htmlWordListDesc
, 7);
2025 LexerModule
lmPHPSCRIPT(SCLEX_PHPSCRIPT
, ColourisePHPScriptDoc
, "phpscript", 0, phpscriptWordListDesc
, 7);