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 isScript
= 0 == strcmp(s
, "script");
228 styler
.ColourTo(end
, chAttr
);
229 return isScript
? SCE_H_SCRIPT
: chAttr
;
232 static void classifyWordHTJS(unsigned int start
, unsigned int end
,
233 WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
234 char chAttr
= SCE_HJ_WORD
;
235 bool wordIsNumber
= isdigit(styler
[start
]) || (styler
[start
] == '.');
237 chAttr
= SCE_HJ_NUMBER
;
241 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
242 s
[i
] = styler
[start
+ i
];
245 if (keywords
.InList(s
))
246 chAttr
= SCE_HJ_KEYWORD
;
248 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
251 static int classifyWordHTVB(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
252 char chAttr
= SCE_HB_IDENTIFIER
;
253 bool wordIsNumber
= isdigit(styler
[start
]) || (styler
[start
] == '.');
255 chAttr
= SCE_HB_NUMBER
;
259 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
260 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
263 if (keywords
.InList(s
)) {
264 chAttr
= SCE_HB_WORD
;
265 if (strcmp(s
, "rem") == 0)
266 chAttr
= SCE_HB_COMMENTLINE
;
269 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
270 if (chAttr
== SCE_HB_COMMENTLINE
)
271 return SCE_HB_COMMENTLINE
;
273 return SCE_HB_DEFAULT
;
276 static void classifyWordHTPy(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, char *prevWord
, script_mode inScriptType
) {
277 bool wordIsNumber
= isdigit(styler
[start
]) != 0;
280 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
281 s
[i
] = styler
[start
+ i
];
284 char chAttr
= SCE_HP_IDENTIFIER
;
285 if (0 == strcmp(prevWord
, "class"))
286 chAttr
= SCE_HP_CLASSNAME
;
287 else if (0 == strcmp(prevWord
, "def"))
288 chAttr
= SCE_HP_DEFNAME
;
289 else if (wordIsNumber
)
290 chAttr
= SCE_HP_NUMBER
;
291 else if (keywords
.InList(s
))
292 chAttr
= SCE_HP_WORD
;
293 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
297 // Update the word colour to default or keyword
298 // Called when in a PHP word
299 static void classifyWordHTPHP(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
300 char chAttr
= SCE_HPHP_DEFAULT
;
301 bool wordIsNumber
= isdigit(styler
[start
]) != 0;
303 chAttr
= SCE_HPHP_NUMBER
;
307 for (; i
< end
- start
+ 1 && i
< 100; i
++) {
308 s
[i
] = static_cast<char>(tolower(styler
[start
+ i
]));
311 if (keywords
.InList(s
))
312 chAttr
= SCE_HPHP_WORD
;
314 styler
.ColourTo(end
, chAttr
);
317 static bool isWordHSGML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
320 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
321 s
[i
] = styler
[start
+ i
];
324 return keywords
.InList(s
);
327 static bool isWordCdata(unsigned int start
, unsigned int end
, Accessor
&styler
) {
330 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
331 s
[i
] = styler
[start
+ i
];
334 return (0 == strcmp(s
, "[CDATA["));
337 // Return the first state to reach when entering a scripting language
338 static int StateForScript(script_type scriptLanguage
) {
340 switch (scriptLanguage
) {
342 Result
= SCE_HB_START
;
345 Result
= SCE_HP_START
;
348 Result
= SCE_HPHP_DEFAULT
;
351 Result
= SCE_H_TAGUNKNOWN
;
354 Result
= SCE_H_SGML_DEFAULT
;
357 Result
= SCE_HJ_START
;
363 static inline bool ishtmlwordchar(char ch
) {
364 return isalnum(ch
) || ch
== '.' || ch
== '-' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#';
367 static inline bool issgmlwordchar(char ch
) {
368 return isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#' || ch
== '[';
371 static bool InTagState(int state
) {
372 return state
== SCE_H_TAG
|| state
== SCE_H_TAGUNKNOWN
||
373 state
== SCE_H_SCRIPT
||
374 state
== SCE_H_ATTRIBUTE
|| state
== SCE_H_ATTRIBUTEUNKNOWN
||
375 state
== SCE_H_NUMBER
|| state
== SCE_H_OTHER
||
376 state
== SCE_H_DOUBLESTRING
|| state
== SCE_H_SINGLESTRING
;
379 static bool IsCommentState(const int state
) {
380 return state
== SCE_H_COMMENT
|| state
== SCE_H_SGML_COMMENT
;
383 static bool isLineEnd(char ch
) {
384 return ch
== '\r' || ch
== '\n';
387 static bool isOKBeforeRE(char ch
) {
388 return (ch
== '(') || (ch
== '=') || (ch
== ',');
391 static bool isPHPStringState(int state
) {
393 (state
== SCE_HPHP_HSTRING
) ||
394 (state
== SCE_HPHP_SIMPLESTRING
) ||
395 (state
== SCE_HPHP_HSTRING_VARIABLE
);
398 static void ColouriseHyperTextDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
400 WordList
&keywords
= *keywordlists
[0];
401 WordList
&keywords2
= *keywordlists
[1];
402 WordList
&keywords3
= *keywordlists
[2];
403 WordList
&keywords4
= *keywordlists
[3];
404 WordList
&keywords5
= *keywordlists
[4];
405 WordList
&keywords6
= *keywordlists
[5]; // SGML (DTD) keywords
407 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
408 styler
.StartAt(startPos
, STYLE_MAX
);
411 int StateToPrint
= initStyle
;
412 int state
= stateForPrintState(StateToPrint
);
414 // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen
415 if (InTagState(state
)) {
416 while ((startPos
> 0) && (InTagState(styler
.StyleAt(startPos
- 1)))) {
420 state
= SCE_H_DEFAULT
;
422 styler
.StartAt(startPos
, STYLE_MAX
);
424 int lineCurrent
= styler
.GetLine(startPos
);
426 if (lineCurrent
> 0) {
427 lineState
= styler
.GetLineState(lineCurrent
);
429 // Default client and ASP scripting language is JavaScript
430 lineState
= eScriptJS
<< 8;
431 lineState
|= styler
.GetPropertyInt("asp.default.language", eScriptJS
) << 4;
433 script_mode inScriptType
= script_mode((lineState
>> 0) & 0x03); // 2 bits of scripting mode
434 bool tagOpened
= (lineState
>> 2) & 0x01; // 1 bit to know if we are in an opened tag
435 bool tagClosing
= (lineState
>> 3) & 0x01; // 1 bit to know if we are in a closing tag
436 script_type aspScript
= script_type((lineState
>> 4) & 0x0F); // 4 bits of script name
437 script_type clientScript
= script_type((lineState
>> 8) & 0x0F); // 4 bits of script name
438 int beforePreProc
= (lineState
>> 12) & 0xFF; // 8 bits of state
440 script_type scriptLanguage
= ScriptOfState(state
);
442 const bool foldHTML
= styler
.GetPropertyInt("fold.html", 0) != 0;
443 const bool fold
= foldHTML
&& styler
.GetPropertyInt("fold");
444 const bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
446 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
447 int levelCurrent
= levelPrev
;
448 int visibleChars
= 0;
452 char chPrevNonWhite
= ' ';
453 styler
.StartSegment(startPos
);
454 const int lengthDoc
= startPos
+ length
;
455 for (int i
= startPos
; i
< lengthDoc
; i
++) {
456 const char chPrev2
= chPrev
;
458 if (ch
!= ' ' && ch
!= '\t')
461 char chNext
= styler
.SafeGetCharAt(i
+ 1);
462 const char chNext2
= styler
.SafeGetCharAt(i
+ 2);
464 // Handle DBCS codepages
465 if (styler
.IsLeadByte(ch
)) {
471 if ((!isspacechar(ch
) || !foldCompact
) && fold
)
474 // decide what is the current state to print (depending of the script tag)
475 StateToPrint
= statePrintForState(state
, inScriptType
);
477 // handle script folding
479 switch (scriptLanguage
) {
482 //not currently supported case eScriptVBS:
484 if ((state
!= SCE_HPHP_COMMENT
) && (state
!= SCE_HPHP_COMMENTLINE
) && (state
!= SCE_HJ_COMMENT
) && (state
!= SCE_HJ_COMMENTLINE
) && (state
!= SCE_HJ_COMMENTDOC
)) {
485 if ((ch
== '{') || (ch
== '}')) {
486 levelCurrent
+= (ch
== '{') ? 1 : -1;
491 if (state
!= SCE_HP_COMMENTLINE
) {
492 if ((ch
== ':') && ((chNext
== '\n') || (chNext
== '\r' && chNext2
== '\n'))) {
494 } else if ((ch
== '\n') && !((chNext
== '\r') && (chNext2
== '\n')) && (chNext
!= '\n')) {
495 // check if the number of tabs is lower than the level
496 int Findlevel
= (levelCurrent
& ~SC_FOLDLEVELBASE
) * 8;
497 for (int j
= 0; Findlevel
> 0; j
++) {
498 char chTmp
= styler
.SafeGetCharAt(i
+ j
+ 1);
501 } else if (chTmp
== ' ') {
509 levelCurrent
-= Findlevel
/ 8;
521 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) {
522 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
523 // Avoid triggering two times on Dos/Win
524 // New line -> record any line state onto /next/ line
527 if (visibleChars
== 0)
528 lev
|= SC_FOLDLEVELWHITEFLAG
;
529 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
530 lev
|= SC_FOLDLEVELHEADERFLAG
;
532 styler
.SetLevel(lineCurrent
, lev
);
534 levelPrev
= levelCurrent
;
537 styler
.SetLineState(lineCurrent
,
538 ((inScriptType
& 0x03) << 0) |
539 ((tagOpened
& 0x01) << 2) |
540 ((tagClosing
& 0x01) << 3) |
541 ((aspScript
& 0x0F) << 4) |
542 ((clientScript
& 0x0F) << 8) |
543 ((beforePreProc
& 0xFF) << 12));
546 // generic end of script processing
547 else if ((inScriptType
== eNonHtmlScript
) && (ch
== '<') && (chNext
== '/')) {
548 // Check if it's the end of the script tag (or any other HTML tag)
550 // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
551 case SCE_H_DOUBLESTRING
:
552 case SCE_H_SINGLESTRING
:
554 case SCE_HJ_COMMENTDOC
:
555 // SCE_HJ_COMMENTLINE removed as this is a common thing done to hide
556 // the end of script marker from some JS interpreters.
557 //case SCE_HJ_COMMENTLINE:
558 case SCE_HJ_DOUBLESTRING
:
559 case SCE_HJ_SINGLESTRING
:
564 case SCE_HP_TRIPLEDOUBLE
:
567 // closing tag of the script (it's a closing HTML tag anyway)
568 styler
.ColourTo(i
- 1, StateToPrint
);
569 state
= SCE_H_TAGUNKNOWN
;
570 inScriptType
= eHtml
;
571 scriptLanguage
= eScriptNone
;
572 clientScript
= eScriptJS
;
580 /////////////////////////////////////
581 // handle the start of PHP pre-processor = Non-HTML
582 else if ((state
!= SCE_H_ASPAT
) &&
583 !isPHPStringState(state
) &&
584 (state
!= SCE_HPHP_COMMENT
) &&
587 styler
.ColourTo(i
- 1, StateToPrint
);
588 beforePreProc
= state
;
589 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment() + 2, i
+ 10, eScriptPHP
);
592 i
+= PrintScriptingIndicatorOffset(styler
, styler
.GetStartSegment() + 2, i
+ 10);
593 if (scriptLanguage
== eScriptXML
)
594 styler
.ColourTo(i
, SCE_H_XMLSTART
);
596 styler
.ColourTo(i
, SCE_H_QUESTION
);
597 state
= StateForScript(scriptLanguage
);
598 if (inScriptType
== eNonHtmlScript
)
599 inScriptType
= eNonHtmlScriptPreProc
;
601 inScriptType
= eNonHtmlPreProc
;
604 if (scriptLanguage
== eScriptXML
)
605 levelCurrent
--; // no folding of the XML first tag (all XML-like tags in this case)
607 ch
= styler
.SafeGetCharAt(i
);
611 // handle the start of ASP pre-processor = Non-HTML
612 else if (!isCommentASPState(state
) && (ch
== '<') && (chNext
== '%')) {
613 styler
.ColourTo(i
- 1, StateToPrint
);
614 beforePreProc
= state
;
615 if (inScriptType
== eNonHtmlScript
)
616 inScriptType
= eNonHtmlScriptPreProc
;
618 inScriptType
= eNonHtmlPreProc
;
620 if (chNext2
== '@') {
621 i
+= 2; // place as if it was the second next char treated
624 } else if ((chNext2
== '-') && (styler
.SafeGetCharAt(i
+ 3) == '-')) {
625 styler
.ColourTo(i
+ 3, SCE_H_ASP
);
626 state
= SCE_H_XCCOMMENT
;
627 scriptLanguage
= eScriptVBS
;
630 if (chNext2
== '=') {
631 i
+= 2; // place as if it was the second next char treated
634 i
++; // place as if it was the next char treated
638 state
= StateForScript(aspScript
);
640 scriptLanguage
= eScriptVBS
;
641 styler
.ColourTo(i
, SCE_H_ASP
);
645 ch
= styler
.SafeGetCharAt(i
);
649 /////////////////////////////////////
650 // handle the start of SGML language (DTD)
651 else if (((scriptLanguage
== eScriptNone
) || (scriptLanguage
== eScriptXML
)) &&
654 (StateToPrint
!= SCE_H_CDATA
) && (!IsCommentState(StateToPrint
))) {
655 beforePreProc
= state
;
656 styler
.ColourTo(i
- 2, StateToPrint
);
657 if ((chNext
== '-') && (chNext2
== '-')) {
658 state
= SCE_H_COMMENT
; // wait for a pending command
660 else if (isWordCdata(i
+ 1, i
+ 7, styler
)) {
663 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
); // <! is default
664 scriptLanguage
= eScriptSGML
;
665 state
= SCE_H_SGML_COMMAND
; // wait for a pending command
667 // fold whole tag (-- when closing the tag)
673 // handle the end of a pre-processor = Non-HTML
675 ((inScriptType
== eNonHtmlPreProc
)
676 || (inScriptType
== eNonHtmlScriptPreProc
)) && (
677 ((scriptLanguage
== eScriptPHP
) && (ch
== '?') && !isPHPStringState(state
) && (state
!= SCE_HPHP_COMMENT
)) ||
678 ((scriptLanguage
!= eScriptNone
) && !isStringState(state
) &&
680 ) && (chNext
== '>')) ||
681 ((scriptLanguage
== eScriptSGML
) && (ch
== '>') && (state
!= SCE_H_SGML_COMMENT
))) {
682 if (state
== SCE_H_ASPAT
) {
683 aspScript
= segIsScriptingIndicator(styler
,
684 styler
.GetStartSegment(), i
- 1, aspScript
);
686 // Bounce out of any ASP mode
689 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
692 classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
695 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
698 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
700 case SCE_H_XCCOMMENT
:
701 styler
.ColourTo(i
- 1, state
);
704 styler
.ColourTo(i
- 1, StateToPrint
);
707 if (scriptLanguage
!= eScriptSGML
) {
712 styler
.ColourTo(i
, SCE_H_ASP
);
713 else if (scriptLanguage
== eScriptXML
)
714 styler
.ColourTo(i
, SCE_H_XMLEND
);
715 else if (scriptLanguage
== eScriptSGML
)
716 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
718 styler
.ColourTo(i
, SCE_H_QUESTION
);
719 state
= beforePreProc
;
720 if (inScriptType
== eNonHtmlScriptPreProc
)
721 inScriptType
= eNonHtmlScript
;
723 inScriptType
= eHtml
;
724 scriptLanguage
= eScriptNone
;
725 // unfold all scripting languages
729 /////////////////////////////////////
734 // in HTML, fold on tag open and unfold on tag close
736 tagClosing
= (chNext
== '/');
737 styler
.ColourTo(i
- 1, StateToPrint
);
739 state
= SCE_H_TAGUNKNOWN
;
740 } else if (ch
== '&') {
741 styler
.ColourTo(i
- 1, SCE_H_DEFAULT
);
742 state
= SCE_H_ENTITY
;
745 case SCE_H_SGML_DEFAULT
:
746 case SCE_H_SGML_BLOCK_DEFAULT
:
747 // if (scriptLanguage == eScriptSGMLblock)
748 // StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
751 styler
.ColourTo(i
- 1, StateToPrint
);
752 state
= SCE_H_SGML_DOUBLESTRING
;
753 } else if (ch
== '\'') {
754 styler
.ColourTo(i
- 1, StateToPrint
);
755 state
= SCE_H_SGML_SIMPLESTRING
;
756 } else if ((ch
== '-') && (chPrev
== '-')) {
757 styler
.ColourTo(i
- 2, StateToPrint
);
758 state
= SCE_H_SGML_COMMENT
;
759 } else if (isalpha(ch
) && (chPrev
== '%')) {
760 styler
.ColourTo(i
- 2, StateToPrint
);
761 state
= SCE_H_SGML_ENTITY
;
762 } else if (ch
== '#') {
763 styler
.ColourTo(i
- 1, StateToPrint
);
764 state
= SCE_H_SGML_SPECIAL
;
765 } else if (ch
== '[') {
766 styler
.ColourTo(i
- 1, StateToPrint
);
767 scriptLanguage
= eScriptSGMLblock
;
768 state
= SCE_H_SGML_BLOCK_DEFAULT
;
769 } else if (ch
== ']') {
770 if (scriptLanguage
== eScriptSGMLblock
) {
771 styler
.ColourTo(i
, StateToPrint
);
772 scriptLanguage
= eScriptSGML
;
774 styler
.ColourTo(i
- 1, StateToPrint
);
775 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
777 state
= SCE_H_SGML_DEFAULT
;
778 } else if (scriptLanguage
== eScriptSGMLblock
) {
779 if ((ch
== '!') && (chPrev
== '<')) {
780 styler
.ColourTo(i
- 2, StateToPrint
);
781 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
782 state
= SCE_H_SGML_COMMAND
;
783 } else if (ch
== '>') {
784 styler
.ColourTo(i
- 1, StateToPrint
);
785 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
789 case SCE_H_SGML_COMMAND
:
790 if ((ch
== '-') && (chPrev
== '-')) {
791 styler
.ColourTo(i
- 2, StateToPrint
);
792 state
= SCE_H_SGML_COMMENT
;
793 } else if (!issgmlwordchar(ch
)) {
794 if (isWordHSGML(styler
.GetStartSegment(), i
- 1, keywords6
, styler
)) {
795 styler
.ColourTo(i
- 1, StateToPrint
);
796 state
= SCE_H_SGML_1ST_PARAM
;
798 state
= SCE_H_SGML_ERROR
;
802 case SCE_H_SGML_1ST_PARAM
:
803 // wait for the beginning of the word
804 if ((ch
== '-') && (chPrev
== '-')) {
805 if (scriptLanguage
== eScriptSGMLblock
) {
806 styler
.ColourTo(i
- 2, SCE_H_SGML_BLOCK_DEFAULT
);
808 styler
.ColourTo(i
- 2, SCE_H_SGML_DEFAULT
);
810 state
= SCE_H_SGML_1ST_PARAM_COMMENT
;
811 } else if (issgmlwordchar(ch
)) {
812 if (scriptLanguage
== eScriptSGMLblock
) {
813 styler
.ColourTo(i
- 1, SCE_H_SGML_BLOCK_DEFAULT
);
815 styler
.ColourTo(i
- 1, SCE_H_SGML_DEFAULT
);
817 // find the length of the word
819 while (ishtmlwordchar(styler
.SafeGetCharAt(i
+ size
)))
821 styler
.ColourTo(i
+ size
- 1, StateToPrint
);
823 visibleChars
+= size
- 1;
824 ch
= styler
.SafeGetCharAt(i
);
825 if (scriptLanguage
== eScriptSGMLblock
) {
826 state
= SCE_H_SGML_BLOCK_DEFAULT
;
828 state
= SCE_H_SGML_DEFAULT
;
833 case SCE_H_SGML_ERROR
:
834 if ((ch
== '-') && (chPrev
== '-')) {
835 styler
.ColourTo(i
- 2, StateToPrint
);
836 state
= SCE_H_SGML_COMMENT
;
838 case SCE_H_SGML_DOUBLESTRING
:
840 styler
.ColourTo(i
, StateToPrint
);
841 state
= SCE_H_SGML_DEFAULT
;
844 case SCE_H_SGML_SIMPLESTRING
:
846 styler
.ColourTo(i
, StateToPrint
);
847 state
= SCE_H_SGML_DEFAULT
;
850 case SCE_H_SGML_COMMENT
:
851 if ((ch
== '-') && (chPrev
== '-')) {
852 styler
.ColourTo(i
, StateToPrint
);
853 state
= SCE_H_SGML_DEFAULT
;
857 if ((chPrev2
== ']') && (chPrev
== ']') && (ch
== '>')) {
858 styler
.ColourTo(i
, StateToPrint
);
859 state
= SCE_H_DEFAULT
;
864 if ((chPrev2
== '-') && (chPrev
== '-') && (ch
== '>')) {
865 styler
.ColourTo(i
, StateToPrint
);
866 state
= SCE_H_DEFAULT
;
870 case SCE_H_SGML_1ST_PARAM_COMMENT
:
871 if ((ch
== '-') && (chPrev
== '-')) {
872 styler
.ColourTo(i
, SCE_H_SGML_COMMENT
);
873 state
= SCE_H_SGML_1ST_PARAM
;
876 case SCE_H_SGML_SPECIAL
:
878 styler
.ColourTo(i
- 1, StateToPrint
);
880 state
= SCE_H_SGML_ERROR
;
882 state
= SCE_H_SGML_DEFAULT
;
886 case SCE_H_SGML_ENTITY
:
888 styler
.ColourTo(i
, StateToPrint
);
889 state
= SCE_H_SGML_DEFAULT
;
890 } else if (!isalnum(ch
) && ch
!= '-' && ch
!= '.') {
891 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
892 state
= SCE_H_SGML_DEFAULT
;
897 styler
.ColourTo(i
, StateToPrint
);
898 state
= SCE_H_DEFAULT
;
900 if (ch
!= '#' && !isalnum(ch
)) { // Should check that '#' follows '&', but it is unlikely anyway...
901 styler
.ColourTo(i
, SCE_H_TAGUNKNOWN
);
902 state
= SCE_H_DEFAULT
;
905 case SCE_H_TAGUNKNOWN
:
906 if (!ishtmlwordchar(ch
) && !((ch
== '/') && (chPrev
== '<')) && ch
!= '[') {
907 int eClass
= classifyTagHTML(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
908 if (eClass
== SCE_H_SCRIPT
) {
910 inScriptType
= eNonHtmlScript
;
911 scriptLanguage
= clientScript
;
914 scriptLanguage
= eScriptNone
;
919 styler
.ColourTo(i
, eClass
);
920 if (inScriptType
== eNonHtmlScript
) {
921 state
= StateForScript(scriptLanguage
);
923 state
= SCE_H_DEFAULT
;
932 } else if (ch
== '/' && chNext
== '>') {
933 if (eClass
== SCE_H_TAGUNKNOWN
) {
934 styler
.ColourTo(i
+ 1, SCE_H_TAGUNKNOWN
);
936 styler
.ColourTo(i
- 1, StateToPrint
);
937 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
941 state
= SCE_H_DEFAULT
;
944 if (eClass
!= SCE_H_TAGUNKNOWN
) {
945 if (eClass
== SCE_H_SGML_DEFAULT
) {
946 state
= SCE_H_SGML_DEFAULT
;
954 case SCE_H_ATTRIBUTE
:
955 if (!ishtmlwordchar(ch
) && ch
!= '/' && ch
!= '-') {
956 if (inScriptType
== eNonHtmlScript
) {
957 int scriptLanguagePrev
= scriptLanguage
;
958 clientScript
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
- 1, scriptLanguage
);
959 scriptLanguage
= clientScript
;
960 if ((scriptLanguagePrev
!= scriptLanguage
) && (scriptLanguage
== eScriptNone
))
961 inScriptType
= eHtml
;
963 classifyAttribHTML(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
965 styler
.ColourTo(i
, SCE_H_TAG
);
966 if (inScriptType
== eNonHtmlScript
) {
967 state
= StateForScript(scriptLanguage
);
969 state
= SCE_H_DEFAULT
;
977 } else if (ch
== '=') {
978 styler
.ColourTo(i
, SCE_H_OTHER
);
987 styler
.ColourTo(i
- 1, StateToPrint
);
988 styler
.ColourTo(i
, SCE_H_TAG
);
989 if (inScriptType
== eNonHtmlScript
) {
990 state
= StateForScript(scriptLanguage
);
992 state
= SCE_H_DEFAULT
;
1000 } else if (ch
== '\"') {
1001 styler
.ColourTo(i
- 1, StateToPrint
);
1002 state
= SCE_H_DOUBLESTRING
;
1003 } else if (ch
== '\'') {
1004 styler
.ColourTo(i
- 1, StateToPrint
);
1005 state
= SCE_H_SINGLESTRING
;
1006 } else if (ch
== '=') {
1007 styler
.ColourTo(i
, StateToPrint
);
1008 state
= SCE_H_VALUE
;
1009 } else if (ch
== '/' && chNext
== '>') {
1010 styler
.ColourTo(i
- 1, StateToPrint
);
1011 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1014 state
= SCE_H_DEFAULT
;
1016 } else if (ch
== '?' && chNext
== '>') {
1017 styler
.ColourTo(i
- 1, StateToPrint
);
1018 styler
.ColourTo(i
+ 1, SCE_H_XMLEND
);
1021 state
= SCE_H_DEFAULT
;
1022 } else if (ishtmlwordchar(ch
)) {
1023 styler
.ColourTo(i
- 1, StateToPrint
);
1024 state
= SCE_H_ATTRIBUTE
;
1027 case SCE_H_DOUBLESTRING
:
1029 if (inScriptType
== eNonHtmlScript
) {
1030 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1032 styler
.ColourTo(i
, SCE_H_DOUBLESTRING
);
1033 state
= SCE_H_OTHER
;
1036 case SCE_H_SINGLESTRING
:
1038 if (inScriptType
== eNonHtmlScript
) {
1039 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1041 styler
.ColourTo(i
, SCE_H_SINGLESTRING
);
1042 state
= SCE_H_OTHER
;
1046 if (!ishtmlwordchar(ch
)) {
1048 // Should really test for being first character
1049 state
= SCE_H_DOUBLESTRING
;
1050 } else if (ch
== '\'') {
1051 state
= SCE_H_SINGLESTRING
;
1053 if (IsNumber(styler
.GetStartSegment(), styler
)) {
1054 styler
.ColourTo(i
- 1, SCE_H_NUMBER
);
1056 styler
.ColourTo(i
- 1, StateToPrint
);
1059 styler
.ColourTo(i
, SCE_H_TAG
);
1060 if (inScriptType
== eNonHtmlScript
) {
1061 state
= StateForScript(scriptLanguage
);
1063 state
= SCE_H_DEFAULT
;
1072 state
= SCE_H_OTHER
;
1077 case SCE_HJ_DEFAULT
:
1079 case SCE_HJ_SYMBOLS
:
1080 if (iswordstart(ch
)) {
1081 styler
.ColourTo(i
- 1, StateToPrint
);
1082 state
= SCE_HJ_WORD
;
1083 } else if (ch
== '/' && chNext
== '*') {
1084 styler
.ColourTo(i
- 1, StateToPrint
);
1086 state
= SCE_HJ_COMMENTDOC
;
1088 state
= SCE_HJ_COMMENT
;
1089 } else if (ch
== '/' && chNext
== '/') {
1090 styler
.ColourTo(i
- 1, StateToPrint
);
1091 state
= SCE_HJ_COMMENTLINE
;
1092 } else if (ch
== '/' && isOKBeforeRE(chPrevNonWhite
)) {
1093 styler
.ColourTo(i
- 1, StateToPrint
);
1094 state
= SCE_HJ_REGEX
;
1095 } else if (ch
== '\"') {
1096 styler
.ColourTo(i
- 1, StateToPrint
);
1097 state
= SCE_HJ_DOUBLESTRING
;
1098 } else if (ch
== '\'') {
1099 styler
.ColourTo(i
- 1, StateToPrint
);
1100 state
= SCE_HJ_SINGLESTRING
;
1101 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1102 styler
.SafeGetCharAt(i
+ 3) == '-') {
1103 styler
.ColourTo(i
- 1, StateToPrint
);
1104 state
= SCE_HJ_COMMENTLINE
;
1105 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1106 styler
.ColourTo(i
- 1, StateToPrint
);
1107 state
= SCE_HJ_COMMENTLINE
;
1109 } else if (isoperator(ch
)) {
1110 styler
.ColourTo(i
- 1, StateToPrint
);
1111 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1112 state
= SCE_HJ_DEFAULT
;
1113 } else if ((ch
== ' ') || (ch
== '\t')) {
1114 if (state
== SCE_HJ_START
) {
1115 styler
.ColourTo(i
- 1, StateToPrint
);
1116 state
= SCE_HJ_DEFAULT
;
1121 if (!iswordchar(ch
)) {
1122 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
1123 //styler.ColourTo(i - 1, eHTJSKeyword);
1124 state
= SCE_HJ_DEFAULT
;
1125 if (ch
== '/' && chNext
== '*') {
1127 state
= SCE_HJ_COMMENTDOC
;
1129 state
= SCE_HJ_COMMENT
;
1130 } else if (ch
== '/' && chNext
== '/') {
1131 state
= SCE_HJ_COMMENTLINE
;
1132 } else if (ch
== '\"') {
1133 state
= SCE_HJ_DOUBLESTRING
;
1134 } else if (ch
== '\'') {
1135 state
= SCE_HJ_SINGLESTRING
;
1136 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1137 styler
.ColourTo(i
- 1, StateToPrint
);
1138 state
= SCE_HJ_COMMENTLINE
;
1140 } else if (isoperator(ch
)) {
1141 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1142 state
= SCE_HJ_DEFAULT
;
1146 case SCE_HJ_COMMENT
:
1147 case SCE_HJ_COMMENTDOC
:
1148 if (ch
== '/' && chPrev
== '*') {
1149 styler
.ColourTo(i
, StateToPrint
);
1150 state
= SCE_HJ_DEFAULT
;
1153 case SCE_HJ_COMMENTLINE
:
1154 if (ch
== '\r' || ch
== '\n') {
1155 styler
.ColourTo(i
- 1, statePrintForState(SCE_HJ_COMMENTLINE
, inScriptType
));
1156 state
= SCE_HJ_DEFAULT
;
1159 case SCE_HJ_DOUBLESTRING
:
1161 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1164 } else if (ch
== '\"') {
1165 styler
.ColourTo(i
, statePrintForState(SCE_HJ_DOUBLESTRING
, inScriptType
));
1166 state
= SCE_HJ_DEFAULT
;
1167 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1168 styler
.ColourTo(i
- 1, StateToPrint
);
1169 state
= SCE_HJ_COMMENTLINE
;
1171 } else if (isLineEnd(ch
)) {
1172 styler
.ColourTo(i
- 1, StateToPrint
);
1173 state
= SCE_HJ_STRINGEOL
;
1176 case SCE_HJ_SINGLESTRING
:
1178 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1181 } else if (ch
== '\'') {
1182 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SINGLESTRING
, inScriptType
));
1183 state
= SCE_HJ_DEFAULT
;
1184 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1185 styler
.ColourTo(i
- 1, StateToPrint
);
1186 state
= SCE_HJ_COMMENTLINE
;
1188 } else if (isLineEnd(ch
)) {
1189 styler
.ColourTo(i
- 1, StateToPrint
);
1190 state
= SCE_HJ_STRINGEOL
;
1193 case SCE_HJ_STRINGEOL
:
1194 if (!isLineEnd(ch
)) {
1195 styler
.ColourTo(i
- 1, StateToPrint
);
1196 state
= SCE_HJ_DEFAULT
;
1197 } else if (!isLineEnd(chNext
)) {
1198 styler
.ColourTo(i
, StateToPrint
);
1199 state
= SCE_HJ_DEFAULT
;
1203 if (ch
== '\r' || ch
== '\n' || ch
== '/') {
1204 styler
.ColourTo(i
, StateToPrint
);
1205 state
= SCE_HJ_DEFAULT
;
1206 } else if (ch
== '\\') {
1207 // Gobble up the quoted character
1208 if (chNext
== '\\' || chNext
== '/') {
1211 chNext
= styler
.SafeGetCharAt(i
+ 1);
1215 case SCE_HB_DEFAULT
:
1217 if (iswordstart(ch
)) {
1218 styler
.ColourTo(i
- 1, StateToPrint
);
1219 state
= SCE_HB_WORD
;
1220 } else if (ch
== '\'') {
1221 styler
.ColourTo(i
- 1, StateToPrint
);
1222 state
= SCE_HB_COMMENTLINE
;
1223 } else if (ch
== '\"') {
1224 styler
.ColourTo(i
- 1, StateToPrint
);
1225 state
= SCE_HB_STRING
;
1226 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1227 styler
.SafeGetCharAt(i
+ 3) == '-') {
1228 styler
.ColourTo(i
- 1, StateToPrint
);
1229 state
= SCE_HB_COMMENTLINE
;
1230 } else if (isoperator(ch
)) {
1231 styler
.ColourTo(i
- 1, StateToPrint
);
1232 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1233 state
= SCE_HB_DEFAULT
;
1234 } else if ((ch
== ' ') || (ch
== '\t')) {
1235 if (state
== SCE_HB_START
) {
1236 styler
.ColourTo(i
- 1, StateToPrint
);
1237 state
= SCE_HB_DEFAULT
;
1242 if (!iswordchar(ch
)) {
1243 state
= classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
1244 if (state
== SCE_HB_DEFAULT
) {
1246 state
= SCE_HB_STRING
;
1247 } else if (ch
== '\'') {
1248 state
= SCE_HB_COMMENTLINE
;
1249 } else if (isoperator(ch
)) {
1250 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1251 state
= SCE_HB_DEFAULT
;
1258 styler
.ColourTo(i
, StateToPrint
);
1259 state
= SCE_HB_DEFAULT
;
1260 } else if (ch
== '\r' || ch
== '\n') {
1261 styler
.ColourTo(i
- 1, StateToPrint
);
1262 state
= SCE_HB_STRINGEOL
;
1265 case SCE_HB_COMMENTLINE
:
1266 if (ch
== '\r' || ch
== '\n') {
1267 styler
.ColourTo(i
- 1, StateToPrint
);
1268 state
= SCE_HB_DEFAULT
;
1271 case SCE_HB_STRINGEOL
:
1272 if (!isLineEnd(ch
)) {
1273 styler
.ColourTo(i
- 1, StateToPrint
);
1274 state
= SCE_HB_DEFAULT
;
1275 } else if (!isLineEnd(chNext
)) {
1276 styler
.ColourTo(i
, StateToPrint
);
1277 state
= SCE_HB_DEFAULT
;
1280 case SCE_HP_DEFAULT
:
1282 if (iswordstart(ch
)) {
1283 styler
.ColourTo(i
- 1, StateToPrint
);
1284 state
= SCE_HP_WORD
;
1285 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1286 styler
.SafeGetCharAt(i
+ 3) == '-') {
1287 styler
.ColourTo(i
- 1, StateToPrint
);
1288 state
= SCE_HP_COMMENTLINE
;
1289 } else if (ch
== '#') {
1290 styler
.ColourTo(i
- 1, StateToPrint
);
1291 state
= SCE_HP_COMMENTLINE
;
1292 } else if (ch
== '\"') {
1293 styler
.ColourTo(i
- 1, StateToPrint
);
1294 if (chNext
== '\"' && chNext2
== '\"') {
1296 state
= SCE_HP_TRIPLEDOUBLE
;
1299 chNext
= styler
.SafeGetCharAt(i
+ 1);
1301 // state = statePrintForState(SCE_HP_STRING,inScriptType);
1302 state
= SCE_HP_STRING
;
1304 } else if (ch
== '\'') {
1305 styler
.ColourTo(i
- 1, StateToPrint
);
1306 if (chNext
== '\'' && chNext2
== '\'') {
1308 state
= SCE_HP_TRIPLE
;
1311 chNext
= styler
.SafeGetCharAt(i
+ 1);
1313 state
= SCE_HP_CHARACTER
;
1315 } else if (isoperator(ch
)) {
1316 styler
.ColourTo(i
- 1, StateToPrint
);
1317 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1318 } else if ((ch
== ' ') || (ch
== '\t')) {
1319 if (state
== SCE_HP_START
) {
1320 styler
.ColourTo(i
- 1, StateToPrint
);
1321 state
= SCE_HP_DEFAULT
;
1326 if (!iswordchar(ch
)) {
1327 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
);
1328 state
= SCE_HP_DEFAULT
;
1330 state
= SCE_HP_COMMENTLINE
;
1331 } else if (ch
== '\"') {
1332 if (chNext
== '\"' && chNext2
== '\"') {
1334 state
= SCE_HP_TRIPLEDOUBLE
;
1337 chNext
= styler
.SafeGetCharAt(i
+ 1);
1339 state
= SCE_HP_STRING
;
1341 } else if (ch
== '\'') {
1342 if (chNext
== '\'' && chNext2
== '\'') {
1344 state
= SCE_HP_TRIPLE
;
1347 chNext
= styler
.SafeGetCharAt(i
+ 1);
1349 state
= SCE_HP_CHARACTER
;
1351 } else if (isoperator(ch
)) {
1352 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1356 case SCE_HP_COMMENTLINE
:
1357 if (ch
== '\r' || ch
== '\n') {
1358 styler
.ColourTo(i
- 1, StateToPrint
);
1359 state
= SCE_HP_DEFAULT
;
1364 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1367 chNext
= styler
.SafeGetCharAt(i
+ 1);
1369 } else if (ch
== '\"') {
1370 styler
.ColourTo(i
, StateToPrint
);
1371 state
= SCE_HP_DEFAULT
;
1374 case SCE_HP_CHARACTER
:
1376 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1379 chNext
= styler
.SafeGetCharAt(i
+ 1);
1381 } else if (ch
== '\'') {
1382 styler
.ColourTo(i
, StateToPrint
);
1383 state
= SCE_HP_DEFAULT
;
1387 if (ch
== '\'' && chPrev
== '\'' && chPrev2
== '\'') {
1388 styler
.ColourTo(i
, StateToPrint
);
1389 state
= SCE_HP_DEFAULT
;
1392 case SCE_HP_TRIPLEDOUBLE
:
1393 if (ch
== '\"' && chPrev
== '\"' && chPrev2
== '\"') {
1394 styler
.ColourTo(i
, StateToPrint
);
1395 state
= SCE_HP_DEFAULT
;
1398 ///////////// start - PHP state handling
1400 if (!iswordstart(ch
)) {
1401 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
1402 if (ch
== '/' && chNext
== '*') {
1404 state
= SCE_HPHP_COMMENT
;
1405 } else if (ch
== '/' && chNext
== '/') {
1407 state
= SCE_HPHP_COMMENTLINE
;
1408 } else if (ch
== '#') {
1409 state
= SCE_HPHP_COMMENTLINE
;
1410 } else if (ch
== '\"') {
1411 state
= SCE_HPHP_HSTRING
;
1412 } else if (ch
== '\'') {
1413 state
= SCE_HPHP_SIMPLESTRING
;
1414 } else if (ch
== '$') {
1415 state
= SCE_HPHP_VARIABLE
;
1416 } else if (isoperator(ch
)) {
1417 state
= SCE_HPHP_OPERATOR
;
1419 state
= SCE_HPHP_DEFAULT
;
1423 case SCE_HPHP_NUMBER
:
1425 styler
.ColourTo(i
- 1, SCE_HPHP_NUMBER
);
1427 state
= SCE_HPHP_OPERATOR
;
1429 state
= SCE_HPHP_DEFAULT
;
1432 case SCE_HPHP_VARIABLE
:
1433 if (!iswordstart(ch
)) {
1434 styler
.ColourTo(i
- 1, SCE_HPHP_VARIABLE
);
1436 state
= SCE_HPHP_OPERATOR
;
1438 state
= SCE_HPHP_DEFAULT
;
1441 case SCE_HPHP_COMMENT
:
1442 if (ch
== '/' && chPrev
== '*') {
1443 styler
.ColourTo(i
, StateToPrint
);
1444 state
= SCE_HPHP_DEFAULT
;
1447 case SCE_HPHP_COMMENTLINE
:
1448 if (ch
== '\r' || ch
== '\n') {
1449 styler
.ColourTo(i
- 1, StateToPrint
);
1450 state
= SCE_HPHP_DEFAULT
;
1453 case SCE_HPHP_HSTRING
:
1455 // skip the next char
1457 } else if (ch
== '$') {
1458 styler
.ColourTo(i
- 1, StateToPrint
);
1459 state
= SCE_HPHP_HSTRING_VARIABLE
;
1460 } else if (ch
== '\"') {
1461 styler
.ColourTo(i
, StateToPrint
);
1462 state
= SCE_HPHP_DEFAULT
;
1465 case SCE_HPHP_SIMPLESTRING
:
1467 // skip the next char
1469 } else if (ch
== '\'') {
1470 styler
.ColourTo(i
, StateToPrint
);
1471 state
= SCE_HPHP_DEFAULT
;
1474 case SCE_HPHP_HSTRING_VARIABLE
:
1475 if (!iswordstart(ch
)) {
1476 styler
.ColourTo(i
- 1, StateToPrint
);
1477 i
--; // strange but it works
1478 state
= SCE_HPHP_HSTRING
;
1481 case SCE_HPHP_OPERATOR
:
1482 case SCE_HPHP_DEFAULT
:
1483 styler
.ColourTo(i
- 1, StateToPrint
);
1485 state
= SCE_HPHP_NUMBER
;
1486 } else if (iswordstart(ch
)) {
1487 state
= SCE_HPHP_WORD
;
1488 } else if (ch
== '/' && chNext
== '*') {
1490 state
= SCE_HPHP_COMMENT
;
1491 } else if (ch
== '/' && chNext
== '/') {
1493 state
= SCE_HPHP_COMMENTLINE
;
1494 } else if (ch
== '#') {
1495 state
= SCE_HPHP_COMMENTLINE
;
1496 } else if (ch
== '\"') {
1497 state
= SCE_HPHP_HSTRING
;
1498 } else if (ch
== '\'') {
1499 state
= SCE_HPHP_SIMPLESTRING
;
1500 } else if (ch
== '$') {
1501 state
= SCE_HPHP_VARIABLE
;
1502 } else if (isoperator(ch
)) {
1503 state
= SCE_HPHP_OPERATOR
;
1504 } else if ((state
== SCE_HPHP_OPERATOR
) && (isspacechar(ch
))) {
1505 state
= SCE_HPHP_DEFAULT
;
1508 ///////////// end - PHP state handling
1511 // Some of the above terminated their lexeme but since the same character starts
1512 // the same class again, only reenter if non empty segment.
1514 bool nonEmptySegment
= i
>= static_cast<int>(styler
.GetStartSegment());
1515 if (state
== SCE_HB_DEFAULT
) { // One of the above succeeded
1516 if ((ch
== '\"') && (nonEmptySegment
)) {
1517 state
= SCE_HB_STRING
;
1518 } else if (ch
== '\'') {
1519 state
= SCE_HB_COMMENTLINE
;
1520 } else if (iswordstart(ch
)) {
1521 state
= SCE_HB_WORD
;
1522 } else if (isoperator(ch
)) {
1523 styler
.ColourTo(i
, SCE_HB_DEFAULT
);
1525 } else if (state
== SCE_HBA_DEFAULT
) { // One of the above succeeded
1526 if ((ch
== '\"') && (nonEmptySegment
)) {
1527 state
= SCE_HBA_STRING
;
1528 } else if (ch
== '\'') {
1529 state
= SCE_HBA_COMMENTLINE
;
1530 } else if (iswordstart(ch
)) {
1531 state
= SCE_HBA_WORD
;
1532 } else if (isoperator(ch
)) {
1533 styler
.ColourTo(i
, SCE_HBA_DEFAULT
);
1535 } else if (state
== SCE_HJ_DEFAULT
) { // One of the above succeeded
1536 if (ch
== '/' && chNext
== '*') {
1537 if (styler
.SafeGetCharAt(i
+ 2) == '*')
1538 state
= SCE_HJ_COMMENTDOC
;
1540 state
= SCE_HJ_COMMENT
;
1541 } else if (ch
== '/' && chNext
== '/') {
1542 state
= SCE_HJ_COMMENTLINE
;
1543 } else if ((ch
== '\"') && (nonEmptySegment
)) {
1544 state
= SCE_HJ_DOUBLESTRING
;
1545 } else if ((ch
== '\'') && (nonEmptySegment
)) {
1546 state
= SCE_HJ_SINGLESTRING
;
1547 } else if (iswordstart(ch
)) {
1548 state
= SCE_HJ_WORD
;
1549 } else if (isoperator(ch
)) {
1550 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1555 StateToPrint
= statePrintForState(state
, inScriptType
);
1556 styler
.ColourTo(lengthDoc
- 1, StateToPrint
);
1558 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
1560 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
1561 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
1565 static bool isASPScript(int state
) {
1567 (state
>= SCE_HJA_START
&& state
<= SCE_HJA_REGEX
) ||
1568 (state
>= SCE_HBA_START
&& state
<= SCE_HBA_STRINGEOL
) ||
1569 (state
>= SCE_HPA_DEFAULT
&& state
<= SCE_HPA_IDENTIFIER
);
1572 static void ColouriseHBAPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1573 WordList
&keywordsVBS
= *keywordlists
[2];
1574 if (sc
.state
== SCE_HBA_WORD
) {
1575 if (!IsAWordChar(sc
.ch
)) {
1577 sc
.GetCurrentLowered(s
, sizeof(s
));
1578 if (keywordsVBS
.InList(s
)) {
1579 if (strcmp(s
, "rem") == 0) {
1580 sc
.ChangeState(SCE_HBA_COMMENTLINE
);
1582 sc
.SetState(SCE_HBA_DEFAULT
);
1585 sc
.SetState(SCE_HBA_DEFAULT
);
1588 sc
.ChangeState(SCE_HBA_IDENTIFIER
);
1589 sc
.SetState(SCE_HBA_DEFAULT
);
1592 } else if (sc
.state
== SCE_HBA_NUMBER
) {
1593 if (!IsAWordChar(sc
.ch
)) {
1594 sc
.SetState(SCE_HBA_DEFAULT
);
1596 } else if (sc
.state
== SCE_HBA_STRING
) {
1597 if (sc
.ch
== '\"') {
1598 sc
.ForwardSetState(SCE_HBA_DEFAULT
);
1599 } else if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1600 sc
.ChangeState(SCE_HBA_STRINGEOL
);
1601 sc
.ForwardSetState(SCE_HBA_DEFAULT
);
1603 } else if (sc
.state
== SCE_HBA_COMMENTLINE
) {
1604 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1605 sc
.SetState(SCE_HBA_DEFAULT
);
1609 if (sc
.state
== SCE_HBA_DEFAULT
) {
1610 if (IsADigit(sc
.ch
) || (sc
.ch
== '.' && IsADigit(sc
.chNext
))) {
1611 sc
.SetState(SCE_HBA_NUMBER
);
1612 } else if (IsAWordStart(sc
.ch
)) {
1613 sc
.SetState(SCE_HBA_WORD
);
1614 } else if (sc
.ch
== '\'') {
1615 sc
.SetState(SCE_HBA_COMMENTLINE
);
1616 } else if (sc
.ch
== '\"') {
1617 sc
.SetState(SCE_HBA_STRING
);
1622 static void ColouriseHTMLPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1623 WordList
&keywordsTags
= *keywordlists
[0];
1624 if (sc
.state
== SCE_H_COMMENT
) {
1625 if (sc
.Match("-->")) {
1628 sc
.ForwardSetState(SCE_H_DEFAULT
);
1630 } else if (sc
.state
== SCE_H_ENTITY
) {
1632 sc
.ForwardSetState(SCE_H_DEFAULT
);
1633 } else if (sc
.ch
!= '#' && (sc
.ch
< 0x80) && !isalnum(sc
.ch
)) { // Should check that '#' follows '&', but it is unlikely anyway...
1634 sc
.ChangeState(SCE_H_TAGUNKNOWN
);
1635 sc
.SetState(SCE_H_DEFAULT
);
1637 } else if (sc
.state
== SCE_H_TAGUNKNOWN
) {
1638 if (!ishtmlwordchar(static_cast<char>(sc
.ch
)) && !((sc
.ch
== '/') && (sc
.chPrev
== '<')) && sc
.ch
!= '[') {
1640 sc
.GetCurrentLowered(s
, sizeof(s
));
1642 if (keywordsTags
.InList(s
+ 2)) {
1643 sc
.ChangeState(SCE_H_TAG
);
1646 if (keywordsTags
.InList(s
+ 1)) {
1647 sc
.ChangeState(SCE_H_TAG
);
1651 sc
.ForwardSetState(SCE_H_DEFAULT
);
1652 } else if (sc
.Match('/', '>')) {
1653 sc
.SetState(SCE_H_TAGEND
);
1655 sc
.ForwardSetState(SCE_H_DEFAULT
);
1657 sc
.SetState(SCE_H_OTHER
);
1660 } else if (sc
.state
== SCE_H_ATTRIBUTE
) {
1661 if (!ishtmlwordchar(static_cast<char>(sc
.ch
))) {
1663 sc
.GetCurrentLowered(s
, sizeof(s
));
1664 if (!keywordsTags
.InList(s
)) {
1665 sc
.ChangeState(SCE_H_ATTRIBUTEUNKNOWN
);
1667 sc
.SetState(SCE_H_OTHER
);
1669 } else if (sc
.state
== SCE_H_OTHER
) {
1671 sc
.SetState(SCE_H_TAG
);
1672 sc
.ForwardSetState(SCE_H_DEFAULT
);
1673 } else if (sc
.Match('/', '>')) {
1674 sc
.SetState(SCE_H_TAG
);
1676 sc
.ForwardSetState(SCE_H_DEFAULT
);
1677 } else if (sc
.chPrev
== '=') {
1678 sc
.SetState(SCE_H_VALUE
);
1680 } else if (sc
.state
== SCE_H_DOUBLESTRING
) {
1681 if (sc
.ch
== '\"') {
1682 sc
.ForwardSetState(SCE_H_OTHER
);
1684 } else if (sc
.state
== SCE_H_SINGLESTRING
) {
1685 if (sc
.ch
== '\'') {
1686 sc
.ForwardSetState(SCE_H_OTHER
);
1688 } else if (sc
.state
== SCE_H_NUMBER
) {
1689 if (!IsADigit(sc
.ch
)) {
1690 sc
.SetState(SCE_H_OTHER
);
1694 if (sc
.state
== SCE_H_DEFAULT
) {
1696 if (sc
.Match("<!--"))
1697 sc
.SetState(SCE_H_COMMENT
);
1699 sc
.SetState(SCE_H_TAGUNKNOWN
);
1700 } else if (sc
.ch
== '&') {
1701 sc
.SetState(SCE_H_ENTITY
);
1703 } else if ((sc
.state
== SCE_H_OTHER
) || (sc
.state
== SCE_H_VALUE
)) {
1704 if (sc
.ch
== '\"') {
1705 sc
.SetState(SCE_H_DOUBLESTRING
);
1706 } else if (sc
.ch
== '\'') {
1707 sc
.SetState(SCE_H_SINGLESTRING
);
1708 } else if (IsADigit(sc
.ch
)) {
1709 sc
.SetState(SCE_H_NUMBER
);
1710 } else if (sc
.ch
== '>') {
1711 sc
.SetState(SCE_H_TAG
);
1712 sc
.ForwardSetState(SCE_H_DEFAULT
);
1713 } else if (ishtmlwordchar(static_cast<char>(sc
.ch
))) {
1714 sc
.SetState(SCE_H_ATTRIBUTE
);
1719 static void ColouriseASPPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1720 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1721 if ((sc
.state
== SCE_H_ASPAT
|| isASPScript(sc
.state
)) && sc
.Match('%', '>')) {
1722 sc
.SetState(SCE_H_ASP
);
1724 sc
.ForwardSetState(SCE_H_DEFAULT
);
1727 // Handle some ASP script
1728 if (sc
.state
>= SCE_HBA_START
&& sc
.state
<= SCE_HBA_STRINGEOL
) {
1729 ColouriseHBAPiece(sc
, keywordlists
);
1730 } else if (sc
.state
>= SCE_H_DEFAULT
&& sc
.state
<= SCE_H_SGML_BLOCK_DEFAULT
) {
1731 ColouriseHTMLPiece(sc
, keywordlists
);
1734 // Enter new sc.state
1735 if ((sc
.state
== SCE_H_DEFAULT
) || (sc
.state
== SCE_H_TAGUNKNOWN
)) {
1736 if (sc
.Match('<', '%')) {
1737 if (sc
.state
== SCE_H_TAGUNKNOWN
)
1738 sc
.ChangeState(SCE_H_ASP
);
1740 sc
.SetState(SCE_H_ASP
);
1744 sc
.ForwardSetState(SCE_H_ASPAT
);
1749 sc
.SetState(SCE_HBA_DEFAULT
);
1755 static void ColouriseASPDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
1757 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
1758 StyleContext
sc(startPos
, length
, initStyle
, styler
, 0x7f);
1759 for (; sc
.More(); sc
.Forward()) {
1760 ColouriseASPPiece(sc
, keywordlists
);
1765 static void ColourisePHPPiece(StyleContext
&sc
, WordList
*keywordlists
[]) {
1766 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1767 if (sc
.state
>= SCE_HPHP_DEFAULT
&& sc
.state
<= SCE_HPHP_OPERATOR
) {
1768 if (!isPHPStringState(sc
.state
) &&
1769 (sc
.state
!= SCE_HPHP_COMMENT
) &&
1770 (sc
.Match('?', '>'))) {
1771 sc
.SetState(SCE_H_QUESTION
);
1773 sc
.ForwardSetState(SCE_H_DEFAULT
);
1777 if (sc
.state
>= SCE_H_DEFAULT
&& sc
.state
<= SCE_H_SGML_BLOCK_DEFAULT
) {
1778 ColouriseHTMLPiece(sc
, keywordlists
);
1781 // Handle some PHP script
1782 if (sc
.state
== SCE_HPHP_WORD
) {
1783 if (!IsAWordStart(sc
.ch
)) {
1784 sc
.SetState(SCE_HPHP_DEFAULT
);
1786 } else if (sc
.state
== SCE_HPHP_COMMENTLINE
) {
1787 if (sc
.ch
== '\r' || sc
.ch
== '\n') {
1788 sc
.SetState(SCE_HPHP_DEFAULT
);
1790 } else if (sc
.state
== SCE_HPHP_COMMENT
) {
1791 if (sc
.Match('*', '/')) {
1794 sc
.SetState(SCE_HPHP_DEFAULT
);
1796 } else if (sc
.state
== SCE_HPHP_HSTRING
) {
1797 if (sc
.ch
== '\"') {
1798 sc
.ForwardSetState(SCE_HPHP_DEFAULT
);
1800 } else if (sc
.state
== SCE_HPHP_SIMPLESTRING
) {
1801 if (sc
.ch
== '\'') {
1802 sc
.ForwardSetState(SCE_HPHP_DEFAULT
);
1804 } else if (sc
.state
== SCE_HPHP_VARIABLE
) {
1805 if (!IsAWordStart(sc
.ch
)) {
1806 sc
.SetState(SCE_HPHP_DEFAULT
);
1808 } else if (sc
.state
== SCE_HPHP_OPERATOR
) {
1809 sc
.SetState(SCE_HPHP_DEFAULT
);
1812 // Enter new sc.state
1813 if ((sc
.state
== SCE_H_DEFAULT
) || (sc
.state
== SCE_H_TAGUNKNOWN
)) {
1814 if (sc
.Match("<?php")) {
1815 sc
.SetState(SCE_H_QUESTION
);
1821 sc
.SetState(SCE_HPHP_DEFAULT
);
1824 if (sc
.state
== SCE_HPHP_DEFAULT
) {
1825 if (IsAWordStart(sc
.ch
)) {
1826 sc
.SetState(SCE_HPHP_WORD
);
1827 } else if (sc
.ch
== '#') {
1828 sc
.SetState(SCE_HPHP_COMMENTLINE
);
1829 } else if (sc
.Match("<!--")) {
1830 sc
.SetState(SCE_HPHP_COMMENTLINE
);
1831 } else if (sc
.Match('/', '/')) {
1832 sc
.SetState(SCE_HPHP_COMMENTLINE
);
1833 } else if (sc
.Match('/', '*')) {
1834 sc
.SetState(SCE_HPHP_COMMENT
);
1835 } else if (sc
.ch
== '\"') {
1836 sc
.SetState(SCE_HPHP_HSTRING
);
1837 } else if (sc
.ch
== '\'') {
1838 sc
.SetState(SCE_HPHP_SIMPLESTRING
);
1839 } else if (sc
.ch
== '$') {
1840 sc
.SetState(SCE_HPHP_VARIABLE
);
1841 } else if (isoperator(static_cast<char>(sc
.ch
))) {
1842 sc
.SetState(SCE_HPHP_OPERATOR
);
1847 static void ColourisePHPDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
1849 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
1850 StyleContext
sc(startPos
, length
, initStyle
, styler
, 0x7f);
1851 for (; sc
.More(); sc
.Forward()) {
1852 ColourisePHPPiece(sc
, keywordlists
);
1857 static const char * const htmlWordListDesc
[] = {
1858 "HTML elements and attributes",
1859 "JavaScript keywords",
1860 "VBScript keywords",
1863 "SGML and DTD keywords",
1867 LexerModule
lmHTML(SCLEX_HTML
, ColouriseHyperTextDoc
, "hypertext", 0, htmlWordListDesc
);
1868 LexerModule
lmXML(SCLEX_XML
, ColouriseHyperTextDoc
, "xml", 0, htmlWordListDesc
);
1869 LexerModule
lmASP(SCLEX_ASP
, ColouriseASPDoc
, "asp", 0, htmlWordListDesc
);
1870 LexerModule
lmPHP(SCLEX_PHP
, ColourisePHPDoc
, "php", 0, htmlWordListDesc
);