1 // Scintilla source code edit control
5 // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
16 #include "Scintilla.h"
20 #include "LexAccessor.h"
22 #include "StyleContext.h"
23 #include "CharacterSet.h"
24 #include "LexerModule.h"
27 using namespace Scintilla
;
30 #define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START)
31 #define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START)
32 #define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START)
34 enum script_type
{ eScriptNone
= 0, eScriptJS
, eScriptVBS
, eScriptPython
, eScriptPHP
, eScriptXML
, eScriptSGML
, eScriptSGMLblock
, eScriptComment
};
35 enum script_mode
{ eHtml
= 0, eNonHtmlScript
, eNonHtmlPreProc
, eNonHtmlScriptPreProc
};
37 static inline bool IsAWordChar(const int ch
) {
38 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_');
41 static inline bool IsAWordStart(const int ch
) {
42 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_');
45 inline bool IsOperator(int ch
) {
46 if (isascii(ch
) && isalnum(ch
))
48 // '.' left out as it is used to make up numbers
49 if (ch
== '%' || ch
== '^' || ch
== '&' || ch
== '*' ||
50 ch
== '(' || ch
== ')' || ch
== '-' || ch
== '+' ||
51 ch
== '=' || ch
== '|' || ch
== '{' || ch
== '}' ||
52 ch
== '[' || ch
== ']' || ch
== ':' || ch
== ';' ||
53 ch
== '<' || ch
== '>' || ch
== ',' || ch
== '/' ||
54 ch
== '?' || ch
== '!' || ch
== '.' || ch
== '~')
59 static void GetTextSegment(Accessor
&styler
, unsigned int start
, unsigned int end
, char *s
, size_t len
) {
61 for (; (i
< end
- start
+ 1) && (i
< len
-1); i
++) {
62 s
[i
] = static_cast<char>(MakeLowerCase(styler
[start
+ i
]));
67 static const char *GetNextWord(Accessor
&styler
, unsigned int start
, char *s
, size_t sLen
) {
70 for (; i
< sLen
-1; i
++) {
71 char ch
= static_cast<char>(styler
.SafeGetCharAt(start
+ i
));
72 if ((i
== 0) && !IsAWordStart(ch
))
74 if ((i
> 0) && !IsAWordChar(ch
))
83 static script_type
segIsScriptingIndicator(Accessor
&styler
, unsigned int start
, unsigned int end
, script_type prevValue
) {
85 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
86 //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
87 if (strstr(s
, "src")) // External script
91 if (strstr(s
, "pyth"))
93 if (strstr(s
, "javas"))
95 if (strstr(s
, "jscr"))
99 if (strstr(s
, "xml")) {
100 const char *xml
= strstr(s
, "xml");
101 for (const char *t
=s
; t
<xml
; t
++) {
112 static int PrintScriptingIndicatorOffset(Accessor
&styler
, unsigned int start
, unsigned int end
) {
115 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
116 if (0 == strncmp(s
, "php", 3)) {
123 static script_type
ScriptOfState(int state
) {
124 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
125 return eScriptPython
;
126 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
128 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
130 } else if ((state
>= SCE_HPHP_DEFAULT
) && (state
<= SCE_HPHP_COMMENTLINE
)) {
132 } else if ((state
>= SCE_H_SGML_DEFAULT
) && (state
< SCE_H_SGML_BLOCK_DEFAULT
)) {
134 } else if (state
== SCE_H_SGML_BLOCK_DEFAULT
) {
135 return eScriptSGMLblock
;
141 static int statePrintForState(int state
, script_mode inScriptType
) {
142 int StateToPrint
= state
;
144 if (state
>= SCE_HJ_START
) {
145 if ((state
>= SCE_HP_START
) && (state
<= SCE_HP_IDENTIFIER
)) {
146 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_PYTHON
);
147 } else if ((state
>= SCE_HB_START
) && (state
<= SCE_HB_STRINGEOL
)) {
148 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_VBS
);
149 } else if ((state
>= SCE_HJ_START
) && (state
<= SCE_HJ_REGEX
)) {
150 StateToPrint
= state
+ ((inScriptType
== eNonHtmlScript
) ? 0 : SCE_HA_JS
);
157 static int stateForPrintState(int StateToPrint
) {
160 if ((StateToPrint
>= SCE_HPA_START
) && (StateToPrint
<= SCE_HPA_IDENTIFIER
)) {
161 state
= StateToPrint
- SCE_HA_PYTHON
;
162 } else if ((StateToPrint
>= SCE_HBA_START
) && (StateToPrint
<= SCE_HBA_STRINGEOL
)) {
163 state
= StateToPrint
- SCE_HA_VBS
;
164 } else if ((StateToPrint
>= SCE_HJA_START
) && (StateToPrint
<= SCE_HJA_REGEX
)) {
165 state
= StateToPrint
- SCE_HA_JS
;
167 state
= StateToPrint
;
173 static inline bool IsNumber(unsigned int start
, Accessor
&styler
) {
174 return IsADigit(styler
[start
]) || (styler
[start
] == '.') ||
175 (styler
[start
] == '-') || (styler
[start
] == '#');
178 static inline bool isStringState(int state
) {
182 case SCE_HJ_DOUBLESTRING
:
183 case SCE_HJ_SINGLESTRING
:
184 case SCE_HJA_DOUBLESTRING
:
185 case SCE_HJA_SINGLESTRING
:
189 case SCE_HP_CHARACTER
:
191 case SCE_HP_TRIPLEDOUBLE
:
193 case SCE_HPA_CHARACTER
:
195 case SCE_HPA_TRIPLEDOUBLE
:
196 case SCE_HPHP_HSTRING
:
197 case SCE_HPHP_SIMPLESTRING
:
198 case SCE_HPHP_HSTRING_VARIABLE
:
199 case SCE_HPHP_COMPLEX_VARIABLE
:
209 static inline bool stateAllowsTermination(int state
) {
210 bool allowTermination
= !isStringState(state
);
211 if (allowTermination
) {
213 case SCE_HB_COMMENTLINE
:
214 case SCE_HPHP_COMMENT
:
215 case SCE_HP_COMMENTLINE
:
216 case SCE_HPA_COMMENTLINE
:
217 allowTermination
= false;
220 return allowTermination
;
223 // not really well done, since it's only comments that should lex the %> and <%
224 static inline bool isCommentASPState(int state
) {
229 case SCE_HJ_COMMENTLINE
:
230 case SCE_HJ_COMMENTDOC
:
231 case SCE_HB_COMMENTLINE
:
232 case SCE_HP_COMMENTLINE
:
233 case SCE_HPHP_COMMENT
:
234 case SCE_HPHP_COMMENTLINE
:
244 static void classifyAttribHTML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
245 bool wordIsNumber
= IsNumber(start
, styler
);
246 char chAttr
= SCE_H_ATTRIBUTEUNKNOWN
;
248 chAttr
= SCE_H_NUMBER
;
251 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
252 if (keywords
.InList(s
))
253 chAttr
= SCE_H_ATTRIBUTE
;
255 if ((chAttr
== SCE_H_ATTRIBUTEUNKNOWN
) && !keywords
)
256 // No keywords -> all are known
257 chAttr
= SCE_H_ATTRIBUTE
;
258 styler
.ColourTo(end
, chAttr
);
261 static int classifyTagHTML(unsigned int start
, unsigned int end
,
262 WordList
&keywords
, Accessor
&styler
, bool &tagDontFold
,
263 bool caseSensitive
, bool isXml
, bool allowScripts
) {
264 char withSpace
[30 + 2] = " ";
265 const char *s
= withSpace
+ 1;
266 // Copy after the '<'
268 for (unsigned int cPos
= start
; cPos
<= end
&& i
< 30; cPos
++) {
269 char ch
= styler
[cPos
];
270 if ((ch
!= '<') && (ch
!= '/')) {
271 withSpace
[i
++] = caseSensitive
? ch
: static_cast<char>(MakeLowerCase(ch
));
275 //The following is only a quick hack, to see if this whole thing would work
276 //we first need the tagname with a trailing space...
278 withSpace
[i
+1] = '\0';
280 // if the current language is XML, I can fold any tag
281 // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.)
282 //...to find it in the list of no-container-tags
283 tagDontFold
= (!isXml
) && (NULL
!= strstr(" area base basefont br col command embed frame hr img input isindex keygen link meta param source track wbr ", withSpace
));
285 //now we can remove the trailing space
288 // No keywords -> all are known
289 char chAttr
= SCE_H_TAGUNKNOWN
;
291 chAttr
= SCE_H_SGML_DEFAULT
;
292 } else if (!keywords
|| keywords
.InList(s
)) {
295 styler
.ColourTo(end
, chAttr
);
296 if (chAttr
== SCE_H_TAG
) {
297 if (allowScripts
&& 0 == strcmp(s
, "script")) {
298 // check to see if this is a self-closing tag by sniffing ahead
299 bool isSelfClose
= false;
300 for (unsigned int cPos
= end
; cPos
<= end
+ 100; cPos
++) {
301 char ch
= styler
.SafeGetCharAt(cPos
, '\0');
302 if (ch
== '\0' || ch
== '>')
304 else if (ch
== '/' && styler
.SafeGetCharAt(cPos
+ 1, '\0') == '>') {
310 // do not enter a script state if the tag self-closed
312 chAttr
= SCE_H_SCRIPT
;
313 } else if (!isXml
&& 0 == strcmp(s
, "comment")) {
314 chAttr
= SCE_H_COMMENT
;
320 static void classifyWordHTJS(unsigned int start
, unsigned int end
,
321 WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
324 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
325 s
[i
] = styler
[start
+ i
];
329 char chAttr
= SCE_HJ_WORD
;
330 bool wordIsNumber
= IsADigit(s
[0]) || ((s
[0] == '.') && IsADigit(s
[1]));
332 chAttr
= SCE_HJ_NUMBER
;
333 } else if (keywords
.InList(s
)) {
334 chAttr
= SCE_HJ_KEYWORD
;
336 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
339 static int classifyWordHTVB(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, script_mode inScriptType
) {
340 char chAttr
= SCE_HB_IDENTIFIER
;
341 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.');
343 chAttr
= SCE_HB_NUMBER
;
346 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
347 if (keywords
.InList(s
)) {
348 chAttr
= SCE_HB_WORD
;
349 if (strcmp(s
, "rem") == 0)
350 chAttr
= SCE_HB_COMMENTLINE
;
353 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
354 if (chAttr
== SCE_HB_COMMENTLINE
)
355 return SCE_HB_COMMENTLINE
;
357 return SCE_HB_DEFAULT
;
360 static void classifyWordHTPy(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, char *prevWord
, script_mode inScriptType
, bool isMako
) {
361 bool wordIsNumber
= IsADigit(styler
[start
]);
364 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
365 s
[i
] = styler
[start
+ i
];
368 char chAttr
= SCE_HP_IDENTIFIER
;
369 if (0 == strcmp(prevWord
, "class"))
370 chAttr
= SCE_HP_CLASSNAME
;
371 else if (0 == strcmp(prevWord
, "def"))
372 chAttr
= SCE_HP_DEFNAME
;
373 else if (wordIsNumber
)
374 chAttr
= SCE_HP_NUMBER
;
375 else if (keywords
.InList(s
))
376 chAttr
= SCE_HP_WORD
;
377 else if (isMako
&& 0 == strcmp(s
, "block"))
378 chAttr
= SCE_HP_WORD
;
379 styler
.ColourTo(end
, statePrintForState(chAttr
, inScriptType
));
383 // Update the word colour to default or keyword
384 // Called when in a PHP word
385 static void classifyWordHTPHP(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
386 char chAttr
= SCE_HPHP_DEFAULT
;
387 bool wordIsNumber
= IsADigit(styler
[start
]) || (styler
[start
] == '.' && start
+1 <= end
&& IsADigit(styler
[start
+1]));
389 chAttr
= SCE_HPHP_NUMBER
;
392 GetTextSegment(styler
, start
, end
, s
, sizeof(s
));
393 if (keywords
.InList(s
))
394 chAttr
= SCE_HPHP_WORD
;
396 styler
.ColourTo(end
, chAttr
);
399 static bool isWordHSGML(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
) {
402 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
403 s
[i
] = styler
[start
+ i
];
406 return keywords
.InList(s
);
409 static bool isWordCdata(unsigned int start
, unsigned int end
, Accessor
&styler
) {
412 for (; i
< end
- start
+ 1 && i
< 30; i
++) {
413 s
[i
] = styler
[start
+ i
];
416 return (0 == strcmp(s
, "[CDATA["));
419 // Return the first state to reach when entering a scripting language
420 static int StateForScript(script_type scriptLanguage
) {
422 switch (scriptLanguage
) {
424 Result
= SCE_HB_START
;
427 Result
= SCE_HP_START
;
430 Result
= SCE_HPHP_DEFAULT
;
433 Result
= SCE_H_TAGUNKNOWN
;
436 Result
= SCE_H_SGML_DEFAULT
;
439 Result
= SCE_H_COMMENT
;
442 Result
= SCE_HJ_START
;
448 static inline bool ishtmlwordchar(int ch
) {
449 return !isascii(ch
) ||
450 (isalnum(ch
) || ch
== '.' || ch
== '-' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#');
453 static inline bool issgmlwordchar(int ch
) {
454 return !isascii(ch
) ||
455 (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
== ':' || ch
== '!' || ch
== '#' || ch
== '[');
458 static inline bool IsPhpWordStart(int ch
) {
459 return (isascii(ch
) && (isalpha(ch
) || (ch
== '_'))) || (ch
>= 0x7f);
462 static inline bool IsPhpWordChar(int ch
) {
463 return IsADigit(ch
) || IsPhpWordStart(ch
);
466 static bool InTagState(int state
) {
467 return state
== SCE_H_TAG
|| state
== SCE_H_TAGUNKNOWN
||
468 state
== SCE_H_SCRIPT
||
469 state
== SCE_H_ATTRIBUTE
|| state
== SCE_H_ATTRIBUTEUNKNOWN
||
470 state
== SCE_H_NUMBER
|| state
== SCE_H_OTHER
||
471 state
== SCE_H_DOUBLESTRING
|| state
== SCE_H_SINGLESTRING
;
474 static bool IsCommentState(const int state
) {
475 return state
== SCE_H_COMMENT
|| state
== SCE_H_SGML_COMMENT
;
478 static bool IsScriptCommentState(const int state
) {
479 return state
== SCE_HJ_COMMENT
|| state
== SCE_HJ_COMMENTLINE
|| state
== SCE_HJA_COMMENT
||
480 state
== SCE_HJA_COMMENTLINE
|| state
== SCE_HB_COMMENTLINE
|| state
== SCE_HBA_COMMENTLINE
;
483 static bool isLineEnd(int ch
) {
484 return ch
== '\r' || ch
== '\n';
487 static bool isOKBeforeRE(int ch
) {
488 return (ch
== '(') || (ch
== '=') || (ch
== ',');
491 static bool isMakoBlockEnd(const int ch
, const int chNext
, const char *blockType
) {
492 if (strlen(blockType
) == 0) {
493 return ((ch
== '%') && (chNext
== '>'));
494 } else if ((0 == strcmp(blockType
, "inherit")) ||
495 (0 == strcmp(blockType
, "namespace")) ||
496 (0 == strcmp(blockType
, "include")) ||
497 (0 == strcmp(blockType
, "page"))) {
498 return ((ch
== '/') && (chNext
== '>'));
499 } else if (0 == strcmp(blockType
, "%")) {
500 if (ch
== '/' && isLineEnd(chNext
))
503 return isLineEnd(ch
);
504 } else if (0 == strcmp(blockType
, "{")) {
511 static bool isDjangoBlockEnd(const int ch
, const int chNext
, const char *blockType
) {
512 if (strlen(blockType
) == 0) {
514 } else if (0 == strcmp(blockType
, "%")) {
515 return ((ch
== '%') && (chNext
== '}'));
516 } else if (0 == strcmp(blockType
, "{")) {
517 return ((ch
== '}') && (chNext
== '}'));
523 static bool isPHPStringState(int state
) {
525 (state
== SCE_HPHP_HSTRING
) ||
526 (state
== SCE_HPHP_SIMPLESTRING
) ||
527 (state
== SCE_HPHP_HSTRING_VARIABLE
) ||
528 (state
== SCE_HPHP_COMPLEX_VARIABLE
);
531 static int FindPhpStringDelimiter(char *phpStringDelimiter
, const int phpStringDelimiterSize
, int i
, const int lengthDoc
, Accessor
&styler
, bool &isSimpleString
) {
533 const int beginning
= i
- 1;
534 bool isValidSimpleString
= false;
536 while (i
< lengthDoc
&& (styler
[i
] == ' ' || styler
[i
] == '\t'))
539 char ch
= styler
.SafeGetCharAt(i
);
540 const char chNext
= styler
.SafeGetCharAt(i
+ 1);
541 if (!IsPhpWordStart(ch
)) {
542 if (ch
== '\'' && IsPhpWordStart(chNext
)) {
545 isSimpleString
= true;
547 phpStringDelimiter
[0] = '\0';
551 phpStringDelimiter
[0] = ch
;
554 for (j
= i
; j
< lengthDoc
&& !isLineEnd(styler
[j
]); j
++) {
555 if (!IsPhpWordChar(styler
[j
])) {
556 if (isSimpleString
&& (styler
[j
] == '\'') && isLineEnd(styler
.SafeGetCharAt(j
+ 1))) {
557 isValidSimpleString
= true;
561 phpStringDelimiter
[0] = '\0';
565 if (j
- i
< phpStringDelimiterSize
- 2)
566 phpStringDelimiter
[j
-i
+1] = styler
[j
];
570 if (isSimpleString
&& !isValidSimpleString
) {
571 phpStringDelimiter
[0] = '\0';
574 phpStringDelimiter
[j
-i
+1 - (isSimpleString
? 1 : 0)] = '\0';
578 static void ColouriseHyperTextDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
579 Accessor
&styler
, bool isXml
) {
580 WordList
&keywords
= *keywordlists
[0];
581 WordList
&keywords2
= *keywordlists
[1];
582 WordList
&keywords3
= *keywordlists
[2];
583 WordList
&keywords4
= *keywordlists
[3];
584 WordList
&keywords5
= *keywordlists
[4];
585 WordList
&keywords6
= *keywordlists
[5]; // SGML (DTD) keywords
587 // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
588 styler
.StartAt(startPos
, static_cast<char>(STYLE_MAX
));
591 char phpStringDelimiter
[200]; // PHP is not limited in length, we are
592 phpStringDelimiter
[0] = '\0';
593 int StateToPrint
= initStyle
;
594 int state
= stateForPrintState(StateToPrint
);
595 char makoBlockType
[200];
596 makoBlockType
[0] = '\0';
598 char djangoBlockType
[2];
599 djangoBlockType
[0] = '\0';
601 // If inside a tag, it may be a script tag, so reread from the start of line starting tag to ensure any language tags are seen
602 if (InTagState(state
)) {
603 while ((startPos
> 0) && (InTagState(styler
.StyleAt(startPos
- 1)))) {
604 int backLineStart
= styler
.LineStart(styler
.GetLine(startPos
-1));
605 length
+= startPos
- backLineStart
;
606 startPos
= backLineStart
;
608 state
= SCE_H_DEFAULT
;
610 // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState
611 if (isPHPStringState(state
)) {
612 while (startPos
> 0 && (isPHPStringState(state
) || !isLineEnd(styler
[startPos
- 1]))) {
615 state
= styler
.StyleAt(startPos
);
618 state
= SCE_H_DEFAULT
;
620 styler
.StartAt(startPos
, static_cast<char>(STYLE_MAX
));
622 int lineCurrent
= styler
.GetLine(startPos
);
624 if (lineCurrent
> 0) {
625 lineState
= styler
.GetLineState(lineCurrent
-1);
627 // Default client and ASP scripting language is JavaScript
628 lineState
= eScriptJS
<< 8;
630 // property asp.default.language
631 // Script in ASP code is initially assumed to be in JavaScript.
632 // To change this to VBScript set asp.default.language to 2. Python is 3.
633 lineState
|= styler
.GetPropertyInt("asp.default.language", eScriptJS
) << 4;
635 script_mode inScriptType
= script_mode((lineState
>> 0) & 0x03); // 2 bits of scripting mode
636 bool tagOpened
= (lineState
>> 2) & 0x01; // 1 bit to know if we are in an opened tag
637 bool tagClosing
= (lineState
>> 3) & 0x01; // 1 bit to know if we are in a closing tag
638 bool tagDontFold
= false; //some HTML tags should not be folded
639 script_type aspScript
= script_type((lineState
>> 4) & 0x0F); // 4 bits of script name
640 script_type clientScript
= script_type((lineState
>> 8) & 0x0F); // 4 bits of script name
641 int beforePreProc
= (lineState
>> 12) & 0xFF; // 8 bits of state
643 script_type scriptLanguage
= ScriptOfState(state
);
644 // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment
645 if (inScriptType
== eNonHtmlScript
&& state
== SCE_H_COMMENT
) {
646 scriptLanguage
= eScriptComment
;
648 script_type beforeLanguage
= ScriptOfState(beforePreProc
);
650 // property fold.html
651 // Folding is turned on or off for HTML and XML files with this option.
652 // The fold option must also be on for folding to occur.
653 const bool foldHTML
= styler
.GetPropertyInt("fold.html", 0) != 0;
655 const bool fold
= foldHTML
&& styler
.GetPropertyInt("fold", 0);
657 // property fold.html.preprocessor
658 // Folding is turned on or off for scripts embedded in HTML files with this option.
659 // The default is on.
660 const bool foldHTMLPreprocessor
= foldHTML
&& styler
.GetPropertyInt("fold.html.preprocessor", 1);
662 const bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
664 // property fold.hypertext.comment
665 // Allow folding for comments in scripts embedded in HTML.
666 // The default is off.
667 const bool foldComment
= fold
&& styler
.GetPropertyInt("fold.hypertext.comment", 0) != 0;
669 // property fold.hypertext.heredoc
670 // Allow folding for heredocs in scripts embedded in HTML.
671 // The default is off.
672 const bool foldHeredoc
= fold
&& styler
.GetPropertyInt("fold.hypertext.heredoc", 0) != 0;
674 // property html.tags.case.sensitive
675 // For XML and HTML, setting this property to 1 will make tags match in a case
676 // sensitive way which is the expected behaviour for XML and XHTML.
677 const bool caseSensitive
= styler
.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
679 // property lexer.xml.allow.scripts
680 // Set to 0 to disable scripts in XML.
681 const bool allowScripts
= styler
.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0;
683 // property lexer.html.mako
684 // Set to 1 to enable the mako template language.
685 const bool isMako
= styler
.GetPropertyInt("lexer.html.mako", 0) != 0;
687 // property lexer.html.django
688 // Set to 1 to enable the django template language.
689 const bool isDjango
= styler
.GetPropertyInt("lexer.html.django", 0) != 0;
691 const CharacterSet
setHTMLWord(CharacterSet::setAlphaNum
, ".-_:!#", 0x80, true);
692 const CharacterSet
setTagContinue(CharacterSet::setAlphaNum
, ".-_:!#[", 0x80, true);
693 const CharacterSet
setAttributeContinue(CharacterSet::setAlphaNum
, ".-_:!#/", 0x80, true);
695 int levelPrev
= styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
696 int levelCurrent
= levelPrev
;
697 int visibleChars
= 0;
698 int lineStartVisibleChars
= 0;
702 int chPrevNonWhite
= ' ';
703 // look back to set chPrevNonWhite properly for better regex colouring
704 if (scriptLanguage
== eScriptJS
&& startPos
> 0) {
708 style
= styler
.StyleAt(back
);
709 if (style
< SCE_HJ_DEFAULT
|| style
> SCE_HJ_COMMENTDOC
)
710 // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
713 if (style
== SCE_HJ_SYMBOLS
) {
714 chPrevNonWhite
= static_cast<unsigned char>(styler
.SafeGetCharAt(back
));
718 styler
.StartSegment(startPos
);
719 const int lengthDoc
= startPos
+ length
;
720 for (int i
= startPos
; i
< lengthDoc
; i
++) {
721 const int chPrev2
= chPrev
;
723 if (!IsASpace(ch
) && state
!= SCE_HJ_COMMENT
&&
724 state
!= SCE_HJ_COMMENTLINE
&& state
!= SCE_HJ_COMMENTDOC
)
726 ch
= static_cast<unsigned char>(styler
[i
]);
727 int chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
728 const int chNext2
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 2));
730 // Handle DBCS codepages
731 if (styler
.IsLeadByte(static_cast<char>(ch
))) {
737 if ((!IsASpace(ch
) || !foldCompact
) && fold
)
740 lineStartVisibleChars
++;
742 // decide what is the current state to print (depending of the script tag)
743 StateToPrint
= statePrintForState(state
, inScriptType
);
745 // handle script folding
747 switch (scriptLanguage
) {
750 //not currently supported case eScriptVBS:
752 if ((state
!= SCE_HPHP_COMMENT
) && (state
!= SCE_HPHP_COMMENTLINE
) && (state
!= SCE_HJ_COMMENT
) && (state
!= SCE_HJ_COMMENTLINE
) && (state
!= SCE_HJ_COMMENTDOC
) && (!isStringState(state
))) {
753 //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle);
754 //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {
757 while ((j
< lengthDoc
) && IsASpaceOrTab(styler
.SafeGetCharAt(j
))) {
760 if (styler
.Match(j
, "region") || styler
.Match(j
, "if")) {
762 } else if (styler
.Match(j
, "end")) {
765 } else if ((ch
== '{') || (ch
== '}') || (foldComment
&& (ch
== '/') && (chNext
== '*'))) {
766 levelCurrent
+= (((ch
== '{') || (ch
== '/')) ? 1 : -1);
768 } else if (((state
== SCE_HPHP_COMMENT
) || (state
== SCE_HJ_COMMENT
)) && foldComment
&& (ch
== '*') && (chNext
== '/')) {
773 if (state
!= SCE_HP_COMMENTLINE
&& !isMako
) {
774 if ((ch
== ':') && ((chNext
== '\n') || (chNext
== '\r' && chNext2
== '\n'))) {
776 } else if ((ch
== '\n') && !((chNext
== '\r') && (chNext2
== '\n')) && (chNext
!= '\n')) {
777 // check if the number of tabs is lower than the level
778 int Findlevel
= (levelCurrent
& ~SC_FOLDLEVELBASE
) * 8;
779 for (int j
= 0; Findlevel
> 0; j
++) {
780 char chTmp
= styler
.SafeGetCharAt(i
+ j
+ 1);
783 } else if (chTmp
== ' ') {
791 levelCurrent
-= Findlevel
/ 8;
803 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) {
804 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
805 // Avoid triggering two times on Dos/Win
806 // New line -> record any line state onto /next/ line
809 if (visibleChars
== 0)
810 lev
|= SC_FOLDLEVELWHITEFLAG
;
811 if ((levelCurrent
> levelPrev
) && (visibleChars
> 0))
812 lev
|= SC_FOLDLEVELHEADERFLAG
;
814 styler
.SetLevel(lineCurrent
, lev
);
816 levelPrev
= levelCurrent
;
818 styler
.SetLineState(lineCurrent
,
819 ((inScriptType
& 0x03) << 0) |
820 ((tagOpened
& 0x01) << 2) |
821 ((tagClosing
& 0x01) << 3) |
822 ((aspScript
& 0x0F) << 4) |
823 ((clientScript
& 0x0F) << 8) |
824 ((beforePreProc
& 0xFF) << 12));
826 lineStartVisibleChars
= 0;
829 // handle start of Mako comment line
830 if (isMako
&& ch
== '#' && chNext
== '#') {
834 // handle end of Mako comment line
835 else if (isMako
&& makoComment
&& (ch
== '\r' || ch
== '\n')) {
837 styler
.ColourTo(i
, SCE_HP_COMMENTLINE
);
838 state
= SCE_HP_DEFAULT
;
841 // Allow falling through to mako handling code if newline is going to end a block
842 if (((ch
== '\r' && chNext
!= '\n') || (ch
== '\n')) &&
843 (!isMako
|| (0 != strcmp(makoBlockType
, "%")))) {
846 // generic end of script processing
847 else if ((inScriptType
== eNonHtmlScript
) && (ch
== '<') && (chNext
== '/')) {
848 // Check if it's the end of the script tag (or any other HTML tag)
850 // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
851 case SCE_H_DOUBLESTRING
:
852 case SCE_H_SINGLESTRING
:
854 case SCE_HJ_COMMENTDOC
:
855 //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
856 // the end of script marker from some JS interpreters.
857 case SCE_HB_COMMENTLINE
:
858 case SCE_HBA_COMMENTLINE
:
859 case SCE_HJ_DOUBLESTRING
:
860 case SCE_HJ_SINGLESTRING
:
866 case SCE_HP_TRIPLEDOUBLE
:
867 case SCE_HPHP_HSTRING
:
868 case SCE_HPHP_SIMPLESTRING
:
869 case SCE_HPHP_COMMENT
:
870 case SCE_HPHP_COMMENTLINE
:
873 // check if the closing tag is a script tag
874 if (const char *tag
=
875 state
== SCE_HJ_COMMENTLINE
|| isXml
? "script" :
876 state
== SCE_H_COMMENT
? "comment" : 0) {
880 chr
= static_cast<int>(*tag
++);
881 } while (chr
!= 0 && chr
== MakeLowerCase(styler
.SafeGetCharAt(j
++)));
884 // closing tag of the script (it's a closing HTML tag anyway)
885 styler
.ColourTo(i
- 1, StateToPrint
);
886 state
= SCE_H_TAGUNKNOWN
;
887 inScriptType
= eHtml
;
888 scriptLanguage
= eScriptNone
;
889 clientScript
= eScriptJS
;
897 /////////////////////////////////////
898 // handle the start of PHP pre-processor = Non-HTML
899 else if ((state
!= SCE_H_ASPAT
) &&
900 !isPHPStringState(state
) &&
901 (state
!= SCE_HPHP_COMMENT
) &&
902 (state
!= SCE_HPHP_COMMENTLINE
) &&
905 !IsScriptCommentState(state
)) {
906 beforeLanguage
= scriptLanguage
;
907 scriptLanguage
= segIsScriptingIndicator(styler
, i
+ 2, i
+ 6, isXml
? eScriptXML
: eScriptPHP
);
908 if (scriptLanguage
!= eScriptPHP
&& isStringState(state
)) continue;
909 styler
.ColourTo(i
- 1, StateToPrint
);
910 beforePreProc
= state
;
913 i
+= PrintScriptingIndicatorOffset(styler
, styler
.GetStartSegment() + 2, i
+ 6);
914 if (scriptLanguage
== eScriptXML
)
915 styler
.ColourTo(i
, SCE_H_XMLSTART
);
917 styler
.ColourTo(i
, SCE_H_QUESTION
);
918 state
= StateForScript(scriptLanguage
);
919 if (inScriptType
== eNonHtmlScript
)
920 inScriptType
= eNonHtmlScriptPreProc
;
922 inScriptType
= eNonHtmlPreProc
;
923 // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
924 if (foldHTMLPreprocessor
&& (scriptLanguage
!= eScriptXML
)) {
928 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
932 // handle the start Mako template Python code
933 else if (isMako
&& scriptLanguage
== eScriptNone
&& ((ch
== '<' && chNext
== '%') ||
934 (lineStartVisibleChars
== 1 && ch
== '%') ||
935 (lineStartVisibleChars
== 1 && ch
== '/' && chNext
== '%') ||
936 (ch
== '$' && chNext
== '{') ||
937 (ch
== '<' && chNext
== '/' && chNext2
== '%'))) {
938 if (ch
== '%' || ch
== '/')
939 strcpy(makoBlockType
, "%");
941 strcpy(makoBlockType
, "{");
942 else if (chNext
== '/')
943 GetNextWord(styler
, i
+3, makoBlockType
, sizeof(makoBlockType
));
945 GetNextWord(styler
, i
+2, makoBlockType
, sizeof(makoBlockType
));
946 styler
.ColourTo(i
- 1, StateToPrint
);
947 beforePreProc
= state
;
948 if (inScriptType
== eNonHtmlScript
)
949 inScriptType
= eNonHtmlScriptPreProc
;
951 inScriptType
= eNonHtmlPreProc
;
956 } else if (ch
!= '%') {
960 state
= SCE_HP_START
;
961 scriptLanguage
= eScriptPython
;
962 styler
.ColourTo(i
, SCE_H_ASP
);
964 if (ch
!= '%' && ch
!= '$' && ch
!= '/') {
965 i
+= static_cast<int>(strlen(makoBlockType
));
966 visibleChars
+= static_cast<int>(strlen(makoBlockType
));
967 if (keywords4
.InList(makoBlockType
))
968 styler
.ColourTo(i
, SCE_HP_WORD
);
970 styler
.ColourTo(i
, SCE_H_TAGUNKNOWN
);
973 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
977 // handle the start/end of Django comment
978 else if (isDjango
&& state
!= SCE_H_COMMENT
&& (ch
== '{' && chNext
== '#')) {
979 styler
.ColourTo(i
- 1, StateToPrint
);
980 beforePreProc
= state
;
981 beforeLanguage
= scriptLanguage
;
982 if (inScriptType
== eNonHtmlScript
)
983 inScriptType
= eNonHtmlScriptPreProc
;
985 inScriptType
= eNonHtmlPreProc
;
988 scriptLanguage
= eScriptComment
;
989 state
= SCE_H_COMMENT
;
990 styler
.ColourTo(i
, SCE_H_ASP
);
991 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
993 } else if (isDjango
&& state
== SCE_H_COMMENT
&& (ch
== '#' && chNext
== '}')) {
994 styler
.ColourTo(i
- 1, StateToPrint
);
997 styler
.ColourTo(i
, SCE_H_ASP
);
998 state
= beforePreProc
;
999 if (inScriptType
== eNonHtmlScriptPreProc
)
1000 inScriptType
= eNonHtmlScript
;
1002 inScriptType
= eHtml
;
1003 scriptLanguage
= beforeLanguage
;
1007 // handle the start Django template code
1008 else if (isDjango
&& scriptLanguage
!= eScriptPython
&& (ch
== '{' && (chNext
== '%' || chNext
== '{'))) {
1010 strcpy(djangoBlockType
, "%");
1012 strcpy(djangoBlockType
, "{");
1013 styler
.ColourTo(i
- 1, StateToPrint
);
1014 beforePreProc
= state
;
1015 if (inScriptType
== eNonHtmlScript
)
1016 inScriptType
= eNonHtmlScriptPreProc
;
1018 inScriptType
= eNonHtmlPreProc
;
1022 state
= SCE_HP_START
;
1023 beforeLanguage
= scriptLanguage
;
1024 scriptLanguage
= eScriptPython
;
1025 styler
.ColourTo(i
, SCE_H_ASP
);
1027 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
1031 // handle the start of ASP pre-processor = Non-HTML
1032 else if (!isMako
&& !isDjango
&& !isCommentASPState(state
) && (ch
== '<') && (chNext
== '%') && !isPHPStringState(state
)) {
1033 styler
.ColourTo(i
- 1, StateToPrint
);
1034 beforePreProc
= state
;
1035 if (inScriptType
== eNonHtmlScript
)
1036 inScriptType
= eNonHtmlScriptPreProc
;
1038 inScriptType
= eNonHtmlPreProc
;
1040 if (chNext2
== '@') {
1041 i
+= 2; // place as if it was the second next char treated
1043 state
= SCE_H_ASPAT
;
1044 } else if ((chNext2
== '-') && (styler
.SafeGetCharAt(i
+ 3) == '-')) {
1045 styler
.ColourTo(i
+ 3, SCE_H_ASP
);
1046 state
= SCE_H_XCCOMMENT
;
1047 scriptLanguage
= eScriptVBS
;
1050 if (chNext2
== '=') {
1051 i
+= 2; // place as if it was the second next char treated
1054 i
++; // place as if it was the next char treated
1058 state
= StateForScript(aspScript
);
1060 scriptLanguage
= eScriptVBS
;
1061 styler
.ColourTo(i
, SCE_H_ASP
);
1062 // fold whole script
1063 if (foldHTMLPreprocessor
)
1066 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
1070 /////////////////////////////////////
1071 // handle the start of SGML language (DTD)
1072 else if (((scriptLanguage
== eScriptNone
) || (scriptLanguage
== eScriptXML
)) &&
1075 (StateToPrint
!= SCE_H_CDATA
) &&
1076 (!IsCommentState(StateToPrint
)) &&
1077 (!IsScriptCommentState(StateToPrint
))) {
1078 beforePreProc
= state
;
1079 styler
.ColourTo(i
- 2, StateToPrint
);
1080 if ((chNext
== '-') && (chNext2
== '-')) {
1081 state
= SCE_H_COMMENT
; // wait for a pending command
1082 styler
.ColourTo(i
+ 2, SCE_H_COMMENT
);
1083 i
+= 2; // follow styling after the --
1084 } else if (isWordCdata(i
+ 1, i
+ 7, styler
)) {
1085 state
= SCE_H_CDATA
;
1087 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
); // <! is default
1088 scriptLanguage
= eScriptSGML
;
1089 state
= SCE_H_SGML_COMMAND
; // wait for a pending command
1091 // fold whole tag (-- when closing the tag)
1092 if (foldHTMLPreprocessor
|| state
== SCE_H_COMMENT
|| state
== SCE_H_CDATA
)
1097 // handle the end of Mako Python code
1099 ((inScriptType
== eNonHtmlPreProc
) || (inScriptType
== eNonHtmlScriptPreProc
)) &&
1100 (scriptLanguage
!= eScriptNone
) && stateAllowsTermination(state
) &&
1101 isMakoBlockEnd(ch
, chNext
, makoBlockType
)) {
1102 if (state
== SCE_H_ASPAT
) {
1103 aspScript
= segIsScriptingIndicator(styler
,
1104 styler
.GetStartSegment(), i
- 1, aspScript
);
1106 if (state
== SCE_HP_WORD
) {
1107 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
, isMako
);
1109 styler
.ColourTo(i
- 1, StateToPrint
);
1111 if (0 != strcmp(makoBlockType
, "%") && (0 != strcmp(makoBlockType
, "{")) && ch
!= '>') {
1115 else if (0 == strcmp(makoBlockType
, "%") && ch
== '/') {
1119 if (0 != strcmp(makoBlockType
, "%") || ch
== '/') {
1120 styler
.ColourTo(i
, SCE_H_ASP
);
1122 state
= beforePreProc
;
1123 if (inScriptType
== eNonHtmlScriptPreProc
)
1124 inScriptType
= eNonHtmlScript
;
1126 inScriptType
= eHtml
;
1127 scriptLanguage
= eScriptNone
;
1131 // handle the end of Django template code
1132 else if (isDjango
&&
1133 ((inScriptType
== eNonHtmlPreProc
) || (inScriptType
== eNonHtmlScriptPreProc
)) &&
1134 (scriptLanguage
!= eScriptNone
) && stateAllowsTermination(state
) &&
1135 isDjangoBlockEnd(ch
, chNext
, djangoBlockType
)) {
1136 if (state
== SCE_H_ASPAT
) {
1137 aspScript
= segIsScriptingIndicator(styler
,
1138 styler
.GetStartSegment(), i
- 1, aspScript
);
1140 if (state
== SCE_HP_WORD
) {
1141 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
, isMako
);
1143 styler
.ColourTo(i
- 1, StateToPrint
);
1147 styler
.ColourTo(i
, SCE_H_ASP
);
1148 state
= beforePreProc
;
1149 if (inScriptType
== eNonHtmlScriptPreProc
)
1150 inScriptType
= eNonHtmlScript
;
1152 inScriptType
= eHtml
;
1153 scriptLanguage
= beforeLanguage
;
1157 // handle the end of a pre-processor = Non-HTML
1158 else if ((!isMako
&& !isDjango
&& ((inScriptType
== eNonHtmlPreProc
) || (inScriptType
== eNonHtmlScriptPreProc
)) &&
1159 (((scriptLanguage
!= eScriptNone
) && stateAllowsTermination(state
))) &&
1160 (((ch
== '%') || (ch
== '?')) && (chNext
== '>'))) ||
1161 ((scriptLanguage
== eScriptSGML
) && (ch
== '>') && (state
!= SCE_H_SGML_COMMENT
))) {
1162 if (state
== SCE_H_ASPAT
) {
1163 aspScript
= segIsScriptingIndicator(styler
,
1164 styler
.GetStartSegment(), i
- 1, aspScript
);
1166 // Bounce out of any ASP mode
1169 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
1172 classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
1175 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
, isMako
);
1178 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
1180 case SCE_H_XCCOMMENT
:
1181 styler
.ColourTo(i
- 1, state
);
1184 styler
.ColourTo(i
- 1, StateToPrint
);
1187 if (scriptLanguage
!= eScriptSGML
) {
1192 styler
.ColourTo(i
, SCE_H_ASP
);
1193 else if (scriptLanguage
== eScriptXML
)
1194 styler
.ColourTo(i
, SCE_H_XMLEND
);
1195 else if (scriptLanguage
== eScriptSGML
)
1196 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
1198 styler
.ColourTo(i
, SCE_H_QUESTION
);
1199 state
= beforePreProc
;
1200 if (inScriptType
== eNonHtmlScriptPreProc
)
1201 inScriptType
= eNonHtmlScript
;
1203 inScriptType
= eHtml
;
1204 // Unfold all scripting languages, except for XML tag
1205 if (foldHTMLPreprocessor
&& (scriptLanguage
!= eScriptXML
)) {
1208 scriptLanguage
= beforeLanguage
;
1211 /////////////////////////////////////
1216 // in HTML, fold on tag open and unfold on tag close
1218 tagClosing
= (chNext
== '/');
1219 styler
.ColourTo(i
- 1, StateToPrint
);
1221 state
= SCE_H_TAGUNKNOWN
;
1222 } else if (ch
== '&') {
1223 styler
.ColourTo(i
- 1, SCE_H_DEFAULT
);
1224 state
= SCE_H_ENTITY
;
1227 case SCE_H_SGML_DEFAULT
:
1228 case SCE_H_SGML_BLOCK_DEFAULT
:
1229 // if (scriptLanguage == eScriptSGMLblock)
1230 // StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
1233 styler
.ColourTo(i
- 1, StateToPrint
);
1234 state
= SCE_H_SGML_DOUBLESTRING
;
1235 } else if (ch
== '\'') {
1236 styler
.ColourTo(i
- 1, StateToPrint
);
1237 state
= SCE_H_SGML_SIMPLESTRING
;
1238 } else if ((ch
== '-') && (chPrev
== '-')) {
1239 if (static_cast<int>(styler
.GetStartSegment()) <= (i
- 2)) {
1240 styler
.ColourTo(i
- 2, StateToPrint
);
1242 state
= SCE_H_SGML_COMMENT
;
1243 } else if (isascii(ch
) && isalpha(ch
) && (chPrev
== '%')) {
1244 styler
.ColourTo(i
- 2, StateToPrint
);
1245 state
= SCE_H_SGML_ENTITY
;
1246 } else if (ch
== '#') {
1247 styler
.ColourTo(i
- 1, StateToPrint
);
1248 state
= SCE_H_SGML_SPECIAL
;
1249 } else if (ch
== '[') {
1250 styler
.ColourTo(i
- 1, StateToPrint
);
1251 scriptLanguage
= eScriptSGMLblock
;
1252 state
= SCE_H_SGML_BLOCK_DEFAULT
;
1253 } else if (ch
== ']') {
1254 if (scriptLanguage
== eScriptSGMLblock
) {
1255 styler
.ColourTo(i
, StateToPrint
);
1256 scriptLanguage
= eScriptSGML
;
1258 styler
.ColourTo(i
- 1, StateToPrint
);
1259 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
1261 state
= SCE_H_SGML_DEFAULT
;
1262 } else if (scriptLanguage
== eScriptSGMLblock
) {
1263 if ((ch
== '!') && (chPrev
== '<')) {
1264 styler
.ColourTo(i
- 2, StateToPrint
);
1265 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
1266 state
= SCE_H_SGML_COMMAND
;
1267 } else if (ch
== '>') {
1268 styler
.ColourTo(i
- 1, StateToPrint
);
1269 styler
.ColourTo(i
, SCE_H_SGML_DEFAULT
);
1273 case SCE_H_SGML_COMMAND
:
1274 if ((ch
== '-') && (chPrev
== '-')) {
1275 styler
.ColourTo(i
- 2, StateToPrint
);
1276 state
= SCE_H_SGML_COMMENT
;
1277 } else if (!issgmlwordchar(ch
)) {
1278 if (isWordHSGML(styler
.GetStartSegment(), i
- 1, keywords6
, styler
)) {
1279 styler
.ColourTo(i
- 1, StateToPrint
);
1280 state
= SCE_H_SGML_1ST_PARAM
;
1282 state
= SCE_H_SGML_ERROR
;
1286 case SCE_H_SGML_1ST_PARAM
:
1287 // wait for the beginning of the word
1288 if ((ch
== '-') && (chPrev
== '-')) {
1289 if (scriptLanguage
== eScriptSGMLblock
) {
1290 styler
.ColourTo(i
- 2, SCE_H_SGML_BLOCK_DEFAULT
);
1292 styler
.ColourTo(i
- 2, SCE_H_SGML_DEFAULT
);
1294 state
= SCE_H_SGML_1ST_PARAM_COMMENT
;
1295 } else if (issgmlwordchar(ch
)) {
1296 if (scriptLanguage
== eScriptSGMLblock
) {
1297 styler
.ColourTo(i
- 1, SCE_H_SGML_BLOCK_DEFAULT
);
1299 styler
.ColourTo(i
- 1, SCE_H_SGML_DEFAULT
);
1301 // find the length of the word
1303 while (setHTMLWord
.Contains(static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ size
))))
1305 styler
.ColourTo(i
+ size
- 1, StateToPrint
);
1307 visibleChars
+= size
- 1;
1308 ch
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
));
1309 if (scriptLanguage
== eScriptSGMLblock
) {
1310 state
= SCE_H_SGML_BLOCK_DEFAULT
;
1312 state
= SCE_H_SGML_DEFAULT
;
1317 case SCE_H_SGML_ERROR
:
1318 if ((ch
== '-') && (chPrev
== '-')) {
1319 styler
.ColourTo(i
- 2, StateToPrint
);
1320 state
= SCE_H_SGML_COMMENT
;
1322 case SCE_H_SGML_DOUBLESTRING
:
1324 styler
.ColourTo(i
, StateToPrint
);
1325 state
= SCE_H_SGML_DEFAULT
;
1328 case SCE_H_SGML_SIMPLESTRING
:
1330 styler
.ColourTo(i
, StateToPrint
);
1331 state
= SCE_H_SGML_DEFAULT
;
1334 case SCE_H_SGML_COMMENT
:
1335 if ((ch
== '-') && (chPrev
== '-')) {
1336 styler
.ColourTo(i
, StateToPrint
);
1337 state
= SCE_H_SGML_DEFAULT
;
1341 if ((chPrev2
== ']') && (chPrev
== ']') && (ch
== '>')) {
1342 styler
.ColourTo(i
, StateToPrint
);
1343 state
= SCE_H_DEFAULT
;
1348 if ((scriptLanguage
!= eScriptComment
) && (chPrev2
== '-') && (chPrev
== '-') && (ch
== '>')) {
1349 styler
.ColourTo(i
, StateToPrint
);
1350 state
= SCE_H_DEFAULT
;
1354 case SCE_H_SGML_1ST_PARAM_COMMENT
:
1355 if ((ch
== '-') && (chPrev
== '-')) {
1356 styler
.ColourTo(i
, SCE_H_SGML_COMMENT
);
1357 state
= SCE_H_SGML_1ST_PARAM
;
1360 case SCE_H_SGML_SPECIAL
:
1361 if (!(isascii(ch
) && isupper(ch
))) {
1362 styler
.ColourTo(i
- 1, StateToPrint
);
1364 state
= SCE_H_SGML_ERROR
;
1366 state
= SCE_H_SGML_DEFAULT
;
1370 case SCE_H_SGML_ENTITY
:
1372 styler
.ColourTo(i
, StateToPrint
);
1373 state
= SCE_H_SGML_DEFAULT
;
1374 } else if (!(isascii(ch
) && isalnum(ch
)) && ch
!= '-' && ch
!= '.') {
1375 styler
.ColourTo(i
, SCE_H_SGML_ERROR
);
1376 state
= SCE_H_SGML_DEFAULT
;
1381 styler
.ColourTo(i
, StateToPrint
);
1382 state
= SCE_H_DEFAULT
;
1384 if (ch
!= '#' && !(isascii(ch
) && isalnum(ch
)) // Should check that '#' follows '&', but it is unlikely anyway...
1385 && ch
!= '.' && ch
!= '-' && ch
!= '_' && ch
!= ':') { // valid in XML
1386 if (!isascii(ch
)) // Possibly start of a multibyte character so don't allow this byte to be in entity style
1387 styler
.ColourTo(i
-1, SCE_H_TAGUNKNOWN
);
1389 styler
.ColourTo(i
, SCE_H_TAGUNKNOWN
);
1390 state
= SCE_H_DEFAULT
;
1393 case SCE_H_TAGUNKNOWN
:
1394 if (!setTagContinue
.Contains(ch
) && !((ch
== '/') && (chPrev
== '<'))) {
1395 int eClass
= classifyTagHTML(styler
.GetStartSegment(),
1396 i
- 1, keywords
, styler
, tagDontFold
, caseSensitive
, isXml
, allowScripts
);
1397 if (eClass
== SCE_H_SCRIPT
|| eClass
== SCE_H_COMMENT
) {
1399 inScriptType
= eNonHtmlScript
;
1400 scriptLanguage
= eClass
== SCE_H_SCRIPT
? clientScript
: eScriptComment
;
1402 scriptLanguage
= eScriptNone
;
1407 styler
.ColourTo(i
, eClass
);
1408 if (inScriptType
== eNonHtmlScript
) {
1409 state
= StateForScript(scriptLanguage
);
1411 state
= SCE_H_DEFAULT
;
1422 } else if (ch
== '/' && chNext
== '>') {
1423 if (eClass
== SCE_H_TAGUNKNOWN
) {
1424 styler
.ColourTo(i
+ 1, SCE_H_TAGUNKNOWN
);
1426 styler
.ColourTo(i
- 1, StateToPrint
);
1427 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1431 state
= SCE_H_DEFAULT
;
1434 if (eClass
!= SCE_H_TAGUNKNOWN
) {
1435 if (eClass
== SCE_H_SGML_DEFAULT
) {
1436 state
= SCE_H_SGML_DEFAULT
;
1438 state
= SCE_H_OTHER
;
1444 case SCE_H_ATTRIBUTE
:
1445 if (!setAttributeContinue
.Contains(ch
)) {
1446 if (inScriptType
== eNonHtmlScript
) {
1447 int scriptLanguagePrev
= scriptLanguage
;
1448 clientScript
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
- 1, scriptLanguage
);
1449 scriptLanguage
= clientScript
;
1450 if ((scriptLanguagePrev
!= scriptLanguage
) && (scriptLanguage
== eScriptNone
))
1451 inScriptType
= eHtml
;
1453 classifyAttribHTML(styler
.GetStartSegment(), i
- 1, keywords
, styler
);
1455 styler
.ColourTo(i
, SCE_H_TAG
);
1456 if (inScriptType
== eNonHtmlScript
) {
1457 state
= StateForScript(scriptLanguage
);
1459 state
= SCE_H_DEFAULT
;
1470 } else if (ch
== '=') {
1471 styler
.ColourTo(i
, SCE_H_OTHER
);
1472 state
= SCE_H_VALUE
;
1474 state
= SCE_H_OTHER
;
1480 styler
.ColourTo(i
- 1, StateToPrint
);
1481 styler
.ColourTo(i
, SCE_H_TAG
);
1482 if (inScriptType
== eNonHtmlScript
) {
1483 state
= StateForScript(scriptLanguage
);
1485 state
= SCE_H_DEFAULT
;
1496 } else if (ch
== '\"') {
1497 styler
.ColourTo(i
- 1, StateToPrint
);
1498 state
= SCE_H_DOUBLESTRING
;
1499 } else if (ch
== '\'') {
1500 styler
.ColourTo(i
- 1, StateToPrint
);
1501 state
= SCE_H_SINGLESTRING
;
1502 } else if (ch
== '=') {
1503 styler
.ColourTo(i
, StateToPrint
);
1504 state
= SCE_H_VALUE
;
1505 } else if (ch
== '/' && chNext
== '>') {
1506 styler
.ColourTo(i
- 1, StateToPrint
);
1507 styler
.ColourTo(i
+ 1, SCE_H_TAGEND
);
1510 state
= SCE_H_DEFAULT
;
1512 } else if (ch
== '?' && chNext
== '>') {
1513 styler
.ColourTo(i
- 1, StateToPrint
);
1514 styler
.ColourTo(i
+ 1, SCE_H_XMLEND
);
1517 state
= SCE_H_DEFAULT
;
1518 } else if (setHTMLWord
.Contains(ch
)) {
1519 styler
.ColourTo(i
- 1, StateToPrint
);
1520 state
= SCE_H_ATTRIBUTE
;
1523 case SCE_H_DOUBLESTRING
:
1525 if (inScriptType
== eNonHtmlScript
) {
1526 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1528 styler
.ColourTo(i
, SCE_H_DOUBLESTRING
);
1529 state
= SCE_H_OTHER
;
1532 case SCE_H_SINGLESTRING
:
1534 if (inScriptType
== eNonHtmlScript
) {
1535 scriptLanguage
= segIsScriptingIndicator(styler
, styler
.GetStartSegment(), i
, scriptLanguage
);
1537 styler
.ColourTo(i
, SCE_H_SINGLESTRING
);
1538 state
= SCE_H_OTHER
;
1542 if (!setHTMLWord
.Contains(ch
)) {
1543 if (ch
== '\"' && chPrev
== '=') {
1544 // Should really test for being first character
1545 state
= SCE_H_DOUBLESTRING
;
1546 } else if (ch
== '\'' && chPrev
== '=') {
1547 state
= SCE_H_SINGLESTRING
;
1549 if (IsNumber(styler
.GetStartSegment(), styler
)) {
1550 styler
.ColourTo(i
- 1, SCE_H_NUMBER
);
1552 styler
.ColourTo(i
- 1, StateToPrint
);
1555 styler
.ColourTo(i
, SCE_H_TAG
);
1556 if (inScriptType
== eNonHtmlScript
) {
1557 state
= StateForScript(scriptLanguage
);
1559 state
= SCE_H_DEFAULT
;
1571 state
= SCE_H_OTHER
;
1576 case SCE_HJ_DEFAULT
:
1578 case SCE_HJ_SYMBOLS
:
1579 if (IsAWordStart(ch
)) {
1580 styler
.ColourTo(i
- 1, StateToPrint
);
1581 state
= SCE_HJ_WORD
;
1582 } else if (ch
== '/' && chNext
== '*') {
1583 styler
.ColourTo(i
- 1, StateToPrint
);
1585 state
= SCE_HJ_COMMENTDOC
;
1587 state
= SCE_HJ_COMMENT
;
1588 if (chNext2
== '/') {
1589 // Eat the * so it isn't used for the end of the comment
1592 } else if (ch
== '/' && chNext
== '/') {
1593 styler
.ColourTo(i
- 1, StateToPrint
);
1594 state
= SCE_HJ_COMMENTLINE
;
1595 } else if (ch
== '/' && isOKBeforeRE(chPrevNonWhite
)) {
1596 styler
.ColourTo(i
- 1, StateToPrint
);
1597 state
= SCE_HJ_REGEX
;
1598 } else if (ch
== '\"') {
1599 styler
.ColourTo(i
- 1, StateToPrint
);
1600 state
= SCE_HJ_DOUBLESTRING
;
1601 } else if (ch
== '\'') {
1602 styler
.ColourTo(i
- 1, StateToPrint
);
1603 state
= SCE_HJ_SINGLESTRING
;
1604 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1605 styler
.SafeGetCharAt(i
+ 3) == '-') {
1606 styler
.ColourTo(i
- 1, StateToPrint
);
1607 state
= SCE_HJ_COMMENTLINE
;
1608 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1609 styler
.ColourTo(i
- 1, StateToPrint
);
1610 state
= SCE_HJ_COMMENTLINE
;
1612 } else if (IsOperator(ch
)) {
1613 styler
.ColourTo(i
- 1, StateToPrint
);
1614 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1615 state
= SCE_HJ_DEFAULT
;
1616 } else if ((ch
== ' ') || (ch
== '\t')) {
1617 if (state
== SCE_HJ_START
) {
1618 styler
.ColourTo(i
- 1, StateToPrint
);
1619 state
= SCE_HJ_DEFAULT
;
1624 if (!IsAWordChar(ch
)) {
1625 classifyWordHTJS(styler
.GetStartSegment(), i
- 1, keywords2
, styler
, inScriptType
);
1626 //styler.ColourTo(i - 1, eHTJSKeyword);
1627 state
= SCE_HJ_DEFAULT
;
1628 if (ch
== '/' && chNext
== '*') {
1630 state
= SCE_HJ_COMMENTDOC
;
1632 state
= SCE_HJ_COMMENT
;
1633 } else if (ch
== '/' && chNext
== '/') {
1634 state
= SCE_HJ_COMMENTLINE
;
1635 } else if (ch
== '\"') {
1636 state
= SCE_HJ_DOUBLESTRING
;
1637 } else if (ch
== '\'') {
1638 state
= SCE_HJ_SINGLESTRING
;
1639 } else if ((ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1640 styler
.ColourTo(i
- 1, StateToPrint
);
1641 state
= SCE_HJ_COMMENTLINE
;
1643 } else if (IsOperator(ch
)) {
1644 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
1645 state
= SCE_HJ_DEFAULT
;
1649 case SCE_HJ_COMMENT
:
1650 case SCE_HJ_COMMENTDOC
:
1651 if (ch
== '/' && chPrev
== '*') {
1652 styler
.ColourTo(i
, StateToPrint
);
1653 state
= SCE_HJ_DEFAULT
;
1657 case SCE_HJ_COMMENTLINE
:
1658 if (ch
== '\r' || ch
== '\n') {
1659 styler
.ColourTo(i
- 1, statePrintForState(SCE_HJ_COMMENTLINE
, inScriptType
));
1660 state
= SCE_HJ_DEFAULT
;
1664 case SCE_HJ_DOUBLESTRING
:
1666 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1669 } else if (ch
== '\"') {
1670 styler
.ColourTo(i
, statePrintForState(SCE_HJ_DOUBLESTRING
, inScriptType
));
1671 state
= SCE_HJ_DEFAULT
;
1672 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1673 styler
.ColourTo(i
- 1, StateToPrint
);
1674 state
= SCE_HJ_COMMENTLINE
;
1676 } else if (isLineEnd(ch
)) {
1677 styler
.ColourTo(i
- 1, StateToPrint
);
1678 state
= SCE_HJ_STRINGEOL
;
1681 case SCE_HJ_SINGLESTRING
:
1683 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1686 } else if (ch
== '\'') {
1687 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SINGLESTRING
, inScriptType
));
1688 state
= SCE_HJ_DEFAULT
;
1689 } else if ((inScriptType
== eNonHtmlScript
) && (ch
== '-') && (chNext
== '-') && (chNext2
== '>')) {
1690 styler
.ColourTo(i
- 1, StateToPrint
);
1691 state
= SCE_HJ_COMMENTLINE
;
1693 } else if (isLineEnd(ch
)) {
1694 styler
.ColourTo(i
- 1, StateToPrint
);
1695 if (chPrev
!= '\\' && (chPrev2
!= '\\' || chPrev
!= '\r' || ch
!= '\n')) {
1696 state
= SCE_HJ_STRINGEOL
;
1700 case SCE_HJ_STRINGEOL
:
1701 if (!isLineEnd(ch
)) {
1702 styler
.ColourTo(i
- 1, StateToPrint
);
1703 state
= SCE_HJ_DEFAULT
;
1704 } else if (!isLineEnd(chNext
)) {
1705 styler
.ColourTo(i
, StateToPrint
);
1706 state
= SCE_HJ_DEFAULT
;
1710 if (ch
== '\r' || ch
== '\n' || ch
== '/') {
1712 while (isascii(chNext
) && islower(chNext
)) { // gobble regex flags
1715 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1718 styler
.ColourTo(i
, StateToPrint
);
1719 state
= SCE_HJ_DEFAULT
;
1720 } else if (ch
== '\\') {
1721 // Gobble up the quoted character
1722 if (chNext
== '\\' || chNext
== '/') {
1725 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1729 case SCE_HB_DEFAULT
:
1731 if (IsAWordStart(ch
)) {
1732 styler
.ColourTo(i
- 1, StateToPrint
);
1733 state
= SCE_HB_WORD
;
1734 } else if (ch
== '\'') {
1735 styler
.ColourTo(i
- 1, StateToPrint
);
1736 state
= SCE_HB_COMMENTLINE
;
1737 } else if (ch
== '\"') {
1738 styler
.ColourTo(i
- 1, StateToPrint
);
1739 state
= SCE_HB_STRING
;
1740 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1741 styler
.SafeGetCharAt(i
+ 3) == '-') {
1742 styler
.ColourTo(i
- 1, StateToPrint
);
1743 state
= SCE_HB_COMMENTLINE
;
1744 } else if (IsOperator(ch
)) {
1745 styler
.ColourTo(i
- 1, StateToPrint
);
1746 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1747 state
= SCE_HB_DEFAULT
;
1748 } else if ((ch
== ' ') || (ch
== '\t')) {
1749 if (state
== SCE_HB_START
) {
1750 styler
.ColourTo(i
- 1, StateToPrint
);
1751 state
= SCE_HB_DEFAULT
;
1756 if (!IsAWordChar(ch
)) {
1757 state
= classifyWordHTVB(styler
.GetStartSegment(), i
- 1, keywords3
, styler
, inScriptType
);
1758 if (state
== SCE_HB_DEFAULT
) {
1760 state
= SCE_HB_STRING
;
1761 } else if (ch
== '\'') {
1762 state
= SCE_HB_COMMENTLINE
;
1763 } else if (IsOperator(ch
)) {
1764 styler
.ColourTo(i
, statePrintForState(SCE_HB_DEFAULT
, inScriptType
));
1765 state
= SCE_HB_DEFAULT
;
1772 styler
.ColourTo(i
, StateToPrint
);
1773 state
= SCE_HB_DEFAULT
;
1774 } else if (ch
== '\r' || ch
== '\n') {
1775 styler
.ColourTo(i
- 1, StateToPrint
);
1776 state
= SCE_HB_STRINGEOL
;
1779 case SCE_HB_COMMENTLINE
:
1780 if (ch
== '\r' || ch
== '\n') {
1781 styler
.ColourTo(i
- 1, StateToPrint
);
1782 state
= SCE_HB_DEFAULT
;
1785 case SCE_HB_STRINGEOL
:
1786 if (!isLineEnd(ch
)) {
1787 styler
.ColourTo(i
- 1, StateToPrint
);
1788 state
= SCE_HB_DEFAULT
;
1789 } else if (!isLineEnd(chNext
)) {
1790 styler
.ColourTo(i
, StateToPrint
);
1791 state
= SCE_HB_DEFAULT
;
1794 case SCE_HP_DEFAULT
:
1796 if (IsAWordStart(ch
)) {
1797 styler
.ColourTo(i
- 1, StateToPrint
);
1798 state
= SCE_HP_WORD
;
1799 } else if ((ch
== '<') && (chNext
== '!') && (chNext2
== '-') &&
1800 styler
.SafeGetCharAt(i
+ 3) == '-') {
1801 styler
.ColourTo(i
- 1, StateToPrint
);
1802 state
= SCE_HP_COMMENTLINE
;
1803 } else if (ch
== '#') {
1804 styler
.ColourTo(i
- 1, StateToPrint
);
1805 state
= SCE_HP_COMMENTLINE
;
1806 } else if (ch
== '\"') {
1807 styler
.ColourTo(i
- 1, StateToPrint
);
1808 if (chNext
== '\"' && chNext2
== '\"') {
1810 state
= SCE_HP_TRIPLEDOUBLE
;
1813 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1815 // state = statePrintForState(SCE_HP_STRING,inScriptType);
1816 state
= SCE_HP_STRING
;
1818 } else if (ch
== '\'') {
1819 styler
.ColourTo(i
- 1, StateToPrint
);
1820 if (chNext
== '\'' && chNext2
== '\'') {
1822 state
= SCE_HP_TRIPLE
;
1825 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1827 state
= SCE_HP_CHARACTER
;
1829 } else if (IsOperator(ch
)) {
1830 styler
.ColourTo(i
- 1, StateToPrint
);
1831 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1832 } else if ((ch
== ' ') || (ch
== '\t')) {
1833 if (state
== SCE_HP_START
) {
1834 styler
.ColourTo(i
- 1, StateToPrint
);
1835 state
= SCE_HP_DEFAULT
;
1840 if (!IsAWordChar(ch
)) {
1841 classifyWordHTPy(styler
.GetStartSegment(), i
- 1, keywords4
, styler
, prevWord
, inScriptType
, isMako
);
1842 state
= SCE_HP_DEFAULT
;
1844 state
= SCE_HP_COMMENTLINE
;
1845 } else if (ch
== '\"') {
1846 if (chNext
== '\"' && chNext2
== '\"') {
1848 state
= SCE_HP_TRIPLEDOUBLE
;
1851 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1853 state
= SCE_HP_STRING
;
1855 } else if (ch
== '\'') {
1856 if (chNext
== '\'' && chNext2
== '\'') {
1858 state
= SCE_HP_TRIPLE
;
1861 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1863 state
= SCE_HP_CHARACTER
;
1865 } else if (IsOperator(ch
)) {
1866 styler
.ColourTo(i
, statePrintForState(SCE_HP_OPERATOR
, inScriptType
));
1870 case SCE_HP_COMMENTLINE
:
1871 if (ch
== '\r' || ch
== '\n') {
1872 styler
.ColourTo(i
- 1, StateToPrint
);
1873 state
= SCE_HP_DEFAULT
;
1878 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1881 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1883 } else if (ch
== '\"') {
1884 styler
.ColourTo(i
, StateToPrint
);
1885 state
= SCE_HP_DEFAULT
;
1888 case SCE_HP_CHARACTER
:
1890 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\') {
1893 chNext
= static_cast<unsigned char>(styler
.SafeGetCharAt(i
+ 1));
1895 } else if (ch
== '\'') {
1896 styler
.ColourTo(i
, StateToPrint
);
1897 state
= SCE_HP_DEFAULT
;
1901 if (ch
== '\'' && chPrev
== '\'' && chPrev2
== '\'') {
1902 styler
.ColourTo(i
, StateToPrint
);
1903 state
= SCE_HP_DEFAULT
;
1906 case SCE_HP_TRIPLEDOUBLE
:
1907 if (ch
== '\"' && chPrev
== '\"' && chPrev2
== '\"') {
1908 styler
.ColourTo(i
, StateToPrint
);
1909 state
= SCE_HP_DEFAULT
;
1912 ///////////// start - PHP state handling
1914 if (!IsAWordChar(ch
)) {
1915 classifyWordHTPHP(styler
.GetStartSegment(), i
- 1, keywords5
, styler
);
1916 if (ch
== '/' && chNext
== '*') {
1918 state
= SCE_HPHP_COMMENT
;
1919 } else if (ch
== '/' && chNext
== '/') {
1921 state
= SCE_HPHP_COMMENTLINE
;
1922 } else if (ch
== '#') {
1923 state
= SCE_HPHP_COMMENTLINE
;
1924 } else if (ch
== '\"') {
1925 state
= SCE_HPHP_HSTRING
;
1926 strcpy(phpStringDelimiter
, "\"");
1927 } else if (styler
.Match(i
, "<<<")) {
1928 bool isSimpleString
= false;
1929 i
= FindPhpStringDelimiter(phpStringDelimiter
, sizeof(phpStringDelimiter
), i
+ 3, lengthDoc
, styler
, isSimpleString
);
1930 if (strlen(phpStringDelimiter
)) {
1931 state
= (isSimpleString
? SCE_HPHP_SIMPLESTRING
: SCE_HPHP_HSTRING
);
1932 if (foldHeredoc
) levelCurrent
++;
1934 } else if (ch
== '\'') {
1935 state
= SCE_HPHP_SIMPLESTRING
;
1936 strcpy(phpStringDelimiter
, "\'");
1937 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1938 state
= SCE_HPHP_VARIABLE
;
1939 } else if (IsOperator(ch
)) {
1940 state
= SCE_HPHP_OPERATOR
;
1942 state
= SCE_HPHP_DEFAULT
;
1946 case SCE_HPHP_NUMBER
:
1947 // recognize bases 8,10 or 16 integers OR floating-point numbers
1949 && strchr(".xXabcdefABCDEF", ch
) == NULL
1950 && ((ch
!= '-' && ch
!= '+') || (chPrev
!= 'e' && chPrev
!= 'E'))) {
1951 styler
.ColourTo(i
- 1, SCE_HPHP_NUMBER
);
1953 state
= SCE_HPHP_OPERATOR
;
1955 state
= SCE_HPHP_DEFAULT
;
1958 case SCE_HPHP_VARIABLE
:
1959 if (!IsPhpWordChar(chNext
)) {
1960 styler
.ColourTo(i
, SCE_HPHP_VARIABLE
);
1961 state
= SCE_HPHP_DEFAULT
;
1964 case SCE_HPHP_COMMENT
:
1965 if (ch
== '/' && chPrev
== '*') {
1966 styler
.ColourTo(i
, StateToPrint
);
1967 state
= SCE_HPHP_DEFAULT
;
1970 case SCE_HPHP_COMMENTLINE
:
1971 if (ch
== '\r' || ch
== '\n') {
1972 styler
.ColourTo(i
- 1, StateToPrint
);
1973 state
= SCE_HPHP_DEFAULT
;
1976 case SCE_HPHP_HSTRING
:
1977 if (ch
== '\\' && (phpStringDelimiter
[0] == '\"' || chNext
== '$' || chNext
== '{')) {
1978 // skip the next char
1980 } else if (((ch
== '{' && chNext
== '$') || (ch
== '$' && chNext
== '{'))
1981 && IsPhpWordStart(chNext2
)) {
1982 styler
.ColourTo(i
- 1, StateToPrint
);
1983 state
= SCE_HPHP_COMPLEX_VARIABLE
;
1984 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
1985 styler
.ColourTo(i
- 1, StateToPrint
);
1986 state
= SCE_HPHP_HSTRING_VARIABLE
;
1987 } else if (styler
.Match(i
, phpStringDelimiter
)) {
1988 if (phpStringDelimiter
[0] == '\"') {
1989 styler
.ColourTo(i
, StateToPrint
);
1990 state
= SCE_HPHP_DEFAULT
;
1991 } else if (isLineEnd(chPrev
)) {
1992 const int psdLength
= static_cast<int>(strlen(phpStringDelimiter
));
1993 const char chAfterPsd
= styler
.SafeGetCharAt(i
+ psdLength
);
1994 const char chAfterPsd2
= styler
.SafeGetCharAt(i
+ psdLength
+ 1);
1995 if (isLineEnd(chAfterPsd
) ||
1996 (chAfterPsd
== ';' && isLineEnd(chAfterPsd2
))) {
1997 i
+= (((i
+ psdLength
) < lengthDoc
) ? psdLength
: lengthDoc
) - 1;
1998 styler
.ColourTo(i
, StateToPrint
);
1999 state
= SCE_HPHP_DEFAULT
;
2000 if (foldHeredoc
) levelCurrent
--;
2005 case SCE_HPHP_SIMPLESTRING
:
2006 if (phpStringDelimiter
[0] == '\'') {
2008 // skip the next char
2010 } else if (ch
== '\'') {
2011 styler
.ColourTo(i
, StateToPrint
);
2012 state
= SCE_HPHP_DEFAULT
;
2014 } else if (isLineEnd(chPrev
) && styler
.Match(i
, phpStringDelimiter
)) {
2015 const int psdLength
= static_cast<int>(strlen(phpStringDelimiter
));
2016 const char chAfterPsd
= styler
.SafeGetCharAt(i
+ psdLength
);
2017 const char chAfterPsd2
= styler
.SafeGetCharAt(i
+ psdLength
+ 1);
2018 if (isLineEnd(chAfterPsd
) ||
2019 (chAfterPsd
== ';' && isLineEnd(chAfterPsd2
))) {
2020 i
+= (((i
+ psdLength
) < lengthDoc
) ? psdLength
: lengthDoc
) - 1;
2021 styler
.ColourTo(i
, StateToPrint
);
2022 state
= SCE_HPHP_DEFAULT
;
2023 if (foldHeredoc
) levelCurrent
--;
2027 case SCE_HPHP_HSTRING_VARIABLE
:
2028 if (!IsPhpWordChar(chNext
)) {
2029 styler
.ColourTo(i
, StateToPrint
);
2030 state
= SCE_HPHP_HSTRING
;
2033 case SCE_HPHP_COMPLEX_VARIABLE
:
2035 styler
.ColourTo(i
, StateToPrint
);
2036 state
= SCE_HPHP_HSTRING
;
2039 case SCE_HPHP_OPERATOR
:
2040 case SCE_HPHP_DEFAULT
:
2041 styler
.ColourTo(i
- 1, StateToPrint
);
2042 if (IsADigit(ch
) || (ch
== '.' && IsADigit(chNext
))) {
2043 state
= SCE_HPHP_NUMBER
;
2044 } else if (IsAWordStart(ch
)) {
2045 state
= SCE_HPHP_WORD
;
2046 } else if (ch
== '/' && chNext
== '*') {
2048 state
= SCE_HPHP_COMMENT
;
2049 } else if (ch
== '/' && chNext
== '/') {
2051 state
= SCE_HPHP_COMMENTLINE
;
2052 } else if (ch
== '#') {
2053 state
= SCE_HPHP_COMMENTLINE
;
2054 } else if (ch
== '\"') {
2055 state
= SCE_HPHP_HSTRING
;
2056 strcpy(phpStringDelimiter
, "\"");
2057 } else if (styler
.Match(i
, "<<<")) {
2058 bool isSimpleString
= false;
2059 i
= FindPhpStringDelimiter(phpStringDelimiter
, sizeof(phpStringDelimiter
), i
+ 3, lengthDoc
, styler
, isSimpleString
);
2060 if (strlen(phpStringDelimiter
)) {
2061 state
= (isSimpleString
? SCE_HPHP_SIMPLESTRING
: SCE_HPHP_HSTRING
);
2062 if (foldHeredoc
) levelCurrent
++;
2064 } else if (ch
== '\'') {
2065 state
= SCE_HPHP_SIMPLESTRING
;
2066 strcpy(phpStringDelimiter
, "\'");
2067 } else if (ch
== '$' && IsPhpWordStart(chNext
)) {
2068 state
= SCE_HPHP_VARIABLE
;
2069 } else if (IsOperator(ch
)) {
2070 state
= SCE_HPHP_OPERATOR
;
2071 } else if ((state
== SCE_HPHP_OPERATOR
) && (IsASpace(ch
))) {
2072 state
= SCE_HPHP_DEFAULT
;
2075 ///////////// end - PHP state handling
2078 // Some of the above terminated their lexeme but since the same character starts
2079 // the same class again, only reenter if non empty segment.
2081 bool nonEmptySegment
= i
>= static_cast<int>(styler
.GetStartSegment());
2082 if (state
== SCE_HB_DEFAULT
) { // One of the above succeeded
2083 if ((ch
== '\"') && (nonEmptySegment
)) {
2084 state
= SCE_HB_STRING
;
2085 } else if (ch
== '\'') {
2086 state
= SCE_HB_COMMENTLINE
;
2087 } else if (IsAWordStart(ch
)) {
2088 state
= SCE_HB_WORD
;
2089 } else if (IsOperator(ch
)) {
2090 styler
.ColourTo(i
, SCE_HB_DEFAULT
);
2092 } else if (state
== SCE_HBA_DEFAULT
) { // One of the above succeeded
2093 if ((ch
== '\"') && (nonEmptySegment
)) {
2094 state
= SCE_HBA_STRING
;
2095 } else if (ch
== '\'') {
2096 state
= SCE_HBA_COMMENTLINE
;
2097 } else if (IsAWordStart(ch
)) {
2098 state
= SCE_HBA_WORD
;
2099 } else if (IsOperator(ch
)) {
2100 styler
.ColourTo(i
, SCE_HBA_DEFAULT
);
2102 } else if (state
== SCE_HJ_DEFAULT
) { // One of the above succeeded
2103 if (ch
== '/' && chNext
== '*') {
2104 if (styler
.SafeGetCharAt(i
+ 2) == '*')
2105 state
= SCE_HJ_COMMENTDOC
;
2107 state
= SCE_HJ_COMMENT
;
2108 } else if (ch
== '/' && chNext
== '/') {
2109 state
= SCE_HJ_COMMENTLINE
;
2110 } else if ((ch
== '\"') && (nonEmptySegment
)) {
2111 state
= SCE_HJ_DOUBLESTRING
;
2112 } else if ((ch
== '\'') && (nonEmptySegment
)) {
2113 state
= SCE_HJ_SINGLESTRING
;
2114 } else if (IsAWordStart(ch
)) {
2115 state
= SCE_HJ_WORD
;
2116 } else if (IsOperator(ch
)) {
2117 styler
.ColourTo(i
, statePrintForState(SCE_HJ_SYMBOLS
, inScriptType
));
2124 classifyWordHTJS(styler
.GetStartSegment(), lengthDoc
- 1, keywords2
, styler
, inScriptType
);
2127 classifyWordHTVB(styler
.GetStartSegment(), lengthDoc
- 1, keywords3
, styler
, inScriptType
);
2130 classifyWordHTPy(styler
.GetStartSegment(), lengthDoc
- 1, keywords4
, styler
, prevWord
, inScriptType
, isMako
);
2133 classifyWordHTPHP(styler
.GetStartSegment(), lengthDoc
- 1, keywords5
, styler
);
2136 StateToPrint
= statePrintForState(state
, inScriptType
);
2137 if (static_cast<int>(styler
.GetStartSegment()) < lengthDoc
)
2138 styler
.ColourTo(lengthDoc
- 1, StateToPrint
);
2142 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
2144 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
2145 styler
.SetLevel(lineCurrent
, levelPrev
| flagsNext
);
2149 static void ColouriseXMLDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
2151 // Passing in true because we're lexing XML
2152 ColouriseHyperTextDoc(startPos
, length
, initStyle
, keywordlists
, styler
, true);
2155 static void ColouriseHTMLDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
2157 // Passing in false because we're notlexing XML
2158 ColouriseHyperTextDoc(startPos
, length
, initStyle
, keywordlists
, styler
, false);
2161 static void ColourisePHPScriptDoc(unsigned int startPos
, int length
, int initStyle
, WordList
*keywordlists
[],
2164 initStyle
= SCE_HPHP_DEFAULT
;
2165 ColouriseHTMLDoc(startPos
, length
, initStyle
, keywordlists
, styler
);
2168 static const char * const htmlWordListDesc
[] = {
2169 "HTML elements and attributes",
2170 "JavaScript keywords",
2171 "VBScript keywords",
2174 "SGML and DTD keywords",
2178 static const char * const phpscriptWordListDesc
[] = {
2188 LexerModule
lmHTML(SCLEX_HTML
, ColouriseHTMLDoc
, "hypertext", 0, htmlWordListDesc
, 8);
2189 LexerModule
lmXML(SCLEX_XML
, ColouriseXMLDoc
, "xml", 0, htmlWordListDesc
, 8);
2190 LexerModule
lmPHPSCRIPT(SCLEX_PHPSCRIPT
, ColourisePHPScriptDoc
, "phpscript", 0, phpscriptWordListDesc
, 8);