1 // Scintilla source code edit control
5 // Copyright 1998-2002 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 script_type
segIsScriptingIndicator(Accessor
&styler
, unsigned int start
, unsigned int end
, script_type prevValue
) {
41 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
42 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
45 //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
46 if (strstr(s
, "src")) // External script
50 if (strstr(s
, "pyth"))
52 if (strstr(s
, "javas"))
54 if (strstr(s
, "jscr"))
64 static int PrintScriptingIndicatorOffset(Accessor
&styler
, unsigned int start
, unsigned int end
) {
68 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
69 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
72 if (0 == strncmp(s
, "php", 3)) {
79 static script_type
ScriptOfState(int state
) {
80 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
82 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
84 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
86 } else if ((state
>= SCE_HPHP_DEFAULT
) && (state
<= SCE_HPHP_COMMENTLINE
)) {
88 } else if ((state
>= SCE_H_SGML_DEFAULT
) && (state
< SCE_H_SGML_BLOCK_DEFAULT
)) {
90 } else if (state
== SCE_H_SGML_BLOCK_DEFAULT
) {
91 return eScriptSGMLblock
;
97 static int statePrintForState(int state
, script_mode inScriptType
) {
100 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
101 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_PYTHON
);
102 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
103 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_VBS
);
104 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
105 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_JS
);
107 StateToPrint
= state
;
113 static int stateForPrintState(int StateToPrint
) {
116 if ((StateToPrint
>= SCE_HPA_START
) && (StateToPrint
<= SCE_HPA_IDENTIFIER
)) {
117 state
= StateToPrint
- SCE_HA_PYTHON
;
118 } else if ((StateToPrint
>= SCE_HBA_START
) && (StateToPrint
<= SCE_HBA_STRINGEOL
)) {
119 state
= StateToPrint
- SCE_HA_VBS
;
120 } else if ((StateToPrint
>= SCE_HJA_START
) && (StateToPrint
<= SCE_HJA_REGEX
)) {
121 state
= StateToPrint
- SCE_HA_JS
;
123 state
= StateToPrint
;
129 static inline bool IsNumber(unsigned int start
, Accessor
&styler
) {
130 return isdigit(styler
[start
]) || (styler
[start
] == '.') ||
131 (styler
[start
] == '-') || (styler
[start
] == '#');
134 static inline bool isStringState(int state
) {
138 case SCE_HJ_DOUBLESTRING
:
139 case SCE_HJ_SINGLESTRING
:
140 case SCE_HJA_DOUBLESTRING
:
141 case SCE_HJA_SINGLESTRING
:
146 case SCE_HPHP_HSTRING
:
147 case SCE_HPHP_SIMPLESTRING
:
157 // not really well done, since it's only comments that should lex the %> and <%
158 static inline bool isCommentASPState(int state
) {
163 case SCE_HJ_COMMENTLINE
:
164 case SCE_HJ_COMMENTDOC
:
165 case SCE_HB_COMMENTLINE
:
166 case SCE_HP_COMMENTLINE
:
167 case SCE_HPHP_COMMENT
:
168 case SCE_HPHP_COMMENTLINE
:
178 static void classifyAttribHTML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
179 bool wordIsNumber
= IsNumber(start
, styler
);
180 char chAttr
= SCE_H_ATTRIBUTEUNKNOWN
;
182 chAttr
= SCE_H_NUMBER
;
186 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
187 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
190 if (keywords
.InList(s
))
191 chAttr
= SCE_H_ATTRIBUTE
;
193 if ((chAttr
== SCE_H_ATTRIBUTEUNKNOWN
) && !keywords
)
194 // No keywords -> all are known
195 chAttr
= SCE_H_ATTRIBUTE
;
196 styler
.ColourTo(end
, chAttr
);
199 static int classifyTagHTML(unsigned int start
, unsigned int end
,
200 WordList
&keywords
, Accessor
&styler
) {
202 // Copy after the '<'
204 for (unsigned int cPos
= start
; cPos
<= end
&& i
< 30; cPos
++) {
205 char ch
= styler
[cPos
];
206 if ((ch
!= '<') && (ch
!= '/'))
207 s
[i
++] = static_cast<char>(tolower(ch
));
210 bool isScript
= false;
211 char chAttr
= SCE_H_TAGUNKNOWN
;
213 chAttr
= SCE_H_SGML_DEFAULT
;
214 } else if (s
[0] == '/') { // Closing tag
215 if (keywords
.InList(s
+ 1))
218 if (keywords
.InList(s
)) {
220 isScript
= 0 == strcmp(s
, "script");
223 if ((chAttr
== SCE_H_TAGUNKNOWN
) && !keywords
)
224 // No keywords -> all are known
226 styler
.ColourTo(end
, chAttr
);
227 return isScript
? SCE_H_SCRIPT
: chAttr
;
230 static void classifyWordHTJS(unsigned int start
, unsigned int end
,
231 WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
232 char chAttr
= SCE_HJ_WORD
;
233 bool wordIsNumber
= isdigit(styler
[start
]) || (styler
[start
] == '.');
235 chAttr
= SCE_HJ_NUMBER
;
239 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
240 s
[i
] = styler
[start
+ i
];
243 if (keywords
.InList(s
))
244 chAttr
= SCE_HJ_KEYWORD
;
246 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
249 static int classifyWordHTVB(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
250 char chAttr
= SCE_HB_IDENTIFIER
;
251 bool wordIsNumber
= isdigit(styler
[start
]) || (styler
[start
] == '.');
253 chAttr
= SCE_HB_NUMBER
;
257 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
258 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
261 if (keywords
.InList(s
)) {
262 chAttr
= SCE_HB_WORD
;
263 if (strcmp(s
, "rem") == 0)
264 chAttr
= SCE_HB_COMMENTLINE
;
267 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
268 if (chAttr
== SCE_HB_COMMENTLINE
)
269 return SCE_HB_COMMENTLINE
;
271 return SCE_HB_DEFAULT
;
274 static void classifyWordHTPy(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, char *prevWord
, script_mode inScriptType
) {
275 bool wordIsNumber
= isdigit(styler
[start
]) != 0;
278 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
279 s
[i
] = styler
[start
+ i
];
282 char chAttr
= SCE_HP_IDENTIFIER
;
283 if (0 == strcmp(prevWord
, "class"))
284 chAttr
= SCE_HP_CLASSNAME
;
285 else if (0 == strcmp(prevWord
, "def"))
286 chAttr
= SCE_HP_DEFNAME
;
287 else if (wordIsNumber
)
288 chAttr
= SCE_HP_NUMBER
;
289 else if (keywords
.InList(s
))
290 chAttr
= SCE_HP_WORD
;
291 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
295 // Update the word colour to default or keyword
296 // Called when in a PHP word
297 static void classifyWordHTPHP(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
298 char chAttr
= SCE_HPHP_DEFAULT
;
299 bool wordIsNumber
= isdigit(styler
[start
]) != 0;
301 chAttr
= SCE_HPHP_NUMBER
;
305 for (; i
< end
- start
+ 1 && i
< 100; i
++) {
306 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
309 if (keywords
.InList(s
))
310 chAttr
= SCE_HPHP_WORD
;
312 styler
.ColourTo(end
, chAttr
);
315 static bool isWordHSGML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
318 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
319 s
[i
] = styler
[start
+ i
];
322 return keywords
.InList(s
);
325 static bool isWordCdata(unsigned int start
, unsigned int end
, Accessor
&styler
) {
328 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
329 s
[i
] = styler
[start
+ i
];
332 return (0 == strcmp(s
, "[CDATA["));
335 // Return the first state to reach when entering a scripting language
336 static int StateForScript(script_type scriptLanguage
) {
338 switch (scriptLanguage
) {
340 Result
= SCE_HB_START
;
343 Result
= SCE_HP_START
;
346 Result
= SCE_HPHP_DEFAULT
;
349 Result
= SCE_H_TAGUNKNOWN
;
352 Result
= SCE_H_SGML_DEFAULT
;
355 Result
= SCE_HJ_START
;
361 static inline bool ishtmlwordchar(char ch
) {
362 return isalnum(ch
) || ch
== '.' || ch
== '-' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#';
365 static inline bool issgmlwordchar(char ch
) {
366 return isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#' || ch
== '[';
369 static bool InTagState(int state
) {
370 return state
== SCE_H_TAG
|| state
== SCE_H_TAGUNKNOWN
||
371 state
== SCE_H_SCRIPT
||
372 state
== SCE_H_ATTRIBUTE
|| state
== SCE_H_ATTRIBUTEUNKNOWN
||
373 state
== SCE_H_NUMBER
|| state
== SCE_H_OTHER
||
374 state
== SCE_H_DOUBLESTRING
|| state
== SCE_H_SINGLESTRING
;
377 static bool IsCommentState(const int state
) {
378 return state
== SCE_H_COMMENT
|| state
== SCE_H_SGML_COMMENT
;
381 static bool isLineEnd(char ch
) {
382 return ch
== '\r' || ch
== '\n';
385 static bool isOKBeforeRE(char ch
) {
386 return (ch
== '(') || (ch
== '=') || (ch
== ',');
389 static bool isPHPStringState(int state
) {
391 (state
== SCE_HPHP_HSTRING
) ||
392 (state
== SCE_HPHP_SIMPLESTRING
) ||
393 (state
== SCE_HPHP_HSTRING_VARIABLE
);
396 static void ColouriseHyperTextDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
398 WordList
&keywords
= *keywordlists
[0];
399 WordList
&keywords2
= *keywordlists
[1];
400 WordList
&keywords3
= *keywordlists
[2];
401 WordList
&keywords4
= *keywordlists
[3];
402 WordList
&keywords5
= *keywordlists
[4];
403 WordList
&keywords6
= *keywordlists
[5]; // SGML (DTD) keywords
405 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
406 styler
.StartAt(startPos
, STYLE_MAX
);
409 int StateToPrint
= initStyle
;
410 int state
= stateForPrintState(StateToPrint
);
412 // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen
413 if (InTagState(state
)) {
414 while ((startPos
> 0) && (InTagState(styler
.StyleAt(startPos
- 1)))) {
418 state
= SCE_H_DEFAULT
;
420 styler
.StartAt(startPos
, STYLE_MAX
);
422 int lineCurrent
= styler
.GetLine(startPos
);
424 if (lineCurrent
> 0) {
425 lineState
= styler
.GetLineState(lineCurrent
);
427 // Default client and ASP scripting language is JavaScript
428 lineState
= eScriptJS
<< 8;
429 lineState
|= styler
.GetPropertyInt("asp.default.language", eScriptJS
) << 4;
431 script_mode inScriptType
= script_mode((lineState
>> 0) & 0x03); // 2 bits of scripting mode
432 bool tagOpened
= (lineState
>> 2) & 0x01; // 1 bit to know if we are in an opened tag
433 bool tagClosing
= (lineState
>> 3) & 0x01; // 1 bit to know if we are in a closing tag
434 script_type aspScript
= script_type((lineState
>> 4) & 0x0F); // 4 bits of script name
435 script_type clientScript
= script_type((lineState
>> 8) & 0x0F); // 4 bits of script name
436 int beforePreProc
= (lineState
>> 12) & 0xFF; // 8 bits of state
438 script_type scriptLanguage
= ScriptOfState(state
);
440 const bool foldHTML
= styler
.GetPropertyInt("fold.html", 0) != 0;
441 const bool fold
= foldHTML
&& styler
.GetPropertyInt("fold");
442 const bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
444 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
445 int levelCurrent
= levelPrev
;
446 int visibleChars
= 0;
450 char chPrevNonWhite
= ' ';
451 styler
.StartSegment(startPos
);
452 const int lengthDoc
= startPos
+ length
;
453 for (int i
= startPos
; i
< lengthDoc
; i
++) {
454 const char chPrev2
= chPrev
;
456 if (ch
!= ' ' && ch
!= '\t')
459 char chNext
= styler
.SafeGetCharAt(i
+ 1);
460 const char chNext2
= styler
.SafeGetCharAt(i
+ 2);
462 // Handle DBCS codepages
463 if (styler
.IsLeadByte(ch
)) {
469 if ((!isspacechar(ch
) || !foldCompact
) && fold
)
472 // decide what is the current state to print (depending of the script tag)
473 StateToPrint
= statePrintForState(state
, inScriptType
);
475 // handle script folding
477 switch (scriptLanguage
) {
480 //not currently supported case eScriptVBS:
482 if ((state
!= SCE_HPHP_COMMENT
) && (state
!= SCE_HPHP_COMMENTLINE
) && (state
!= SCE_HJ_COMMENT
) && (state
!= SCE_HJ_COMMENTLINE
) && (state
!= SCE_HJ_COMMENTDOC
)) {
483 if ((ch
== '{') || (ch
== '}')) {
484 levelCurrent
+= (ch
== '{') ? 1 : -1;
489 if (state
!= SCE_HP_COMMENTLINE
) {
490 if ((ch
== ':') && ((chNext
== '\n') || (chNext
== '\r' && chNext2
== '\n'))) {
492 } else if ((ch
== '\n') && !((chNext
== '\r') && (chNext2
== '\n')) && (chNext
!= '\n')) {
493 // check if the number of tabs is lower than the level
494 int Findlevel
= (levelCurrent
& ~SC_FOLDLEVELBASE
) * 8;
495 for (int j
= 0; Findlevel
> 0; j
++) {
496 char chTmp
= styler
.SafeGetCharAt(i
+ j
+ 1);
499 } else if (chTmp
== ' ') {
507 levelCurrent
-= Findlevel
/ 8;
519 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) {
520 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
521 // Avoid triggering two times on Dos/Win
522 // New line -> record any line state onto /next/ line
525 if (visibleChars
== 0)
526 lev
|= SC_FOLDLEVELWHITEFLAG
;
527 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
528 lev
|= SC_FOLDLEVELHEADERFLAG
;
530 styler
.SetLevel(lineCurrent
, lev
);
532 levelPrev
= levelCurrent
;
535 styler
.SetLineState(lineCurrent
,
536 ((inScriptType
& 0x03) << 0) |
537 ((tagOpened
& 0x01) << 2) |
538 ((tagClosing
& 0x01) << 3) |
539 ((aspScript
& 0x0F) << 4) |
540 ((clientScript
& 0x0F) << 8) |
541 ((beforePreProc
& 0xFF) << 12));
544 // generic end of script processing
545 else if ((inScriptType
== eNonHtmlScript
) && (ch
== '<') && (chNext
== '/')) {
546 // Check if it's the end of the script tag (or any other HTML tag)
548 // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
549 case SCE_H_DOUBLESTRING
:
550 case SCE_H_SINGLESTRING
:
552 case SCE_HJ_COMMENTDOC
:
553 // SCE_HJ_COMMENTLINE removed as this is a common thing done to hide
554 // the end of script marker from some JS interpreters.
555 //case SCE_HJ_COMMENTLINE:
556 case SCE_HJ_DOUBLESTRING
:
557 case SCE_HJ_SINGLESTRING
:
561 case SCE_HP_TRIPLEDOUBLE
:
564 // closing tag of the script (it's a closing HTML tag anyway)
565 styler
.ColourTo(i
- 1, StateToPrint
);
566 state
= SCE_H_TAGUNKNOWN
;
567 inScriptType
= eHtml
;
568 scriptLanguage
= eScriptNone
;
569 clientScript
= eScriptJS
;
577 /////////////////////////////////////
578 // handle the start of PHP pre-processor = Non-HTML
579 else if ((state
!= SCE_H_ASPAT
) &&
580 !isPHPStringState(state
) &&
581 (state
!= SCE_HPHP_COMMENT
) &&
584 styler
.ColourTo(i
- 1, StateToPrint
);
585 beforePreProc
= state
;
586 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment() + 2, i
+ 10, eScriptPHP
);
589 i
+= PrintScriptingIndicatorOffset(styler
, styler
.GetStartSegment() + 2, i
+ 10);
590 if (scriptLanguage
== eScriptXML
)
591 styler
.ColourTo(i
, SCE_H_XMLSTART
);
593 styler
.ColourTo(i
, SCE_H_QUESTION
);
594 state
= StateForScript(scriptLanguage
);
595 if (inScriptType
== eNonHtmlScript
)
596 inScriptType
= eNonHtmlScriptPreProc
;
598 inScriptType
= eNonHtmlPreProc
;
601 if (scriptLanguage
== eScriptXML
)
602 levelCurrent
--; // no folding of the XML first tag (all XML-like tags in this case)
604 ch
= styler
.SafeGetCharAt(i
);
608 // handle the start of ASP pre-processor = Non-HTML
609 else if (!isCommentASPState(state
) && (ch
== '<') && (chNext
== '%')) {
610 styler
.ColourTo(i
- 1, StateToPrint
);
611 beforePreProc
= state
;
612 if (inScriptType
== eNonHtmlScript
)
613 inScriptType
= eNonHtmlScriptPreProc
;
615 inScriptType
= eNonHtmlPreProc
;
617 if (chNext2
== '@') {
618 i
+= 2; // place as if it was the second next char treated
621 } else if ((chNext2
== '-') && (styler
.SafeGetCharAt(i
+ 3) == '-')) {
622 styler
.ColourTo(i
+ 3, SCE_H_ASP
);
623 state
= SCE_H_XCCOMMENT
;
624 scriptLanguage
= eScriptVBS
;
627 if (chNext2
== '=') {
628 i
+= 2; // place as if it was the second next char treated
631 i
++; // place as if it was the next char treated
635 state
= StateForScript(aspScript
);
637 scriptLanguage
= eScriptVBS
;
638 styler
.ColourTo(i
, SCE_H_ASP
);
642 ch
= styler
.SafeGetCharAt(i
);
646 /////////////////////////////////////
647 // handle the start of SGML language (DTD)
648 else if (((scriptLanguage
== eScriptNone
) || (scriptLanguage
== eScriptXML
)) &&
651 (StateToPrint
!= SCE_H_CDATA
) && (!IsCommentState(StateToPrint
))) {
652 beforePreProc
= state
;
653 styler
.ColourTo(i
- 2, StateToPrint
);
654 if ((chNext
== '-') && (chNext2
== '-')) {
655 state
= SCE_H_COMMENT
; // wait for a pending command
657 else if (isWordCdata(i
+ 1, i
+ 7, styler
)) {
660 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
); // <! is default
661 scriptLanguage
= eScriptSGML
;
662 state
= SCE_H_SGML_COMMAND
; // wait for a pending command
664 // fold whole tag (-- when closing the tag)
670 // handle the end of a pre-processor = Non-HTML
672 ((inScriptType
== eNonHtmlPreProc
)
673 || (inScriptType
== eNonHtmlScriptPreProc
)) && (
674 ((scriptLanguage
== eScriptPHP
) && (ch
== '?') && !isPHPStringState(state
) && (state
!= SCE_HPHP_COMMENT
)) ||
675 ((scriptLanguage
!= eScriptNone
) && !isStringState(state
) &&
677 ) && (chNext
== '>')) ||
678 ((scriptLanguage
== eScriptSGML
) && (ch
== '>') && (state
!= SCE_H_SGML_COMMENT
))) {
679 if (state
== SCE_H_ASPAT
) {
680 aspScript
= segIsScriptingIndicator(styler
,
681 styler
.GetStartSegment(), i
- 1, aspScript
);
683 // Bounce out of any ASP mode
686 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
689 classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
692 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
695 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
697 case SCE_H_XCCOMMENT
:
698 styler
.ColourTo(i
- 1, state
);
701 styler
.ColourTo(i
- 1, StateToPrint
);
704 if (scriptLanguage
!= eScriptSGML
) {
709 styler
.ColourTo(i
, SCE_H_ASP
);
710 else if (scriptLanguage
== eScriptXML
)
711 styler
.ColourTo(i
, SCE_H_XMLEND
);
712 else if (scriptLanguage
== eScriptSGML
)
713 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
715 styler
.ColourTo(i
, SCE_H_QUESTION
);
716 state
= beforePreProc
;
717 if (inScriptType
== eNonHtmlScriptPreProc
)
718 inScriptType
= eNonHtmlScript
;
720 inScriptType
= eHtml
;
721 scriptLanguage
= eScriptNone
;
722 // unfold all scripting languages
726 /////////////////////////////////////
731 // in HTML, fold on tag open and unfold on tag close
733 tagClosing
= (chNext
== '/');
734 styler
.ColourTo(i
- 1, StateToPrint
);
736 state
= SCE_H_TAGUNKNOWN
;
737 } else if (ch
== '&') {
738 styler
.ColourTo(i
- 1, SCE_H_DEFAULT
);
739 state
= SCE_H_ENTITY
;
742 case SCE_H_SGML_DEFAULT
:
743 case SCE_H_SGML_BLOCK_DEFAULT
:
744 // if (scriptLanguage == eScriptSGMLblock)
745 // StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
748 styler
.ColourTo(i
- 1, StateToPrint
);
749 state
= SCE_H_SGML_DOUBLESTRING
;
750 } else if (ch
== '\'') {
751 styler
.ColourTo(i
- 1, StateToPrint
);
752 state
= SCE_H_SGML_SIMPLESTRING
;
753 } else if ((ch
== '-') && (chPrev
== '-')) {
754 styler
.ColourTo(i
- 2, StateToPrint
);
755 state
= SCE_H_SGML_COMMENT
;
756 } else if (isalpha(ch
) && (chPrev
== '%')) {
757 styler
.ColourTo(i
- 2, StateToPrint
);
758 state
= SCE_H_SGML_ENTITY
;
759 } else if (ch
== '#') {
760 styler
.ColourTo(i
- 1, StateToPrint
);
761 state
= SCE_H_SGML_SPECIAL
;
762 } else if (ch
== '[') {
763 styler
.ColourTo(i
- 1, StateToPrint
);
764 scriptLanguage
= eScriptSGMLblock
;
765 state
= SCE_H_SGML_BLOCK_DEFAULT
;
766 } else if (ch
== ']') {
767 if (scriptLanguage
== eScriptSGMLblock
) {
768 styler
.ColourTo(i
, StateToPrint
);
769 scriptLanguage
= eScriptSGML
;
771 styler
.ColourTo(i
- 1, StateToPrint
);
772 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
774 state
= SCE_H_SGML_DEFAULT
;
775 } else if (scriptLanguage
== eScriptSGMLblock
) {
776 if ((ch
== '!') && (chPrev
== '<')) {
777 styler
.ColourTo(i
- 2, StateToPrint
);
778 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
779 state
= SCE_H_SGML_COMMAND
;
780 } else if (ch
== '>') {
781 styler
.ColourTo(i
- 1, StateToPrint
);
782 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
786 case SCE_H_SGML_COMMAND
:
787 if ((ch
== '-') && (chPrev
== '-')) {
788 styler
.ColourTo(i
- 2, StateToPrint
);
789 state
= SCE_H_SGML_COMMENT
;
790 } else if (!issgmlwordchar(ch
)) {
791 if (isWordHSGML(styler
.GetStartSegment(), i
- 1, keywords6
, styler
)) {
792 styler
.ColourTo(i
- 1, StateToPrint
);
793 state
= SCE_H_SGML_1ST_PARAM
;
795 state
= SCE_H_SGML_ERROR
;
799 case SCE_H_SGML_1ST_PARAM
:
800 // wait for the beginning of the word
801 if ((ch
== '-') && (chPrev
== '-')) {
802 if (scriptLanguage
== eScriptSGMLblock
) {
803 styler
.ColourTo(i
- 2, SCE_H_SGML_BLOCK_DEFAULT
);
805 styler
.ColourTo(i
- 2, SCE_H_SGML_DEFAULT
);
807 state
= SCE_H_SGML_1ST_PARAM_COMMENT
;
808 } else if (issgmlwordchar(ch
)) {
809 if (scriptLanguage
== eScriptSGMLblock
) {
810 styler
.ColourTo(i
- 1, SCE_H_SGML_BLOCK_DEFAULT
);
812 styler
.ColourTo(i
- 1, SCE_H_SGML_DEFAULT
);
814 // find the length of the word
816 while (ishtmlwordchar(styler
.SafeGetCharAt(i
+ size
)))
818 styler
.ColourTo(i
+ size
- 1, StateToPrint
);
820 visibleChars
+= size
- 1;
821 ch
= styler
.SafeGetCharAt(i
);
822 if (scriptLanguage
== eScriptSGMLblock
) {
823 state
= SCE_H_SGML_BLOCK_DEFAULT
;
825 state
= SCE_H_SGML_DEFAULT
;
830 case SCE_H_SGML_ERROR
:
831 if ((ch
== '-') && (chPrev
== '-')) {
832 styler
.ColourTo(i
- 2, StateToPrint
);
833 state
= SCE_H_SGML_COMMENT
;
835 case SCE_H_SGML_DOUBLESTRING
:
837 styler
.ColourTo(i
, StateToPrint
);
838 state
= SCE_H_SGML_DEFAULT
;
841 case SCE_H_SGML_SIMPLESTRING
:
843 styler
.ColourTo(i
, StateToPrint
);
844 state
= SCE_H_SGML_DEFAULT
;
847 case SCE_H_SGML_COMMENT
:
848 if ((ch
== '-') && (chPrev
== '-')) {
849 styler
.ColourTo(i
, StateToPrint
);
850 state
= SCE_H_SGML_DEFAULT
;
854 if ((chPrev2
== ']') && (chPrev
== ']') && (ch
== '>')) {
855 styler
.ColourTo(i
, StateToPrint
);
856 state
= SCE_H_DEFAULT
;
861 if ((chPrev2
== '-') && (chPrev
== '-') && (ch
== '>')) {
862 styler
.ColourTo(i
, StateToPrint
);
863 state
= SCE_H_DEFAULT
;
867 case SCE_H_SGML_1ST_PARAM_COMMENT
:
868 if ((ch
== '-') && (chPrev
== '-')) {
869 styler
.ColourTo(i
, SCE_H_SGML_COMMENT
);
870 state
= SCE_H_SGML_1ST_PARAM
;
873 case SCE_H_SGML_SPECIAL
:
875 styler
.ColourTo(i
- 1, StateToPrint
);
877 state
= SCE_H_SGML_ERROR
;
879 state
= SCE_H_SGML_DEFAULT
;
883 case SCE_H_SGML_ENTITY
:
885 styler
.ColourTo(i
, StateToPrint
);
886 state
= SCE_H_SGML_DEFAULT
;
887 } else if (!isalnum(ch
) && ch
!= '-' && ch
!= '.') {
888 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
889 state
= SCE_H_SGML_DEFAULT
;
894 styler
.ColourTo(i
, StateToPrint
);
895 state
= SCE_H_DEFAULT
;
897 if (ch
!= '#' && !isalnum(ch
)) { // Should check that '#' follows '&', but it is unlikely anyway...
898 styler
.ColourTo(i
, SCE_H_TAGUNKNOWN
);
899 state
= SCE_H_DEFAULT
;
902 case SCE_H_TAGUNKNOWN
:
903 if (!ishtmlwordchar(ch
) && !((ch
== '/') && (chPrev
== '<')) && ch
!= '[') {
904 int eClass
= classifyTagHTML(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
905 if (eClass
== SCE_H_SCRIPT
) {
907 inScriptType
= eNonHtmlScript
;
908 scriptLanguage
= clientScript
;
911 scriptLanguage
= eScriptNone
;
916 styler
.ColourTo(i
, eClass
);
917 if (inScriptType
== eNonHtmlScript
) {
918 state
= StateForScript(scriptLanguage
);
920 state
= SCE_H_DEFAULT
;
929 } else if (ch
== '/' && chNext
== '>') {
930 if (eClass
== SCE_H_TAGUNKNOWN
) {
931 styler
.ColourTo(i
+ 1, SCE_H_TAGUNKNOWN
);
933 styler
.ColourTo(i
- 1, StateToPrint
);
934 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
938 state
= SCE_H_DEFAULT
;
941 if (eClass
!= SCE_H_TAGUNKNOWN
) {
942 if (eClass
== SCE_H_SGML_DEFAULT
) {
943 state
= SCE_H_SGML_DEFAULT
;
951 case SCE_H_ATTRIBUTE
:
952 if (!ishtmlwordchar(ch
) && ch
!= '/' && ch
!= '-') {
953 if (inScriptType
== eNonHtmlScript
) {
954 int scriptLanguagePrev
= scriptLanguage
;
955 clientScript
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
- 1, scriptLanguage
);
956 scriptLanguage
= clientScript
;
957 if ((scriptLanguagePrev
!= scriptLanguage
) && (scriptLanguage
== eScriptNone
))
958 inScriptType
= eHtml
;
960 classifyAttribHTML(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
962 styler
.ColourTo(i
, SCE_H_TAG
);
963 if (inScriptType
== eNonHtmlScript
) {
964 state
= StateForScript(scriptLanguage
);
966 state
= SCE_H_DEFAULT
;
974 } else if (ch
== '=') {
975 styler
.ColourTo(i
, SCE_H_OTHER
);
984 styler
.ColourTo(i
- 1, StateToPrint
);
985 styler
.ColourTo(i
, SCE_H_TAG
);
986 if (inScriptType
== eNonHtmlScript
) {
987 state
= StateForScript(scriptLanguage
);
989 state
= SCE_H_DEFAULT
;
997 } else if (ch
== '\"') {
998 styler
.ColourTo(i
- 1, StateToPrint
);
999 state
= SCE_H_DOUBLESTRING
;
1000 } else if (ch
== '\'') {
1001 styler
.ColourTo(i
- 1, StateToPrint
);
1002 state
= SCE_H_SINGLESTRING
;
1003 } else if (ch
== '=') {
1004 styler
.ColourTo(i
, StateToPrint
);
1005 state
= SCE_H_VALUE
;
1006 } else if (ch
== '/' && chNext
== '>') {
1007 styler
.ColourTo(i
- 1, StateToPrint
);
1008 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1011 state
= SCE_H_DEFAULT
;
1013 } else if (ch
== '?' && chNext
== '>') {
1014 styler
.ColourTo(i
- 1, StateToPrint
);
1015 styler
.ColourTo(i
+ 1, SCE_H_XMLEND
);
1018 state
= SCE_H_DEFAULT
;
1019 } else if (ishtmlwordchar(ch
)) {
1020 styler
.ColourTo(i
- 1, StateToPrint
);
1021 state
= SCE_H_ATTRIBUTE
;
1024 case SCE_H_DOUBLESTRING
:
1026 if (inScriptType
== eNonHtmlScript
) {
1027 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1029 styler
.ColourTo(i
, SCE_H_DOUBLESTRING
);
1030 state
= SCE_H_OTHER
;
1033 case SCE_H_SINGLESTRING
:
1035 if (inScriptType
== eNonHtmlScript
) {
1036 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1038 styler
.ColourTo(i
, SCE_H_SINGLESTRING
);
1039 state
= SCE_H_OTHER
;
1043 if (!ishtmlwordchar(ch
)) {
1045 // Should really test for being first character
1046 state
= SCE_H_DOUBLESTRING
;
1047 } else if (ch
== '\'') {
1048 state
= SCE_H_SINGLESTRING
;
1050 if (IsNumber(styler
.GetStartSegment(), styler
)) {
1051 styler
.ColourTo(i
- 1, SCE_H_NUMBER
);
1053 styler
.ColourTo(i
- 1, StateToPrint
);
1056 styler
.ColourTo(i
, SCE_H_TAG
);
1057 if (inScriptType
== eNonHtmlScript
) {
1058 state
= StateForScript(scriptLanguage
);
1060 state
= SCE_H_DEFAULT
;
1069 state
= SCE_H_OTHER
;
1074 case SCE_HJ_DEFAULT
:
1076 case SCE_HJ_SYMBOLS
:
1077 if (iswordstart(ch
)) {
1078 styler
.ColourTo(i
- 1, StateToPrint
);
1079 state
= SCE_HJ_WORD
;
1080 } else if (ch
== '/' && chNext
== '*') {
1081 styler
.ColourTo(i
- 1, StateToPrint
);
1083 state
= SCE_HJ_COMMENTDOC
;
1085 state
= SCE_HJ_COMMENT
;
1086 } else if (ch
== '/' && chNext
== '/') {
1087 styler
.ColourTo(i
- 1, StateToPrint
);
1088 state
= SCE_HJ_COMMENTLINE
;
1089 } else if (ch
== '/' && isOKBeforeRE(chPrevNonWhite
)) {
1090 styler
.ColourTo(i
- 1, StateToPrint
);
1091 state
= SCE_HJ_REGEX
;
1092 } else if (ch
== '\"') {
1093 styler
.ColourTo(i
- 1, StateToPrint
);
1094 state
= SCE_HJ_DOUBLESTRING
;
1095 } else if (ch
== '\'') {
1096 styler
.ColourTo(i
- 1, StateToPrint
);
1097 state
= SCE_HJ_SINGLESTRING
;
1098 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1099 styler
.SafeGetCharAt(i
+ 3) == '-') {
1100 styler
.ColourTo(i
- 1, StateToPrint
);
1101 state
= SCE_HJ_COMMENTLINE
;
1102 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1103 styler
.ColourTo(i
- 1, StateToPrint
);
1104 state
= SCE_HJ_COMMENTLINE
;
1106 } else if (isoperator(ch
)) {
1107 styler
.ColourTo(i
- 1, StateToPrint
);
1108 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1109 state
= SCE_HJ_DEFAULT
;
1110 } else if ((ch
== ' ') || (ch
== '\t')) {
1111 if (state
== SCE_HJ_START
) {
1112 styler
.ColourTo(i
- 1, StateToPrint
);
1113 state
= SCE_HJ_DEFAULT
;
1118 if (!iswordchar(ch
)) {
1119 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
1120 //styler.ColourTo(i - 1, eHTJSKeyword);
1121 state
= SCE_HJ_DEFAULT
;
1122 if (ch
== '/' && chNext
== '*') {
1124 state
= SCE_HJ_COMMENTDOC
;
1126 state
= SCE_HJ_COMMENT
;
1127 } else if (ch
== '/' && chNext
== '/') {
1128 state
= SCE_HJ_COMMENTLINE
;
1129 } else if (ch
== '\"') {
1130 state
= SCE_HJ_DOUBLESTRING
;
1131 } else if (ch
== '\'') {
1132 state
= SCE_HJ_SINGLESTRING
;
1133 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1134 styler
.ColourTo(i
- 1, StateToPrint
);
1135 state
= SCE_HJ_COMMENTLINE
;
1137 } else if (isoperator(ch
)) {
1138 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1139 state
= SCE_HJ_DEFAULT
;
1143 case SCE_HJ_COMMENT
:
1144 case SCE_HJ_COMMENTDOC
:
1145 if (ch
== '/' && chPrev
== '*') {
1146 styler
.ColourTo(i
, StateToPrint
);
1147 state
= SCE_HJ_DEFAULT
;
1150 case SCE_HJ_COMMENTLINE
:
1151 if (ch
== '\r' || ch
== '\n') {
1152 styler
.ColourTo(i
- 1, statePrintForState(SCE_HJ_COMMENTLINE
, inScriptType
));
1153 state
= SCE_HJ_DEFAULT
;
1156 case SCE_HJ_DOUBLESTRING
:
1158 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1161 } else if (ch
== '\"') {
1162 styler
.ColourTo(i
, statePrintForState(SCE_HJ_DOUBLESTRING
, inScriptType
));
1163 state
= SCE_HJ_DEFAULT
;
1164 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1165 styler
.ColourTo(i
- 1, StateToPrint
);
1166 state
= SCE_HJ_COMMENTLINE
;
1168 } else if (isLineEnd(ch
)) {
1169 styler
.ColourTo(i
- 1, StateToPrint
);
1170 state
= SCE_HJ_STRINGEOL
;
1173 case SCE_HJ_SINGLESTRING
:
1175 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1178 } else if (ch
== '\'') {
1179 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SINGLESTRING
, inScriptType
));
1180 state
= SCE_HJ_DEFAULT
;
1181 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1182 styler
.ColourTo(i
- 1, StateToPrint
);
1183 state
= SCE_HJ_COMMENTLINE
;
1185 } else if (isLineEnd(ch
)) {
1186 styler
.ColourTo(i
- 1, StateToPrint
);
1187 state
= SCE_HJ_STRINGEOL
;
1190 case SCE_HJ_STRINGEOL
:
1191 if (!isLineEnd(ch
)) {
1192 styler
.ColourTo(i
- 1, StateToPrint
);
1193 state
= SCE_HJ_DEFAULT
;
1194 } else if (!isLineEnd(chNext
)) {
1195 styler
.ColourTo(i
, StateToPrint
);
1196 state
= SCE_HJ_DEFAULT
;
1200 if (ch
== '\r' || ch
== '\n' || ch
== '/') {
1201 styler
.ColourTo(i
, StateToPrint
);
1202 state
= SCE_HJ_DEFAULT
;
1203 } else if (ch
== '\\') {
1204 // Gobble up the quoted character
1205 if (chNext
== '\\' || chNext
== '/') {
1208 chNext
= styler
.SafeGetCharAt(i
+ 1);
1212 case SCE_HB_DEFAULT
:
1214 if (iswordstart(ch
)) {
1215 styler
.ColourTo(i
- 1, StateToPrint
);
1216 state
= SCE_HB_WORD
;
1217 } else if (ch
== '\'') {
1218 styler
.ColourTo(i
- 1, StateToPrint
);
1219 state
= SCE_HB_COMMENTLINE
;
1220 } else if (ch
== '\"') {
1221 styler
.ColourTo(i
- 1, StateToPrint
);
1222 state
= SCE_HB_STRING
;
1223 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1224 styler
.SafeGetCharAt(i
+ 3) == '-') {
1225 styler
.ColourTo(i
- 1, StateToPrint
);
1226 state
= SCE_HB_COMMENTLINE
;
1227 } else if (isoperator(ch
)) {
1228 styler
.ColourTo(i
- 1, StateToPrint
);
1229 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1230 state
= SCE_HB_DEFAULT
;
1231 } else if ((ch
== ' ') || (ch
== '\t')) {
1232 if (state
== SCE_HB_START
) {
1233 styler
.ColourTo(i
- 1, StateToPrint
);
1234 state
= SCE_HB_DEFAULT
;
1239 if (!iswordchar(ch
)) {
1240 state
= classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
1241 if (state
== SCE_HB_DEFAULT
) {
1243 state
= SCE_HB_STRING
;
1244 } else if (ch
== '\'') {
1245 state
= SCE_HB_COMMENTLINE
;
1246 } else if (isoperator(ch
)) {
1247 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1248 state
= SCE_HB_DEFAULT
;
1255 styler
.ColourTo(i
, StateToPrint
);
1256 state
= SCE_HB_DEFAULT
;
1257 } else if (ch
== '\r' || ch
== '\n') {
1258 styler
.ColourTo(i
- 1, StateToPrint
);
1259 state
= SCE_HB_STRINGEOL
;
1262 case SCE_HB_COMMENTLINE
:
1263 if (ch
== '\r' || ch
== '\n') {
1264 styler
.ColourTo(i
- 1, StateToPrint
);
1265 state
= SCE_HB_DEFAULT
;
1268 case SCE_HB_STRINGEOL
:
1269 if (!isLineEnd(ch
)) {
1270 styler
.ColourTo(i
- 1, StateToPrint
);
1271 state
= SCE_HB_DEFAULT
;
1272 } else if (!isLineEnd(chNext
)) {
1273 styler
.ColourTo(i
, StateToPrint
);
1274 state
= SCE_HB_DEFAULT
;
1277 case SCE_HP_DEFAULT
:
1279 if (iswordstart(ch
)) {
1280 styler
.ColourTo(i
- 1, StateToPrint
);
1281 state
= SCE_HP_WORD
;
1282 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1283 styler
.SafeGetCharAt(i
+ 3) == '-') {
1284 styler
.ColourTo(i
- 1, StateToPrint
);
1285 state
= SCE_HP_COMMENTLINE
;
1286 } else if (ch
== '#') {
1287 styler
.ColourTo(i
- 1, StateToPrint
);
1288 state
= SCE_HP_COMMENTLINE
;
1289 } else if (ch
== '\"') {
1290 styler
.ColourTo(i
- 1, StateToPrint
);
1291 if (chNext
== '\"' && chNext2
== '\"') {
1293 state
= SCE_HP_TRIPLEDOUBLE
;
1296 chNext
= styler
.SafeGetCharAt(i
+ 1);
1298 // state = statePrintForState(SCE_HP_STRING,inScriptType);
1299 state
= SCE_HP_STRING
;
1301 } else if (ch
== '\'') {
1302 styler
.ColourTo(i
- 1, StateToPrint
);
1303 if (chNext
== '\'' && chNext2
== '\'') {
1305 state
= SCE_HP_TRIPLE
;
1308 chNext
= styler
.SafeGetCharAt(i
+ 1);
1310 state
= SCE_HP_CHARACTER
;
1312 } else if (isoperator(ch
)) {
1313 styler
.ColourTo(i
- 1, StateToPrint
);
1314 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1315 } else if ((ch
== ' ') || (ch
== '\t')) {
1316 if (state
== SCE_HP_START
) {
1317 styler
.ColourTo(i
- 1, StateToPrint
);
1318 state
= SCE_HP_DEFAULT
;
1323 if (!iswordchar(ch
)) {
1324 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
1325 state
= SCE_HP_DEFAULT
;
1327 state
= SCE_HP_COMMENTLINE
;
1328 } else if (ch
== '\"') {
1329 if (chNext
== '\"' && chNext2
== '\"') {
1331 state
= SCE_HP_TRIPLEDOUBLE
;
1334 chNext
= styler
.SafeGetCharAt(i
+ 1);
1336 state
= SCE_HP_STRING
;
1338 } else if (ch
== '\'') {
1339 if (chNext
== '\'' && chNext2
== '\'') {
1341 state
= SCE_HP_TRIPLE
;
1344 chNext
= styler
.SafeGetCharAt(i
+ 1);
1346 state
= SCE_HP_CHARACTER
;
1348 } else if (isoperator(ch
)) {
1349 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1353 case SCE_HP_COMMENTLINE
:
1354 if (ch
== '\r' || ch
== '\n') {
1355 styler
.ColourTo(i
- 1, StateToPrint
);
1356 state
= SCE_HP_DEFAULT
;
1361 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1364 chNext
= styler
.SafeGetCharAt(i
+ 1);
1366 } else if (ch
== '\"') {
1367 styler
.ColourTo(i
, StateToPrint
);
1368 state
= SCE_HP_DEFAULT
;
1371 case SCE_HP_CHARACTER
:
1373 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1376 chNext
= styler
.SafeGetCharAt(i
+ 1);
1378 } else if (ch
== '\'') {
1379 styler
.ColourTo(i
, StateToPrint
);
1380 state
= SCE_HP_DEFAULT
;
1384 if (ch
== '\'' && chPrev
== '\'' && chPrev2
== '\'') {
1385 styler
.ColourTo(i
, StateToPrint
);
1386 state
= SCE_HP_DEFAULT
;
1389 case SCE_HP_TRIPLEDOUBLE
:
1390 if (ch
== '\"' && chPrev
== '\"' && chPrev2
== '\"') {
1391 styler
.ColourTo(i
, StateToPrint
);
1392 state
= SCE_HP_DEFAULT
;
1395 ///////////// start - PHP state handling
1397 if (!iswordstart(ch
)) {
1398 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
1399 if (ch
== '/' && chNext
== '*') {
1401 state
= SCE_HPHP_COMMENT
;
1402 } else if (ch
== '/' && chNext
== '/') {
1404 state
= SCE_HPHP_COMMENTLINE
;
1405 } else if (ch
== '#') {
1406 state
= SCE_HPHP_COMMENTLINE
;
1407 } else if (ch
== '\"') {
1408 state
= SCE_HPHP_HSTRING
;
1409 } else if (ch
== '\'') {
1410 state
= SCE_HPHP_SIMPLESTRING
;
1411 } else if (ch
== '$') {
1412 state
= SCE_HPHP_VARIABLE
;
1413 } else if (isoperator(ch
)) {
1414 state
= SCE_HPHP_OPERATOR
;
1416 state
= SCE_HPHP_DEFAULT
;
1420 case SCE_HPHP_NUMBER
:
1422 styler
.ColourTo(i
- 1, SCE_HPHP_NUMBER
);
1424 state
= SCE_HPHP_OPERATOR
;
1426 state
= SCE_HPHP_DEFAULT
;
1429 case SCE_HPHP_VARIABLE
:
1430 if (!iswordstart(ch
)) {
1431 styler
.ColourTo(i
- 1, SCE_HPHP_VARIABLE
);
1433 state
= SCE_HPHP_OPERATOR
;
1435 state
= SCE_HPHP_DEFAULT
;
1438 case SCE_HPHP_COMMENT
:
1439 if (ch
== '/' && chPrev
== '*') {
1440 styler
.ColourTo(i
, StateToPrint
);
1441 state
= SCE_HPHP_DEFAULT
;
1444 case SCE_HPHP_COMMENTLINE
:
1445 if (ch
== '\r' || ch
== '\n') {
1446 styler
.ColourTo(i
- 1, StateToPrint
);
1447 state
= SCE_HPHP_DEFAULT
;
1450 case SCE_HPHP_HSTRING
:
1452 // skip the next char
1454 } else if (ch
== '$') {
1455 styler
.ColourTo(i
- 1, StateToPrint
);
1456 state
= SCE_HPHP_HSTRING_VARIABLE
;
1457 } else if (ch
== '\"') {
1458 styler
.ColourTo(i
, StateToPrint
);
1459 state
= SCE_HPHP_DEFAULT
;
1462 case SCE_HPHP_SIMPLESTRING
:
1464 // skip the next char
1466 } else if (ch
== '\'') {
1467 styler
.ColourTo(i
, StateToPrint
);
1468 state
= SCE_HPHP_DEFAULT
;
1471 case SCE_HPHP_HSTRING_VARIABLE
:
1472 if (!iswordstart(ch
)) {
1473 styler
.ColourTo(i
- 1, StateToPrint
);
1474 i
--; // strange but it works
1475 state
= SCE_HPHP_HSTRING
;
1478 case SCE_HPHP_OPERATOR
:
1479 case SCE_HPHP_DEFAULT
:
1480 styler
.ColourTo(i
- 1, StateToPrint
);
1482 state
= SCE_HPHP_NUMBER
;
1483 } else if (iswordstart(ch
)) {
1484 state
= SCE_HPHP_WORD
;
1485 } else if (ch
== '/' && chNext
== '*') {
1487 state
= SCE_HPHP_COMMENT
;
1488 } else if (ch
== '/' && chNext
== '/') {
1490 state
= SCE_HPHP_COMMENTLINE
;
1491 } else if (ch
== '#') {
1492 state
= SCE_HPHP_COMMENTLINE
;
1493 } else if (ch
== '\"') {
1494 state
= SCE_HPHP_HSTRING
;
1495 } else if (ch
== '\'') {
1496 state
= SCE_HPHP_SIMPLESTRING
;
1497 } else if (ch
== '$') {
1498 state
= SCE_HPHP_VARIABLE
;
1499 } else if (isoperator(ch
)) {
1500 state
= SCE_HPHP_OPERATOR
;
1501 } else if ((state
== SCE_HPHP_OPERATOR
) && (isspacechar(ch
))) {
1502 state
= SCE_HPHP_DEFAULT
;
1505 ///////////// end - PHP state handling
1508 // Some of the above terminated their lexeme but since the same character starts
1509 // the same class again, only reenter if non empty segment.
1511 bool nonEmptySegment
= i
>= static_cast<int>(styler
.GetStartSegment());
1512 if (state
== SCE_HB_DEFAULT
) { // One of the above succeeded
1513 if ((ch
== '\"') && (nonEmptySegment
)) {
1514 state
= SCE_HB_STRING
;
1515 } else if (ch
== '\'') {
1516 state
= SCE_HB_COMMENTLINE
;
1517 } else if (iswordstart(ch
)) {
1518 state
= SCE_HB_WORD
;
1519 } else if (isoperator(ch
)) {
1520 styler
.ColourTo(i
, SCE_HB_DEFAULT
);
1522 } else if (state
== SCE_HBA_DEFAULT
) { // One of the above succeeded
1523 if ((ch
== '\"') && (nonEmptySegment
)) {
1524 state
= SCE_HBA_STRING
;
1525 } else if (ch
== '\'') {
1526 state
= SCE_HBA_COMMENTLINE
;
1527 } else if (iswordstart(ch
)) {
1528 state
= SCE_HBA_WORD
;
1529 } else if (isoperator(ch
)) {
1530 styler
.ColourTo(i
, SCE_HBA_DEFAULT
);
1532 } else if (state
== SCE_HJ_DEFAULT
) { // One of the above succeeded
1533 if (ch
== '/' && chNext
== '*') {
1534 if (styler
.SafeGetCharAt(i
+ 2) == '*')
1535 state
= SCE_HJ_COMMENTDOC
;
1537 state
= SCE_HJ_COMMENT
;
1538 } else if (ch
== '/' && chNext
== '/') {
1539 state
= SCE_HJ_COMMENTLINE
;
1540 } else if ((ch
== '\"') && (nonEmptySegment
)) {
1541 state
= SCE_HJ_DOUBLESTRING
;
1542 } else if ((ch
== '\'') && (nonEmptySegment
)) {
1543 state
= SCE_HJ_SINGLESTRING
;
1544 } else if (iswordstart(ch
)) {
1545 state
= SCE_HJ_WORD
;
1546 } else if (isoperator(ch
)) {
1547 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1552 StateToPrint
= statePrintForState(state
, inScriptType
);
1553 styler
.ColourTo(lengthDoc
- 1, StateToPrint
);
1555 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
1557 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
1558 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
1562 static bool isASPScript(int state
) {
1564 (state
>= SCE_HJA_START
&& state
<= SCE_HJA_REGEX
) ||
1565 (state
>= SCE_HBA_START
&& state
<= SCE_HBA_STRINGEOL
) ||
1566 (state
>= SCE_HPA_DEFAULT
&& state
<= SCE_HPA_IDENTIFIER
);
1569 static void ColouriseHBAPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1570 WordList
&keywordsVBS
= *keywordlists
[2];
1571 if (sc
.state
== SCE_HBA_WORD
) {
1572 if (!IsAWordChar(sc
.ch
)) {
1574 sc
.GetCurrentLowered(s
, sizeof(s
));
1575 if (keywordsVBS
.InList(s
)) {
1576 if (strcmp(s
, "rem") == 0) {
1577 sc
.ChangeState(SCE_HBA_COMMENTLINE
);
1579 sc
.SetState(SCE_HBA_DEFAULT
);
1582 sc
.SetState(SCE_HBA_DEFAULT
);
1585 sc
.ChangeState(SCE_HBA_IDENTIFIER
);
1586 sc
.SetState(SCE_HBA_DEFAULT
);
1589 } else if (sc
.state
== SCE_HBA_NUMBER
) {
1590 if (!IsAWordChar(sc
.ch
)) {
1591 sc
.SetState(SCE_HBA_DEFAULT
);
1593 } else if (sc
.state
== SCE_HBA_STRING
) {
1594 if (sc
.ch
== '\"') {
1595 sc
.ForwardSetState(SCE_HBA_DEFAULT
);
1596 } else if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1597 sc
.ChangeState(SCE_HBA_STRINGEOL
);
1598 sc
.ForwardSetState(SCE_HBA_DEFAULT
);
1600 } else if (sc
.state
== SCE_HBA_COMMENTLINE
) {
1601 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1602 sc
.SetState(SCE_HBA_DEFAULT
);
1606 if (sc
.state
== SCE_HBA_DEFAULT
) {
1607 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
1608 sc
.SetState(SCE_HBA_NUMBER
);
1609 } else if (IsAWordStart(sc
.ch
)) {
1610 sc
.SetState(SCE_HBA_WORD
);
1611 } else if (sc
.ch
== '\'') {
1612 sc
.SetState(SCE_HBA_COMMENTLINE
);
1613 } else if (sc
.ch
== '\"') {
1614 sc
.SetState(SCE_HBA_STRING
);
1619 static void ColouriseHTMLPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1620 WordList
&keywordsTags
= *keywordlists
[0];
1621 if (sc
.state
== SCE_H_COMMENT
) {
1622 if (sc
.Match("-->")) {
1625 sc
.ForwardSetState(SCE_H_DEFAULT
);
1627 } else if (sc
.state
== SCE_H_ENTITY
) {
1629 sc
.ForwardSetState(SCE_H_DEFAULT
);
1630 } else if (sc
.ch
!= '#' && (sc
.ch
< 0x80) && !isalnum(sc
.ch
)) { // Should check that '#' follows '&', but it is unlikely anyway...
1631 sc
.ChangeState(SCE_H_TAGUNKNOWN
);
1632 sc
.SetState(SCE_H_DEFAULT
);
1634 } else if (sc
.state
== SCE_H_TAGUNKNOWN
) {
1635 if (!ishtmlwordchar(static_cast<char>(sc
.ch
)) && !((sc
.ch
== '/') && (sc
.chPrev
== '<')) && sc
.ch
!= '[') {
1637 sc
.GetCurrentLowered(s
, sizeof(s
));
1639 if (keywordsTags
.InList(s
+ 2)) {
1640 sc
.ChangeState(SCE_H_TAG
);
1643 if (keywordsTags
.InList(s
+ 1)) {
1644 sc
.ChangeState(SCE_H_TAG
);
1648 sc
.ForwardSetState(SCE_H_DEFAULT
);
1649 } else if (sc
.Match('/', '>')) {
1650 sc
.SetState(SCE_H_TAGEND
);
1652 sc
.ForwardSetState(SCE_H_DEFAULT
);
1654 sc
.SetState(SCE_H_OTHER
);
1657 } else if (sc
.state
== SCE_H_ATTRIBUTE
) {
1658 if (!ishtmlwordchar(static_cast<char>(sc
.ch
))) {
1660 sc
.GetCurrentLowered(s
, sizeof(s
));
1661 if (!keywordsTags
.InList(s
)) {
1662 sc
.ChangeState(SCE_H_ATTRIBUTEUNKNOWN
);
1664 sc
.SetState(SCE_H_OTHER
);
1666 } else if (sc
.state
== SCE_H_OTHER
) {
1668 sc
.SetState(SCE_H_TAG
);
1669 sc
.ForwardSetState(SCE_H_DEFAULT
);
1670 } else if (sc
.Match('/', '>')) {
1671 sc
.SetState(SCE_H_TAG
);
1673 sc
.ForwardSetState(SCE_H_DEFAULT
);
1674 } else if (sc
.chPrev
== '=') {
1675 sc
.SetState(SCE_H_VALUE
);
1677 } else if (sc
.state
== SCE_H_DOUBLESTRING
) {
1678 if (sc
.ch
== '\"') {
1679 sc
.ForwardSetState(SCE_H_OTHER
);
1681 } else if (sc
.state
== SCE_H_SINGLESTRING
) {
1682 if (sc
.ch
== '\'') {
1683 sc
.ForwardSetState(SCE_H_OTHER
);
1685 } else if (sc
.state
== SCE_H_NUMBER
) {
1686 if (!IsADigit(sc
.ch
)) {
1687 sc
.SetState(SCE_H_OTHER
);
1691 if (sc
.state
== SCE_H_DEFAULT
) {
1693 if (sc
.Match("<!--"))
1694 sc
.SetState(SCE_H_COMMENT
);
1696 sc
.SetState(SCE_H_TAGUNKNOWN
);
1697 } else if (sc
.ch
== '&') {
1698 sc
.SetState(SCE_H_ENTITY
);
1700 } else if ((sc
.state
== SCE_H_OTHER
) || (sc
.state
== SCE_H_VALUE
)) {
1701 if (sc
.ch
== '\"') {
1702 sc
.SetState(SCE_H_DOUBLESTRING
);
1703 } else if (sc
.ch
== '\'') {
1704 sc
.SetState(SCE_H_SINGLESTRING
);
1705 } else if (IsADigit(sc
.ch
)) {
1706 sc
.SetState(SCE_H_NUMBER
);
1707 } else if (sc
.ch
== '>') {
1708 sc
.SetState(SCE_H_TAG
);
1709 sc
.ForwardSetState(SCE_H_DEFAULT
);
1710 } else if (ishtmlwordchar(static_cast<char>(sc
.ch
))) {
1711 sc
.SetState(SCE_H_ATTRIBUTE
);
1716 static void ColouriseASPPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1717 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1718 if ((sc
.state
== SCE_H_ASPAT
|| isASPScript(sc
.state
)) && sc
.Match('%', '>')) {
1719 sc
.SetState(SCE_H_ASP
);
1721 sc
.ForwardSetState(SCE_H_DEFAULT
);
1724 // Handle some ASP script
1725 if (sc
.state
>= SCE_HBA_START
&& sc
.state
<= SCE_HBA_STRINGEOL
) {
1726 ColouriseHBAPiece(sc
, keywordlists
);
1727 } else if (sc
.state
>= SCE_H_DEFAULT
&& sc
.state
<= SCE_H_SGML_BLOCK_DEFAULT
) {
1728 ColouriseHTMLPiece(sc
, keywordlists
);
1731 // Enter new sc.state
1732 if ((sc
.state
== SCE_H_DEFAULT
) || (sc
.state
== SCE_H_TAGUNKNOWN
)) {
1733 if (sc
.Match('<', '%')) {
1734 if (sc
.state
== SCE_H_TAGUNKNOWN
)
1735 sc
.ChangeState(SCE_H_ASP
);
1737 sc
.SetState(SCE_H_ASP
);
1741 sc
.ForwardSetState(SCE_H_ASPAT
);
1746 sc
.SetState(SCE_HBA_DEFAULT
);
1752 static void ColouriseASPDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
1754 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
1755 StyleContext
sc(startPos
, length
, initStyle
, styler
, 0x7f);
1756 for (; sc
.More(); sc
.Forward()) {
1757 ColouriseASPPiece(sc
, keywordlists
);
1762 static void ColourisePHPPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1763 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1764 if (sc
.state
>= SCE_HPHP_DEFAULT
&& sc
.state
<= SCE_HPHP_OPERATOR
) {
1765 if (!isPHPStringState(sc
.state
) &&
1766 (sc
.state
!= SCE_HPHP_COMMENT
) &&
1767 (sc
.Match('?', '>'))) {
1768 sc
.SetState(SCE_H_QUESTION
);
1770 sc
.ForwardSetState(SCE_H_DEFAULT
);
1774 if (sc
.state
>= SCE_H_DEFAULT
&& sc
.state
<= SCE_H_SGML_BLOCK_DEFAULT
) {
1775 ColouriseHTMLPiece(sc
, keywordlists
);
1778 // Handle some PHP script
1779 if (sc
.state
== SCE_HPHP_WORD
) {
1780 if (!IsAWordStart(sc
.ch
)) {
1781 sc
.SetState(SCE_HPHP_DEFAULT
);
1783 } else if (sc
.state
== SCE_HPHP_COMMENTLINE
) {
1784 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1785 sc
.SetState(SCE_HPHP_DEFAULT
);
1787 } else if (sc
.state
== SCE_HPHP_COMMENT
) {
1788 if (sc
.Match('*', '/')) {
1791 sc
.SetState(SCE_HPHP_DEFAULT
);
1793 } else if (sc
.state
== SCE_HPHP_HSTRING
) {
1794 if (sc
.ch
== '\"') {
1795 sc
.ForwardSetState(SCE_HPHP_DEFAULT
);
1797 } else if (sc
.state
== SCE_HPHP_SIMPLESTRING
) {
1798 if (sc
.ch
== '\'') {
1799 sc
.ForwardSetState(SCE_HPHP_DEFAULT
);
1801 } else if (sc
.state
== SCE_HPHP_VARIABLE
) {
1802 if (!IsAWordStart(sc
.ch
)) {
1803 sc
.SetState(SCE_HPHP_DEFAULT
);
1805 } else if (sc
.state
== SCE_HPHP_OPERATOR
) {
1806 sc
.SetState(SCE_HPHP_DEFAULT
);
1809 // Enter new sc.state
1810 if ((sc
.state
== SCE_H_DEFAULT
) || (sc
.state
== SCE_H_TAGUNKNOWN
)) {
1811 if (sc
.Match("<?php")) {
1812 sc
.SetState(SCE_H_QUESTION
);
1818 sc
.SetState(SCE_HPHP_DEFAULT
);
1821 if (sc
.state
== SCE_HPHP_DEFAULT
) {
1822 if (IsAWordStart(sc
.ch
)) {
1823 sc
.SetState(SCE_HPHP_WORD
);
1824 } else if (sc
.ch
== '#') {
1825 sc
.SetState(SCE_HPHP_COMMENTLINE
);
1826 } else if (sc
.Match("<!--")) {
1827 sc
.SetState(SCE_HPHP_COMMENTLINE
);
1828 } else if (sc
.Match('/', '/')) {
1829 sc
.SetState(SCE_HPHP_COMMENTLINE
);
1830 } else if (sc
.Match('/', '*')) {
1831 sc
.SetState(SCE_HPHP_COMMENT
);
1832 } else if (sc
.ch
== '\"') {
1833 sc
.SetState(SCE_HPHP_HSTRING
);
1834 } else if (sc
.ch
== '\'') {
1835 sc
.SetState(SCE_HPHP_SIMPLESTRING
);
1836 } else if (sc
.ch
== '$') {
1837 sc
.SetState(SCE_HPHP_VARIABLE
);
1838 } else if (isoperator(static_cast<char>(sc
.ch
))) {
1839 sc
.SetState(SCE_HPHP_OPERATOR
);
1844 static void ColourisePHPDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
1846 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
1847 StyleContext
sc(startPos
, length
, initStyle
, styler
, 0x7f);
1848 for (; sc
.More(); sc
.Forward()) {
1849 ColourisePHPPiece(sc
, keywordlists
);
1854 LexerModule
lmHTML(SCLEX_HTML
, ColouriseHyperTextDoc
, "hypertext");
1855 LexerModule
lmXML(SCLEX_XML
, ColouriseHyperTextDoc
, "xml");
1856 LexerModule
lmASP(SCLEX_ASP
, ColouriseASPDoc
, "asp");
1857 LexerModule
lmPHP(SCLEX_PHP
, ColourisePHPDoc
, "php");