1 // Scintilla source code edit control
\r
2 /** @file LexHTML.cxx
\r
5 // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
\r
6 // The License.txt file describes the conditions under which this software may be distributed.
\r
14 #include "Platform.h"
\r
16 #include "PropSet.h"
\r
17 #include "Accessor.h"
\r
18 #include "StyleContext.h"
\r
19 #include "KeyWords.h"
\r
20 #include "Scintilla.h"
\r
21 #include "SciLexer.h"
\r
22 #include "CharacterSet.h"
\r
24 #ifdef SCI_NAMESPACE
\r
25 using namespace Scintilla;
\r
28 #define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START)
\r
29 #define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START)
\r
30 #define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START)
\r
32 enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock, eScriptComment };
\r
33 enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc };
\r
35 static inline bool IsAWordChar(const int ch) {
\r
36 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
\r
39 static inline bool IsAWordStart(const int ch) {
\r
40 return (ch < 0x80) && (isalnum(ch) || ch == '_');
\r
43 inline bool IsOperator(int ch) {
\r
44 if (isascii(ch) && isalnum(ch))
\r
46 // '.' left out as it is used to make up numbers
\r
47 if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
\r
48 ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
\r
49 ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
\r
50 ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
\r
51 ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
\r
52 ch == '?' || ch == '!' || ch == '.' || ch == '~')
\r
57 static inline int MakeLowerCase(int ch) {
\r
58 if (ch < 'A' || ch > 'Z')
\r
61 return ch - 'A' + 'a';
\r
64 static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) {
\r
66 for (; (i < end - start + 1) && (i < len-1); i++) {
\r
67 s[i] = static_cast<char>(MakeLowerCase(styler[start + i]));
\r
72 static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) {
\r
74 GetTextSegment(styler, start, end, s, sizeof(s));
\r
75 //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
\r
76 if (strstr(s, "src")) // External script
\r
78 if (strstr(s, "vbs"))
\r
80 if (strstr(s, "pyth"))
\r
81 return eScriptPython;
\r
82 if (strstr(s, "javas"))
\r
84 if (strstr(s, "jscr"))
\r
86 if (strstr(s, "php"))
\r
88 if (strstr(s, "xml")) {
\r
89 const char *xml = strstr(s, "xml");
\r
90 for (const char *t=s; t<xml; t++) {
\r
91 if (!IsASpace(*t)) {
\r
101 static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, unsigned int end) {
\r
104 GetTextSegment(styler, start, end, s, sizeof(s));
\r
105 if (0 == strncmp(s, "php", 3)) {
\r
112 static script_type ScriptOfState(int state) {
\r
113 if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
\r
114 return eScriptPython;
\r
115 } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
\r
117 } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
\r
119 } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) {
\r
121 } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) {
\r
122 return eScriptSGML;
\r
123 } else if (state == SCE_H_SGML_BLOCK_DEFAULT) {
\r
124 return eScriptSGMLblock;
\r
126 return eScriptNone;
\r
130 static int statePrintForState(int state, script_mode inScriptType) {
\r
131 int StateToPrint = state;
\r
133 if (state >= SCE_HJ_START) {
\r
134 if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
\r
135 StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON);
\r
136 } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
\r
137 StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS);
\r
138 } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
\r
139 StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS);
\r
143 return StateToPrint;
\r
146 static int stateForPrintState(int StateToPrint) {
\r
149 if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) {
\r
150 state = StateToPrint - SCE_HA_PYTHON;
\r
151 } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) {
\r
152 state = StateToPrint - SCE_HA_VBS;
\r
153 } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) {
\r
154 state = StateToPrint - SCE_HA_JS;
\r
156 state = StateToPrint;
\r
162 static inline bool IsNumber(unsigned int start, Accessor &styler) {
\r
163 return IsADigit(styler[start]) || (styler[start] == '.') ||
\r
164 (styler[start] == '-') || (styler[start] == '#');
\r
167 static inline bool isStringState(int state) {
\r
171 case SCE_HJ_DOUBLESTRING:
\r
172 case SCE_HJ_SINGLESTRING:
\r
173 case SCE_HJA_DOUBLESTRING:
\r
174 case SCE_HJA_SINGLESTRING:
\r
175 case SCE_HB_STRING:
\r
176 case SCE_HBA_STRING:
\r
177 case SCE_HP_STRING:
\r
178 case SCE_HP_CHARACTER:
\r
179 case SCE_HP_TRIPLE:
\r
180 case SCE_HP_TRIPLEDOUBLE:
\r
181 case SCE_HPA_STRING:
\r
182 case SCE_HPA_CHARACTER:
\r
183 case SCE_HPA_TRIPLE:
\r
184 case SCE_HPA_TRIPLEDOUBLE:
\r
185 case SCE_HPHP_HSTRING:
\r
186 case SCE_HPHP_SIMPLESTRING:
\r
187 case SCE_HPHP_HSTRING_VARIABLE:
\r
188 case SCE_HPHP_COMPLEX_VARIABLE:
\r
198 static inline bool stateAllowsTermination(int state) {
\r
199 bool allowTermination = !isStringState(state);
\r
200 if (allowTermination) {
\r
202 case SCE_HB_COMMENTLINE:
\r
203 case SCE_HPHP_COMMENT:
\r
204 case SCE_HP_COMMENTLINE:
\r
205 case SCE_HPA_COMMENTLINE:
\r
206 allowTermination = false;
\r
209 return allowTermination;
\r
212 // not really well done, since it's only comments that should lex the %> and <%
\r
213 static inline bool isCommentASPState(int state) {
\r
217 case SCE_HJ_COMMENT:
\r
218 case SCE_HJ_COMMENTLINE:
\r
219 case SCE_HJ_COMMENTDOC:
\r
220 case SCE_HB_COMMENTLINE:
\r
221 case SCE_HP_COMMENTLINE:
\r
222 case SCE_HPHP_COMMENT:
\r
223 case SCE_HPHP_COMMENTLINE:
\r
233 static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
\r
234 bool wordIsNumber = IsNumber(start, styler);
\r
235 char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
\r
236 if (wordIsNumber) {
\r
237 chAttr = SCE_H_NUMBER;
\r
240 GetTextSegment(styler, start, end, s, sizeof(s));
\r
241 if (keywords.InList(s))
\r
242 chAttr = SCE_H_ATTRIBUTE;
\r
244 if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords)
\r
245 // No keywords -> all are known
\r
246 chAttr = SCE_H_ATTRIBUTE;
\r
247 styler.ColourTo(end, chAttr);
\r
250 static int classifyTagHTML(unsigned int start, unsigned int end,
\r
251 WordList &keywords, Accessor &styler, bool &tagDontFold,
\r
252 bool caseSensitive, bool isXml, bool allowScripts) {
\r
254 // Copy after the '<'
\r
255 unsigned int i = 0;
\r
256 for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) {
\r
257 char ch = styler[cPos];
\r
258 if ((ch != '<') && (ch != '/')) {
\r
259 s[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch));
\r
263 //The following is only a quick hack, to see if this whole thing would work
\r
264 //we first need the tagname with a trailing space...
\r
268 // if the current language is XML, I can fold any tag
\r
269 // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.)
\r
270 //...to find it in the list of no-container-tags
\r
271 tagDontFold = (!isXml) && (NULL != strstr("meta link img area br hr input ", s));
\r
273 //now we can remove the trailing space
\r
276 // No keywords -> all are known
\r
277 // Name of a closing tag starts at s + 1
\r
278 char chAttr = SCE_H_TAGUNKNOWN;
\r
280 chAttr = SCE_H_SGML_DEFAULT;
\r
281 } else if (!keywords || keywords.InList(s[0] == '/' ? s + 1 : s)) {
\r
282 chAttr = SCE_H_TAG;
\r
284 styler.ColourTo(end, chAttr);
\r
285 if (chAttr == SCE_H_TAG) {
\r
286 if (allowScripts && 0 == strcmp(s, "script")) {
\r
287 chAttr = SCE_H_SCRIPT;
\r
288 } else if (!isXml && 0 == strcmp(s, "comment")) {
\r
289 chAttr = SCE_H_COMMENT;
\r
295 static void classifyWordHTJS(unsigned int start, unsigned int end,
\r
296 WordList &keywords, Accessor &styler, script_mode inScriptType) {
\r
297 char chAttr = SCE_HJ_WORD;
\r
298 bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.');
\r
300 chAttr = SCE_HJ_NUMBER;
\r
303 unsigned int i = 0;
\r
304 for (; i < end - start + 1 && i < 30; i++) {
\r
305 s[i] = styler[start + i];
\r
308 if (keywords.InList(s))
\r
309 chAttr = SCE_HJ_KEYWORD;
\r
311 styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
\r
314 static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) {
\r
315 char chAttr = SCE_HB_IDENTIFIER;
\r
316 bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.');
\r
318 chAttr = SCE_HB_NUMBER;
\r
321 GetTextSegment(styler, start, end, s, sizeof(s));
\r
322 if (keywords.InList(s)) {
\r
323 chAttr = SCE_HB_WORD;
\r
324 if (strcmp(s, "rem") == 0)
\r
325 chAttr = SCE_HB_COMMENTLINE;
\r
328 styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
\r
329 if (chAttr == SCE_HB_COMMENTLINE)
\r
330 return SCE_HB_COMMENTLINE;
\r
332 return SCE_HB_DEFAULT;
\r
335 static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType) {
\r
336 bool wordIsNumber = IsADigit(styler[start]);
\r
338 unsigned int i = 0;
\r
339 for (; i < end - start + 1 && i < 30; i++) {
\r
340 s[i] = styler[start + i];
\r
343 char chAttr = SCE_HP_IDENTIFIER;
\r
344 if (0 == strcmp(prevWord, "class"))
\r
345 chAttr = SCE_HP_CLASSNAME;
\r
346 else if (0 == strcmp(prevWord, "def"))
\r
347 chAttr = SCE_HP_DEFNAME;
\r
348 else if (wordIsNumber)
\r
349 chAttr = SCE_HP_NUMBER;
\r
350 else if (keywords.InList(s))
\r
351 chAttr = SCE_HP_WORD;
\r
352 styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
\r
353 strcpy(prevWord, s);
\r
356 // Update the word colour to default or keyword
\r
357 // Called when in a PHP word
\r
358 static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
\r
359 char chAttr = SCE_HPHP_DEFAULT;
\r
360 bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1]));
\r
362 chAttr = SCE_HPHP_NUMBER;
\r
365 GetTextSegment(styler, start, end, s, sizeof(s));
\r
366 if (keywords.InList(s))
\r
367 chAttr = SCE_HPHP_WORD;
\r
369 styler.ColourTo(end, chAttr);
\r
372 static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
\r
374 unsigned int i = 0;
\r
375 for (; i < end - start + 1 && i < 30; i++) {
\r
376 s[i] = styler[start + i];
\r
379 return keywords.InList(s);
\r
382 static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) {
\r
384 unsigned int i = 0;
\r
385 for (; i < end - start + 1 && i < 30; i++) {
\r
386 s[i] = styler[start + i];
\r
389 return (0 == strcmp(s, "[CDATA["));
\r
392 // Return the first state to reach when entering a scripting language
\r
393 static int StateForScript(script_type scriptLanguage) {
\r
395 switch (scriptLanguage) {
\r
397 Result = SCE_HB_START;
\r
399 case eScriptPython:
\r
400 Result = SCE_HP_START;
\r
403 Result = SCE_HPHP_DEFAULT;
\r
406 Result = SCE_H_TAGUNKNOWN;
\r
409 Result = SCE_H_SGML_DEFAULT;
\r
411 case eScriptComment:
\r
412 Result = SCE_H_COMMENT;
\r
415 Result = SCE_HJ_START;
\r
421 static inline bool ishtmlwordchar(int ch) {
\r
422 return !isascii(ch) ||
\r
423 (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#');
\r
426 static inline bool issgmlwordchar(int ch) {
\r
427 return !isascii(ch) ||
\r
428 (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '[');
\r
431 static inline bool IsPhpWordStart(int ch) {
\r
432 return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f);
\r
435 static inline bool IsPhpWordChar(int ch) {
\r
436 return IsADigit(ch) || IsPhpWordStart(ch);
\r
439 static bool InTagState(int state) {
\r
440 return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN ||
\r
441 state == SCE_H_SCRIPT ||
\r
442 state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN ||
\r
443 state == SCE_H_NUMBER || state == SCE_H_OTHER ||
\r
444 state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING;
\r
447 static bool IsCommentState(const int state) {
\r
448 return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT;
\r
451 static bool IsScriptCommentState(const int state) {
\r
452 return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT ||
\r
453 state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE;
\r
456 static bool isLineEnd(int ch) {
\r
457 return ch == '\r' || ch == '\n';
\r
460 static bool isOKBeforeRE(int ch) {
\r
461 return (ch == '(') || (ch == '=') || (ch == ',');
\r
464 static bool isPHPStringState(int state) {
\r
466 (state == SCE_HPHP_HSTRING) ||
\r
467 (state == SCE_HPHP_SIMPLESTRING) ||
\r
468 (state == SCE_HPHP_HSTRING_VARIABLE) ||
\r
469 (state == SCE_HPHP_COMPLEX_VARIABLE);
\r
472 static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler, bool &isSimpleString) {
\r
474 const int beginning = i - 1;
\r
475 bool isValidSimpleString = false;
\r
477 while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t'))
\r
480 char ch = styler.SafeGetCharAt(i);
\r
481 const char chNext = styler.SafeGetCharAt(i + 1);
\r
482 if (!IsPhpWordStart(ch)) {
\r
483 if (ch == '\'' && IsPhpWordStart(chNext)) {
\r
486 isSimpleString = true;
\r
488 phpStringDelimiter[0] = '\0';
\r
492 phpStringDelimiter[0] = ch;
\r
495 for (j = i; j < lengthDoc && !isLineEnd(styler[j]); j++) {
\r
496 if (!IsPhpWordChar(styler[j])) {
\r
497 if (isSimpleString && (styler[j] == '\'') && isLineEnd(styler.SafeGetCharAt(j + 1))) {
\r
498 isValidSimpleString = true;
\r
502 phpStringDelimiter[0] = '\0';
\r
506 if (j - i < phpStringDelimiterSize - 2)
\r
507 phpStringDelimiter[j-i+1] = styler[j];
\r
511 if (isSimpleString && !isValidSimpleString) {
\r
512 phpStringDelimiter[0] = '\0';
\r
515 phpStringDelimiter[j-i+1 - (isSimpleString ? 1 : 0)] = '\0';
\r
519 static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
\r
520 Accessor &styler, bool isXml) {
\r
521 WordList &keywords = *keywordlists[0];
\r
522 WordList &keywords2 = *keywordlists[1];
\r
523 WordList &keywords3 = *keywordlists[2];
\r
524 WordList &keywords4 = *keywordlists[3];
\r
525 WordList &keywords5 = *keywordlists[4];
\r
526 WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords
\r
528 // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
\r
529 styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
\r
530 char prevWord[200];
\r
531 prevWord[0] = '\0';
\r
532 char phpStringDelimiter[200]; // PHP is not limited in length, we are
\r
533 phpStringDelimiter[0] = '\0';
\r
534 int StateToPrint = initStyle;
\r
535 int state = stateForPrintState(StateToPrint);
\r
537 // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen
\r
538 if (InTagState(state)) {
\r
539 while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) {
\r
543 state = SCE_H_DEFAULT;
\r
545 // String can be heredoc, must find a delimiter first. Reread from beginning of line containing the string, to get the correct lineState
\r
546 if (isPHPStringState(state)) {
\r
547 while (startPos > 0 && (isPHPStringState(state) || !isLineEnd(styler[startPos - 1]))) {
\r
550 state = styler.StyleAt(startPos);
\r
553 state = SCE_H_DEFAULT;
\r
555 styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
\r
557 int lineCurrent = styler.GetLine(startPos);
\r
559 if (lineCurrent > 0) {
\r
560 lineState = styler.GetLineState(lineCurrent);
\r
562 // Default client and ASP scripting language is JavaScript
\r
563 lineState = eScriptJS << 8;
\r
564 lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4;
\r
566 script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode
\r
567 bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag
\r
568 bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag
\r
569 bool tagDontFold = false; //some HTML tags should not be folded
\r
570 script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name
\r
571 script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name
\r
572 int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state
\r
574 script_type scriptLanguage = ScriptOfState(state);
\r
575 // If eNonHtmlScript coincides with SCE_H_COMMENT, assume eScriptComment
\r
576 if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) {
\r
577 scriptLanguage = eScriptComment;
\r
580 const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0;
\r
581 const bool fold = foldHTML && styler.GetPropertyInt("fold", 0);
\r
582 const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1);
\r
583 const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
\r
584 const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0;
\r
585 const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0;
\r
586 const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
\r
587 const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0;
\r
589 const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
\r
590 const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true);
\r
591 const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true);
\r
593 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
\r
594 int levelCurrent = levelPrev;
\r
595 int visibleChars = 0;
\r
599 int chPrevNonWhite = ' ';
\r
600 // look back to set chPrevNonWhite properly for better regex colouring
\r
601 if (scriptLanguage == eScriptJS && startPos > 0) {
\r
602 int back = startPos;
\r
605 style = styler.StyleAt(back);
\r
606 if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC)
\r
607 // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
\r
610 if (style == SCE_HJ_SYMBOLS) {
\r
611 chPrevNonWhite = static_cast<unsigned char>(styler.SafeGetCharAt(back));
\r
615 styler.StartSegment(startPos);
\r
616 const int lengthDoc = startPos + length;
\r
617 for (int i = startPos; i < lengthDoc; i++) {
\r
618 const int chPrev2 = chPrev;
\r
620 if (!IsASpace(ch) && state != SCE_HJ_COMMENT &&
\r
621 state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC)
\r
622 chPrevNonWhite = ch;
\r
623 ch = static_cast<unsigned char>(styler[i]);
\r
624 int chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
625 const int chNext2 = static_cast<unsigned char>(styler.SafeGetCharAt(i + 2));
\r
627 // Handle DBCS codepages
\r
628 if (styler.IsLeadByte(static_cast<char>(ch))) {
\r
634 if ((!IsASpace(ch) || !foldCompact) && fold)
\r
637 // decide what is the current state to print (depending of the script tag)
\r
638 StateToPrint = statePrintForState(state, inScriptType);
\r
640 // handle script folding
\r
642 switch (scriptLanguage) {
\r
645 //not currently supported case eScriptVBS:
\r
647 if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) {
\r
648 //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle);
\r
649 //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {
\r
650 if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) {
\r
651 levelCurrent += ((ch == '{') || (ch == '/')) ? 1 : -1;
\r
653 } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) {
\r
657 case eScriptPython:
\r
658 if (state != SCE_HP_COMMENTLINE) {
\r
659 if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) {
\r
661 } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) {
\r
662 // check if the number of tabs is lower than the level
\r
663 int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8;
\r
664 for (int j = 0; Findlevel > 0; j++) {
\r
665 char chTmp = styler.SafeGetCharAt(i + j + 1);
\r
666 if (chTmp == '\t') {
\r
668 } else if (chTmp == ' ') {
\r
675 if (Findlevel > 0) {
\r
676 levelCurrent -= Findlevel / 8;
\r
688 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
\r
689 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
\r
690 // Avoid triggering two times on Dos/Win
\r
691 // New line -> record any line state onto /next/ line
\r
693 int lev = levelPrev;
\r
694 if (visibleChars == 0)
\r
695 lev |= SC_FOLDLEVELWHITEFLAG;
\r
696 if ((levelCurrent > levelPrev) && (visibleChars > 0))
\r
697 lev |= SC_FOLDLEVELHEADERFLAG;
\r
699 styler.SetLevel(lineCurrent, lev);
\r
701 levelPrev = levelCurrent;
\r
704 styler.SetLineState(lineCurrent,
\r
705 ((inScriptType & 0x03) << 0) |
\r
706 ((tagOpened & 0x01) << 2) |
\r
707 ((tagClosing & 0x01) << 3) |
\r
708 ((aspScript & 0x0F) << 4) |
\r
709 ((clientScript & 0x0F) << 8) |
\r
710 ((beforePreProc & 0xFF) << 12));
\r
713 // generic end of script processing
\r
714 else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) {
\r
715 // Check if it's the end of the script tag (or any other HTML tag)
\r
717 // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
\r
718 case SCE_H_DOUBLESTRING:
\r
719 case SCE_H_SINGLESTRING:
\r
720 case SCE_HJ_COMMENT:
\r
721 case SCE_HJ_COMMENTDOC:
\r
722 //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
\r
723 // the end of script marker from some JS interpreters.
\r
724 case SCE_HB_COMMENTLINE:
\r
725 case SCE_HBA_COMMENTLINE:
\r
726 case SCE_HJ_DOUBLESTRING:
\r
727 case SCE_HJ_SINGLESTRING:
\r
729 case SCE_HB_STRING:
\r
730 case SCE_HBA_STRING:
\r
731 case SCE_HP_STRING:
\r
732 case SCE_HP_TRIPLE:
\r
733 case SCE_HP_TRIPLEDOUBLE:
\r
734 case SCE_HPHP_HSTRING:
\r
735 case SCE_HPHP_SIMPLESTRING:
\r
736 case SCE_HPHP_COMMENT:
\r
737 case SCE_HPHP_COMMENTLINE:
\r
740 // check if the closing tag is a script tag
\r
741 if (const char *tag =
\r
742 state == SCE_HJ_COMMENTLINE || isXml ? "script" :
\r
743 state == SCE_H_COMMENT ? "comment" : 0) {
\r
747 chr = static_cast<int>(*tag++);
\r
748 } while (chr != 0 && chr == MakeLowerCase(styler.SafeGetCharAt(j++)));
\r
749 if (chr != 0) break;
\r
751 // closing tag of the script (it's a closing HTML tag anyway)
\r
752 styler.ColourTo(i - 1, StateToPrint);
\r
753 state = SCE_H_TAGUNKNOWN;
\r
754 inScriptType = eHtml;
\r
755 scriptLanguage = eScriptNone;
\r
756 clientScript = eScriptJS;
\r
764 /////////////////////////////////////
\r
765 // handle the start of PHP pre-processor = Non-HTML
\r
766 else if ((state != SCE_H_ASPAT) &&
\r
767 !isPHPStringState(state) &&
\r
768 (state != SCE_HPHP_COMMENT) &&
\r
771 !IsScriptCommentState(state) ) {
\r
772 scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, eScriptPHP);
\r
773 if (scriptLanguage != eScriptPHP && isStringState(state)) continue;
\r
774 styler.ColourTo(i - 1, StateToPrint);
\r
775 beforePreProc = state;
\r
778 i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 6);
\r
779 if (scriptLanguage == eScriptXML)
\r
780 styler.ColourTo(i, SCE_H_XMLSTART);
\r
782 styler.ColourTo(i, SCE_H_QUESTION);
\r
783 state = StateForScript(scriptLanguage);
\r
784 if (inScriptType == eNonHtmlScript)
\r
785 inScriptType = eNonHtmlScriptPreProc;
\r
787 inScriptType = eNonHtmlPreProc;
\r
788 // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
\r
789 if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
\r
792 // should be better
\r
793 ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
\r
797 // handle the start of ASP pre-processor = Non-HTML
\r
798 else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) {
\r
799 styler.ColourTo(i - 1, StateToPrint);
\r
800 beforePreProc = state;
\r
801 if (inScriptType == eNonHtmlScript)
\r
802 inScriptType = eNonHtmlScriptPreProc;
\r
804 inScriptType = eNonHtmlPreProc;
\r
806 if (chNext2 == '@') {
\r
807 i += 2; // place as if it was the second next char treated
\r
809 state = SCE_H_ASPAT;
\r
810 } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) {
\r
811 styler.ColourTo(i + 3, SCE_H_ASP);
\r
812 state = SCE_H_XCCOMMENT;
\r
813 scriptLanguage = eScriptVBS;
\r
816 if (chNext2 == '=') {
\r
817 i += 2; // place as if it was the second next char treated
\r
820 i++; // place as if it was the next char treated
\r
824 state = StateForScript(aspScript);
\r
826 scriptLanguage = eScriptVBS;
\r
827 styler.ColourTo(i, SCE_H_ASP);
\r
828 // fold whole script
\r
829 if (foldHTMLPreprocessor)
\r
831 // should be better
\r
832 ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
\r
836 /////////////////////////////////////
\r
837 // handle the start of SGML language (DTD)
\r
838 else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) &&
\r
841 (StateToPrint != SCE_H_CDATA) &&
\r
842 (!IsCommentState(StateToPrint)) &&
\r
843 (!IsScriptCommentState(StateToPrint)) ) {
\r
844 beforePreProc = state;
\r
845 styler.ColourTo(i - 2, StateToPrint);
\r
846 if ((chNext == '-') && (chNext2 == '-')) {
\r
847 state = SCE_H_COMMENT; // wait for a pending command
\r
848 styler.ColourTo(i + 2, SCE_H_COMMENT);
\r
849 i += 2; // follow styling after the --
\r
850 } else if (isWordCdata(i + 1, i + 7, styler)) {
\r
851 state = SCE_H_CDATA;
\r
853 styler.ColourTo(i, SCE_H_SGML_DEFAULT); // <! is default
\r
854 scriptLanguage = eScriptSGML;
\r
855 state = SCE_H_SGML_COMMAND; // wait for a pending command
\r
857 // fold whole tag (-- when closing the tag)
\r
858 if (foldHTMLPreprocessor)
\r
863 // handle the end of a pre-processor = Non-HTML
\r
865 ((inScriptType == eNonHtmlPreProc)
\r
866 || (inScriptType == eNonHtmlScriptPreProc)) && (
\r
867 ((scriptLanguage != eScriptNone) && stateAllowsTermination(state) && ((ch == '%') || (ch == '?')))
\r
868 ) && (chNext == '>')) ||
\r
869 ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) {
\r
870 if (state == SCE_H_ASPAT) {
\r
871 aspScript = segIsScriptingIndicator(styler,
\r
872 styler.GetStartSegment(), i - 1, aspScript);
\r
874 // Bounce out of any ASP mode
\r
877 classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
\r
880 classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
\r
883 classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
\r
885 case SCE_HPHP_WORD:
\r
886 classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
\r
888 case SCE_H_XCCOMMENT:
\r
889 styler.ColourTo(i - 1, state);
\r
892 styler.ColourTo(i - 1, StateToPrint);
\r
895 if (scriptLanguage != eScriptSGML) {
\r
900 styler.ColourTo(i, SCE_H_ASP);
\r
901 else if (scriptLanguage == eScriptXML)
\r
902 styler.ColourTo(i, SCE_H_XMLEND);
\r
903 else if (scriptLanguage == eScriptSGML)
\r
904 styler.ColourTo(i, SCE_H_SGML_DEFAULT);
\r
906 styler.ColourTo(i, SCE_H_QUESTION);
\r
907 state = beforePreProc;
\r
908 if (inScriptType == eNonHtmlScriptPreProc)
\r
909 inScriptType = eNonHtmlScript;
\r
911 inScriptType = eHtml;
\r
912 // Unfold all scripting languages, except for XML tag
\r
913 if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
\r
916 scriptLanguage = eScriptNone;
\r
919 /////////////////////////////////////
\r
922 case SCE_H_DEFAULT:
\r
924 // in HTML, fold on tag open and unfold on tag close
\r
926 tagClosing = (chNext == '/');
\r
927 styler.ColourTo(i - 1, StateToPrint);
\r
929 state = SCE_H_TAGUNKNOWN;
\r
930 } else if (ch == '&') {
\r
931 styler.ColourTo(i - 1, SCE_H_DEFAULT);
\r
932 state = SCE_H_ENTITY;
\r
935 case SCE_H_SGML_DEFAULT:
\r
936 case SCE_H_SGML_BLOCK_DEFAULT:
\r
937 // if (scriptLanguage == eScriptSGMLblock)
\r
938 // StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
\r
941 styler.ColourTo(i - 1, StateToPrint);
\r
942 state = SCE_H_SGML_DOUBLESTRING;
\r
943 } else if (ch == '\'') {
\r
944 styler.ColourTo(i - 1, StateToPrint);
\r
945 state = SCE_H_SGML_SIMPLESTRING;
\r
946 } else if ((ch == '-') && (chPrev == '-')) {
\r
947 if (static_cast<int>(styler.GetStartSegment()) <= (i - 2)) {
\r
948 styler.ColourTo(i - 2, StateToPrint);
\r
950 state = SCE_H_SGML_COMMENT;
\r
951 } else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) {
\r
952 styler.ColourTo(i - 2, StateToPrint);
\r
953 state = SCE_H_SGML_ENTITY;
\r
954 } else if (ch == '#') {
\r
955 styler.ColourTo(i - 1, StateToPrint);
\r
956 state = SCE_H_SGML_SPECIAL;
\r
957 } else if (ch == '[') {
\r
958 styler.ColourTo(i - 1, StateToPrint);
\r
959 scriptLanguage = eScriptSGMLblock;
\r
960 state = SCE_H_SGML_BLOCK_DEFAULT;
\r
961 } else if (ch == ']') {
\r
962 if (scriptLanguage == eScriptSGMLblock) {
\r
963 styler.ColourTo(i, StateToPrint);
\r
964 scriptLanguage = eScriptSGML;
\r
966 styler.ColourTo(i - 1, StateToPrint);
\r
967 styler.ColourTo(i, SCE_H_SGML_ERROR);
\r
969 state = SCE_H_SGML_DEFAULT;
\r
970 } else if (scriptLanguage == eScriptSGMLblock) {
\r
971 if ((ch == '!') && (chPrev == '<')) {
\r
972 styler.ColourTo(i - 2, StateToPrint);
\r
973 styler.ColourTo(i, SCE_H_SGML_DEFAULT);
\r
974 state = SCE_H_SGML_COMMAND;
\r
975 } else if (ch == '>') {
\r
976 styler.ColourTo(i - 1, StateToPrint);
\r
977 styler.ColourTo(i, SCE_H_SGML_DEFAULT);
\r
981 case SCE_H_SGML_COMMAND:
\r
982 if ((ch == '-') && (chPrev == '-')) {
\r
983 styler.ColourTo(i - 2, StateToPrint);
\r
984 state = SCE_H_SGML_COMMENT;
\r
985 } else if (!issgmlwordchar(ch)) {
\r
986 if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) {
\r
987 styler.ColourTo(i - 1, StateToPrint);
\r
988 state = SCE_H_SGML_1ST_PARAM;
\r
990 state = SCE_H_SGML_ERROR;
\r
994 case SCE_H_SGML_1ST_PARAM:
\r
995 // wait for the beginning of the word
\r
996 if ((ch == '-') && (chPrev == '-')) {
\r
997 if (scriptLanguage == eScriptSGMLblock) {
\r
998 styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT);
\r
1000 styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT);
\r
1002 state = SCE_H_SGML_1ST_PARAM_COMMENT;
\r
1003 } else if (issgmlwordchar(ch)) {
\r
1004 if (scriptLanguage == eScriptSGMLblock) {
\r
1005 styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT);
\r
1007 styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT);
\r
1009 // find the length of the word
\r
1011 while (setHTMLWord.Contains(static_cast<unsigned char>(styler.SafeGetCharAt(i + size))))
\r
1013 styler.ColourTo(i + size - 1, StateToPrint);
\r
1015 visibleChars += size - 1;
\r
1016 ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
\r
1017 if (scriptLanguage == eScriptSGMLblock) {
\r
1018 state = SCE_H_SGML_BLOCK_DEFAULT;
\r
1020 state = SCE_H_SGML_DEFAULT;
\r
1025 case SCE_H_SGML_ERROR:
\r
1026 if ((ch == '-') && (chPrev == '-')) {
\r
1027 styler.ColourTo(i - 2, StateToPrint);
\r
1028 state = SCE_H_SGML_COMMENT;
\r
1030 case SCE_H_SGML_DOUBLESTRING:
\r
1032 styler.ColourTo(i, StateToPrint);
\r
1033 state = SCE_H_SGML_DEFAULT;
\r
1036 case SCE_H_SGML_SIMPLESTRING:
\r
1038 styler.ColourTo(i, StateToPrint);
\r
1039 state = SCE_H_SGML_DEFAULT;
\r
1042 case SCE_H_SGML_COMMENT:
\r
1043 if ((ch == '-') && (chPrev == '-')) {
\r
1044 styler.ColourTo(i, StateToPrint);
\r
1045 state = SCE_H_SGML_DEFAULT;
\r
1049 if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) {
\r
1050 styler.ColourTo(i, StateToPrint);
\r
1051 state = SCE_H_DEFAULT;
\r
1055 case SCE_H_COMMENT:
\r
1056 if ((scriptLanguage != eScriptComment) && (chPrev2 == '-') && (chPrev == '-') && (ch == '>')) {
\r
1057 styler.ColourTo(i, StateToPrint);
\r
1058 state = SCE_H_DEFAULT;
\r
1062 case SCE_H_SGML_1ST_PARAM_COMMENT:
\r
1063 if ((ch == '-') && (chPrev == '-')) {
\r
1064 styler.ColourTo(i, SCE_H_SGML_COMMENT);
\r
1065 state = SCE_H_SGML_1ST_PARAM;
\r
1068 case SCE_H_SGML_SPECIAL:
\r
1069 if (!(isascii(ch) && isupper(ch))) {
\r
1070 styler.ColourTo(i - 1, StateToPrint);
\r
1071 if (isalnum(ch)) {
\r
1072 state = SCE_H_SGML_ERROR;
\r
1074 state = SCE_H_SGML_DEFAULT;
\r
1078 case SCE_H_SGML_ENTITY:
\r
1080 styler.ColourTo(i, StateToPrint);
\r
1081 state = SCE_H_SGML_DEFAULT;
\r
1082 } else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') {
\r
1083 styler.ColourTo(i, SCE_H_SGML_ERROR);
\r
1084 state = SCE_H_SGML_DEFAULT;
\r
1087 case SCE_H_ENTITY:
\r
1089 styler.ColourTo(i, StateToPrint);
\r
1090 state = SCE_H_DEFAULT;
\r
1092 if (ch != '#' && !(isascii(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway...
\r
1093 && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML
\r
1094 styler.ColourTo(i, SCE_H_TAGUNKNOWN);
\r
1095 state = SCE_H_DEFAULT;
\r
1098 case SCE_H_TAGUNKNOWN:
\r
1099 if (!setTagContinue.Contains(ch) && !((ch == '/') && (chPrev == '<'))) {
\r
1100 int eClass = classifyTagHTML(styler.GetStartSegment(),
\r
1101 i - 1, keywords, styler, tagDontFold, caseSensitive, isXml, allowScripts);
\r
1102 if (eClass == SCE_H_SCRIPT || eClass == SCE_H_COMMENT) {
\r
1103 if (!tagClosing) {
\r
1104 inScriptType = eNonHtmlScript;
\r
1105 scriptLanguage = eClass == SCE_H_SCRIPT ? clientScript : eScriptComment;
\r
1107 scriptLanguage = eScriptNone;
\r
1109 eClass = SCE_H_TAG;
\r
1112 styler.ColourTo(i, eClass);
\r
1113 if (inScriptType == eNonHtmlScript) {
\r
1114 state = StateForScript(scriptLanguage);
\r
1116 state = SCE_H_DEFAULT;
\r
1118 tagOpened = false;
\r
1119 if (!tagDontFold) {
\r
1126 tagClosing = false;
\r
1127 } else if (ch == '/' && chNext == '>') {
\r
1128 if (eClass == SCE_H_TAGUNKNOWN) {
\r
1129 styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN);
\r
1131 styler.ColourTo(i - 1, StateToPrint);
\r
1132 styler.ColourTo(i + 1, SCE_H_TAGEND);
\r
1136 state = SCE_H_DEFAULT;
\r
1137 tagOpened = false;
\r
1139 if (eClass != SCE_H_TAGUNKNOWN) {
\r
1140 if (eClass == SCE_H_SGML_DEFAULT) {
\r
1141 state = SCE_H_SGML_DEFAULT;
\r
1143 state = SCE_H_OTHER;
\r
1149 case SCE_H_ATTRIBUTE:
\r
1150 if (!setAttributeContinue.Contains(ch)) {
\r
1151 if (inScriptType == eNonHtmlScript) {
\r
1152 int scriptLanguagePrev = scriptLanguage;
\r
1153 clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage);
\r
1154 scriptLanguage = clientScript;
\r
1155 if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone))
\r
1156 inScriptType = eHtml;
\r
1158 classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
\r
1160 styler.ColourTo(i, SCE_H_TAG);
\r
1161 if (inScriptType == eNonHtmlScript) {
\r
1162 state = StateForScript(scriptLanguage);
\r
1164 state = SCE_H_DEFAULT;
\r
1166 tagOpened = false;
\r
1167 if (!tagDontFold) {
\r
1174 tagClosing = false;
\r
1175 } else if (ch == '=') {
\r
1176 styler.ColourTo(i, SCE_H_OTHER);
\r
1177 state = SCE_H_VALUE;
\r
1179 state = SCE_H_OTHER;
\r
1185 styler.ColourTo(i - 1, StateToPrint);
\r
1186 styler.ColourTo(i, SCE_H_TAG);
\r
1187 if (inScriptType == eNonHtmlScript) {
\r
1188 state = StateForScript(scriptLanguage);
\r
1190 state = SCE_H_DEFAULT;
\r
1192 tagOpened = false;
\r
1193 if (!tagDontFold) {
\r
1200 tagClosing = false;
\r
1201 } else if (ch == '\"') {
\r
1202 styler.ColourTo(i - 1, StateToPrint);
\r
1203 state = SCE_H_DOUBLESTRING;
\r
1204 } else if (ch == '\'') {
\r
1205 styler.ColourTo(i - 1, StateToPrint);
\r
1206 state = SCE_H_SINGLESTRING;
\r
1207 } else if (ch == '=') {
\r
1208 styler.ColourTo(i, StateToPrint);
\r
1209 state = SCE_H_VALUE;
\r
1210 } else if (ch == '/' && chNext == '>') {
\r
1211 styler.ColourTo(i - 1, StateToPrint);
\r
1212 styler.ColourTo(i + 1, SCE_H_TAGEND);
\r
1215 state = SCE_H_DEFAULT;
\r
1216 tagOpened = false;
\r
1217 } else if (ch == '?' && chNext == '>') {
\r
1218 styler.ColourTo(i - 1, StateToPrint);
\r
1219 styler.ColourTo(i + 1, SCE_H_XMLEND);
\r
1222 state = SCE_H_DEFAULT;
\r
1223 } else if (setHTMLWord.Contains(ch)) {
\r
1224 styler.ColourTo(i - 1, StateToPrint);
\r
1225 state = SCE_H_ATTRIBUTE;
\r
1228 case SCE_H_DOUBLESTRING:
\r
1230 if (inScriptType == eNonHtmlScript) {
\r
1231 scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
\r
1233 styler.ColourTo(i, SCE_H_DOUBLESTRING);
\r
1234 state = SCE_H_OTHER;
\r
1237 case SCE_H_SINGLESTRING:
\r
1239 if (inScriptType == eNonHtmlScript) {
\r
1240 scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
\r
1242 styler.ColourTo(i, SCE_H_SINGLESTRING);
\r
1243 state = SCE_H_OTHER;
\r
1247 if (!setHTMLWord.Contains(ch)) {
\r
1248 if (ch == '\"' && chPrev == '=') {
\r
1249 // Should really test for being first character
\r
1250 state = SCE_H_DOUBLESTRING;
\r
1251 } else if (ch == '\'' && chPrev == '=') {
\r
1252 state = SCE_H_SINGLESTRING;
\r
1254 if (IsNumber(styler.GetStartSegment(), styler)) {
\r
1255 styler.ColourTo(i - 1, SCE_H_NUMBER);
\r
1257 styler.ColourTo(i - 1, StateToPrint);
\r
1260 styler.ColourTo(i, SCE_H_TAG);
\r
1261 if (inScriptType == eNonHtmlScript) {
\r
1262 state = StateForScript(scriptLanguage);
\r
1264 state = SCE_H_DEFAULT;
\r
1266 tagOpened = false;
\r
1267 if (!tagDontFold) {
\r
1274 tagClosing = false;
\r
1276 state = SCE_H_OTHER;
\r
1281 case SCE_HJ_DEFAULT:
\r
1282 case SCE_HJ_START:
\r
1283 case SCE_HJ_SYMBOLS:
\r
1284 if (IsAWordStart(ch)) {
\r
1285 styler.ColourTo(i - 1, StateToPrint);
\r
1286 state = SCE_HJ_WORD;
\r
1287 } else if (ch == '/' && chNext == '*') {
\r
1288 styler.ColourTo(i - 1, StateToPrint);
\r
1289 if (chNext2 == '*')
\r
1290 state = SCE_HJ_COMMENTDOC;
\r
1292 state = SCE_HJ_COMMENT;
\r
1293 } else if (ch == '/' && chNext == '/') {
\r
1294 styler.ColourTo(i - 1, StateToPrint);
\r
1295 state = SCE_HJ_COMMENTLINE;
\r
1296 } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
\r
1297 styler.ColourTo(i - 1, StateToPrint);
\r
1298 state = SCE_HJ_REGEX;
\r
1299 } else if (ch == '\"') {
\r
1300 styler.ColourTo(i - 1, StateToPrint);
\r
1301 state = SCE_HJ_DOUBLESTRING;
\r
1302 } else if (ch == '\'') {
\r
1303 styler.ColourTo(i - 1, StateToPrint);
\r
1304 state = SCE_HJ_SINGLESTRING;
\r
1305 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
\r
1306 styler.SafeGetCharAt(i + 3) == '-') {
\r
1307 styler.ColourTo(i - 1, StateToPrint);
\r
1308 state = SCE_HJ_COMMENTLINE;
\r
1309 } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
\r
1310 styler.ColourTo(i - 1, StateToPrint);
\r
1311 state = SCE_HJ_COMMENTLINE;
\r
1313 } else if (IsOperator(ch)) {
\r
1314 styler.ColourTo(i - 1, StateToPrint);
\r
1315 styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
\r
1316 state = SCE_HJ_DEFAULT;
\r
1317 } else if ((ch == ' ') || (ch == '\t')) {
\r
1318 if (state == SCE_HJ_START) {
\r
1319 styler.ColourTo(i - 1, StateToPrint);
\r
1320 state = SCE_HJ_DEFAULT;
\r
1325 if (!IsAWordChar(ch)) {
\r
1326 classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
\r
1327 //styler.ColourTo(i - 1, eHTJSKeyword);
\r
1328 state = SCE_HJ_DEFAULT;
\r
1329 if (ch == '/' && chNext == '*') {
\r
1330 if (chNext2 == '*')
\r
1331 state = SCE_HJ_COMMENTDOC;
\r
1333 state = SCE_HJ_COMMENT;
\r
1334 } else if (ch == '/' && chNext == '/') {
\r
1335 state = SCE_HJ_COMMENTLINE;
\r
1336 } else if (ch == '\"') {
\r
1337 state = SCE_HJ_DOUBLESTRING;
\r
1338 } else if (ch == '\'') {
\r
1339 state = SCE_HJ_SINGLESTRING;
\r
1340 } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
\r
1341 styler.ColourTo(i - 1, StateToPrint);
\r
1342 state = SCE_HJ_COMMENTLINE;
\r
1344 } else if (IsOperator(ch)) {
\r
1345 styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
\r
1346 state = SCE_HJ_DEFAULT;
\r
1350 case SCE_HJ_COMMENT:
\r
1351 case SCE_HJ_COMMENTDOC:
\r
1352 if (ch == '/' && chPrev == '*') {
\r
1353 styler.ColourTo(i, StateToPrint);
\r
1354 state = SCE_HJ_DEFAULT;
\r
1358 case SCE_HJ_COMMENTLINE:
\r
1359 if (ch == '\r' || ch == '\n') {
\r
1360 styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType));
\r
1361 state = SCE_HJ_DEFAULT;
\r
1365 case SCE_HJ_DOUBLESTRING:
\r
1367 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
\r
1370 } else if (ch == '\"') {
\r
1371 styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType));
\r
1372 state = SCE_HJ_DEFAULT;
\r
1373 } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
\r
1374 styler.ColourTo(i - 1, StateToPrint);
\r
1375 state = SCE_HJ_COMMENTLINE;
\r
1377 } else if (isLineEnd(ch)) {
\r
1378 styler.ColourTo(i - 1, StateToPrint);
\r
1379 state = SCE_HJ_STRINGEOL;
\r
1382 case SCE_HJ_SINGLESTRING:
\r
1384 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
\r
1387 } else if (ch == '\'') {
\r
1388 styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType));
\r
1389 state = SCE_HJ_DEFAULT;
\r
1390 } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
\r
1391 styler.ColourTo(i - 1, StateToPrint);
\r
1392 state = SCE_HJ_COMMENTLINE;
\r
1394 } else if (isLineEnd(ch)) {
\r
1395 styler.ColourTo(i - 1, StateToPrint);
\r
1396 state = SCE_HJ_STRINGEOL;
\r
1399 case SCE_HJ_STRINGEOL:
\r
1400 if (!isLineEnd(ch)) {
\r
1401 styler.ColourTo(i - 1, StateToPrint);
\r
1402 state = SCE_HJ_DEFAULT;
\r
1403 } else if (!isLineEnd(chNext)) {
\r
1404 styler.ColourTo(i, StateToPrint);
\r
1405 state = SCE_HJ_DEFAULT;
\r
1408 case SCE_HJ_REGEX:
\r
1409 if (ch == '\r' || ch == '\n' || ch == '/') {
\r
1411 while (isascii(chNext) && islower(chNext)) { // gobble regex flags
\r
1414 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1417 styler.ColourTo(i, StateToPrint);
\r
1418 state = SCE_HJ_DEFAULT;
\r
1419 } else if (ch == '\\') {
\r
1420 // Gobble up the quoted character
\r
1421 if (chNext == '\\' || chNext == '/') {
\r
1424 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1428 case SCE_HB_DEFAULT:
\r
1429 case SCE_HB_START:
\r
1430 if (IsAWordStart(ch)) {
\r
1431 styler.ColourTo(i - 1, StateToPrint);
\r
1432 state = SCE_HB_WORD;
\r
1433 } else if (ch == '\'') {
\r
1434 styler.ColourTo(i - 1, StateToPrint);
\r
1435 state = SCE_HB_COMMENTLINE;
\r
1436 } else if (ch == '\"') {
\r
1437 styler.ColourTo(i - 1, StateToPrint);
\r
1438 state = SCE_HB_STRING;
\r
1439 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
\r
1440 styler.SafeGetCharAt(i + 3) == '-') {
\r
1441 styler.ColourTo(i - 1, StateToPrint);
\r
1442 state = SCE_HB_COMMENTLINE;
\r
1443 } else if (IsOperator(ch)) {
\r
1444 styler.ColourTo(i - 1, StateToPrint);
\r
1445 styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
\r
1446 state = SCE_HB_DEFAULT;
\r
1447 } else if ((ch == ' ') || (ch == '\t')) {
\r
1448 if (state == SCE_HB_START) {
\r
1449 styler.ColourTo(i - 1, StateToPrint);
\r
1450 state = SCE_HB_DEFAULT;
\r
1455 if (!IsAWordChar(ch)) {
\r
1456 state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
\r
1457 if (state == SCE_HB_DEFAULT) {
\r
1459 state = SCE_HB_STRING;
\r
1460 } else if (ch == '\'') {
\r
1461 state = SCE_HB_COMMENTLINE;
\r
1462 } else if (IsOperator(ch)) {
\r
1463 styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
\r
1464 state = SCE_HB_DEFAULT;
\r
1469 case SCE_HB_STRING:
\r
1471 styler.ColourTo(i, StateToPrint);
\r
1472 state = SCE_HB_DEFAULT;
\r
1473 } else if (ch == '\r' || ch == '\n') {
\r
1474 styler.ColourTo(i - 1, StateToPrint);
\r
1475 state = SCE_HB_STRINGEOL;
\r
1478 case SCE_HB_COMMENTLINE:
\r
1479 if (ch == '\r' || ch == '\n') {
\r
1480 styler.ColourTo(i - 1, StateToPrint);
\r
1481 state = SCE_HB_DEFAULT;
\r
1484 case SCE_HB_STRINGEOL:
\r
1485 if (!isLineEnd(ch)) {
\r
1486 styler.ColourTo(i - 1, StateToPrint);
\r
1487 state = SCE_HB_DEFAULT;
\r
1488 } else if (!isLineEnd(chNext)) {
\r
1489 styler.ColourTo(i, StateToPrint);
\r
1490 state = SCE_HB_DEFAULT;
\r
1493 case SCE_HP_DEFAULT:
\r
1494 case SCE_HP_START:
\r
1495 if (IsAWordStart(ch)) {
\r
1496 styler.ColourTo(i - 1, StateToPrint);
\r
1497 state = SCE_HP_WORD;
\r
1498 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
\r
1499 styler.SafeGetCharAt(i + 3) == '-') {
\r
1500 styler.ColourTo(i - 1, StateToPrint);
\r
1501 state = SCE_HP_COMMENTLINE;
\r
1502 } else if (ch == '#') {
\r
1503 styler.ColourTo(i - 1, StateToPrint);
\r
1504 state = SCE_HP_COMMENTLINE;
\r
1505 } else if (ch == '\"') {
\r
1506 styler.ColourTo(i - 1, StateToPrint);
\r
1507 if (chNext == '\"' && chNext2 == '\"') {
\r
1509 state = SCE_HP_TRIPLEDOUBLE;
\r
1512 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1514 // state = statePrintForState(SCE_HP_STRING,inScriptType);
\r
1515 state = SCE_HP_STRING;
\r
1517 } else if (ch == '\'') {
\r
1518 styler.ColourTo(i - 1, StateToPrint);
\r
1519 if (chNext == '\'' && chNext2 == '\'') {
\r
1521 state = SCE_HP_TRIPLE;
\r
1524 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1526 state = SCE_HP_CHARACTER;
\r
1528 } else if (IsOperator(ch)) {
\r
1529 styler.ColourTo(i - 1, StateToPrint);
\r
1530 styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
\r
1531 } else if ((ch == ' ') || (ch == '\t')) {
\r
1532 if (state == SCE_HP_START) {
\r
1533 styler.ColourTo(i - 1, StateToPrint);
\r
1534 state = SCE_HP_DEFAULT;
\r
1539 if (!IsAWordChar(ch)) {
\r
1540 classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
\r
1541 state = SCE_HP_DEFAULT;
\r
1543 state = SCE_HP_COMMENTLINE;
\r
1544 } else if (ch == '\"') {
\r
1545 if (chNext == '\"' && chNext2 == '\"') {
\r
1547 state = SCE_HP_TRIPLEDOUBLE;
\r
1550 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1552 state = SCE_HP_STRING;
\r
1554 } else if (ch == '\'') {
\r
1555 if (chNext == '\'' && chNext2 == '\'') {
\r
1557 state = SCE_HP_TRIPLE;
\r
1560 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1562 state = SCE_HP_CHARACTER;
\r
1564 } else if (IsOperator(ch)) {
\r
1565 styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
\r
1569 case SCE_HP_COMMENTLINE:
\r
1570 if (ch == '\r' || ch == '\n') {
\r
1571 styler.ColourTo(i - 1, StateToPrint);
\r
1572 state = SCE_HP_DEFAULT;
\r
1575 case SCE_HP_STRING:
\r
1577 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
\r
1580 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1582 } else if (ch == '\"') {
\r
1583 styler.ColourTo(i, StateToPrint);
\r
1584 state = SCE_HP_DEFAULT;
\r
1587 case SCE_HP_CHARACTER:
\r
1589 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
\r
1592 chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
\r
1594 } else if (ch == '\'') {
\r
1595 styler.ColourTo(i, StateToPrint);
\r
1596 state = SCE_HP_DEFAULT;
\r
1599 case SCE_HP_TRIPLE:
\r
1600 if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
\r
1601 styler.ColourTo(i, StateToPrint);
\r
1602 state = SCE_HP_DEFAULT;
\r
1605 case SCE_HP_TRIPLEDOUBLE:
\r
1606 if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
\r
1607 styler.ColourTo(i, StateToPrint);
\r
1608 state = SCE_HP_DEFAULT;
\r
1611 ///////////// start - PHP state handling
\r
1612 case SCE_HPHP_WORD:
\r
1613 if (!IsAWordChar(ch)) {
\r
1614 classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
\r
1615 if (ch == '/' && chNext == '*') {
\r
1617 state = SCE_HPHP_COMMENT;
\r
1618 } else if (ch == '/' && chNext == '/') {
\r
1620 state = SCE_HPHP_COMMENTLINE;
\r
1621 } else if (ch == '#') {
\r
1622 state = SCE_HPHP_COMMENTLINE;
\r
1623 } else if (ch == '\"') {
\r
1624 state = SCE_HPHP_HSTRING;
\r
1625 strcpy(phpStringDelimiter, "\"");
\r
1626 } else if (styler.Match(i, "<<<")) {
\r
1627 bool isSimpleString = false;
\r
1628 i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
\r
1629 if (strlen(phpStringDelimiter)) {
\r
1630 state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
\r
1631 if (foldHeredoc) levelCurrent++;
\r
1633 } else if (ch == '\'') {
\r
1634 state = SCE_HPHP_SIMPLESTRING;
\r
1635 strcpy(phpStringDelimiter, "\'");
\r
1636 } else if (ch == '$' && IsPhpWordStart(chNext)) {
\r
1637 state = SCE_HPHP_VARIABLE;
\r
1638 } else if (IsOperator(ch)) {
\r
1639 state = SCE_HPHP_OPERATOR;
\r
1641 state = SCE_HPHP_DEFAULT;
\r
1645 case SCE_HPHP_NUMBER:
\r
1646 // recognize bases 8,10 or 16 integers OR floating-point numbers
\r
1648 && strchr(".xXabcdefABCDEF", ch) == NULL
\r
1649 && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) {
\r
1650 styler.ColourTo(i - 1, SCE_HPHP_NUMBER);
\r
1651 if (IsOperator(ch))
\r
1652 state = SCE_HPHP_OPERATOR;
\r
1654 state = SCE_HPHP_DEFAULT;
\r
1657 case SCE_HPHP_VARIABLE:
\r
1658 if (!IsPhpWordChar(chNext)) {
\r
1659 styler.ColourTo(i, SCE_HPHP_VARIABLE);
\r
1660 state = SCE_HPHP_DEFAULT;
\r
1663 case SCE_HPHP_COMMENT:
\r
1664 if (ch == '/' && chPrev == '*') {
\r
1665 styler.ColourTo(i, StateToPrint);
\r
1666 state = SCE_HPHP_DEFAULT;
\r
1669 case SCE_HPHP_COMMENTLINE:
\r
1670 if (ch == '\r' || ch == '\n') {
\r
1671 styler.ColourTo(i - 1, StateToPrint);
\r
1672 state = SCE_HPHP_DEFAULT;
\r
1675 case SCE_HPHP_HSTRING:
\r
1676 if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) {
\r
1677 // skip the next char
\r
1679 } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{'))
\r
1680 && IsPhpWordStart(chNext2)) {
\r
1681 styler.ColourTo(i - 1, StateToPrint);
\r
1682 state = SCE_HPHP_COMPLEX_VARIABLE;
\r
1683 } else if (ch == '$' && IsPhpWordStart(chNext)) {
\r
1684 styler.ColourTo(i - 1, StateToPrint);
\r
1685 state = SCE_HPHP_HSTRING_VARIABLE;
\r
1686 } else if (styler.Match(i, phpStringDelimiter)) {
\r
1687 if (phpStringDelimiter[0] == '\"') {
\r
1688 styler.ColourTo(i, StateToPrint);
\r
1689 state = SCE_HPHP_DEFAULT;
\r
1690 } else if (isLineEnd(chPrev)) {
\r
1691 const int psdLength = strlen(phpStringDelimiter);
\r
1692 const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
\r
1693 const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
\r
1694 if (isLineEnd(chAfterPsd) ||
\r
1695 (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
\r
1696 i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
\r
1697 styler.ColourTo(i, StateToPrint);
\r
1698 state = SCE_HPHP_DEFAULT;
\r
1699 if (foldHeredoc) levelCurrent--;
\r
1704 case SCE_HPHP_SIMPLESTRING:
\r
1705 if (phpStringDelimiter[0] == '\'') {
\r
1707 // skip the next char
\r
1709 } else if (ch == '\'') {
\r
1710 styler.ColourTo(i, StateToPrint);
\r
1711 state = SCE_HPHP_DEFAULT;
\r
1713 } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) {
\r
1714 const int psdLength = strlen(phpStringDelimiter);
\r
1715 const char chAfterPsd = styler.SafeGetCharAt(i + psdLength);
\r
1716 const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1);
\r
1717 if (isLineEnd(chAfterPsd) ||
\r
1718 (chAfterPsd == ';' && isLineEnd(chAfterPsd2))) {
\r
1719 i += (((i + psdLength) < lengthDoc) ? psdLength : lengthDoc) - 1;
\r
1720 styler.ColourTo(i, StateToPrint);
\r
1721 state = SCE_HPHP_DEFAULT;
\r
1722 if (foldHeredoc) levelCurrent--;
\r
1726 case SCE_HPHP_HSTRING_VARIABLE:
\r
1727 if (!IsPhpWordChar(chNext)) {
\r
1728 styler.ColourTo(i, StateToPrint);
\r
1729 state = SCE_HPHP_HSTRING;
\r
1732 case SCE_HPHP_COMPLEX_VARIABLE:
\r
1734 styler.ColourTo(i, StateToPrint);
\r
1735 state = SCE_HPHP_HSTRING;
\r
1738 case SCE_HPHP_OPERATOR:
\r
1739 case SCE_HPHP_DEFAULT:
\r
1740 styler.ColourTo(i - 1, StateToPrint);
\r
1741 if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) {
\r
1742 state = SCE_HPHP_NUMBER;
\r
1743 } else if (IsAWordStart(ch)) {
\r
1744 state = SCE_HPHP_WORD;
\r
1745 } else if (ch == '/' && chNext == '*') {
\r
1747 state = SCE_HPHP_COMMENT;
\r
1748 } else if (ch == '/' && chNext == '/') {
\r
1750 state = SCE_HPHP_COMMENTLINE;
\r
1751 } else if (ch == '#') {
\r
1752 state = SCE_HPHP_COMMENTLINE;
\r
1753 } else if (ch == '\"') {
\r
1754 state = SCE_HPHP_HSTRING;
\r
1755 strcpy(phpStringDelimiter, "\"");
\r
1756 } else if (styler.Match(i, "<<<")) {
\r
1757 bool isSimpleString = false;
\r
1758 i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler, isSimpleString);
\r
1759 if (strlen(phpStringDelimiter)) {
\r
1760 state = (isSimpleString ? SCE_HPHP_SIMPLESTRING : SCE_HPHP_HSTRING);
\r
1761 if (foldHeredoc) levelCurrent++;
\r
1763 } else if (ch == '\'') {
\r
1764 state = SCE_HPHP_SIMPLESTRING;
\r
1765 strcpy(phpStringDelimiter, "\'");
\r
1766 } else if (ch == '$' && IsPhpWordStart(chNext)) {
\r
1767 state = SCE_HPHP_VARIABLE;
\r
1768 } else if (IsOperator(ch)) {
\r
1769 state = SCE_HPHP_OPERATOR;
\r
1770 } else if ((state == SCE_HPHP_OPERATOR) && (IsASpace(ch))) {
\r
1771 state = SCE_HPHP_DEFAULT;
\r
1774 ///////////// end - PHP state handling
\r
1777 // Some of the above terminated their lexeme but since the same character starts
\r
1778 // the same class again, only reenter if non empty segment.
\r
1780 bool nonEmptySegment = i >= static_cast<int>(styler.GetStartSegment());
\r
1781 if (state == SCE_HB_DEFAULT) { // One of the above succeeded
\r
1782 if ((ch == '\"') && (nonEmptySegment)) {
\r
1783 state = SCE_HB_STRING;
\r
1784 } else if (ch == '\'') {
\r
1785 state = SCE_HB_COMMENTLINE;
\r
1786 } else if (IsAWordStart(ch)) {
\r
1787 state = SCE_HB_WORD;
\r
1788 } else if (IsOperator(ch)) {
\r
1789 styler.ColourTo(i, SCE_HB_DEFAULT);
\r
1791 } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded
\r
1792 if ((ch == '\"') && (nonEmptySegment)) {
\r
1793 state = SCE_HBA_STRING;
\r
1794 } else if (ch == '\'') {
\r
1795 state = SCE_HBA_COMMENTLINE;
\r
1796 } else if (IsAWordStart(ch)) {
\r
1797 state = SCE_HBA_WORD;
\r
1798 } else if (IsOperator(ch)) {
\r
1799 styler.ColourTo(i, SCE_HBA_DEFAULT);
\r
1801 } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded
\r
1802 if (ch == '/' && chNext == '*') {
\r
1803 if (styler.SafeGetCharAt(i + 2) == '*')
\r
1804 state = SCE_HJ_COMMENTDOC;
\r
1806 state = SCE_HJ_COMMENT;
\r
1807 } else if (ch == '/' && chNext == '/') {
\r
1808 state = SCE_HJ_COMMENTLINE;
\r
1809 } else if ((ch == '\"') && (nonEmptySegment)) {
\r
1810 state = SCE_HJ_DOUBLESTRING;
\r
1811 } else if ((ch == '\'') && (nonEmptySegment)) {
\r
1812 state = SCE_HJ_SINGLESTRING;
\r
1813 } else if (IsAWordStart(ch)) {
\r
1814 state = SCE_HJ_WORD;
\r
1815 } else if (IsOperator(ch)) {
\r
1816 styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
\r
1823 classifyWordHTJS(styler.GetStartSegment(), lengthDoc - 1, keywords2, styler, inScriptType);
\r
1826 classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType);
\r
1829 classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType);
\r
1831 case SCE_HPHP_WORD:
\r
1832 classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler);
\r
1835 StateToPrint = statePrintForState(state, inScriptType);
\r
1836 styler.ColourTo(lengthDoc - 1, StateToPrint);
\r
1840 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
\r
1842 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
\r
1843 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
\r
1847 static void ColouriseXMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
\r
1848 Accessor &styler) {
\r
1849 // Passing in true because we're lexing XML
\r
1850 ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, true);
\r
1853 static void ColouriseHTMLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
\r
1854 Accessor &styler) {
\r
1855 // Passing in false because we're notlexing XML
\r
1856 ColouriseHyperTextDoc(startPos, length, initStyle, keywordlists, styler, false);
\r
1859 static bool isASPScript(int state) {
\r
1861 (state >= SCE_HJA_START && state <= SCE_HJA_REGEX) ||
\r
1862 (state >= SCE_HBA_START && state <= SCE_HBA_STRINGEOL) ||
\r
1863 (state >= SCE_HPA_DEFAULT && state <= SCE_HPA_IDENTIFIER);
\r
1866 static void ColouriseHBAPiece(StyleContext &sc, WordList *keywordlists[]) {
\r
1867 WordList &keywordsVBS = *keywordlists[2];
\r
1868 if (sc.state == SCE_HBA_WORD) {
\r
1869 if (!IsAWordChar(sc.ch)) {
\r
1871 sc.GetCurrentLowered(s, sizeof(s));
\r
1872 if (keywordsVBS.InList(s)) {
\r
1873 if (strcmp(s, "rem") == 0) {
\r
1874 sc.ChangeState(SCE_HBA_COMMENTLINE);
\r
1875 if (sc.atLineEnd) {
\r
1876 sc.SetState(SCE_HBA_DEFAULT);
\r
1879 sc.SetState(SCE_HBA_DEFAULT);
\r
1882 sc.ChangeState(SCE_HBA_IDENTIFIER);
\r
1883 sc.SetState(SCE_HBA_DEFAULT);
\r
1886 } else if (sc.state == SCE_HBA_NUMBER) {
\r
1887 if (!IsAWordChar(sc.ch)) {
\r
1888 sc.SetState(SCE_HBA_DEFAULT);
\r
1890 } else if (sc.state == SCE_HBA_STRING) {
\r
1891 if (sc.ch == '\"') {
\r
1892 sc.ForwardSetState(SCE_HBA_DEFAULT);
\r
1893 } else if (sc.ch == '\r' || sc.ch == '\n') {
\r
1894 sc.ChangeState(SCE_HBA_STRINGEOL);
\r
1895 sc.ForwardSetState(SCE_HBA_DEFAULT);
\r
1897 } else if (sc.state == SCE_HBA_COMMENTLINE) {
\r
1898 if (sc.ch == '\r' || sc.ch == '\n') {
\r
1899 sc.SetState(SCE_HBA_DEFAULT);
\r
1903 if (sc.state == SCE_HBA_DEFAULT) {
\r
1904 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
\r
1905 sc.SetState(SCE_HBA_NUMBER);
\r
1906 } else if (IsAWordStart(sc.ch)) {
\r
1907 sc.SetState(SCE_HBA_WORD);
\r
1908 } else if (sc.ch == '\'') {
\r
1909 sc.SetState(SCE_HBA_COMMENTLINE);
\r
1910 } else if (sc.ch == '\"') {
\r
1911 sc.SetState(SCE_HBA_STRING);
\r
1916 static void ColouriseHTMLPiece(StyleContext &sc, WordList *keywordlists[]) {
\r
1917 WordList &keywordsTags = *keywordlists[0];
\r
1918 if (sc.state == SCE_H_COMMENT) {
\r
1919 if (sc.Match("-->")) {
\r
1922 sc.ForwardSetState(SCE_H_DEFAULT);
\r
1924 } else if (sc.state == SCE_H_ENTITY) {
\r
1925 if (sc.ch == ';') {
\r
1926 sc.ForwardSetState(SCE_H_DEFAULT);
\r
1927 } else if (sc.ch != '#' && (sc.ch < 0x80) && !isalnum(sc.ch) // Should check that '#' follows '&', but it is unlikely anyway...
\r
1928 && sc.ch != '.' && sc.ch != '-' && sc.ch != '_' && sc.ch != ':') { // valid in XML
\r
1929 sc.ChangeState(SCE_H_TAGUNKNOWN);
\r
1930 sc.SetState(SCE_H_DEFAULT);
\r
1932 } else if (sc.state == SCE_H_TAGUNKNOWN) {
\r
1933 if (!ishtmlwordchar(sc.ch) && !((sc.ch == '/') && (sc.chPrev == '<')) && sc.ch != '[') {
\r
1935 sc.GetCurrentLowered(s, sizeof(s));
\r
1936 if (s[1] == '/') {
\r
1937 if (keywordsTags.InList(s + 2)) {
\r
1938 sc.ChangeState(SCE_H_TAG);
\r
1941 if (keywordsTags.InList(s + 1)) {
\r
1942 sc.ChangeState(SCE_H_TAG);
\r
1945 if (sc.ch == '>') {
\r
1946 sc.ForwardSetState(SCE_H_DEFAULT);
\r
1947 } else if (sc.Match('/', '>')) {
\r
1948 sc.SetState(SCE_H_TAGEND);
\r
1950 sc.ForwardSetState(SCE_H_DEFAULT);
\r
1952 sc.SetState(SCE_H_OTHER);
\r
1955 } else if (sc.state == SCE_H_ATTRIBUTE) {
\r
1956 if (!ishtmlwordchar(sc.ch)) {
\r
1958 sc.GetCurrentLowered(s, sizeof(s));
\r
1959 if (!keywordsTags.InList(s)) {
\r
1960 sc.ChangeState(SCE_H_ATTRIBUTEUNKNOWN);
\r
1962 sc.SetState(SCE_H_OTHER);
\r
1964 } else if (sc.state == SCE_H_OTHER) {
\r
1965 if (sc.ch == '>') {
\r
1966 sc.SetState(SCE_H_TAG);
\r
1967 sc.ForwardSetState(SCE_H_DEFAULT);
\r
1968 } else if (sc.Match('/', '>')) {
\r
1969 sc.SetState(SCE_H_TAG);
\r
1971 sc.ForwardSetState(SCE_H_DEFAULT);
\r
1972 } else if (sc.chPrev == '=') {
\r
1973 sc.SetState(SCE_H_VALUE);
\r
1975 } else if (sc.state == SCE_H_DOUBLESTRING) {
\r
1976 if (sc.ch == '\"') {
\r
1977 sc.ForwardSetState(SCE_H_OTHER);
\r
1979 } else if (sc.state == SCE_H_SINGLESTRING) {
\r
1980 if (sc.ch == '\'') {
\r
1981 sc.ForwardSetState(SCE_H_OTHER);
\r
1983 } else if (sc.state == SCE_H_NUMBER) {
\r
1984 if (!IsADigit(sc.ch)) {
\r
1985 sc.SetState(SCE_H_OTHER);
\r
1989 if (sc.state == SCE_H_DEFAULT) {
\r
1990 if (sc.ch == '<') {
\r
1991 if (sc.Match("<!--"))
\r
1992 sc.SetState(SCE_H_COMMENT);
\r
1994 sc.SetState(SCE_H_TAGUNKNOWN);
\r
1995 } else if (sc.ch == '&') {
\r
1996 sc.SetState(SCE_H_ENTITY);
\r
1998 } else if ((sc.state == SCE_H_OTHER) || (sc.state == SCE_H_VALUE)) {
\r
1999 if (sc.ch == '\"' && sc.chPrev == '=') {
\r
2000 sc.SetState(SCE_H_DOUBLESTRING);
\r
2001 } else if (sc.ch == '\'' && sc.chPrev == '=') {
\r
2002 sc.SetState(SCE_H_SINGLESTRING);
\r
2003 } else if (IsADigit(sc.ch)) {
\r
2004 sc.SetState(SCE_H_NUMBER);
\r
2005 } else if (sc.ch == '>') {
\r
2006 sc.SetState(SCE_H_TAG);
\r
2007 sc.ForwardSetState(SCE_H_DEFAULT);
\r
2008 } else if (ishtmlwordchar(sc.ch)) {
\r
2009 sc.SetState(SCE_H_ATTRIBUTE);
\r
2014 static void ColouriseASPPiece(StyleContext &sc, WordList *keywordlists[]) {
\r
2015 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
\r
2016 if ((sc.state == SCE_H_ASPAT || isASPScript(sc.state)) && sc.Match('%', '>')) {
\r
2017 sc.SetState(SCE_H_ASP);
\r
2019 sc.ForwardSetState(SCE_H_DEFAULT);
\r
2022 // Handle some ASP script
\r
2023 if (sc.state >= SCE_HBA_START && sc.state <= SCE_HBA_STRINGEOL) {
\r
2024 ColouriseHBAPiece(sc, keywordlists);
\r
2025 } else if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
\r
2026 ColouriseHTMLPiece(sc, keywordlists);
\r
2029 // Enter new sc.state
\r
2030 if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
\r
2031 if (sc.Match('<', '%')) {
\r
2032 if (sc.state == SCE_H_TAGUNKNOWN)
\r
2033 sc.ChangeState(SCE_H_ASP);
\r
2035 sc.SetState(SCE_H_ASP);
\r
2038 if (sc.ch == '@') {
\r
2039 sc.ForwardSetState(SCE_H_ASPAT);
\r
2041 if (sc.ch == '=') {
\r
2044 sc.SetState(SCE_HBA_DEFAULT);
\r
2050 static void ColouriseASPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
\r
2051 Accessor &styler) {
\r
2052 // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
\r
2053 StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(STYLE_MAX));
\r
2054 for (; sc.More(); sc.Forward()) {
\r
2055 ColouriseASPPiece(sc, keywordlists);
\r
2060 static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {
\r
2061 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
\r
2062 if (sc.state >= SCE_HPHP_DEFAULT && sc.state <= SCE_HPHP_OPERATOR) {
\r
2063 if (!isPHPStringState(sc.state) &&
\r
2064 (sc.state != SCE_HPHP_COMMENT) &&
\r
2065 (sc.Match('?', '>'))) {
\r
2066 sc.SetState(SCE_H_QUESTION);
\r
2068 sc.ForwardSetState(SCE_H_DEFAULT);
\r
2072 if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
\r
2073 ColouriseHTMLPiece(sc, keywordlists);
\r
2076 // Handle some PHP script
\r
2077 if (sc.state == SCE_HPHP_WORD) {
\r
2078 if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
\r
2079 sc.SetState(SCE_HPHP_DEFAULT);
\r
2081 } else if (sc.state == SCE_HPHP_COMMENTLINE) {
\r
2082 if (sc.ch == '\r' || sc.ch == '\n') {
\r
2083 sc.SetState(SCE_HPHP_DEFAULT);
\r
2085 } else if (sc.state == SCE_HPHP_COMMENT) {
\r
2086 if (sc.Match('*', '/')) {
\r
2089 sc.SetState(SCE_HPHP_DEFAULT);
\r
2091 } else if (sc.state == SCE_HPHP_HSTRING) {
\r
2092 if (sc.ch == '\"') {
\r
2093 sc.ForwardSetState(SCE_HPHP_DEFAULT);
\r
2095 } else if (sc.state == SCE_HPHP_SIMPLESTRING) {
\r
2096 if (sc.ch == '\'') {
\r
2097 sc.ForwardSetState(SCE_HPHP_DEFAULT);
\r
2099 } else if (sc.state == SCE_HPHP_VARIABLE) {
\r
2100 if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
\r
2101 sc.SetState(SCE_HPHP_DEFAULT);
\r
2103 } else if (sc.state == SCE_HPHP_OPERATOR) {
\r
2104 sc.SetState(SCE_HPHP_DEFAULT);
\r
2107 // Enter new sc.state
\r
2108 if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
\r
2109 if (sc.Match("<?php")) {
\r
2110 sc.SetState(SCE_H_QUESTION);
\r
2116 sc.SetState(SCE_HPHP_DEFAULT);
\r
2119 if (sc.state == SCE_HPHP_DEFAULT) {
\r
2120 if (IsPhpWordStart(static_cast<char>(sc.ch))) {
\r
2121 sc.SetState(SCE_HPHP_WORD);
\r
2122 } else if (sc.ch == '#') {
\r
2123 sc.SetState(SCE_HPHP_COMMENTLINE);
\r
2124 } else if (sc.Match("<!--")) {
\r
2125 sc.SetState(SCE_HPHP_COMMENTLINE);
\r
2126 } else if (sc.Match('/', '/')) {
\r
2127 sc.SetState(SCE_HPHP_COMMENTLINE);
\r
2128 } else if (sc.Match('/', '*')) {
\r
2129 sc.SetState(SCE_HPHP_COMMENT);
\r
2130 } else if (sc.ch == '\"') {
\r
2131 sc.SetState(SCE_HPHP_HSTRING);
\r
2132 } else if (sc.ch == '\'') {
\r
2133 sc.SetState(SCE_HPHP_SIMPLESTRING);
\r
2134 } else if (sc.ch == '$' && IsPhpWordStart(static_cast<char>(sc.chNext))) {
\r
2135 sc.SetState(SCE_HPHP_VARIABLE);
\r
2136 } else if (IsOperator(static_cast<char>(sc.ch))) {
\r
2137 sc.SetState(SCE_HPHP_OPERATOR);
\r
2142 static void ColourisePHPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
\r
2143 Accessor &styler) {
\r
2144 // Lexer for HTML requires more lexical states (8 bits worth) than most lexers
\r
2145 StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(STYLE_MAX));
\r
2146 for (; sc.More(); sc.Forward()) {
\r
2147 ColourisePHPPiece(sc, keywordlists);
\r
2152 static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
\r
2153 Accessor &styler) {
\r
2154 if (startPos == 0)
\r
2155 initStyle = SCE_HPHP_DEFAULT;
\r
2156 ColouriseHTMLDoc(startPos, length, initStyle, keywordlists, styler);
\r
2159 static const char * const htmlWordListDesc[] = {
\r
2160 "HTML elements and attributes",
\r
2161 "JavaScript keywords",
\r
2162 "VBScript keywords",
\r
2163 "Python keywords",
\r
2165 "SGML and DTD keywords",
\r
2169 static const char * const phpscriptWordListDesc[] = {
\r
2179 LexerModule lmHTML(SCLEX_HTML, ColouriseHTMLDoc, "hypertext", 0, htmlWordListDesc, 8);
\r
2180 LexerModule lmXML(SCLEX_XML, ColouriseXMLDoc, "xml", 0, htmlWordListDesc, 8);
\r
2181 // SCLEX_ASP and SCLEX_PHP should not be used in new code: use SCLEX_HTML instead.
\r
2182 LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc, 8);
\r
2183 LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc, 8);
\r
2184 LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 8);
\r