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"
22 #include "CharacterSet.h"
25 using namespace Scintilla
;
28 #define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START)
29 #define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START)
30 #define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START)
32 enum script_type
{ eScriptNone
= 0, eScriptJS
, eScriptVBS
, eScriptPython
, eScriptPHP
, eScriptXML
, eScriptSGML
, eScriptSGMLblock
};
33 enum script_mode
{ eHtml
= 0, eNonHtmlScript
, eNonHtmlPreProc
, eNonHtmlScriptPreProc
};
35 static inline bool IsAWordChar(const int ch
) {
36 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
39 static inline bool IsAWordStart(const int ch
) {
40 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
43 inline bool IsOperator(int ch
) {
44 if (isascii(ch
) && isalnum(ch
))
46 // '.' left out as it is used to make up numbers
47 if (ch
== '%' || ch
== '^' || ch
== '&' || ch
== '*' ||
48 ch
== '(' || ch
== ')' || ch
== '-' || ch
== '+' ||
49 ch
== '=' || ch
== '|' || ch
== '{' || ch
== '}' ||
50 ch
== '[' || ch
== ']' || ch
== ':' || ch
== ';' ||
51 ch
== '<' || ch
== '>' || ch
== ',' || ch
== '/' ||
52 ch
== '?' || ch
== '!' || ch
== '.' || ch
== '~')
57 static inline int MakeLowerCase(int ch
) {
58 if (ch
< 'A' || ch
> 'Z')
61 return ch
- 'A' + 'a';
64 static void GetTextSegment(Accessor
&styler
, unsigned int start
, unsigned int end
, char *s
, size_t len
) {
66 for (; (i
< end
- start
+ 1) && (i
< len
-1); i
++) {
67 s
[i
] = static_cast<char>(MakeLowerCase(styler
[start
+ i
]));
72 static script_type
segIsScriptingIndicator(Accessor
&styler
, unsigned int start
, unsigned int end
, script_type prevValue
) {
74 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
75 //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
76 if (strstr(s
, "src")) // External script
80 if (strstr(s
, "pyth"))
82 if (strstr(s
, "javas"))
84 if (strstr(s
, "jscr"))
88 if (strstr(s
, "xml")) {
89 const char *xml
= strstr(s
, "xml");
90 for (const char *t
=s
; t
<xml
; t
++) {
101 static int PrintScriptingIndicatorOffset(Accessor
&styler
, unsigned int start
, unsigned int end
) {
104 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
105 if (0 == strncmp(s
, "php", 3)) {
112 static script_type
ScriptOfState(int state
) {
113 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
114 return eScriptPython
;
115 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
117 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
119 } else if ((state
>= SCE_HPHP_DEFAULT
) && (state
<= SCE_HPHP_COMMENTLINE
)) {
121 } else if ((state
>= SCE_H_SGML_DEFAULT
) && (state
< SCE_H_SGML_BLOCK_DEFAULT
)) {
123 } else if (state
== SCE_H_SGML_BLOCK_DEFAULT
) {
124 return eScriptSGMLblock
;
130 static int statePrintForState(int state
, script_mode inScriptType
) {
131 int StateToPrint
= state
;
133 if (state
>= SCE_HJ_START
) {
134 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
135 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_PYTHON
);
136 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
137 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_VBS
);
138 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
139 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_JS
);
146 static int stateForPrintState(int StateToPrint
) {
149 if ((StateToPrint
>= SCE_HPA_START
) && (StateToPrint
<= SCE_HPA_IDENTIFIER
)) {
150 state
= StateToPrint
- SCE_HA_PYTHON
;
151 } else if ((StateToPrint
>= SCE_HBA_START
) && (StateToPrint
<= SCE_HBA_STRINGEOL
)) {
152 state
= StateToPrint
- SCE_HA_VBS
;
153 } else if ((StateToPrint
>= SCE_HJA_START
) && (StateToPrint
<= SCE_HJA_REGEX
)) {
154 state
= StateToPrint
- SCE_HA_JS
;
156 state
= StateToPrint
;
162 static inline bool IsNumber(unsigned int start
, Accessor
&styler
) {
163 return IsADigit(styler
[start
]) || (styler
[start
] == '.') ||
164 (styler
[start
] == '-') || (styler
[start
] == '#');
167 static inline bool isStringState(int state
) {
171 case SCE_HJ_DOUBLESTRING
:
172 case SCE_HJ_SINGLESTRING
:
173 case SCE_HJA_DOUBLESTRING
:
174 case SCE_HJA_SINGLESTRING
:
178 case SCE_HP_CHARACTER
:
180 case SCE_HP_TRIPLEDOUBLE
:
182 case SCE_HPA_CHARACTER
:
184 case SCE_HPA_TRIPLEDOUBLE
:
185 case SCE_HPHP_HSTRING
:
186 case SCE_HPHP_SIMPLESTRING
:
187 case SCE_HPHP_HSTRING_VARIABLE
:
188 case SCE_HPHP_COMPLEX_VARIABLE
:
198 static inline bool stateAllowsTermination(int state
) {
199 bool allowTermination
= !isStringState(state
);
200 if (allowTermination
) {
202 case SCE_HB_COMMENTLINE
:
203 case SCE_HPHP_COMMENT
:
204 case SCE_HP_COMMENTLINE
:
205 case SCE_HPA_COMMENTLINE
:
206 allowTermination
= false;
209 return allowTermination
;
212 // not really well done, since it's only comments that should lex the %> and <%
213 static inline bool isCommentASPState(int state
) {
218 case SCE_HJ_COMMENTLINE
:
219 case SCE_HJ_COMMENTDOC
:
220 case SCE_HB_COMMENTLINE
:
221 case SCE_HP_COMMENTLINE
:
222 case SCE_HPHP_COMMENT
:
223 case SCE_HPHP_COMMENTLINE
:
233 static void classifyAttribHTML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
234 bool wordIsNumber
= IsNumber(start
, styler
);
235 char chAttr
= SCE_H_ATTRIBUTEUNKNOWN
;
237 chAttr
= SCE_H_NUMBER
;
240 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
241 if (keywords
.InList(s
))
242 chAttr
= SCE_H_ATTRIBUTE
;
244 if ((chAttr
== SCE_H_ATTRIBUTEUNKNOWN
) && !keywords
)
245 // No keywords -> all are known
246 chAttr
= SCE_H_ATTRIBUTE
;
247 styler
.ColourTo(end
, chAttr
);
250 static int classifyTagHTML(unsigned int start
, unsigned int end
,
251 WordList
&keywords
, Accessor
&styler
, bool &tagDontFold
,
252 bool caseSensitive
, bool isXml
) {
254 // Copy after the '<'
256 for (unsigned int cPos
= start
; cPos
<= end
&& i
< 30; cPos
++) {
257 char ch
= styler
[cPos
];
258 if ((ch
!= '<') && (ch
!= '/')) {
259 s
[i
++] = caseSensitive
? ch
: static_cast<char>(MakeLowerCase(ch
));
263 //The following is only a quick hack, to see if this whole thing would work
264 //we first need the tagname with a trailing space...
268 // if the current language is XML, I can fold any tag
269 // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.)
270 //...to find it in the list of no-container-tags
271 tagDontFold
= (!isXml
) && (NULL
!= strstr("meta link img area br hr input ",s
));
273 //now we can remove the trailing space
276 bool isScript
= false;
277 char chAttr
= SCE_H_TAGUNKNOWN
;
279 chAttr
= SCE_H_SGML_DEFAULT
;
280 } else if (s
[0] == '/') { // Closing tag
281 if (keywords
.InList(s
+ 1))
284 if (keywords
.InList(s
)) {
286 isScript
= 0 == strcmp(s
, "script");
289 if ((chAttr
== SCE_H_TAGUNKNOWN
) && !keywords
) {
290 // No keywords -> all are known
292 isScript
= 0 == strcmp(s
, "script");
294 styler
.ColourTo(end
, chAttr
);
295 return isScript
? SCE_H_SCRIPT
: chAttr
;
298 static void classifyWordHTJS(unsigned int start
, unsigned int end
,
299 WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
300 char chAttr
= SCE_HJ_WORD
;
301 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.');
303 chAttr
= SCE_HJ_NUMBER
;
307 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
308 s
[i
] = styler
[start
+ i
];
311 if (keywords
.InList(s
))
312 chAttr
= SCE_HJ_KEYWORD
;
314 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
317 static int classifyWordHTVB(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
318 char chAttr
= SCE_HB_IDENTIFIER
;
319 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.');
321 chAttr
= SCE_HB_NUMBER
;
324 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
325 if (keywords
.InList(s
)) {
326 chAttr
= SCE_HB_WORD
;
327 if (strcmp(s
, "rem") == 0)
328 chAttr
= SCE_HB_COMMENTLINE
;
331 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
332 if (chAttr
== SCE_HB_COMMENTLINE
)
333 return SCE_HB_COMMENTLINE
;
335 return SCE_HB_DEFAULT
;
338 static void classifyWordHTPy(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, char *prevWord
, script_mode inScriptType
) {
339 bool wordIsNumber
= IsADigit(styler
[start
]);
342 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
343 s
[i
] = styler
[start
+ i
];
346 char chAttr
= SCE_HP_IDENTIFIER
;
347 if (0 == strcmp(prevWord
, "class"))
348 chAttr
= SCE_HP_CLASSNAME
;
349 else if (0 == strcmp(prevWord
, "def"))
350 chAttr
= SCE_HP_DEFNAME
;
351 else if (wordIsNumber
)
352 chAttr
= SCE_HP_NUMBER
;
353 else if (keywords
.InList(s
))
354 chAttr
= SCE_HP_WORD
;
355 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
359 // Update the word colour to default or keyword
360 // Called when in a PHP word
361 static void classifyWordHTPHP(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
362 char chAttr
= SCE_HPHP_DEFAULT
;
363 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.' && start
+1 <= end
&& IsADigit(styler
[start
+1]));
365 chAttr
= SCE_HPHP_NUMBER
;
368 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
369 if (keywords
.InList(s
))
370 chAttr
= SCE_HPHP_WORD
;
372 styler
.ColourTo(end
, chAttr
);
375 static bool isWordHSGML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
378 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
379 s
[i
] = styler
[start
+ i
];
382 return keywords
.InList(s
);
385 static bool isWordCdata(unsigned int start
, unsigned int end
, Accessor
&styler
) {
388 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
389 s
[i
] = styler
[start
+ i
];
392 return (0 == strcmp(s
, "[CDATA["));
395 // Return the first state to reach when entering a scripting language
396 static int StateForScript(script_type scriptLanguage
) {
398 switch (scriptLanguage
) {
400 Result
= SCE_HB_START
;
403 Result
= SCE_HP_START
;
406 Result
= SCE_HPHP_DEFAULT
;
409 Result
= SCE_H_TAGUNKNOWN
;
412 Result
= SCE_H_SGML_DEFAULT
;
415 Result
= SCE_HJ_START
;
421 static inline bool ishtmlwordchar(int ch
) {
422 return !isascii(ch
) ||
423 (isalnum(ch
) || ch
== '.' || ch
== '-' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#');
426 static inline bool issgmlwordchar(int ch
) {
427 return !isascii(ch
) ||
428 (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#' || ch
== '[');
431 static inline bool IsPhpWordStart(int ch
) {
432 return (isascii(ch
) && (isalpha(ch
) || (ch
== '_'))) || (ch
>= 0x7f);
435 static inline bool IsPhpWordChar(int ch
) {
436 return IsADigit(ch
) || IsPhpWordStart(ch
);
439 static bool InTagState(int state
) {
440 return state
== SCE_H_TAG
|| state
== SCE_H_TAGUNKNOWN
||
441 state
== SCE_H_SCRIPT
||
442 state
== SCE_H_ATTRIBUTE
|| state
== SCE_H_ATTRIBUTEUNKNOWN
||
443 state
== SCE_H_NUMBER
|| state
== SCE_H_OTHER
||
444 state
== SCE_H_DOUBLESTRING
|| state
== SCE_H_SINGLESTRING
;
447 static bool IsCommentState(const int state
) {
448 return state
== SCE_H_COMMENT
|| state
== SCE_H_SGML_COMMENT
;
451 static bool IsScriptCommentState(const int state
) {
452 return state
== SCE_HJ_COMMENT
|| state
== SCE_HJ_COMMENTLINE
|| state
== SCE_HJA_COMMENT
||
453 state
== SCE_HJA_COMMENTLINE
|| state
== SCE_HB_COMMENTLINE
|| state
== SCE_HBA_COMMENTLINE
;
456 static bool isLineEnd(int ch
) {
457 return ch
== '\r' || ch
== '\n';
460 static bool isOKBeforeRE(int ch
) {
461 return (ch
== '(') || (ch
== '=') || (ch
== ',');
464 static bool isPHPStringState(int state
) {
466 (state
== SCE_HPHP_HSTRING
) ||
467 (state
== SCE_HPHP_SIMPLESTRING
) ||
468 (state
== SCE_HPHP_HSTRING_VARIABLE
) ||
469 (state
== SCE_HPHP_COMPLEX_VARIABLE
);
472 static int FindPhpStringDelimiter(char *phpStringDelimiter
, const int phpStringDelimiterSize
, int i
, const int lengthDoc
, Accessor
&styler
) {
474 while (i
< lengthDoc
&& (styler
[i
] == ' ' || styler
[i
] == '\t'))
476 phpStringDelimiter
[0] = '\n';
477 for (j
= i
; j
< lengthDoc
&& styler
[j
] != '\n' && styler
[j
] != '\r'; j
++) {
478 if (j
- i
< phpStringDelimiterSize
- 2)
479 phpStringDelimiter
[j
-i
+1] = styler
[j
];
483 phpStringDelimiter
[j
-i
+1] = '\0';
487 static void ColouriseHyperTextDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
488 Accessor
&styler
, bool isXml
) {
489 WordList
&keywords
= *keywordlists
[0];
490 WordList
&keywords2
= *keywordlists
[1];
491 WordList
&keywords3
= *keywordlists
[2];
492 WordList
&keywords4
= *keywordlists
[3];
493 WordList
&keywords5
= *keywordlists
[4];
494 WordList
&keywords6
= *keywordlists
[5]; // SGML (DTD) keywords
496 // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
497 styler
.StartAt(startPos
, static_cast<char>(STYLE_MAX
));
500 char phpStringDelimiter
[200]; // PHP is not limited in length, we are
501 phpStringDelimiter
[0] = '\0';
502 int StateToPrint
= initStyle
;
503 int state
= stateForPrintState(StateToPrint
);
505 // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen
506 if (InTagState(state
)) {
507 while ((startPos
> 0) && (InTagState(styler
.StyleAt(startPos
- 1)))) {
511 state
= SCE_H_DEFAULT
;
513 // String can be heredoc, must find a delimiter first
514 while (startPos
> 0 && isPHPStringState(state
) && state
!= SCE_HPHP_SIMPLESTRING
) {
517 state
= styler
.StyleAt(startPos
);
519 styler
.StartAt(startPos
, static_cast<char>(STYLE_MAX
));
521 int lineCurrent
= styler
.GetLine(startPos
);
523 if (lineCurrent
> 0) {
524 lineState
= styler
.GetLineState(lineCurrent
);
526 // Default client and ASP scripting language is JavaScript
527 lineState
= eScriptJS
<< 8;
528 lineState
|= styler
.GetPropertyInt("asp.default.language", eScriptJS
) << 4;
530 script_mode inScriptType
= script_mode((lineState
>> 0) & 0x03); // 2 bits of scripting mode
531 bool tagOpened
= (lineState
>> 2) & 0x01; // 1 bit to know if we are in an opened tag
532 bool tagClosing
= (lineState
>> 3) & 0x01; // 1 bit to know if we are in a closing tag
533 bool tagDontFold
= false; //some HTML tags should not be folded
534 script_type aspScript
= script_type((lineState
>> 4) & 0x0F); // 4 bits of script name
535 script_type clientScript
= script_type((lineState
>> 8) & 0x0F); // 4 bits of script name
536 int beforePreProc
= (lineState
>> 12) & 0xFF; // 8 bits of state
538 script_type scriptLanguage
= ScriptOfState(state
);
540 const bool foldHTML
= styler
.GetPropertyInt("fold.html", 0) != 0;
541 const bool fold
= foldHTML
&& styler
.GetPropertyInt("fold", 0);
542 const bool foldHTMLPreprocessor
= foldHTML
&& styler
.GetPropertyInt("fold.html.preprocessor", 1);
543 const bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
544 const bool caseSensitive
= styler
.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
546 const CharacterSet
setHTMLWord(CharacterSet::setAlphaNum
, ".-_:!#", 0x80, true);
547 const CharacterSet
setTagContinue(CharacterSet::setAlphaNum
, ".-_:!#[", 0x80, true);
548 const CharacterSet
setAttributeContinue(CharacterSet::setAlphaNum
, ".-_:!#/", 0x80, true);
550 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
551 int levelCurrent
= levelPrev
;
552 int visibleChars
= 0;
556 int chPrevNonWhite
= ' ';
557 // look back to set chPrevNonWhite properly for better regex colouring
558 if (scriptLanguage
== eScriptJS
&& startPos
> 0) {
562 style
= styler
.StyleAt(back
);
563 if (style
< SCE_HJ_DEFAULT
|| style
> SCE_HJ_COMMENTDOC
)
564 // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
567 if (style
== SCE_HJ_SYMBOLS
) {
568 chPrevNonWhite
= static_cast<unsigned char>(styler
.SafeGetCharAt(back
));
572 styler
.StartSegment(startPos
);
573 const int lengthDoc
= startPos
+ length
;
574 for (int i
= startPos
; i
< lengthDoc
; i
++) {
575 const int chPrev2
= chPrev
;
577 if (!IsASpace(ch
) && state
!= SCE_HJ_COMMENT
&&
578 state
!= SCE_HJ_COMMENTLINE
&& state
!= SCE_HJ_COMMENTDOC
)
580 ch
= static_cast<unsigned char>(styler
[i
]);
581 int chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
582 const int chNext2
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 2));
584 // Handle DBCS codepages
585 if (styler
.IsLeadByte(static_cast<char>(ch
))) {
591 if ((!IsASpace(ch
) || !foldCompact
) && fold
)
594 // decide what is the current state to print (depending of the script tag)
595 StateToPrint
= statePrintForState(state
, inScriptType
);
597 // handle script folding
599 switch (scriptLanguage
) {
602 //not currently supported case eScriptVBS:
604 if ((state
!= SCE_HPHP_COMMENT
) && (state
!= SCE_HPHP_COMMENTLINE
) && (state
!= SCE_HJ_COMMENT
) && (state
!= SCE_HJ_COMMENTLINE
) && (state
!= SCE_HJ_COMMENTDOC
) && (!isStringState(state
))) {
605 //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle);
606 //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {
607 if ((ch
== '{') || (ch
== '}')) {
608 levelCurrent
+= (ch
== '{') ? 1 : -1;
613 if (state
!= SCE_HP_COMMENTLINE
) {
614 if ((ch
== ':') && ((chNext
== '\n') || (chNext
== '\r' && chNext2
== '\n'))) {
616 } else if ((ch
== '\n') && !((chNext
== '\r') && (chNext2
== '\n')) && (chNext
!= '\n')) {
617 // check if the number of tabs is lower than the level
618 int Findlevel
= (levelCurrent
& ~SC_FOLDLEVELBASE
) * 8;
619 for (int j
= 0; Findlevel
> 0; j
++) {
620 char chTmp
= styler
.SafeGetCharAt(i
+ j
+ 1);
623 } else if (chTmp
== ' ') {
631 levelCurrent
-= Findlevel
/ 8;
643 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) {
644 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
645 // Avoid triggering two times on Dos/Win
646 // New line -> record any line state onto /next/ line
649 if (visibleChars
== 0)
650 lev
|= SC_FOLDLEVELWHITEFLAG
;
651 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
652 lev
|= SC_FOLDLEVELHEADERFLAG
;
654 styler
.SetLevel(lineCurrent
, lev
);
656 levelPrev
= levelCurrent
;
659 styler
.SetLineState(lineCurrent
,
660 ((inScriptType
& 0x03) << 0) |
661 ((tagOpened
& 0x01) << 2) |
662 ((tagClosing
& 0x01) << 3) |
663 ((aspScript
& 0x0F) << 4) |
664 ((clientScript
& 0x0F) << 8) |
665 ((beforePreProc
& 0xFF) << 12));
668 // generic end of script processing
669 else if ((inScriptType
== eNonHtmlScript
) && (ch
== '<') && (chNext
== '/')) {
670 // Check if it's the end of the script tag (or any other HTML tag)
672 // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
673 case SCE_H_DOUBLESTRING
:
674 case SCE_H_SINGLESTRING
:
676 case SCE_HJ_COMMENTDOC
:
677 //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
678 // the end of script marker from some JS interpreters.
679 case SCE_HB_COMMENTLINE
:
680 case SCE_HBA_COMMENTLINE
:
681 case SCE_HJ_DOUBLESTRING
:
682 case SCE_HJ_SINGLESTRING
:
688 case SCE_HP_TRIPLEDOUBLE
:
691 // check if the closing tag is a script tag
692 if (state
== SCE_HJ_COMMENTLINE
|| isXml
) {
693 char tag
[7]; // room for the <script> tag
695 char chr
= styler
.SafeGetCharAt(i
+2);
696 while (j
< 6 && !IsASpace(chr
)) {
697 tag
[j
++] = static_cast<char>(MakeLowerCase(chr
));
698 chr
= styler
.SafeGetCharAt(i
+2+j
);
701 if (strcmp(tag
, "script") != 0) break;
703 // closing tag of the script (it's a closing HTML tag anyway)
704 styler
.ColourTo(i
- 1, StateToPrint
);
705 state
= SCE_H_TAGUNKNOWN
;
706 inScriptType
= eHtml
;
707 scriptLanguage
= eScriptNone
;
708 clientScript
= eScriptJS
;
716 /////////////////////////////////////
717 // handle the start of PHP pre-processor = Non-HTML
718 else if ((state
!= SCE_H_ASPAT
) &&
719 !isPHPStringState(state
) &&
720 (state
!= SCE_HPHP_COMMENT
) &&
723 !IsScriptCommentState(state
) ) {
724 scriptLanguage
= segIsScriptingIndicator(styler
, i
+ 2, i
+ 10, eScriptPHP
);
725 if (scriptLanguage
!= eScriptPHP
&& isStringState(state
)) continue;
726 styler
.ColourTo(i
- 1, StateToPrint
);
727 beforePreProc
= state
;
730 i
+= PrintScriptingIndicatorOffset(styler
, styler
.GetStartSegment() + 2, i
+ 10);
731 if (scriptLanguage
== eScriptXML
)
732 styler
.ColourTo(i
, SCE_H_XMLSTART
);
734 styler
.ColourTo(i
, SCE_H_QUESTION
);
735 state
= StateForScript(scriptLanguage
);
736 if (inScriptType
== eNonHtmlScript
)
737 inScriptType
= eNonHtmlScriptPreProc
;
739 inScriptType
= eNonHtmlPreProc
;
740 // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
741 if (foldHTMLPreprocessor
&& (scriptLanguage
!= eScriptXML
)) {
745 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
749 // handle the start of ASP pre-processor = Non-HTML
750 else if (!isCommentASPState(state
) && (ch
== '<') && (chNext
== '%') && !isPHPStringState(state
)) {
751 styler
.ColourTo(i
- 1, StateToPrint
);
752 beforePreProc
= state
;
753 if (inScriptType
== eNonHtmlScript
)
754 inScriptType
= eNonHtmlScriptPreProc
;
756 inScriptType
= eNonHtmlPreProc
;
758 if (chNext2
== '@') {
759 i
+= 2; // place as if it was the second next char treated
762 } else if ((chNext2
== '-') && (styler
.SafeGetCharAt(i
+ 3) == '-')) {
763 styler
.ColourTo(i
+ 3, SCE_H_ASP
);
764 state
= SCE_H_XCCOMMENT
;
765 scriptLanguage
= eScriptVBS
;
768 if (chNext2
== '=') {
769 i
+= 2; // place as if it was the second next char treated
772 i
++; // place as if it was the next char treated
776 state
= StateForScript(aspScript
);
778 scriptLanguage
= eScriptVBS
;
779 styler
.ColourTo(i
, SCE_H_ASP
);
781 if (foldHTMLPreprocessor
)
784 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
788 /////////////////////////////////////
789 // handle the start of SGML language (DTD)
790 else if (((scriptLanguage
== eScriptNone
) || (scriptLanguage
== eScriptXML
)) &&
793 (StateToPrint
!= SCE_H_CDATA
) &&
794 (!IsCommentState(StateToPrint
)) &&
795 (!IsScriptCommentState(StateToPrint
)) ) {
796 beforePreProc
= state
;
797 styler
.ColourTo(i
- 2, StateToPrint
);
798 if ((chNext
== '-') && (chNext2
== '-')) {
799 state
= SCE_H_COMMENT
; // wait for a pending command
800 styler
.ColourTo(i
+ 2, SCE_H_COMMENT
);
801 i
+= 2; // follow styling after the --
802 } else if (isWordCdata(i
+ 1, i
+ 7, styler
)) {
805 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
); // <! is default
806 scriptLanguage
= eScriptSGML
;
807 state
= SCE_H_SGML_COMMAND
; // wait for a pending command
809 // fold whole tag (-- when closing the tag)
810 if (foldHTMLPreprocessor
)
815 // handle the end of a pre-processor = Non-HTML
817 ((inScriptType
== eNonHtmlPreProc
)
818 || (inScriptType
== eNonHtmlScriptPreProc
)) && (
819 ((scriptLanguage
!= eScriptNone
) && stateAllowsTermination(state
) && ((ch
== '%') || (ch
== '?')))
820 ) && (chNext
== '>')) ||
821 ((scriptLanguage
== eScriptSGML
) && (ch
== '>') && (state
!= SCE_H_SGML_COMMENT
))) {
822 if (state
== SCE_H_ASPAT
) {
823 aspScript
= segIsScriptingIndicator(styler
,
824 styler
.GetStartSegment(), i
- 1, aspScript
);
826 // Bounce out of any ASP mode
829 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
832 classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
835 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
838 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
840 case SCE_H_XCCOMMENT
:
841 styler
.ColourTo(i
- 1, state
);
844 styler
.ColourTo(i
- 1, StateToPrint
);
847 if (scriptLanguage
!= eScriptSGML
) {
852 styler
.ColourTo(i
, SCE_H_ASP
);
853 else if (scriptLanguage
== eScriptXML
)
854 styler
.ColourTo(i
, SCE_H_XMLEND
);
855 else if (scriptLanguage
== eScriptSGML
)
856 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
858 styler
.ColourTo(i
, SCE_H_QUESTION
);
859 state
= beforePreProc
;
860 if (inScriptType
== eNonHtmlScriptPreProc
)
861 inScriptType
= eNonHtmlScript
;
863 inScriptType
= eHtml
;
864 // Unfold all scripting languages, except for XML tag
865 if (foldHTMLPreprocessor
&& (scriptLanguage
!= eScriptXML
)) {
868 scriptLanguage
= eScriptNone
;
871 /////////////////////////////////////
876 // in HTML, fold on tag open and unfold on tag close
878 tagClosing
= (chNext
== '/');
879 styler
.ColourTo(i
- 1, StateToPrint
);
881 state
= SCE_H_TAGUNKNOWN
;
882 } else if (ch
== '&') {
883 styler
.ColourTo(i
- 1, SCE_H_DEFAULT
);
884 state
= SCE_H_ENTITY
;
887 case SCE_H_SGML_DEFAULT
:
888 case SCE_H_SGML_BLOCK_DEFAULT
:
889 // if (scriptLanguage == eScriptSGMLblock)
890 // StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
893 styler
.ColourTo(i
- 1, StateToPrint
);
894 state
= SCE_H_SGML_DOUBLESTRING
;
895 } else if (ch
== '\'') {
896 styler
.ColourTo(i
- 1, StateToPrint
);
897 state
= SCE_H_SGML_SIMPLESTRING
;
898 } else if ((ch
== '-') && (chPrev
== '-')) {
899 if (static_cast<int>(styler
.GetStartSegment()) <= (i
- 2)) {
900 styler
.ColourTo(i
- 2, StateToPrint
);
902 state
= SCE_H_SGML_COMMENT
;
903 } else if (isascii(ch
) && isalpha(ch
) && (chPrev
== '%')) {
904 styler
.ColourTo(i
- 2, StateToPrint
);
905 state
= SCE_H_SGML_ENTITY
;
906 } else if (ch
== '#') {
907 styler
.ColourTo(i
- 1, StateToPrint
);
908 state
= SCE_H_SGML_SPECIAL
;
909 } else if (ch
== '[') {
910 styler
.ColourTo(i
- 1, StateToPrint
);
911 scriptLanguage
= eScriptSGMLblock
;
912 state
= SCE_H_SGML_BLOCK_DEFAULT
;
913 } else if (ch
== ']') {
914 if (scriptLanguage
== eScriptSGMLblock
) {
915 styler
.ColourTo(i
, StateToPrint
);
916 scriptLanguage
= eScriptSGML
;
918 styler
.ColourTo(i
- 1, StateToPrint
);
919 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
921 state
= SCE_H_SGML_DEFAULT
;
922 } else if (scriptLanguage
== eScriptSGMLblock
) {
923 if ((ch
== '!') && (chPrev
== '<')) {
924 styler
.ColourTo(i
- 2, StateToPrint
);
925 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
926 state
= SCE_H_SGML_COMMAND
;
927 } else if (ch
== '>') {
928 styler
.ColourTo(i
- 1, StateToPrint
);
929 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
933 case SCE_H_SGML_COMMAND
:
934 if ((ch
== '-') && (chPrev
== '-')) {
935 styler
.ColourTo(i
- 2, StateToPrint
);
936 state
= SCE_H_SGML_COMMENT
;
937 } else if (!issgmlwordchar(ch
)) {
938 if (isWordHSGML(styler
.GetStartSegment(), i
- 1, keywords6
, styler
)) {
939 styler
.ColourTo(i
- 1, StateToPrint
);
940 state
= SCE_H_SGML_1ST_PARAM
;
942 state
= SCE_H_SGML_ERROR
;
946 case SCE_H_SGML_1ST_PARAM
:
947 // wait for the beginning of the word
948 if ((ch
== '-') && (chPrev
== '-')) {
949 if (scriptLanguage
== eScriptSGMLblock
) {
950 styler
.ColourTo(i
- 2, SCE_H_SGML_BLOCK_DEFAULT
);
952 styler
.ColourTo(i
- 2, SCE_H_SGML_DEFAULT
);
954 state
= SCE_H_SGML_1ST_PARAM_COMMENT
;
955 } else if (issgmlwordchar(ch
)) {
956 if (scriptLanguage
== eScriptSGMLblock
) {
957 styler
.ColourTo(i
- 1, SCE_H_SGML_BLOCK_DEFAULT
);
959 styler
.ColourTo(i
- 1, SCE_H_SGML_DEFAULT
);
961 // find the length of the word
963 while (setHTMLWord
.Contains(static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ size
))))
965 styler
.ColourTo(i
+ size
- 1, StateToPrint
);
967 visibleChars
+= size
- 1;
968 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
969 if (scriptLanguage
== eScriptSGMLblock
) {
970 state
= SCE_H_SGML_BLOCK_DEFAULT
;
972 state
= SCE_H_SGML_DEFAULT
;
977 case SCE_H_SGML_ERROR
:
978 if ((ch
== '-') && (chPrev
== '-')) {
979 styler
.ColourTo(i
- 2, StateToPrint
);
980 state
= SCE_H_SGML_COMMENT
;
982 case SCE_H_SGML_DOUBLESTRING
:
984 styler
.ColourTo(i
, StateToPrint
);
985 state
= SCE_H_SGML_DEFAULT
;
988 case SCE_H_SGML_SIMPLESTRING
:
990 styler
.ColourTo(i
, StateToPrint
);
991 state
= SCE_H_SGML_DEFAULT
;
994 case SCE_H_SGML_COMMENT
:
995 if ((ch
== '-') && (chPrev
== '-')) {
996 styler
.ColourTo(i
, StateToPrint
);
997 state
= SCE_H_SGML_DEFAULT
;
1001 if ((chPrev2
== ']') && (chPrev
== ']') && (ch
== '>')) {
1002 styler
.ColourTo(i
, StateToPrint
);
1003 state
= SCE_H_DEFAULT
;
1008 if ((chPrev2
== '-') && (chPrev
== '-') && (ch
== '>')) {
1009 styler
.ColourTo(i
, StateToPrint
);
1010 state
= SCE_H_DEFAULT
;
1014 case SCE_H_SGML_1ST_PARAM_COMMENT
:
1015 if ((ch
== '-') && (chPrev
== '-')) {
1016 styler
.ColourTo(i
, SCE_H_SGML_COMMENT
);
1017 state
= SCE_H_SGML_1ST_PARAM
;
1020 case SCE_H_SGML_SPECIAL
:
1021 if (!(isascii(ch
) && isupper(ch
))) {
1022 styler
.ColourTo(i
- 1, StateToPrint
);
1024 state
= SCE_H_SGML_ERROR
;
1026 state
= SCE_H_SGML_DEFAULT
;
1030 case SCE_H_SGML_ENTITY
:
1032 styler
.ColourTo(i
, StateToPrint
);
1033 state
= SCE_H_SGML_DEFAULT
;
1034 } else if (!(isascii(ch
) && isalnum(ch
)) && ch
!= '-' && ch
!= '.') {
1035 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
1036 state
= SCE_H_SGML_DEFAULT
;
1041 styler
.ColourTo(i
, StateToPrint
);
1042 state
= SCE_H_DEFAULT
;
1044 if (ch
!= '#' && !(isascii(ch
) && isalnum(ch
)) // Should check that '#' follows '&', but it is unlikely anyway...
1045 && ch
!= '.' && ch
!= '-' && ch
!= '_' && ch
!= ':') { // valid in XML
1046 styler
.ColourTo(i
, SCE_H_TAGUNKNOWN
);
1047 state
= SCE_H_DEFAULT
;
1050 case SCE_H_TAGUNKNOWN
:
1051 if (!setTagContinue
.Contains(ch
) && !((ch
== '/') && (chPrev
== '<'))) {
1052 int eClass
= classifyTagHTML(styler
.GetStartSegment(),
1053 i
- 1, keywords
, styler
, tagDontFold
, caseSensitive
, isXml
);
1054 if (eClass
== SCE_H_SCRIPT
) {
1056 inScriptType
= eNonHtmlScript
;
1057 scriptLanguage
= clientScript
;
1060 scriptLanguage
= eScriptNone
;
1065 styler
.ColourTo(i
, eClass
);
1066 if (inScriptType
== eNonHtmlScript
) {
1067 state
= StateForScript(scriptLanguage
);
1069 state
= SCE_H_DEFAULT
;
1080 } else if (ch
== '/' && chNext
== '>') {
1081 if (eClass
== SCE_H_TAGUNKNOWN
) {
1082 styler
.ColourTo(i
+ 1, SCE_H_TAGUNKNOWN
);
1084 styler
.ColourTo(i
- 1, StateToPrint
);
1085 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1089 state
= SCE_H_DEFAULT
;
1092 if (eClass
!= SCE_H_TAGUNKNOWN
) {
1093 if (eClass
== SCE_H_SGML_DEFAULT
) {
1094 state
= SCE_H_SGML_DEFAULT
;
1096 state
= SCE_H_OTHER
;
1102 case SCE_H_ATTRIBUTE
:
1103 if (!setAttributeContinue
.Contains(ch
)) {
1104 if (inScriptType
== eNonHtmlScript
) {
1105 int scriptLanguagePrev
= scriptLanguage
;
1106 clientScript
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
- 1, scriptLanguage
);
1107 scriptLanguage
= clientScript
;
1108 if ((scriptLanguagePrev
!= scriptLanguage
) && (scriptLanguage
== eScriptNone
))
1109 inScriptType
= eHtml
;
1111 classifyAttribHTML(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
1113 styler
.ColourTo(i
, SCE_H_TAG
);
1114 if (inScriptType
== eNonHtmlScript
) {
1115 state
= StateForScript(scriptLanguage
);
1117 state
= SCE_H_DEFAULT
;
1128 } else if (ch
== '=') {
1129 styler
.ColourTo(i
, SCE_H_OTHER
);
1130 state
= SCE_H_VALUE
;
1132 state
= SCE_H_OTHER
;
1138 styler
.ColourTo(i
- 1, StateToPrint
);
1139 styler
.ColourTo(i
, SCE_H_TAG
);
1140 if (inScriptType
== eNonHtmlScript
) {
1141 state
= StateForScript(scriptLanguage
);
1143 state
= SCE_H_DEFAULT
;
1154 } else if (ch
== '\"') {
1155 styler
.ColourTo(i
- 1, StateToPrint
);
1156 state
= SCE_H_DOUBLESTRING
;
1157 } else if (ch
== '\'') {
1158 styler
.ColourTo(i
- 1, StateToPrint
);
1159 state
= SCE_H_SINGLESTRING
;
1160 } else if (ch
== '=') {
1161 styler
.ColourTo(i
, StateToPrint
);
1162 state
= SCE_H_VALUE
;
1163 } else if (ch
== '/' && chNext
== '>') {
1164 styler
.ColourTo(i
- 1, StateToPrint
);
1165 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1168 state
= SCE_H_DEFAULT
;
1170 } else if (ch
== '?' && chNext
== '>') {
1171 styler
.ColourTo(i
- 1, StateToPrint
);
1172 styler
.ColourTo(i
+ 1, SCE_H_XMLEND
);
1175 state
= SCE_H_DEFAULT
;
1176 } else if (setHTMLWord
.Contains(ch
)) {
1177 styler
.ColourTo(i
- 1, StateToPrint
);
1178 state
= SCE_H_ATTRIBUTE
;
1181 case SCE_H_DOUBLESTRING
:
1183 if (inScriptType
== eNonHtmlScript
) {
1184 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1186 styler
.ColourTo(i
, SCE_H_DOUBLESTRING
);
1187 state
= SCE_H_OTHER
;
1190 case SCE_H_SINGLESTRING
:
1192 if (inScriptType
== eNonHtmlScript
) {
1193 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1195 styler
.ColourTo(i
, SCE_H_SINGLESTRING
);
1196 state
= SCE_H_OTHER
;
1200 if (!setHTMLWord
.Contains(ch
)) {
1201 if (ch
== '\"' && chPrev
== '=') {
1202 // Should really test for being first character
1203 state
= SCE_H_DOUBLESTRING
;
1204 } else if (ch
== '\'' && chPrev
== '=') {
1205 state
= SCE_H_SINGLESTRING
;
1207 if (IsNumber(styler
.GetStartSegment(), styler
)) {
1208 styler
.ColourTo(i
- 1, SCE_H_NUMBER
);
1210 styler
.ColourTo(i
- 1, StateToPrint
);
1213 styler
.ColourTo(i
, SCE_H_TAG
);
1214 if (inScriptType
== eNonHtmlScript
) {
1215 state
= StateForScript(scriptLanguage
);
1217 state
= SCE_H_DEFAULT
;
1229 state
= SCE_H_OTHER
;
1234 case SCE_HJ_DEFAULT
:
1236 case SCE_HJ_SYMBOLS
:
1237 if (IsAWordStart(ch
)) {
1238 styler
.ColourTo(i
- 1, StateToPrint
);
1239 state
= SCE_HJ_WORD
;
1240 } else if (ch
== '/' && chNext
== '*') {
1241 styler
.ColourTo(i
- 1, StateToPrint
);
1243 state
= SCE_HJ_COMMENTDOC
;
1245 state
= SCE_HJ_COMMENT
;
1246 } else if (ch
== '/' && chNext
== '/') {
1247 styler
.ColourTo(i
- 1, StateToPrint
);
1248 state
= SCE_HJ_COMMENTLINE
;
1249 } else if (ch
== '/' && isOKBeforeRE(chPrevNonWhite
)) {
1250 styler
.ColourTo(i
- 1, StateToPrint
);
1251 state
= SCE_HJ_REGEX
;
1252 } else if (ch
== '\"') {
1253 styler
.ColourTo(i
- 1, StateToPrint
);
1254 state
= SCE_HJ_DOUBLESTRING
;
1255 } else if (ch
== '\'') {
1256 styler
.ColourTo(i
- 1, StateToPrint
);
1257 state
= SCE_HJ_SINGLESTRING
;
1258 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1259 styler
.SafeGetCharAt(i
+ 3) == '-') {
1260 styler
.ColourTo(i
- 1, StateToPrint
);
1261 state
= SCE_HJ_COMMENTLINE
;
1262 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1263 styler
.ColourTo(i
- 1, StateToPrint
);
1264 state
= SCE_HJ_COMMENTLINE
;
1266 } else if (IsOperator(ch
)) {
1267 styler
.ColourTo(i
- 1, StateToPrint
);
1268 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1269 state
= SCE_HJ_DEFAULT
;
1270 } else if ((ch
== ' ') || (ch
== '\t')) {
1271 if (state
== SCE_HJ_START
) {
1272 styler
.ColourTo(i
- 1, StateToPrint
);
1273 state
= SCE_HJ_DEFAULT
;
1278 if (!IsAWordChar(ch
)) {
1279 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
1280 //styler.ColourTo(i - 1, eHTJSKeyword);
1281 state
= SCE_HJ_DEFAULT
;
1282 if (ch
== '/' && chNext
== '*') {
1284 state
= SCE_HJ_COMMENTDOC
;
1286 state
= SCE_HJ_COMMENT
;
1287 } else if (ch
== '/' && chNext
== '/') {
1288 state
= SCE_HJ_COMMENTLINE
;
1289 } else if (ch
== '\"') {
1290 state
= SCE_HJ_DOUBLESTRING
;
1291 } else if (ch
== '\'') {
1292 state
= SCE_HJ_SINGLESTRING
;
1293 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1294 styler
.ColourTo(i
- 1, StateToPrint
);
1295 state
= SCE_HJ_COMMENTLINE
;
1297 } else if (IsOperator(ch
)) {
1298 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1299 state
= SCE_HJ_DEFAULT
;
1303 case SCE_HJ_COMMENT
:
1304 case SCE_HJ_COMMENTDOC
:
1305 if (ch
== '/' && chPrev
== '*') {
1306 styler
.ColourTo(i
, StateToPrint
);
1307 state
= SCE_HJ_DEFAULT
;
1311 case SCE_HJ_COMMENTLINE
:
1312 if (ch
== '\r' || ch
== '\n') {
1313 styler
.ColourTo(i
- 1, statePrintForState(SCE_HJ_COMMENTLINE
, inScriptType
));
1314 state
= SCE_HJ_DEFAULT
;
1318 case SCE_HJ_DOUBLESTRING
:
1320 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1323 } else if (ch
== '\"') {
1324 styler
.ColourTo(i
, statePrintForState(SCE_HJ_DOUBLESTRING
, inScriptType
));
1325 state
= SCE_HJ_DEFAULT
;
1326 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1327 styler
.ColourTo(i
- 1, StateToPrint
);
1328 state
= SCE_HJ_COMMENTLINE
;
1330 } else if (isLineEnd(ch
)) {
1331 styler
.ColourTo(i
- 1, StateToPrint
);
1332 state
= SCE_HJ_STRINGEOL
;
1335 case SCE_HJ_SINGLESTRING
:
1337 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1340 } else if (ch
== '\'') {
1341 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SINGLESTRING
, inScriptType
));
1342 state
= SCE_HJ_DEFAULT
;
1343 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1344 styler
.ColourTo(i
- 1, StateToPrint
);
1345 state
= SCE_HJ_COMMENTLINE
;
1347 } else if (isLineEnd(ch
)) {
1348 styler
.ColourTo(i
- 1, StateToPrint
);
1349 state
= SCE_HJ_STRINGEOL
;
1352 case SCE_HJ_STRINGEOL
:
1353 if (!isLineEnd(ch
)) {
1354 styler
.ColourTo(i
- 1, StateToPrint
);
1355 state
= SCE_HJ_DEFAULT
;
1356 } else if (!isLineEnd(chNext
)) {
1357 styler
.ColourTo(i
, StateToPrint
);
1358 state
= SCE_HJ_DEFAULT
;
1362 if (ch
== '\r' || ch
== '\n' || ch
== '/') {
1364 while (isascii(chNext
) && islower(chNext
)) { // gobble regex flags
1367 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1370 styler
.ColourTo(i
, StateToPrint
);
1371 state
= SCE_HJ_DEFAULT
;
1372 } else if (ch
== '\\') {
1373 // Gobble up the quoted character
1374 if (chNext
== '\\' || chNext
== '/') {
1377 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1381 case SCE_HB_DEFAULT
:
1383 if (IsAWordStart(ch
)) {
1384 styler
.ColourTo(i
- 1, StateToPrint
);
1385 state
= SCE_HB_WORD
;
1386 } else if (ch
== '\'') {
1387 styler
.ColourTo(i
- 1, StateToPrint
);
1388 state
= SCE_HB_COMMENTLINE
;
1389 } else if (ch
== '\"') {
1390 styler
.ColourTo(i
- 1, StateToPrint
);
1391 state
= SCE_HB_STRING
;
1392 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1393 styler
.SafeGetCharAt(i
+ 3) == '-') {
1394 styler
.ColourTo(i
- 1, StateToPrint
);
1395 state
= SCE_HB_COMMENTLINE
;
1396 } else if (IsOperator(ch
)) {
1397 styler
.ColourTo(i
- 1, StateToPrint
);
1398 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1399 state
= SCE_HB_DEFAULT
;
1400 } else if ((ch
== ' ') || (ch
== '\t')) {
1401 if (state
== SCE_HB_START
) {
1402 styler
.ColourTo(i
- 1, StateToPrint
);
1403 state
= SCE_HB_DEFAULT
;
1408 if (!IsAWordChar(ch
)) {
1409 state
= classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
1410 if (state
== SCE_HB_DEFAULT
) {
1412 state
= SCE_HB_STRING
;
1413 } else if (ch
== '\'') {
1414 state
= SCE_HB_COMMENTLINE
;
1415 } else if (IsOperator(ch
)) {
1416 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1417 state
= SCE_HB_DEFAULT
;
1424 styler
.ColourTo(i
, StateToPrint
);
1425 state
= SCE_HB_DEFAULT
;
1426 } else if (ch
== '\r' || ch
== '\n') {
1427 styler
.ColourTo(i
- 1, StateToPrint
);
1428 state
= SCE_HB_STRINGEOL
;
1431 case SCE_HB_COMMENTLINE
:
1432 if (ch
== '\r' || ch
== '\n') {
1433 styler
.ColourTo(i
- 1, StateToPrint
);
1434 state
= SCE_HB_DEFAULT
;
1437 case SCE_HB_STRINGEOL
:
1438 if (!isLineEnd(ch
)) {
1439 styler
.ColourTo(i
- 1, StateToPrint
);
1440 state
= SCE_HB_DEFAULT
;
1441 } else if (!isLineEnd(chNext
)) {
1442 styler
.ColourTo(i
, StateToPrint
);
1443 state
= SCE_HB_DEFAULT
;
1446 case SCE_HP_DEFAULT
:
1448 if (IsAWordStart(ch
)) {
1449 styler
.ColourTo(i
- 1, StateToPrint
);
1450 state
= SCE_HP_WORD
;
1451 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1452 styler
.SafeGetCharAt(i
+ 3) == '-') {
1453 styler
.ColourTo(i
- 1, StateToPrint
);
1454 state
= SCE_HP_COMMENTLINE
;
1455 } else if (ch
== '#') {
1456 styler
.ColourTo(i
- 1, StateToPrint
);
1457 state
= SCE_HP_COMMENTLINE
;
1458 } else if (ch
== '\"') {
1459 styler
.ColourTo(i
- 1, StateToPrint
);
1460 if (chNext
== '\"' && chNext2
== '\"') {
1462 state
= SCE_HP_TRIPLEDOUBLE
;
1465 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1467 // state = statePrintForState(SCE_HP_STRING,inScriptType);
1468 state
= SCE_HP_STRING
;
1470 } else if (ch
== '\'') {
1471 styler
.ColourTo(i
- 1, StateToPrint
);
1472 if (chNext
== '\'' && chNext2
== '\'') {
1474 state
= SCE_HP_TRIPLE
;
1477 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1479 state
= SCE_HP_CHARACTER
;
1481 } else if (IsOperator(ch
)) {
1482 styler
.ColourTo(i
- 1, StateToPrint
);
1483 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1484 } else if ((ch
== ' ') || (ch
== '\t')) {
1485 if (state
== SCE_HP_START
) {
1486 styler
.ColourTo(i
- 1, StateToPrint
);
1487 state
= SCE_HP_DEFAULT
;
1492 if (!IsAWordChar(ch
)) {
1493 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
1494 state
= SCE_HP_DEFAULT
;
1496 state
= SCE_HP_COMMENTLINE
;
1497 } else if (ch
== '\"') {
1498 if (chNext
== '\"' && chNext2
== '\"') {
1500 state
= SCE_HP_TRIPLEDOUBLE
;
1503 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1505 state
= SCE_HP_STRING
;
1507 } else if (ch
== '\'') {
1508 if (chNext
== '\'' && chNext2
== '\'') {
1510 state
= SCE_HP_TRIPLE
;
1513 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1515 state
= SCE_HP_CHARACTER
;
1517 } else if (IsOperator(ch
)) {
1518 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1522 case SCE_HP_COMMENTLINE
:
1523 if (ch
== '\r' || ch
== '\n') {
1524 styler
.ColourTo(i
- 1, StateToPrint
);
1525 state
= SCE_HP_DEFAULT
;
1530 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1533 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1535 } else if (ch
== '\"') {
1536 styler
.ColourTo(i
, StateToPrint
);
1537 state
= SCE_HP_DEFAULT
;
1540 case SCE_HP_CHARACTER
:
1542 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1545 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1547 } else if (ch
== '\'') {
1548 styler
.ColourTo(i
, StateToPrint
);
1549 state
= SCE_HP_DEFAULT
;
1553 if (ch
== '\'' && chPrev
== '\'' && chPrev2
== '\'') {
1554 styler
.ColourTo(i
, StateToPrint
);
1555 state
= SCE_HP_DEFAULT
;
1558 case SCE_HP_TRIPLEDOUBLE
:
1559 if (ch
== '\"' && chPrev
== '\"' && chPrev2
== '\"') {
1560 styler
.ColourTo(i
, StateToPrint
);
1561 state
= SCE_HP_DEFAULT
;
1564 ///////////// start - PHP state handling
1566 if (!IsAWordChar(ch
)) {
1567 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
1568 if (ch
== '/' && chNext
== '*') {
1570 state
= SCE_HPHP_COMMENT
;
1571 } else if (ch
== '/' && chNext
== '/') {
1573 state
= SCE_HPHP_COMMENTLINE
;
1574 } else if (ch
== '#') {
1575 state
= SCE_HPHP_COMMENTLINE
;
1576 } else if (ch
== '\"') {
1577 state
= SCE_HPHP_HSTRING
;
1578 strcpy(phpStringDelimiter
, "\"");
1579 } else if (styler
.Match(i
, "<<<")) {
1580 state
= SCE_HPHP_HSTRING
;
1581 i
= FindPhpStringDelimiter(phpStringDelimiter
, sizeof(phpStringDelimiter
), i
+ 3, lengthDoc
, styler
);
1582 } else if (ch
== '\'') {
1583 state
= SCE_HPHP_SIMPLESTRING
;
1584 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1585 state
= SCE_HPHP_VARIABLE
;
1586 } else if (IsOperator(ch
)) {
1587 state
= SCE_HPHP_OPERATOR
;
1589 state
= SCE_HPHP_DEFAULT
;
1593 case SCE_HPHP_NUMBER
:
1594 // recognize bases 8,10 or 16 integers OR floating-point numbers
1596 && strchr(".xXabcdefABCDEF", ch
) == NULL
1597 && ((ch
!= '-' && ch
!= '+') || (chPrev
!= 'e' && chPrev
!= 'E'))) {
1598 styler
.ColourTo(i
- 1, SCE_HPHP_NUMBER
);
1600 state
= SCE_HPHP_OPERATOR
;
1602 state
= SCE_HPHP_DEFAULT
;
1605 case SCE_HPHP_VARIABLE
:
1606 if (!IsPhpWordChar(ch
)) {
1607 styler
.ColourTo(i
- 1, SCE_HPHP_VARIABLE
);
1609 state
= SCE_HPHP_OPERATOR
;
1611 state
= SCE_HPHP_DEFAULT
;
1614 case SCE_HPHP_COMMENT
:
1615 if (ch
== '/' && chPrev
== '*') {
1616 styler
.ColourTo(i
, StateToPrint
);
1617 state
= SCE_HPHP_DEFAULT
;
1620 case SCE_HPHP_COMMENTLINE
:
1621 if (ch
== '\r' || ch
== '\n') {
1622 styler
.ColourTo(i
- 1, StateToPrint
);
1623 state
= SCE_HPHP_DEFAULT
;
1626 case SCE_HPHP_HSTRING
:
1627 if (ch
== '\\' && (phpStringDelimiter
[0] == '\"' || chNext
== '$' || chNext
== '{')) {
1628 // skip the next char
1630 } else if (((ch
== '{' && chNext
== '$') || (ch
== '$' && chNext
== '{'))
1631 && IsPhpWordStart(chNext2
)) {
1632 styler
.ColourTo(i
- 1, StateToPrint
);
1633 state
= SCE_HPHP_COMPLEX_VARIABLE
;
1634 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1635 styler
.ColourTo(i
- 1, StateToPrint
);
1636 state
= SCE_HPHP_HSTRING_VARIABLE
;
1637 } else if (styler
.Match(i
, phpStringDelimiter
)) {
1638 const int psdLength
= strlen(phpStringDelimiter
);
1639 if ((psdLength
> 1) && ((i
+ psdLength
) < lengthDoc
))
1641 styler
.ColourTo(i
, StateToPrint
);
1642 state
= SCE_HPHP_DEFAULT
;
1645 case SCE_HPHP_SIMPLESTRING
:
1647 // skip the next char
1649 } else if (ch
== '\'') {
1650 styler
.ColourTo(i
, StateToPrint
);
1651 state
= SCE_HPHP_DEFAULT
;
1654 case SCE_HPHP_HSTRING_VARIABLE
:
1655 if (!IsPhpWordChar(ch
)) {
1656 styler
.ColourTo(i
- 1, StateToPrint
);
1657 i
--; // strange but it works
1658 state
= SCE_HPHP_HSTRING
;
1661 case SCE_HPHP_COMPLEX_VARIABLE
:
1663 styler
.ColourTo(i
, StateToPrint
);
1664 state
= SCE_HPHP_HSTRING
;
1667 case SCE_HPHP_OPERATOR
:
1668 case SCE_HPHP_DEFAULT
:
1669 styler
.ColourTo(i
- 1, StateToPrint
);
1670 if (IsADigit(ch
) || (ch
== '.' && IsADigit(chNext
))) {
1671 state
= SCE_HPHP_NUMBER
;
1672 } else if (IsAWordStart(ch
)) {
1673 state
= SCE_HPHP_WORD
;
1674 } else if (ch
== '/' && chNext
== '*') {
1676 state
= SCE_HPHP_COMMENT
;
1677 } else if (ch
== '/' && chNext
== '/') {
1679 state
= SCE_HPHP_COMMENTLINE
;
1680 } else if (ch
== '#') {
1681 state
= SCE_HPHP_COMMENTLINE
;
1682 } else if (ch
== '\"') {
1683 state
= SCE_HPHP_HSTRING
;
1684 strcpy(phpStringDelimiter
, "\"");
1685 } else if (styler
.Match(i
, "<<<")) {
1686 state
= SCE_HPHP_HSTRING
;
1687 i
= FindPhpStringDelimiter(phpStringDelimiter
, sizeof(phpStringDelimiter
), i
+ 3, lengthDoc
, styler
);
1688 } else if (ch
== '\'') {
1689 state
= SCE_HPHP_SIMPLESTRING
;
1690 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1691 state
= SCE_HPHP_VARIABLE
;
1692 } else if (IsOperator(ch
)) {
1693 state
= SCE_HPHP_OPERATOR
;
1694 } else if ((state
== SCE_HPHP_OPERATOR
) && (IsASpace(ch
))) {
1695 state
= SCE_HPHP_DEFAULT
;
1698 ///////////// end - PHP state handling
1701 // Some of the above terminated their lexeme but since the same character starts
1702 // the same class again, only reenter if non empty segment.
1704 bool nonEmptySegment
= i
>= static_cast<int>(styler
.GetStartSegment());
1705 if (state
== SCE_HB_DEFAULT
) { // One of the above succeeded
1706 if ((ch
== '\"') && (nonEmptySegment
)) {
1707 state
= SCE_HB_STRING
;
1708 } else if (ch
== '\'') {
1709 state
= SCE_HB_COMMENTLINE
;
1710 } else if (IsAWordStart(ch
)) {
1711 state
= SCE_HB_WORD
;
1712 } else if (IsOperator(ch
)) {
1713 styler
.ColourTo(i
, SCE_HB_DEFAULT
);
1715 } else if (state
== SCE_HBA_DEFAULT
) { // One of the above succeeded
1716 if ((ch
== '\"') && (nonEmptySegment
)) {
1717 state
= SCE_HBA_STRING
;
1718 } else if (ch
== '\'') {
1719 state
= SCE_HBA_COMMENTLINE
;
1720 } else if (IsAWordStart(ch
)) {
1721 state
= SCE_HBA_WORD
;
1722 } else if (IsOperator(ch
)) {
1723 styler
.ColourTo(i
, SCE_HBA_DEFAULT
);
1725 } else if (state
== SCE_HJ_DEFAULT
) { // One of the above succeeded
1726 if (ch
== '/' && chNext
== '*') {
1727 if (styler
.SafeGetCharAt(i
+ 2) == '*')
1728 state
= SCE_HJ_COMMENTDOC
;
1730 state
= SCE_HJ_COMMENT
;
1731 } else if (ch
== '/' && chNext
== '/') {
1732 state
= SCE_HJ_COMMENTLINE
;
1733 } else if ((ch
== '\"') && (nonEmptySegment
)) {
1734 state
= SCE_HJ_DOUBLESTRING
;
1735 } else if ((ch
== '\'') && (nonEmptySegment
)) {
1736 state
= SCE_HJ_SINGLESTRING
;
1737 } else if (IsAWordStart(ch
)) {
1738 state
= SCE_HJ_WORD
;
1739 } else if (IsOperator(ch
)) {
1740 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1745 StateToPrint
= statePrintForState(state
, inScriptType
);
1746 styler
.ColourTo(lengthDoc
- 1, StateToPrint
);
1748 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
1750 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
1751 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
1755 static void ColouriseXMLDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
1757 // Passing in true because we're lexing XML
1758 ColouriseHyperTextDoc(startPos
, length
, initStyle
, keywordlists
,styler
, true);
1761 static void ColouriseHTMLDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
1763 // Passing in false because we're notlexing XML
1764 ColouriseHyperTextDoc(startPos
, length
, initStyle
, keywordlists
,styler
, false);
1767 static bool isASPScript(int state
) {
1769 (state
>= SCE_HJA_START
&& state
<= SCE_HJA_REGEX
) ||
1770 (state
>= SCE_HBA_START
&& state
<= SCE_HBA_STRINGEOL
) ||
1771 (state
>= SCE_HPA_DEFAULT
&& state
<= SCE_HPA_IDENTIFIER
);
1774 static void ColouriseHBAPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1775 WordList
&keywordsVBS
= *keywordlists
[2];
1776 if (sc
.state
== SCE_HBA_WORD
) {
1777 if (!IsAWordChar(sc
.ch
)) {
1779 sc
.GetCurrentLowered(s
, sizeof(s
));
1780 if (keywordsVBS
.InList(s
)) {
1781 if (strcmp(s
, "rem") == 0) {
1782 sc
.ChangeState(SCE_HBA_COMMENTLINE
);
1784 sc
.SetState(SCE_HBA_DEFAULT
);
1787 sc
.SetState(SCE_HBA_DEFAULT
);
1790 sc
.ChangeState(SCE_HBA_IDENTIFIER
);
1791 sc
.SetState(SCE_HBA_DEFAULT
);
1794 } else if (sc
.state
== SCE_HBA_NUMBER
) {
1795 if (!IsAWordChar(sc
.ch
)) {
1796 sc
.SetState(SCE_HBA_DEFAULT
);
1798 } else if (sc
.state
== SCE_HBA_STRING
) {
1799 if (sc
.ch
== '\"') {
1800 sc
.ForwardSetState(SCE_HBA_DEFAULT
);
1801 } else if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1802 sc
.ChangeState(SCE_HBA_STRINGEOL
);
1803 sc
.ForwardSetState(SCE_HBA_DEFAULT
);
1805 } else if (sc
.state
== SCE_HBA_COMMENTLINE
) {
1806 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1807 sc
.SetState(SCE_HBA_DEFAULT
);
1811 if (sc
.state
== SCE_HBA_DEFAULT
) {
1812 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
1813 sc
.SetState(SCE_HBA_NUMBER
);
1814 } else if (IsAWordStart(sc
.ch
)) {
1815 sc
.SetState(SCE_HBA_WORD
);
1816 } else if (sc
.ch
== '\'') {
1817 sc
.SetState(SCE_HBA_COMMENTLINE
);
1818 } else if (sc
.ch
== '\"') {
1819 sc
.SetState(SCE_HBA_STRING
);
1824 static void ColouriseHTMLPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1825 WordList
&keywordsTags
= *keywordlists
[0];
1826 if (sc
.state
== SCE_H_COMMENT
) {
1827 if (sc
.Match("-->")) {
1830 sc
.ForwardSetState(SCE_H_DEFAULT
);
1832 } else if (sc
.state
== SCE_H_ENTITY
) {
1834 sc
.ForwardSetState(SCE_H_DEFAULT
);
1835 } else if (sc
.ch
!= '#' && (sc
.ch
< 0x80) && !isalnum(sc
.ch
) // Should check that '#' follows '&', but it is unlikely anyway...
1836 && sc
.ch
!= '.' && sc
.ch
!= '-' && sc
.ch
!= '_' && sc
.ch
!= ':') { // valid in XML
1837 sc
.ChangeState(SCE_H_TAGUNKNOWN
);
1838 sc
.SetState(SCE_H_DEFAULT
);
1840 } else if (sc
.state
== SCE_H_TAGUNKNOWN
) {
1841 if (!ishtmlwordchar(sc
.ch
) && !((sc
.ch
== '/') && (sc
.chPrev
== '<')) && sc
.ch
!= '[') {
1843 sc
.GetCurrentLowered(s
, sizeof(s
));
1845 if (keywordsTags
.InList(s
+ 2)) {
1846 sc
.ChangeState(SCE_H_TAG
);
1849 if (keywordsTags
.InList(s
+ 1)) {
1850 sc
.ChangeState(SCE_H_TAG
);
1854 sc
.ForwardSetState(SCE_H_DEFAULT
);
1855 } else if (sc
.Match('/', '>')) {
1856 sc
.SetState(SCE_H_TAGEND
);
1858 sc
.ForwardSetState(SCE_H_DEFAULT
);
1860 sc
.SetState(SCE_H_OTHER
);
1863 } else if (sc
.state
== SCE_H_ATTRIBUTE
) {
1864 if (!ishtmlwordchar(sc
.ch
)) {
1866 sc
.GetCurrentLowered(s
, sizeof(s
));
1867 if (!keywordsTags
.InList(s
)) {
1868 sc
.ChangeState(SCE_H_ATTRIBUTEUNKNOWN
);
1870 sc
.SetState(SCE_H_OTHER
);
1872 } else if (sc
.state
== SCE_H_OTHER
) {
1874 sc
.SetState(SCE_H_TAG
);
1875 sc
.ForwardSetState(SCE_H_DEFAULT
);
1876 } else if (sc
.Match('/', '>')) {
1877 sc
.SetState(SCE_H_TAG
);
1879 sc
.ForwardSetState(SCE_H_DEFAULT
);
1880 } else if (sc
.chPrev
== '=') {
1881 sc
.SetState(SCE_H_VALUE
);
1883 } else if (sc
.state
== SCE_H_DOUBLESTRING
) {
1884 if (sc
.ch
== '\"') {
1885 sc
.ForwardSetState(SCE_H_OTHER
);
1887 } else if (sc
.state
== SCE_H_SINGLESTRING
) {
1888 if (sc
.ch
== '\'') {
1889 sc
.ForwardSetState(SCE_H_OTHER
);
1891 } else if (sc
.state
== SCE_H_NUMBER
) {
1892 if (!IsADigit(sc
.ch
)) {
1893 sc
.SetState(SCE_H_OTHER
);
1897 if (sc
.state
== SCE_H_DEFAULT
) {
1899 if (sc
.Match("<!--"))
1900 sc
.SetState(SCE_H_COMMENT
);
1902 sc
.SetState(SCE_H_TAGUNKNOWN
);
1903 } else if (sc
.ch
== '&') {
1904 sc
.SetState(SCE_H_ENTITY
);
1906 } else if ((sc
.state
== SCE_H_OTHER
) || (sc
.state
== SCE_H_VALUE
)) {
1907 if (sc
.ch
== '\"' && sc
.chPrev
== '=') {
1908 sc
.SetState(SCE_H_DOUBLESTRING
);
1909 } else if (sc
.ch
== '\'' && sc
.chPrev
== '=') {
1910 sc
.SetState(SCE_H_SINGLESTRING
);
1911 } else if (IsADigit(sc
.ch
)) {
1912 sc
.SetState(SCE_H_NUMBER
);
1913 } else if (sc
.ch
== '>') {
1914 sc
.SetState(SCE_H_TAG
);
1915 sc
.ForwardSetState(SCE_H_DEFAULT
);
1916 } else if (ishtmlwordchar(sc
.ch
)) {
1917 sc
.SetState(SCE_H_ATTRIBUTE
);
1922 static void ColouriseASPPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1923 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1924 if ((sc
.state
== SCE_H_ASPAT
|| isASPScript(sc
.state
)) && sc
.Match('%', '>')) {
1925 sc
.SetState(SCE_H_ASP
);
1927 sc
.ForwardSetState(SCE_H_DEFAULT
);
1930 // Handle some ASP script
1931 if (sc
.state
>= SCE_HBA_START
&& sc
.state
<= SCE_HBA_STRINGEOL
) {
1932 ColouriseHBAPiece(sc
, keywordlists
);
1933 } else if (sc
.state
>= SCE_H_DEFAULT
&& sc
.state
<= SCE_H_SGML_BLOCK_DEFAULT
) {
1934 ColouriseHTMLPiece(sc
, keywordlists
);
1937 // Enter new sc.state
1938 if ((sc
.state
== SCE_H_DEFAULT
) || (sc
.state
== SCE_H_TAGUNKNOWN
)) {
1939 if (sc
.Match('<', '%')) {
1940 if (sc
.state
== SCE_H_TAGUNKNOWN
)
1941 sc
.ChangeState(SCE_H_ASP
);
1943 sc
.SetState(SCE_H_ASP
);
1947 sc
.ForwardSetState(SCE_H_ASPAT
);
1952 sc
.SetState(SCE_HBA_DEFAULT
);
1958 static void ColouriseASPDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
1960 // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
1961 StyleContext
sc(startPos
, length
, initStyle
, styler
, static_cast<char>(STYLE_MAX
));
1962 for (; sc
.More(); sc
.Forward()) {
1963 ColouriseASPPiece(sc
, keywordlists
);
1968 static void ColourisePHPPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1969 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1970 if (sc
.state
>= SCE_HPHP_DEFAULT
&& sc
.state
<= SCE_HPHP_OPERATOR
) {
1971 if (!isPHPStringState(sc
.state
) &&
1972 (sc
.state
!= SCE_HPHP_COMMENT
) &&
1973 (sc
.Match('?', '>'))) {
1974 sc
.SetState(SCE_H_QUESTION
);
1976 sc
.ForwardSetState(SCE_H_DEFAULT
);
1980 if (sc
.state
>= SCE_H_DEFAULT
&& sc
.state
<= SCE_H_SGML_BLOCK_DEFAULT
) {
1981 ColouriseHTMLPiece(sc
, keywordlists
);
1984 // Handle some PHP script
1985 if (sc
.state
== SCE_HPHP_WORD
) {
1986 if (!IsPhpWordChar(static_cast<char>(sc
.ch
))) {
1987 sc
.SetState(SCE_HPHP_DEFAULT
);
1989 } else if (sc
.state
== SCE_HPHP_COMMENTLINE
) {
1990 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1991 sc
.SetState(SCE_HPHP_DEFAULT
);
1993 } else if (sc
.state
== SCE_HPHP_COMMENT
) {
1994 if (sc
.Match('*', '/')) {
1997 sc
.SetState(SCE_HPHP_DEFAULT
);
1999 } else if (sc
.state
== SCE_HPHP_HSTRING
) {
2000 if (sc
.ch
== '\"') {
2001 sc
.ForwardSetState(SCE_HPHP_DEFAULT
);
2003 } else if (sc
.state
== SCE_HPHP_SIMPLESTRING
) {
2004 if (sc
.ch
== '\'') {
2005 sc
.ForwardSetState(SCE_HPHP_DEFAULT
);
2007 } else if (sc
.state
== SCE_HPHP_VARIABLE
) {
2008 if (!IsPhpWordChar(static_cast<char>(sc
.ch
))) {
2009 sc
.SetState(SCE_HPHP_DEFAULT
);
2011 } else if (sc
.state
== SCE_HPHP_OPERATOR
) {
2012 sc
.SetState(SCE_HPHP_DEFAULT
);
2015 // Enter new sc.state
2016 if ((sc
.state
== SCE_H_DEFAULT
) || (sc
.state
== SCE_H_TAGUNKNOWN
)) {
2017 if (sc
.Match("<?php")) {
2018 sc
.SetState(SCE_H_QUESTION
);
2024 sc
.SetState(SCE_HPHP_DEFAULT
);
2027 if (sc
.state
== SCE_HPHP_DEFAULT
) {
2028 if (IsPhpWordStart(static_cast<char>(sc
.ch
))) {
2029 sc
.SetState(SCE_HPHP_WORD
);
2030 } else if (sc
.ch
== '#') {
2031 sc
.SetState(SCE_HPHP_COMMENTLINE
);
2032 } else if (sc
.Match("<!--")) {
2033 sc
.SetState(SCE_HPHP_COMMENTLINE
);
2034 } else if (sc
.Match('/', '/')) {
2035 sc
.SetState(SCE_HPHP_COMMENTLINE
);
2036 } else if (sc
.Match('/', '*')) {
2037 sc
.SetState(SCE_HPHP_COMMENT
);
2038 } else if (sc
.ch
== '\"') {
2039 sc
.SetState(SCE_HPHP_HSTRING
);
2040 } else if (sc
.ch
== '\'') {
2041 sc
.SetState(SCE_HPHP_SIMPLESTRING
);
2042 } else if (sc
.ch
== '$' && IsPhpWordStart(static_cast<char>(sc
.chNext
))) {
2043 sc
.SetState(SCE_HPHP_VARIABLE
);
2044 } else if (IsOperator(static_cast<char>(sc
.ch
))) {
2045 sc
.SetState(SCE_HPHP_OPERATOR
);
2050 static void ColourisePHPDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
2052 // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
2053 StyleContext
sc(startPos
, length
, initStyle
, styler
, static_cast<char>(STYLE_MAX
));
2054 for (; sc
.More(); sc
.Forward()) {
2055 ColourisePHPPiece(sc
, keywordlists
);
2060 static void ColourisePHPScriptDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
2062 if(startPos
== 0) initStyle
= SCE_HPHP_DEFAULT
;
2063 ColouriseHTMLDoc(startPos
,length
,initStyle
,keywordlists
,styler
);
2066 static const char * const htmlWordListDesc
[] = {
2067 "HTML elements and attributes",
2068 "JavaScript keywords",
2069 "VBScript keywords",
2072 "SGML and DTD keywords",
2076 static const char * const phpscriptWordListDesc
[] = {
2086 LexerModule
lmHTML(SCLEX_HTML
, ColouriseHTMLDoc
, "hypertext", 0, htmlWordListDesc
, 8);
2087 LexerModule
lmXML(SCLEX_XML
, ColouriseXMLDoc
, "xml", 0, htmlWordListDesc
, 8);
2088 // SCLEX_ASP and SCLEX_PHP should not be used in new code: use SCLEX_HTML instead.
2089 LexerModule
lmASP(SCLEX_ASP
, ColouriseASPDoc
, "asp", 0, htmlWordListDesc
, 8);
2090 LexerModule
lmPHP(SCLEX_PHP
, ColourisePHPDoc
, "php", 0, htmlWordListDesc
, 8);
2091 LexerModule
lmPHPSCRIPT(SCLEX_PHPSCRIPT
, ColourisePHPScriptDoc
, "phpscript", 0, phpscriptWordListDesc
, 8);