]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/stc/scintilla/src/LexHTML.cxx
Updated Scintilla to version 1.70
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexHTML.cxx
CommitLineData
65ec6247
RD
1// Scintilla source code edit control
2/** @file LexHTML.cxx
3 ** Lexer for HTML.
1a2fb4cd 4 **/
1e9bafca 5// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
f6bcfd97
BP
6// The License.txt file describes the conditions under which this software may be distributed.
7
65ec6247
RD
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11#include <stdio.h>
12#include <stdarg.h>
f6bcfd97
BP
13
14#include "Platform.h"
15
16#include "PropSet.h"
17#include "Accessor.h"
1a2fb4cd 18#include "StyleContext.h"
f6bcfd97
BP
19#include "KeyWords.h"
20#include "Scintilla.h"
21#include "SciLexer.h"
22
d134f170
RD
23#define SCE_HA_JS (SCE_HJA_START - SCE_HJ_START)
24#define SCE_HA_VBS (SCE_HBA_START - SCE_HB_START)
25#define SCE_HA_PYTHON (SCE_HPA_START - SCE_HP_START)
26
1a2fb4cd
RD
27enum script_type { eScriptNone = 0, eScriptJS, eScriptVBS, eScriptPython, eScriptPHP, eScriptXML, eScriptSGML, eScriptSGMLblock };
28enum script_mode { eHtml = 0, eNonHtmlScript, eNonHtmlPreProc, eNonHtmlScriptPreProc };
d134f170 29
1a2fb4cd
RD
30static inline bool IsAWordChar(const int ch) {
31 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
32}
33
34static inline bool IsAWordStart(const int ch) {
35 return (ch < 0x80) && (isalnum(ch) || ch == '_');
36}
37
1e9bafca
RD
38static inline int MakeLowerCase(int ch) {
39 if (ch < 'A' || ch > 'Z')
40 return ch;
41 else
42 return ch - 'A' + 'a';
43}
44
45static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) {
46 size_t i = 0;
47 for (; (i < end - start + 1) && (i < len-1); i++) {
48 s[i] = static_cast<char>(MakeLowerCase(styler[start + i]));
f6bcfd97 49 }
b8b0e402 50 s[i] = '\0';
1e9bafca
RD
51}
52
53static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) {
54 char s[100];
55 GetTextSegment(styler, start, end, s, sizeof(s));
d134f170 56 //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
65ec6247
RD
57 if (strstr(s, "src")) // External script
58 return eScriptNone;
f6bcfd97
BP
59 if (strstr(s, "vbs"))
60 return eScriptVBS;
61 if (strstr(s, "pyth"))
62 return eScriptPython;
63 if (strstr(s, "javas"))
64 return eScriptJS;
65 if (strstr(s, "jscr"))
66 return eScriptJS;
d134f170
RD
67 if (strstr(s, "php"))
68 return eScriptPHP;
69 if (strstr(s, "xml"))
70 return eScriptXML;
71
f6bcfd97
BP
72 return prevValue;
73}
74
d134f170
RD
75static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, unsigned int end) {
76 int iResult = 0;
1e9bafca
RD
77 char s[100];
78 GetTextSegment(styler, start, end, s, sizeof(s));
d134f170
RD
79 if (0 == strncmp(s, "php", 3)) {
80 iResult = 3;
81 }
82
83 return iResult;
84}
85
1a2fb4cd 86static script_type ScriptOfState(int state) {
d134f170 87 if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
b8b0e402 88 return eScriptPython;
d134f170 89 } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
b8b0e402 90 return eScriptVBS;
65ec6247 91 } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
b8b0e402 92 return eScriptJS;
d134f170 93 } else if ((state >= SCE_HPHP_DEFAULT) && (state <= SCE_HPHP_COMMENTLINE)) {
b8b0e402 94 return eScriptPHP;
1a2fb4cd 95 } else if ((state >= SCE_H_SGML_DEFAULT) && (state < SCE_H_SGML_BLOCK_DEFAULT)) {
b8b0e402
RD
96 return eScriptSGML;
97 } else if (state == SCE_H_SGML_BLOCK_DEFAULT) {
98 return eScriptSGMLblock;
d134f170 99 } else {
b8b0e402 100 return eScriptNone;
d134f170 101 }
d134f170
RD
102}
103
1a2fb4cd 104static int statePrintForState(int state, script_mode inScriptType) {
d134f170
RD
105 int StateToPrint;
106
107 if ((state >= SCE_HP_START) && (state <= SCE_HP_IDENTIFIER)) {
108 StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_PYTHON);
109 } else if ((state >= SCE_HB_START) && (state <= SCE_HB_STRINGEOL)) {
110 StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_VBS);
65ec6247 111 } else if ((state >= SCE_HJ_START) && (state <= SCE_HJ_REGEX)) {
d134f170
RD
112 StateToPrint = state + ((inScriptType == eNonHtmlScript) ? 0 : SCE_HA_JS);
113 } else {
114 StateToPrint = state;
115 }
116
117 return StateToPrint;
118}
119
120static int stateForPrintState(int StateToPrint) {
121 int state;
122
123 if ((StateToPrint >= SCE_HPA_START) && (StateToPrint <= SCE_HPA_IDENTIFIER)) {
124 state = StateToPrint - SCE_HA_PYTHON;
125 } else if ((StateToPrint >= SCE_HBA_START) && (StateToPrint <= SCE_HBA_STRINGEOL)) {
126 state = StateToPrint - SCE_HA_VBS;
65ec6247 127 } else if ((StateToPrint >= SCE_HJA_START) && (StateToPrint <= SCE_HJA_REGEX)) {
d134f170
RD
128 state = StateToPrint - SCE_HA_JS;
129 } else {
130 state = StateToPrint;
131 }
132
133 return state;
134}
135
136static inline bool IsNumber(unsigned int start, Accessor &styler) {
88a8b04e 137 return IsADigit(styler[start]) || (styler[start] == '.') ||
65ec6247
RD
138 (styler[start] == '-') || (styler[start] == '#');
139}
140
141static inline bool isStringState(int state) {
142 bool bResult;
143
144 switch (state) {
145 case SCE_HJ_DOUBLESTRING:
146 case SCE_HJ_SINGLESTRING:
147 case SCE_HJA_DOUBLESTRING:
148 case SCE_HJA_SINGLESTRING:
149 case SCE_HB_STRING:
150 case SCE_HBA_STRING:
151 case SCE_HP_STRING:
b8193d80
RD
152 case SCE_HP_CHARACTER:
153 case SCE_HP_TRIPLE:
154 case SCE_HP_TRIPLEDOUBLE:
65ec6247 155 case SCE_HPA_STRING:
b8193d80
RD
156 case SCE_HPA_CHARACTER:
157 case SCE_HPA_TRIPLE:
158 case SCE_HPA_TRIPLEDOUBLE:
65ec6247
RD
159 case SCE_HPHP_HSTRING:
160 case SCE_HPHP_SIMPLESTRING:
591d01be
RD
161 case SCE_HPHP_HSTRING_VARIABLE:
162 case SCE_HPHP_COMPLEX_VARIABLE:
65ec6247
RD
163 bResult = true;
164 break;
165 default :
166 bResult = false;
167 break;
168 }
169 return bResult;
170}
171
b8193d80
RD
172static inline bool stateAllowsTermination(int state) {
173 bool allowTermination = !isStringState(state);
174 if (allowTermination) {
175 switch (state) {
176 case SCE_HPHP_COMMENT:
177 case SCE_HP_COMMENTLINE:
178 case SCE_HPA_COMMENTLINE:
179 allowTermination = false;
180 }
181 }
182 return allowTermination;
183}
184
65ec6247
RD
185// not really well done, since it's only comments that should lex the %> and <%
186static inline bool isCommentASPState(int state) {
187 bool bResult;
188
189 switch (state) {
190 case SCE_HJ_COMMENT:
191 case SCE_HJ_COMMENTLINE:
192 case SCE_HJ_COMMENTDOC:
193 case SCE_HB_COMMENTLINE:
194 case SCE_HP_COMMENTLINE:
195 case SCE_HPHP_COMMENT:
196 case SCE_HPHP_COMMENTLINE:
197 bResult = true;
198 break;
199 default :
200 bResult = false;
201 break;
202 }
203 return bResult;
d134f170
RD
204}
205
206static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
207 bool wordIsNumber = IsNumber(start, styler);
f6bcfd97
BP
208 char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
209 if (wordIsNumber) {
210 chAttr = SCE_H_NUMBER;
211 } else {
1e9bafca
RD
212 char s[100];
213 GetTextSegment(styler, start, end, s, sizeof(s));
f6bcfd97
BP
214 if (keywords.InList(s))
215 chAttr = SCE_H_ATTRIBUTE;
216 }
d134f170
RD
217 if ((chAttr == SCE_H_ATTRIBUTEUNKNOWN) && !keywords)
218 // No keywords -> all are known
219 chAttr = SCE_H_ATTRIBUTE;
f6bcfd97
BP
220 styler.ColourTo(end, chAttr);
221}
222
223static int classifyTagHTML(unsigned int start, unsigned int end,
9e730a78
RD
224 WordList &keywords, Accessor &styler, bool &tagDontFold,
225 bool caseSensitive) {
226 char s[30 + 2];
f6bcfd97
BP
227 // Copy after the '<'
228 unsigned int i = 0;
d134f170 229 for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) {
f6bcfd97 230 char ch = styler[cPos];
9e730a78 231 if ((ch != '<') && (ch != '/')) {
1e9bafca 232 s[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch));
9e730a78 233 }
f6bcfd97 234 }
9e730a78
RD
235
236 //The following is only a quick hack, to see if this whole thing would work
237 //we first need the tagname with a trailing space...
238 s[i] = ' ';
239 s[i+1] = '\0';
240
241 //...to find it in the list of no-container-tags
242 // (There are many more. We will need a keywordlist in the property file for this)
243 tagDontFold = (NULL != strstr("meta link img area br hr input ",s));
244
245 //now we can remove the trailing space
f6bcfd97 246 s[i] = '\0';
9e730a78 247
65ec6247 248 bool isScript = false;
f6bcfd97 249 char chAttr = SCE_H_TAGUNKNOWN;
b8b0e402
RD
250 if (s[0] == '!') {
251 chAttr = SCE_H_SGML_DEFAULT;
f6bcfd97
BP
252 } else if (s[0] == '/') { // Closing tag
253 if (keywords.InList(s + 1))
254 chAttr = SCE_H_TAG;
255 } else {
256 if (keywords.InList(s)) {
257 chAttr = SCE_H_TAG;
65ec6247 258 isScript = 0 == strcmp(s, "script");
f6bcfd97
BP
259 }
260 }
a834585d 261 if ((chAttr == SCE_H_TAGUNKNOWN) && !keywords) {
d134f170
RD
262 // No keywords -> all are known
263 chAttr = SCE_H_TAG;
a834585d
RD
264 isScript = 0 == strcmp(s, "script");
265 }
f6bcfd97 266 styler.ColourTo(end, chAttr);
65ec6247 267 return isScript ? SCE_H_SCRIPT : chAttr;
f6bcfd97
BP
268}
269
270static void classifyWordHTJS(unsigned int start, unsigned int end,
1a2fb4cd 271 WordList &keywords, Accessor &styler, script_mode inScriptType) {
f6bcfd97 272 char chAttr = SCE_HJ_WORD;
88a8b04e 273 bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.');
f6bcfd97
BP
274 if (wordIsNumber)
275 chAttr = SCE_HJ_NUMBER;
276 else {
d134f170 277 char s[30 + 1];
b8b0e402
RD
278 unsigned int i = 0;
279 for (; i < end - start + 1 && i < 30; i++) {
d134f170 280 s[i] = styler[start + i];
d134f170 281 }
b8b0e402 282 s[i] = '\0';
f6bcfd97
BP
283 if (keywords.InList(s))
284 chAttr = SCE_HJ_KEYWORD;
285 }
d134f170 286 styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
f6bcfd97
BP
287}
288
1a2fb4cd 289static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) {
f6bcfd97 290 char chAttr = SCE_HB_IDENTIFIER;
88a8b04e 291 bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.');
f6bcfd97
BP
292 if (wordIsNumber)
293 chAttr = SCE_HB_NUMBER;
294 else {
1e9bafca
RD
295 char s[100];
296 GetTextSegment(styler, start, end, s, sizeof(s));
f6bcfd97
BP
297 if (keywords.InList(s)) {
298 chAttr = SCE_HB_WORD;
299 if (strcmp(s, "rem") == 0)
300 chAttr = SCE_HB_COMMENTLINE;
301 }
302 }
d134f170 303 styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
f6bcfd97
BP
304 if (chAttr == SCE_HB_COMMENTLINE)
305 return SCE_HB_COMMENTLINE;
306 else
307 return SCE_HB_DEFAULT;
308}
309
1a2fb4cd 310static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType) {
88a8b04e 311 bool wordIsNumber = IsADigit(styler[start]);
d134f170 312 char s[30 + 1];
b8b0e402
RD
313 unsigned int i = 0;
314 for (; i < end - start + 1 && i < 30; i++) {
f6bcfd97 315 s[i] = styler[start + i];
f6bcfd97 316 }
b8b0e402 317 s[i] = '\0';
f6bcfd97
BP
318 char chAttr = SCE_HP_IDENTIFIER;
319 if (0 == strcmp(prevWord, "class"))
320 chAttr = SCE_HP_CLASSNAME;
321 else if (0 == strcmp(prevWord, "def"))
322 chAttr = SCE_HP_DEFNAME;
323 else if (wordIsNumber)
324 chAttr = SCE_HP_NUMBER;
325 else if (keywords.InList(s))
326 chAttr = SCE_HP_WORD;
d134f170 327 styler.ColourTo(end, statePrintForState(chAttr, inScriptType));
f6bcfd97
BP
328 strcpy(prevWord, s);
329}
330
d134f170
RD
331// Update the word colour to default or keyword
332// Called when in a PHP word
333static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
334 char chAttr = SCE_HPHP_DEFAULT;
a33203cb 335 bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.' && start+1 <= end && IsADigit(styler[start+1]));
d134f170
RD
336 if (wordIsNumber)
337 chAttr = SCE_HPHP_NUMBER;
338 else {
1e9bafca
RD
339 char s[100];
340 GetTextSegment(styler, start, end, s, sizeof(s));
d134f170
RD
341 if (keywords.InList(s))
342 chAttr = SCE_HPHP_WORD;
f6bcfd97 343 }
f6bcfd97 344 styler.ColourTo(end, chAttr);
d134f170
RD
345}
346
b8b0e402
RD
347static bool isWordHSGML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
348 char s[30 + 1];
349 unsigned int i = 0;
350 for (; i < end - start + 1 && i < 30; i++) {
351 s[i] = styler[start + i];
352 }
353 s[i] = '\0';
354 return keywords.InList(s);
355}
356
357static bool isWordCdata(unsigned int start, unsigned int end, Accessor &styler) {
358 char s[30 + 1];
359 unsigned int i = 0;
360 for (; i < end - start + 1 && i < 30; i++) {
361 s[i] = styler[start + i];
362 }
363 s[i] = '\0';
364 return (0 == strcmp(s, "[CDATA["));
365}
366
d134f170 367// Return the first state to reach when entering a scripting language
1a2fb4cd 368static int StateForScript(script_type scriptLanguage) {
d134f170
RD
369 int Result;
370 switch (scriptLanguage) {
371 case eScriptVBS:
372 Result = SCE_HB_START;
373 break;
374 case eScriptPython:
375 Result = SCE_HP_START;
376 break;
377 case eScriptPHP:
378 Result = SCE_HPHP_DEFAULT;
379 break;
380 case eScriptXML:
381 Result = SCE_H_TAGUNKNOWN;
382 break;
b8b0e402
RD
383 case eScriptSGML:
384 Result = SCE_H_SGML_DEFAULT;
385 break;
d134f170
RD
386 default :
387 Result = SCE_HJ_START;
388 break;
389 }
390 return Result;
f6bcfd97
BP
391}
392
1a2fb4cd 393static inline bool ishtmlwordchar(char ch) {
88a8b04e
RD
394 return !isascii(ch) ||
395 (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#');
f6bcfd97
BP
396}
397
1a2fb4cd 398static inline bool issgmlwordchar(char ch) {
88a8b04e
RD
399 return !isascii(ch) ||
400 (isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '[');
b8b0e402
RD
401}
402
9e730a78 403static inline bool IsPhpWordStart(const unsigned char ch) {
88a8b04e 404 return (isascii(ch) && (isalpha(ch) || (ch == '_'))) || (ch >= 0x7f);
9e730a78
RD
405}
406
407static inline bool IsPhpWordChar(char ch) {
88a8b04e 408 return IsADigit(ch) || IsPhpWordStart(ch);
9e730a78
RD
409}
410
f6bcfd97
BP
411static bool InTagState(int state) {
412 return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN ||
d134f170
RD
413 state == SCE_H_SCRIPT ||
414 state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN ||
415 state == SCE_H_NUMBER || state == SCE_H_OTHER ||
416 state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING;
f6bcfd97
BP
417}
418
b8b0e402
RD
419static bool IsCommentState(const int state) {
420 return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT;
421}
422
1e9bafca
RD
423static bool IsScriptCommentState(const int state) {
424 return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT ||
425 state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE;
426}
427
f6bcfd97
BP
428static bool isLineEnd(char ch) {
429 return ch == '\r' || ch == '\n';
430}
431
65ec6247
RD
432static bool isOKBeforeRE(char ch) {
433 return (ch == '(') || (ch == '=') || (ch == ',');
434}
435
436static bool isPHPStringState(int state) {
b8b0e402
RD
437 return
438 (state == SCE_HPHP_HSTRING) ||
439 (state == SCE_HPHP_SIMPLESTRING) ||
591d01be
RD
440 (state == SCE_HPHP_HSTRING_VARIABLE) ||
441 (state == SCE_HPHP_COMPLEX_VARIABLE);
442}
443
444static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler) {
445 int j;
1e9bafca
RD
446 while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t'))
447 i++;
591d01be
RD
448 phpStringDelimiter[0] = '\n';
449 for (j = i; j < lengthDoc && styler[j] != '\n' && styler[j] != '\r'; j++) {
450 if (j - i < phpStringDelimiterSize - 2)
451 phpStringDelimiter[j-i+1] = styler[j];
452 else
453 i++;
454 }
455 phpStringDelimiter[j-i+1] = '\0';
456 return j;
65ec6247
RD
457}
458
d134f170
RD
459static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
460 Accessor &styler) {
d134f170
RD
461 WordList &keywords = *keywordlists[0];
462 WordList &keywords2 = *keywordlists[1];
463 WordList &keywords3 = *keywordlists[2];
464 WordList &keywords4 = *keywordlists[3];
465 WordList &keywords5 = *keywordlists[4];
b8b0e402 466 WordList &keywords6 = *keywordlists[5]; // SGML (DTD) keywords
d134f170 467
f6bcfd97 468 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
b8b0e402 469 styler.StartAt(startPos, STYLE_MAX);
f6bcfd97
BP
470 char prevWord[200];
471 prevWord[0] = '\0';
591d01be
RD
472 char phpStringDelimiter[200]; // PHP is not limited in length, we are
473 phpStringDelimiter[0] = '\0';
d134f170
RD
474 int StateToPrint = initStyle;
475 int state = stateForPrintState(StateToPrint);
476
477 // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen
f6bcfd97 478 if (InTagState(state)) {
65ec6247 479 while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) {
f6bcfd97 480 startPos--;
b8b0e402 481 length++;
f6bcfd97
BP
482 }
483 state = SCE_H_DEFAULT;
484 }
591d01be
RD
485 // String can be heredoc, must find a delimiter first
486 while (startPos > 0 && isPHPStringState(state) && state != SCE_HPHP_SIMPLESTRING) {
487 startPos--;
488 length++;
489 state = styler.StyleAt(startPos);
490 }
b8b0e402 491 styler.StartAt(startPos, STYLE_MAX);
f6bcfd97 492
f6bcfd97 493 int lineCurrent = styler.GetLine(startPos);
b8b0e402
RD
494 int lineState;
495 if (lineCurrent > 0) {
f6bcfd97 496 lineState = styler.GetLineState(lineCurrent);
b8b0e402
RD
497 } else {
498 // Default client and ASP scripting language is JavaScript
499 lineState = eScriptJS << 8;
500 lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4;
501 }
1a2fb4cd 502 script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode
b8b0e402
RD
503 bool tagOpened = (lineState >> 2) & 0x01; // 1 bit to know if we are in an opened tag
504 bool tagClosing = (lineState >> 3) & 0x01; // 1 bit to know if we are in a closing tag
9e730a78 505 bool tagDontFold = false; //some HTML tags should not be folded
1a2fb4cd
RD
506 script_type aspScript = script_type((lineState >> 4) & 0x0F); // 4 bits of script name
507 script_type clientScript = script_type((lineState >> 8) & 0x0F); // 4 bits of script name
b8b0e402 508 int beforePreProc = (lineState >> 12) & 0xFF; // 8 bits of state
d134f170 509
1a2fb4cd 510 script_type scriptLanguage = ScriptOfState(state);
d134f170 511
1a2fb4cd 512 const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0;
9e730a78
RD
513 const bool fold = foldHTML && styler.GetPropertyInt("fold", 0);
514 const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1);
1a2fb4cd 515 const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
9e730a78 516 const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0;
65ec6247 517
d134f170
RD
518 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
519 int levelCurrent = levelPrev;
b8b0e402 520 int visibleChars = 0;
d134f170 521
f6bcfd97 522 char chPrev = ' ';
d134f170 523 char ch = ' ';
65ec6247 524 char chPrevNonWhite = ' ';
1e9bafca
RD
525 // look back to set chPrevNonWhite properly for better regex colouring
526 if (scriptLanguage == eScriptJS && startPos > 0) {
527 int back = startPos;
528 int style = 0;
529 while (--back) {
530 style = styler.StyleAt(back);
531 if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC)
532 // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
533 break;
534 }
535 if (style == SCE_HJ_SYMBOLS) {
536 chPrevNonWhite = styler.SafeGetCharAt(back);
537 }
538 }
539
f6bcfd97 540 styler.StartSegment(startPos);
b8b0e402 541 const int lengthDoc = startPos + length;
f6bcfd97 542 for (int i = startPos; i < lengthDoc; i++) {
b8b0e402 543 const char chPrev2 = chPrev;
d134f170 544 chPrev = ch;
1e9bafca
RD
545 if (!isspacechar(ch) && state != SCE_HJ_COMMENT &&
546 state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC)
65ec6247 547 chPrevNonWhite = ch;
d134f170 548 ch = styler[i];
f6bcfd97 549 char chNext = styler.SafeGetCharAt(i + 1);
b8b0e402 550 const char chNext2 = styler.SafeGetCharAt(i + 2);
f6bcfd97 551
d134f170 552 // Handle DBCS codepages
f6bcfd97 553 if (styler.IsLeadByte(ch)) {
f6bcfd97
BP
554 chPrev = ' ';
555 i += 1;
556 continue;
557 }
558
65ec6247 559 if ((!isspacechar(ch) || !foldCompact) && fold)
d134f170
RD
560 visibleChars++;
561
65ec6247
RD
562 // decide what is the current state to print (depending of the script tag)
563 StateToPrint = statePrintForState(state, inScriptType);
564
d134f170
RD
565 // handle script folding
566 if (fold) {
567 switch (scriptLanguage) {
568 case eScriptJS:
569 case eScriptPHP:
570 //not currently supported case eScriptVBS:
65ec6247 571
9e730a78
RD
572 if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) {
573 //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle);
574 //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) {
65ec6247
RD
575 if ((ch == '{') || (ch == '}')) {
576 levelCurrent += (ch == '{') ? 1 : -1;
d134f170
RD
577 }
578 }
579 break;
580 case eScriptPython:
581 if (state != SCE_HP_COMMENTLINE) {
65ec6247
RD
582 if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) {
583 levelCurrent++;
584 } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) {
585 // check if the number of tabs is lower than the level
586 int Findlevel = (levelCurrent & ~SC_FOLDLEVELBASE) * 8;
b8b0e402 587 for (int j = 0; Findlevel > 0; j++) {
65ec6247
RD
588 char chTmp = styler.SafeGetCharAt(i + j + 1);
589 if (chTmp == '\t') {
590 Findlevel -= 8;
b8b0e402 591 } else if (chTmp == ' ') {
65ec6247 592 Findlevel--;
b8b0e402
RD
593 } else {
594 break;
595 }
65ec6247 596 }
d134f170 597
65ec6247
RD
598 if (Findlevel > 0) {
599 levelCurrent -= Findlevel / 8;
b8b0e402
RD
600 if (Findlevel % 8)
601 levelCurrent--;
d134f170
RD
602 }
603 }
604 }
605 break;
1a2fb4cd
RD
606 default:
607 break;
d134f170
RD
608 }
609 }
610
f6bcfd97 611 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
d134f170
RD
612 // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
613 // Avoid triggering two times on Dos/Win
f6bcfd97 614 // New line -> record any line state onto /next/ line
d134f170
RD
615 if (fold) {
616 int lev = levelPrev;
617 if (visibleChars == 0)
618 lev |= SC_FOLDLEVELWHITEFLAG;
619 if ((levelCurrent > levelPrev) && (visibleChars > 0))
620 lev |= SC_FOLDLEVELHEADERFLAG;
65ec6247 621
d134f170
RD
622 styler.SetLevel(lineCurrent, lev);
623 visibleChars = 0;
624 levelPrev = levelCurrent;
625 }
f6bcfd97 626 lineCurrent++;
d134f170 627 styler.SetLineState(lineCurrent,
b8b0e402
RD
628 ((inScriptType & 0x03) << 0) |
629 ((tagOpened & 0x01) << 2) |
630 ((tagClosing & 0x01) << 3) |
631 ((aspScript & 0x0F) << 4) |
632 ((clientScript & 0x0F) << 8) |
633 ((beforePreProc & 0xFF) << 12));
d134f170
RD
634 }
635
636 // generic end of script processing
637 else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) {
638 // Check if it's the end of the script tag (or any other HTML tag)
639 switch (state) {
640 // in these cases, you can embed HTML tags (to confirm !!!!!!!!!!!!!!!!!!!!!!)
641 case SCE_H_DOUBLESTRING:
642 case SCE_H_SINGLESTRING:
643 case SCE_HJ_COMMENT:
644 case SCE_HJ_COMMENTDOC:
1e9bafca
RD
645 //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
646 // the end of script marker from some JS interpreters.
d134f170
RD
647 case SCE_HJ_DOUBLESTRING:
648 case SCE_HJ_SINGLESTRING:
a834585d 649 case SCE_HJ_REGEX:
d134f170
RD
650 case SCE_HB_STRING:
651 case SCE_HP_STRING:
652 case SCE_HP_TRIPLE:
653 case SCE_HP_TRIPLEDOUBLE:
654 break;
655 default :
1e9bafca
RD
656 // check if the closing tag is a script tag
657 if (state == SCE_HJ_COMMENTLINE) {
658 char tag[7]; // room for the <script> tag
659 char chr; // current char
660 int j=0;
661 chr = styler.SafeGetCharAt(i+2);
662 while (j < 6 && !isspacechar(chr)) {
663 tag[j++] = static_cast<char>(MakeLowerCase(chr));
664 chr = styler.SafeGetCharAt(i+2+j);
665 }
666 tag[j] = '\0';
667 if (strcmp(tag, "script") != 0) break;
668 }
b8b0e402 669 // closing tag of the script (it's a closing HTML tag anyway)
d134f170
RD
670 styler.ColourTo(i - 1, StateToPrint);
671 state = SCE_H_TAGUNKNOWN;
672 inScriptType = eHtml;
673 scriptLanguage = eScriptNone;
b8b0e402 674 clientScript = eScriptJS;
d134f170 675 i += 2;
b8b0e402
RD
676 visibleChars += 2;
677 tagClosing = true;
d134f170
RD
678 continue;
679 }
680 }
681
682 /////////////////////////////////////
683 // handle the start of PHP pre-processor = Non-HTML
b8b0e402
RD
684 else if ((state != SCE_H_ASPAT) &&
685 !isPHPStringState(state) &&
686 (state != SCE_HPHP_COMMENT) &&
687 (ch == '<') &&
1e9bafca
RD
688 (chNext == '?') &&
689 !IsScriptCommentState(state) ) {
b8193d80 690 scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 10, eScriptPHP);
a33203cb 691 if (scriptLanguage != eScriptPHP && isStringState(state)) continue;
d134f170
RD
692 styler.ColourTo(i - 1, StateToPrint);
693 beforePreProc = state;
d134f170 694 i++;
b8b0e402 695 visibleChars++;
d134f170
RD
696 i += PrintScriptingIndicatorOffset(styler, styler.GetStartSegment() + 2, i + 10);
697 if (scriptLanguage == eScriptXML)
698 styler.ColourTo(i, SCE_H_XMLSTART);
699 else
700 styler.ColourTo(i, SCE_H_QUESTION);
701 state = StateForScript(scriptLanguage);
702 if (inScriptType == eNonHtmlScript)
703 inScriptType = eNonHtmlScriptPreProc;
704 else
705 inScriptType = eNonHtmlPreProc;
1e9bafca
RD
706 // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
707 if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
9e730a78 708 levelCurrent++;
9e730a78 709 }
65ec6247
RD
710 // should be better
711 ch = styler.SafeGetCharAt(i);
d134f170 712 continue;
f6bcfd97 713 }
d134f170
RD
714
715 // handle the start of ASP pre-processor = Non-HTML
1e9bafca 716 else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) {
d134f170
RD
717 styler.ColourTo(i - 1, StateToPrint);
718 beforePreProc = state;
719 if (inScriptType == eNonHtmlScript)
720 inScriptType = eNonHtmlScriptPreProc;
721 else
722 inScriptType = eNonHtmlPreProc;
723
f6bcfd97 724 if (chNext2 == '@') {
d134f170 725 i += 2; // place as if it was the second next char treated
b8b0e402 726 visibleChars += 2;
f6bcfd97 727 state = SCE_H_ASPAT;
65ec6247
RD
728 } else if ((chNext2 == '-') && (styler.SafeGetCharAt(i + 3) == '-')) {
729 styler.ColourTo(i + 3, SCE_H_ASP);
730 state = SCE_H_XCCOMMENT;
731 scriptLanguage = eScriptVBS;
732 continue;
f6bcfd97 733 } else {
f6bcfd97 734 if (chNext2 == '=') {
d134f170 735 i += 2; // place as if it was the second next char treated
b8b0e402 736 visibleChars += 2;
65ec6247 737 } else {
d134f170 738 i++; // place as if it was the next char treated
b8b0e402 739 visibleChars++;
f6bcfd97 740 }
d134f170 741
b8b0e402 742 state = StateForScript(aspScript);
f6bcfd97 743 }
65ec6247 744 scriptLanguage = eScriptVBS;
d134f170 745 styler.ColourTo(i, SCE_H_ASP);
65ec6247 746 // fold whole script
9e730a78
RD
747 if (foldHTMLPreprocessor)
748 levelCurrent++;
65ec6247
RD
749 // should be better
750 ch = styler.SafeGetCharAt(i);
f6bcfd97
BP
751 continue;
752 }
d134f170 753
b8b0e402
RD
754 /////////////////////////////////////
755 // handle the start of SGML language (DTD)
756 else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) &&
1e9bafca
RD
757 (chPrev == '<') &&
758 (ch == '!') &&
759 (StateToPrint != SCE_H_CDATA) &&
760 (!IsCommentState(StateToPrint)) &&
761 (!IsScriptCommentState(StateToPrint)) ) {
b8b0e402
RD
762 beforePreProc = state;
763 styler.ColourTo(i - 2, StateToPrint);
764 if ((chNext == '-') && (chNext2 == '-')) {
765 state = SCE_H_COMMENT; // wait for a pending command
1e9bafca
RD
766 styler.ColourTo(i + 2, SCE_H_COMMENT);
767 i += 2; // follow styling after the --
768 } else if (isWordCdata(i + 1, i + 7, styler)) {
b8b0e402
RD
769 state = SCE_H_CDATA;
770 } else {
771 styler.ColourTo(i, SCE_H_SGML_DEFAULT); // <! is default
772 scriptLanguage = eScriptSGML;
773 state = SCE_H_SGML_COMMAND; // wait for a pending command
774 }
775 // fold whole tag (-- when closing the tag)
9e730a78
RD
776 if (foldHTMLPreprocessor)
777 levelCurrent++;
b8b0e402
RD
778 continue;
779 }
780
d134f170 781 // handle the end of a pre-processor = Non-HTML
b8b0e402
RD
782 else if ((
783 ((inScriptType == eNonHtmlPreProc)
784 || (inScriptType == eNonHtmlScriptPreProc)) && (
b8193d80 785 ((scriptLanguage != eScriptNone) && stateAllowsTermination(state) && ((ch == '%') || (ch == '?')))
b8b0e402
RD
786 ) && (chNext == '>')) ||
787 ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) {
d134f170 788 if (state == SCE_H_ASPAT) {
b8b0e402
RD
789 aspScript = segIsScriptingIndicator(styler,
790 styler.GetStartSegment(), i - 1, aspScript);
d134f170 791 }
f6bcfd97 792 // Bounce out of any ASP mode
d134f170
RD
793 switch (state) {
794 case SCE_HJ_WORD:
795 classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
796 break;
797 case SCE_HB_WORD:
798 classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
799 break;
800 case SCE_HP_WORD:
801 classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
802 break;
803 case SCE_HPHP_WORD:
804 classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
805 break;
65ec6247
RD
806 case SCE_H_XCCOMMENT:
807 styler.ColourTo(i - 1, state);
808 break;
d134f170
RD
809 default :
810 styler.ColourTo(i - 1, StateToPrint);
811 break;
f6bcfd97 812 }
b8b0e402
RD
813 if (scriptLanguage != eScriptSGML) {
814 i++;
815 visibleChars++;
816 }
d134f170
RD
817 if (ch == '%')
818 styler.ColourTo(i, SCE_H_ASP);
819 else if (scriptLanguage == eScriptXML)
820 styler.ColourTo(i, SCE_H_XMLEND);
b8b0e402
RD
821 else if (scriptLanguage == eScriptSGML)
822 styler.ColourTo(i, SCE_H_SGML_DEFAULT);
d134f170
RD
823 else
824 styler.ColourTo(i, SCE_H_QUESTION);
825 state = beforePreProc;
826 if (inScriptType == eNonHtmlScriptPreProc)
827 inScriptType = eNonHtmlScript;
828 else
829 inScriptType = eHtml;
1e9bafca
RD
830 // Unfold all scripting languages, except for XML tag
831 if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
9e730a78 832 levelCurrent--;
1e9bafca
RD
833 }
834 scriptLanguage = eScriptNone;
f6bcfd97
BP
835 continue;
836 }
d134f170
RD
837 /////////////////////////////////////
838
839 switch (state) {
840 case SCE_H_DEFAULT:
f6bcfd97 841 if (ch == '<') {
65ec6247
RD
842 // in HTML, fold on tag open and unfold on tag close
843 tagOpened = true;
b8b0e402 844 tagClosing = (chNext == '/');
d134f170 845 styler.ColourTo(i - 1, StateToPrint);
b8b0e402 846 if (chNext != '!')
d134f170 847 state = SCE_H_TAGUNKNOWN;
f6bcfd97
BP
848 } else if (ch == '&') {
849 styler.ColourTo(i - 1, SCE_H_DEFAULT);
850 state = SCE_H_ENTITY;
851 }
d134f170 852 break;
b8b0e402 853 case SCE_H_SGML_DEFAULT:
1a2fb4cd
RD
854 case SCE_H_SGML_BLOCK_DEFAULT:
855// if (scriptLanguage == eScriptSGMLblock)
856// StateToPrint = SCE_H_SGML_BLOCK_DEFAULT;
b8b0e402
RD
857
858 if (ch == '\"') {
859 styler.ColourTo(i - 1, StateToPrint);
860 state = SCE_H_SGML_DOUBLESTRING;
861 } else if (ch == '\'') {
862 styler.ColourTo(i - 1, StateToPrint);
863 state = SCE_H_SGML_SIMPLESTRING;
864 } else if ((ch == '-') && (chPrev == '-')) {
865 styler.ColourTo(i - 2, StateToPrint);
866 state = SCE_H_SGML_COMMENT;
88a8b04e 867 } else if (isascii(ch) && isalpha(ch) && (chPrev == '%')) {
b8b0e402
RD
868 styler.ColourTo(i - 2, StateToPrint);
869 state = SCE_H_SGML_ENTITY;
870 } else if (ch == '#') {
871 styler.ColourTo(i - 1, StateToPrint);
872 state = SCE_H_SGML_SPECIAL;
873 } else if (ch == '[') {
874 styler.ColourTo(i - 1, StateToPrint);
875 scriptLanguage = eScriptSGMLblock;
1a2fb4cd 876 state = SCE_H_SGML_BLOCK_DEFAULT;
b8b0e402
RD
877 } else if (ch == ']') {
878 if (scriptLanguage == eScriptSGMLblock) {
879 styler.ColourTo(i, StateToPrint);
880 scriptLanguage = eScriptSGML;
881 } else {
882 styler.ColourTo(i - 1, StateToPrint);
883 styler.ColourTo(i, SCE_H_SGML_ERROR);
884 }
1a2fb4cd 885 state = SCE_H_SGML_DEFAULT;
b8b0e402
RD
886 } else if (scriptLanguage == eScriptSGMLblock) {
887 if ((ch == '!') && (chPrev == '<')) {
888 styler.ColourTo(i - 2, StateToPrint);
889 styler.ColourTo(i, SCE_H_SGML_DEFAULT);
890 state = SCE_H_SGML_COMMAND;
891 } else if (ch == '>') {
892 styler.ColourTo(i - 1, StateToPrint);
893 styler.ColourTo(i, SCE_H_SGML_DEFAULT);
894 }
895 }
896 break;
897 case SCE_H_SGML_COMMAND:
898 if ((ch == '-') && (chPrev == '-')) {
899 styler.ColourTo(i - 2, StateToPrint);
900 state = SCE_H_SGML_COMMENT;
901 } else if (!issgmlwordchar(ch)) {
902 if (isWordHSGML(styler.GetStartSegment(), i - 1, keywords6, styler)) {
903 styler.ColourTo(i - 1, StateToPrint);
904 state = SCE_H_SGML_1ST_PARAM;
905 } else {
906 state = SCE_H_SGML_ERROR;
907 }
908 }
909 break;
910 case SCE_H_SGML_1ST_PARAM:
911 // wait for the beginning of the word
912 if ((ch == '-') && (chPrev == '-')) {
913 if (scriptLanguage == eScriptSGMLblock) {
914 styler.ColourTo(i - 2, SCE_H_SGML_BLOCK_DEFAULT);
915 } else {
916 styler.ColourTo(i - 2, SCE_H_SGML_DEFAULT);
917 }
918 state = SCE_H_SGML_1ST_PARAM_COMMENT;
919 } else if (issgmlwordchar(ch)) {
920 if (scriptLanguage == eScriptSGMLblock) {
921 styler.ColourTo(i - 1, SCE_H_SGML_BLOCK_DEFAULT);
922 } else {
923 styler.ColourTo(i - 1, SCE_H_SGML_DEFAULT);
924 }
925 // find the length of the word
926 int size = 1;
927 while (ishtmlwordchar(styler.SafeGetCharAt(i + size)))
928 size++;
929 styler.ColourTo(i + size - 1, StateToPrint);
930 i += size - 1;
931 visibleChars += size - 1;
932 ch = styler.SafeGetCharAt(i);
1a2fb4cd
RD
933 if (scriptLanguage == eScriptSGMLblock) {
934 state = SCE_H_SGML_BLOCK_DEFAULT;
935 } else {
936 state = SCE_H_SGML_DEFAULT;
937 }
b8b0e402
RD
938 continue;
939 }
940 break;
941 case SCE_H_SGML_ERROR:
942 if ((ch == '-') && (chPrev == '-')) {
943 styler.ColourTo(i - 2, StateToPrint);
944 state = SCE_H_SGML_COMMENT;
945 }
946 case SCE_H_SGML_DOUBLESTRING:
947 if (ch == '\"') {
d134f170 948 styler.ColourTo(i, StateToPrint);
b8b0e402
RD
949 state = SCE_H_SGML_DEFAULT;
950 }
951 break;
952 case SCE_H_SGML_SIMPLESTRING:
953 if (ch == '\'') {
954 styler.ColourTo(i, StateToPrint);
955 state = SCE_H_SGML_DEFAULT;
956 }
957 break;
958 case SCE_H_SGML_COMMENT:
959 if ((ch == '-') && (chPrev == '-')) {
960 styler.ColourTo(i, StateToPrint);
961 state = SCE_H_SGML_DEFAULT;
d134f170
RD
962 }
963 break;
964 case SCE_H_CDATA:
b8b0e402 965 if ((chPrev2 == ']') && (chPrev == ']') && (ch == '>')) {
d134f170 966 styler.ColourTo(i, StateToPrint);
f6bcfd97 967 state = SCE_H_DEFAULT;
b8b0e402 968 levelCurrent--;
65ec6247
RD
969 }
970 break;
b8b0e402
RD
971 case SCE_H_COMMENT:
972 if ((chPrev2 == '-') && (chPrev == '-') && (ch == '>')) {
65ec6247
RD
973 styler.ColourTo(i, StateToPrint);
974 state = SCE_H_DEFAULT;
b8b0e402
RD
975 levelCurrent--;
976 }
977 break;
978 case SCE_H_SGML_1ST_PARAM_COMMENT:
979 if ((ch == '-') && (chPrev == '-')) {
980 styler.ColourTo(i, SCE_H_SGML_COMMENT);
981 state = SCE_H_SGML_1ST_PARAM;
982 }
983 break;
984 case SCE_H_SGML_SPECIAL:
88a8b04e 985 if (!(isascii(ch) && isupper(ch))) {
b8b0e402
RD
986 styler.ColourTo(i - 1, StateToPrint);
987 if (isalnum(ch)) {
988 state = SCE_H_SGML_ERROR;
989 } else {
990 state = SCE_H_SGML_DEFAULT;
991 }
992 }
993 break;
994 case SCE_H_SGML_ENTITY:
995 if (ch == ';') {
996 styler.ColourTo(i, StateToPrint);
997 state = SCE_H_SGML_DEFAULT;
88a8b04e 998 } else if (!(isascii(ch) && isalnum(ch)) && ch != '-' && ch != '.') {
b8b0e402
RD
999 styler.ColourTo(i, SCE_H_SGML_ERROR);
1000 state = SCE_H_SGML_DEFAULT;
f6bcfd97 1001 }
d134f170
RD
1002 break;
1003 case SCE_H_ENTITY:
f6bcfd97 1004 if (ch == ';') {
d134f170 1005 styler.ColourTo(i, StateToPrint);
f6bcfd97
BP
1006 state = SCE_H_DEFAULT;
1007 }
591d01be
RD
1008 if (ch != '#' && !(isascii(ch) && isalnum(ch)) // Should check that '#' follows '&', but it is unlikely anyway...
1009 && ch != '.' && ch != '-' && ch != '_' && ch != ':') { // valid in XML
d134f170
RD
1010 styler.ColourTo(i, SCE_H_TAGUNKNOWN);
1011 state = SCE_H_DEFAULT;
1012 }
1013 break;
1014 case SCE_H_TAGUNKNOWN:
65ec6247 1015 if (!ishtmlwordchar(ch) && !((ch == '/') && (chPrev == '<')) && ch != '[') {
9e730a78
RD
1016 int eClass = classifyTagHTML(styler.GetStartSegment(),
1017 i - 1, keywords, styler, tagDontFold, caseSensitive);
d134f170 1018 if (eClass == SCE_H_SCRIPT) {
b8b0e402
RD
1019 if (!tagClosing) {
1020 inScriptType = eNonHtmlScript;
1021 scriptLanguage = clientScript;
1022 eClass = SCE_H_TAG;
1023 } else {
1024 scriptLanguage = eScriptNone;
1025 eClass = SCE_H_TAG;
1026 }
f6bcfd97
BP
1027 }
1028 if (ch == '>') {
65ec6247 1029 styler.ColourTo(i, eClass);
d134f170
RD
1030 if (inScriptType == eNonHtmlScript) {
1031 state = StateForScript(scriptLanguage);
f6bcfd97
BP
1032 } else {
1033 state = SCE_H_DEFAULT;
1034 }
65ec6247 1035 tagOpened = false;
9e730a78
RD
1036 if (!tagDontFold){
1037 if (tagClosing) {
1038 levelCurrent--;
1039 } else {
1040 levelCurrent++;
1041 }
b8b0e402 1042 }
65ec6247 1043 tagClosing = false;
b8b0e402 1044 } else if (ch == '/' && chNext == '>') {
65ec6247 1045 if (eClass == SCE_H_TAGUNKNOWN) {
b8b0e402 1046 styler.ColourTo(i + 1, SCE_H_TAGUNKNOWN);
f6bcfd97 1047 } else {
b8b0e402
RD
1048 styler.ColourTo(i - 1, StateToPrint);
1049 styler.ColourTo(i + 1, SCE_H_TAGEND);
65ec6247 1050 }
b8b0e402
RD
1051 i++;
1052 ch = chNext;
1053 state = SCE_H_DEFAULT;
65ec6247
RD
1054 tagOpened = false;
1055 } else {
1056 if (eClass != SCE_H_TAGUNKNOWN) {
b8b0e402
RD
1057 if (eClass == SCE_H_SGML_DEFAULT) {
1058 state = SCE_H_SGML_DEFAULT;
65ec6247
RD
1059 } else {
1060 state = SCE_H_OTHER;
1061 }
f6bcfd97
BP
1062 }
1063 }
1064 }
d134f170
RD
1065 break;
1066 case SCE_H_ATTRIBUTE:
f6bcfd97 1067 if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
d134f170 1068 if (inScriptType == eNonHtmlScript) {
65ec6247 1069 int scriptLanguagePrev = scriptLanguage;
b8b0e402
RD
1070 clientScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i - 1, scriptLanguage);
1071 scriptLanguage = clientScript;
65ec6247
RD
1072 if ((scriptLanguagePrev != scriptLanguage) && (scriptLanguage == eScriptNone))
1073 inScriptType = eHtml;
d134f170 1074 }
f6bcfd97
BP
1075 classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
1076 if (ch == '>') {
1077 styler.ColourTo(i, SCE_H_TAG);
d134f170
RD
1078 if (inScriptType == eNonHtmlScript) {
1079 state = StateForScript(scriptLanguage);
f6bcfd97
BP
1080 } else {
1081 state = SCE_H_DEFAULT;
1082 }
65ec6247 1083 tagOpened = false;
9e730a78
RD
1084 if (!tagDontFold){
1085 if (tagClosing){
1086 levelCurrent--;
1087 } else {
1088 levelCurrent++;
1089 }
1090 }
65ec6247 1091 tagClosing = false;
d134f170
RD
1092 } else if (ch == '=') {
1093 styler.ColourTo(i, SCE_H_OTHER);
1094 state = SCE_H_VALUE;
f6bcfd97
BP
1095 } else {
1096 state = SCE_H_OTHER;
1097 }
1098 }
d134f170
RD
1099 break;
1100 case SCE_H_OTHER:
f6bcfd97 1101 if (ch == '>') {
d134f170 1102 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1103 styler.ColourTo(i, SCE_H_TAG);
d134f170
RD
1104 if (inScriptType == eNonHtmlScript) {
1105 state = StateForScript(scriptLanguage);
f6bcfd97
BP
1106 } else {
1107 state = SCE_H_DEFAULT;
1108 }
65ec6247 1109 tagOpened = false;
9e730a78
RD
1110 if (!tagDontFold){
1111 if (tagClosing){
1112 levelCurrent--;
1113 } else {
1114 levelCurrent++;
1115 }
1116 }
65ec6247 1117 tagClosing = false;
f6bcfd97 1118 } else if (ch == '\"') {
d134f170 1119 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1120 state = SCE_H_DOUBLESTRING;
1121 } else if (ch == '\'') {
d134f170 1122 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1123 state = SCE_H_SINGLESTRING;
d134f170
RD
1124 } else if (ch == '=') {
1125 styler.ColourTo(i, StateToPrint);
1126 state = SCE_H_VALUE;
f6bcfd97 1127 } else if (ch == '/' && chNext == '>') {
d134f170 1128 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1129 styler.ColourTo(i + 1, SCE_H_TAGEND);
1130 i++;
1131 ch = chNext;
1132 state = SCE_H_DEFAULT;
65ec6247 1133 tagOpened = false;
f6bcfd97 1134 } else if (ch == '?' && chNext == '>') {
d134f170 1135 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1136 styler.ColourTo(i + 1, SCE_H_XMLEND);
1137 i++;
1138 ch = chNext;
1139 state = SCE_H_DEFAULT;
1140 } else if (ishtmlwordchar(ch)) {
d134f170 1141 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1142 state = SCE_H_ATTRIBUTE;
1143 }
d134f170
RD
1144 break;
1145 case SCE_H_DOUBLESTRING:
f6bcfd97 1146 if (ch == '\"') {
d134f170 1147 if (inScriptType == eNonHtmlScript) {
f6bcfd97 1148 scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
d134f170 1149 }
f6bcfd97
BP
1150 styler.ColourTo(i, SCE_H_DOUBLESTRING);
1151 state = SCE_H_OTHER;
1152 }
d134f170
RD
1153 break;
1154 case SCE_H_SINGLESTRING:
f6bcfd97 1155 if (ch == '\'') {
d134f170 1156 if (inScriptType == eNonHtmlScript) {
f6bcfd97 1157 scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
d134f170 1158 }
f6bcfd97
BP
1159 styler.ColourTo(i, SCE_H_SINGLESTRING);
1160 state = SCE_H_OTHER;
1161 }
d134f170
RD
1162 break;
1163 case SCE_H_VALUE:
1164 if (!ishtmlwordchar(ch)) {
9e730a78 1165 if (ch == '\"' && chPrev == '=') {
d134f170
RD
1166 // Should really test for being first character
1167 state = SCE_H_DOUBLESTRING;
9e730a78 1168 } else if (ch == '\'' && chPrev == '=') {
d134f170
RD
1169 state = SCE_H_SINGLESTRING;
1170 } else {
1171 if (IsNumber(styler.GetStartSegment(), styler)) {
1172 styler.ColourTo(i - 1, SCE_H_NUMBER);
1173 } else {
1174 styler.ColourTo(i - 1, StateToPrint);
1175 }
1176 if (ch == '>') {
1177 styler.ColourTo(i, SCE_H_TAG);
1178 if (inScriptType == eNonHtmlScript) {
1179 state = StateForScript(scriptLanguage);
1180 } else {
1181 state = SCE_H_DEFAULT;
1182 }
65ec6247 1183 tagOpened = false;
9e730a78
RD
1184 if (!tagDontFold){
1185 if (tagClosing){
1186 levelCurrent--;
1187 } else {
1188 levelCurrent++;
1189 }
1190 }
65ec6247 1191 tagClosing = false;
d134f170
RD
1192 } else {
1193 state = SCE_H_OTHER;
1194 }
1195 }
1196 }
1197 break;
1198 case SCE_HJ_DEFAULT:
1199 case SCE_HJ_START:
1200 case SCE_HJ_SYMBOLS:
f6bcfd97 1201 if (iswordstart(ch)) {
d134f170 1202 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1203 state = SCE_HJ_WORD;
1204 } else if (ch == '/' && chNext == '*') {
d134f170 1205 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1206 if (chNext2 == '*')
1207 state = SCE_HJ_COMMENTDOC;
1208 else
1209 state = SCE_HJ_COMMENT;
1210 } else if (ch == '/' && chNext == '/') {
d134f170 1211 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1212 state = SCE_HJ_COMMENTLINE;
65ec6247
RD
1213 } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
1214 styler.ColourTo(i - 1, StateToPrint);
1215 state = SCE_HJ_REGEX;
f6bcfd97 1216 } else if (ch == '\"') {
d134f170 1217 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1218 state = SCE_HJ_DOUBLESTRING;
1219 } else if (ch == '\'') {
d134f170 1220 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1221 state = SCE_HJ_SINGLESTRING;
f6bcfd97 1222 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
d134f170
RD
1223 styler.SafeGetCharAt(i + 3) == '-') {
1224 styler.ColourTo(i - 1, StateToPrint);
1225 state = SCE_HJ_COMMENTLINE;
1226 } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
1227 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1228 state = SCE_HJ_COMMENTLINE;
d134f170 1229 i += 2;
f6bcfd97 1230 } else if (isoperator(ch)) {
d134f170
RD
1231 styler.ColourTo(i - 1, StateToPrint);
1232 styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
f6bcfd97
BP
1233 state = SCE_HJ_DEFAULT;
1234 } else if ((ch == ' ') || (ch == '\t')) {
1235 if (state == SCE_HJ_START) {
d134f170 1236 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1237 state = SCE_HJ_DEFAULT;
1238 }
1239 }
d134f170
RD
1240 break;
1241 case SCE_HJ_WORD:
f6bcfd97 1242 if (!iswordchar(ch)) {
d134f170 1243 classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler, inScriptType);
f6bcfd97
BP
1244 //styler.ColourTo(i - 1, eHTJSKeyword);
1245 state = SCE_HJ_DEFAULT;
1246 if (ch == '/' && chNext == '*') {
1247 if (chNext2 == '*')
1248 state = SCE_HJ_COMMENTDOC;
1249 else
1250 state = SCE_HJ_COMMENT;
1251 } else if (ch == '/' && chNext == '/') {
1252 state = SCE_HJ_COMMENTLINE;
1253 } else if (ch == '\"') {
1254 state = SCE_HJ_DOUBLESTRING;
1255 } else if (ch == '\'') {
1256 state = SCE_HJ_SINGLESTRING;
d134f170
RD
1257 } else if ((ch == '-') && (chNext == '-') && (chNext2 == '>')) {
1258 styler.ColourTo(i - 1, StateToPrint);
1259 state = SCE_HJ_COMMENTLINE;
1260 i += 2;
f6bcfd97 1261 } else if (isoperator(ch)) {
d134f170 1262 styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
f6bcfd97
BP
1263 state = SCE_HJ_DEFAULT;
1264 }
1265 }
d134f170
RD
1266 break;
1267 case SCE_HJ_COMMENT:
1268 case SCE_HJ_COMMENTDOC:
f6bcfd97 1269 if (ch == '/' && chPrev == '*') {
d134f170 1270 styler.ColourTo(i, StateToPrint);
f6bcfd97 1271 state = SCE_HJ_DEFAULT;
1e9bafca 1272 ch = ' ';
f6bcfd97 1273 }
d134f170
RD
1274 break;
1275 case SCE_HJ_COMMENTLINE:
f6bcfd97 1276 if (ch == '\r' || ch == '\n') {
d134f170 1277 styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType));
f6bcfd97 1278 state = SCE_HJ_DEFAULT;
1e9bafca 1279 ch = ' ';
f6bcfd97 1280 }
d134f170
RD
1281 break;
1282 case SCE_HJ_DOUBLESTRING:
f6bcfd97
BP
1283 if (ch == '\\') {
1284 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1285 i++;
1286 }
1287 } else if (ch == '\"') {
d134f170 1288 styler.ColourTo(i, statePrintForState(SCE_HJ_DOUBLESTRING, inScriptType));
f6bcfd97 1289 state = SCE_HJ_DEFAULT;
d134f170
RD
1290 } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
1291 styler.ColourTo(i - 1, StateToPrint);
1292 state = SCE_HJ_COMMENTLINE;
1293 i += 2;
f6bcfd97 1294 } else if (isLineEnd(ch)) {
d134f170 1295 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1296 state = SCE_HJ_STRINGEOL;
1297 }
d134f170
RD
1298 break;
1299 case SCE_HJ_SINGLESTRING:
f6bcfd97
BP
1300 if (ch == '\\') {
1301 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1302 i++;
1303 }
1304 } else if (ch == '\'') {
d134f170 1305 styler.ColourTo(i, statePrintForState(SCE_HJ_SINGLESTRING, inScriptType));
f6bcfd97 1306 state = SCE_HJ_DEFAULT;
d134f170
RD
1307 } else if ((inScriptType == eNonHtmlScript) && (ch == '-') && (chNext == '-') && (chNext2 == '>')) {
1308 styler.ColourTo(i - 1, StateToPrint);
1309 state = SCE_HJ_COMMENTLINE;
1310 i += 2;
f6bcfd97 1311 } else if (isLineEnd(ch)) {
d134f170 1312 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1313 state = SCE_HJ_STRINGEOL;
1314 }
d134f170
RD
1315 break;
1316 case SCE_HJ_STRINGEOL:
f6bcfd97 1317 if (!isLineEnd(ch)) {
d134f170 1318 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1319 state = SCE_HJ_DEFAULT;
1320 } else if (!isLineEnd(chNext)) {
d134f170 1321 styler.ColourTo(i, StateToPrint);
f6bcfd97
BP
1322 state = SCE_HJ_DEFAULT;
1323 }
d134f170 1324 break;
65ec6247
RD
1325 case SCE_HJ_REGEX:
1326 if (ch == '\r' || ch == '\n' || ch == '/') {
1e9bafca
RD
1327 if (ch == '/') {
1328 while (isascii(chNext) && islower(chNext)) { // gobble regex flags
1329 i++;
1330 ch = chNext;
1331 chNext = styler.SafeGetCharAt(i + 1);
1332 }
1333 }
65ec6247
RD
1334 styler.ColourTo(i, StateToPrint);
1335 state = SCE_HJ_DEFAULT;
1336 } else if (ch == '\\') {
1337 // Gobble up the quoted character
1338 if (chNext == '\\' || chNext == '/') {
1339 i++;
1340 ch = chNext;
1341 chNext = styler.SafeGetCharAt(i + 1);
1342 }
1343 }
1344 break;
d134f170
RD
1345 case SCE_HB_DEFAULT:
1346 case SCE_HB_START:
f6bcfd97 1347 if (iswordstart(ch)) {
d134f170 1348 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1349 state = SCE_HB_WORD;
1350 } else if (ch == '\'') {
d134f170 1351 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1352 state = SCE_HB_COMMENTLINE;
1353 } else if (ch == '\"') {
d134f170 1354 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1355 state = SCE_HB_STRING;
f6bcfd97 1356 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
d134f170
RD
1357 styler.SafeGetCharAt(i + 3) == '-') {
1358 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1359 state = SCE_HB_COMMENTLINE;
1360 } else if (isoperator(ch)) {
d134f170 1361 styler.ColourTo(i - 1, StateToPrint);
65ec6247 1362 styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
f6bcfd97
BP
1363 state = SCE_HB_DEFAULT;
1364 } else if ((ch == ' ') || (ch == '\t')) {
1365 if (state == SCE_HB_START) {
d134f170 1366 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1367 state = SCE_HB_DEFAULT;
1368 }
1369 }
d134f170
RD
1370 break;
1371 case SCE_HB_WORD:
f6bcfd97 1372 if (!iswordchar(ch)) {
d134f170 1373 state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType);
f6bcfd97
BP
1374 if (state == SCE_HB_DEFAULT) {
1375 if (ch == '\"') {
1376 state = SCE_HB_STRING;
1377 } else if (ch == '\'') {
1378 state = SCE_HB_COMMENTLINE;
1379 } else if (isoperator(ch)) {
d134f170 1380 styler.ColourTo(i, statePrintForState(SCE_HB_DEFAULT, inScriptType));
f6bcfd97
BP
1381 state = SCE_HB_DEFAULT;
1382 }
1383 }
1384 }
d134f170
RD
1385 break;
1386 case SCE_HB_STRING:
f6bcfd97 1387 if (ch == '\"') {
d134f170 1388 styler.ColourTo(i, StateToPrint);
f6bcfd97 1389 state = SCE_HB_DEFAULT;
f6bcfd97 1390 } else if (ch == '\r' || ch == '\n') {
d134f170 1391 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1392 state = SCE_HB_STRINGEOL;
1393 }
d134f170
RD
1394 break;
1395 case SCE_HB_COMMENTLINE:
f6bcfd97 1396 if (ch == '\r' || ch == '\n') {
d134f170 1397 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1398 state = SCE_HB_DEFAULT;
f6bcfd97 1399 }
d134f170
RD
1400 break;
1401 case SCE_HB_STRINGEOL:
f6bcfd97 1402 if (!isLineEnd(ch)) {
d134f170 1403 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1404 state = SCE_HB_DEFAULT;
1405 } else if (!isLineEnd(chNext)) {
d134f170 1406 styler.ColourTo(i, StateToPrint);
f6bcfd97
BP
1407 state = SCE_HB_DEFAULT;
1408 }
d134f170
RD
1409 break;
1410 case SCE_HP_DEFAULT:
1411 case SCE_HP_START:
f6bcfd97 1412 if (iswordstart(ch)) {
d134f170 1413 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97 1414 state = SCE_HP_WORD;
f6bcfd97 1415 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
d134f170
RD
1416 styler.SafeGetCharAt(i + 3) == '-') {
1417 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1418 state = SCE_HP_COMMENTLINE;
1419 } else if (ch == '#') {
d134f170 1420 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1421 state = SCE_HP_COMMENTLINE;
1422 } else if (ch == '\"') {
d134f170 1423 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1424 if (chNext == '\"' && chNext2 == '\"') {
1425 i += 2;
1426 state = SCE_HP_TRIPLEDOUBLE;
1427 ch = ' ';
1428 chPrev = ' ';
1429 chNext = styler.SafeGetCharAt(i + 1);
1430 } else {
d134f170 1431 // state = statePrintForState(SCE_HP_STRING,inScriptType);
f6bcfd97
BP
1432 state = SCE_HP_STRING;
1433 }
1434 } else if (ch == '\'') {
d134f170 1435 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1436 if (chNext == '\'' && chNext2 == '\'') {
1437 i += 2;
1438 state = SCE_HP_TRIPLE;
1439 ch = ' ';
1440 chPrev = ' ';
1441 chNext = styler.SafeGetCharAt(i + 1);
1442 } else {
1443 state = SCE_HP_CHARACTER;
1444 }
1445 } else if (isoperator(ch)) {
d134f170
RD
1446 styler.ColourTo(i - 1, StateToPrint);
1447 styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
f6bcfd97
BP
1448 } else if ((ch == ' ') || (ch == '\t')) {
1449 if (state == SCE_HP_START) {
d134f170 1450 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1451 state = SCE_HP_DEFAULT;
1452 }
1453 }
d134f170
RD
1454 break;
1455 case SCE_HP_WORD:
f6bcfd97 1456 if (!iswordchar(ch)) {
d134f170 1457 classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType);
f6bcfd97
BP
1458 state = SCE_HP_DEFAULT;
1459 if (ch == '#') {
1460 state = SCE_HP_COMMENTLINE;
1461 } else if (ch == '\"') {
1462 if (chNext == '\"' && chNext2 == '\"') {
1463 i += 2;
1464 state = SCE_HP_TRIPLEDOUBLE;
1465 ch = ' ';
1466 chPrev = ' ';
1467 chNext = styler.SafeGetCharAt(i + 1);
1468 } else {
1469 state = SCE_HP_STRING;
1470 }
1471 } else if (ch == '\'') {
1472 if (chNext == '\'' && chNext2 == '\'') {
1473 i += 2;
1474 state = SCE_HP_TRIPLE;
1475 ch = ' ';
1476 chPrev = ' ';
1477 chNext = styler.SafeGetCharAt(i + 1);
1478 } else {
1479 state = SCE_HP_CHARACTER;
1480 }
1481 } else if (isoperator(ch)) {
d134f170 1482 styler.ColourTo(i, statePrintForState(SCE_HP_OPERATOR, inScriptType));
f6bcfd97
BP
1483 }
1484 }
d134f170
RD
1485 break;
1486 case SCE_HP_COMMENTLINE:
f6bcfd97 1487 if (ch == '\r' || ch == '\n') {
d134f170 1488 styler.ColourTo(i - 1, StateToPrint);
f6bcfd97
BP
1489 state = SCE_HP_DEFAULT;
1490 }
d134f170
RD
1491 break;
1492 case SCE_HP_STRING:
f6bcfd97
BP
1493 if (ch == '\\') {
1494 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1495 i++;
1496 ch = chNext;
1497 chNext = styler.SafeGetCharAt(i + 1);
1498 }
1499 } else if (ch == '\"') {
d134f170 1500 styler.ColourTo(i, StateToPrint);
f6bcfd97
BP
1501 state = SCE_HP_DEFAULT;
1502 }
d134f170
RD
1503 break;
1504 case SCE_HP_CHARACTER:
f6bcfd97
BP
1505 if (ch == '\\') {
1506 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1507 i++;
1508 ch = chNext;
1509 chNext = styler.SafeGetCharAt(i + 1);
1510 }
1511 } else if (ch == '\'') {
d134f170 1512 styler.ColourTo(i, StateToPrint);
f6bcfd97
BP
1513 state = SCE_HP_DEFAULT;
1514 }
d134f170
RD
1515 break;
1516 case SCE_HP_TRIPLE:
f6bcfd97 1517 if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
d134f170 1518 styler.ColourTo(i, StateToPrint);
f6bcfd97
BP
1519 state = SCE_HP_DEFAULT;
1520 }
d134f170
RD
1521 break;
1522 case SCE_HP_TRIPLEDOUBLE:
f6bcfd97 1523 if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
d134f170 1524 styler.ColourTo(i, StateToPrint);
f6bcfd97
BP
1525 state = SCE_HP_DEFAULT;
1526 }
d134f170
RD
1527 break;
1528 ///////////// start - PHP state handling
1529 case SCE_HPHP_WORD:
9e730a78 1530 if (!iswordchar(ch)) {
d134f170
RD
1531 classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
1532 if (ch == '/' && chNext == '*') {
1533 i++;
1534 state = SCE_HPHP_COMMENT;
1535 } else if (ch == '/' && chNext == '/') {
1536 i++;
1537 state = SCE_HPHP_COMMENTLINE;
1538 } else if (ch == '#') {
1539 state = SCE_HPHP_COMMENTLINE;
f6bcfd97 1540 } else if (ch == '\"') {
d134f170 1541 state = SCE_HPHP_HSTRING;
591d01be
RD
1542 strcpy(phpStringDelimiter, "\"");
1543 } else if (styler.Match(i, "<<<")) {
1544 state = SCE_HPHP_HSTRING;
1545 i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler);
f6bcfd97 1546 } else if (ch == '\'') {
d134f170 1547 state = SCE_HPHP_SIMPLESTRING;
9e730a78 1548 } else if (ch == '$' && IsPhpWordStart(chNext)) {
d134f170 1549 state = SCE_HPHP_VARIABLE;
65ec6247
RD
1550 } else if (isoperator(ch)) {
1551 state = SCE_HPHP_OPERATOR;
d134f170
RD
1552 } else {
1553 state = SCE_HPHP_DEFAULT;
f6bcfd97
BP
1554 }
1555 }
d134f170
RD
1556 break;
1557 case SCE_HPHP_NUMBER:
1e9bafca
RD
1558 // recognize bases 8,10 or 16 integers OR floating-point numbers
1559 if (!IsADigit(ch)
1560 && strchr(".xXabcdefABCDEF", ch) == NULL
1561 && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) {
d134f170 1562 styler.ColourTo(i - 1, SCE_HPHP_NUMBER);
b8b0e402
RD
1563 if (isoperator(ch))
1564 state = SCE_HPHP_OPERATOR;
1565 else
65ec6247 1566 state = SCE_HPHP_DEFAULT;
d134f170
RD
1567 }
1568 break;
1569 case SCE_HPHP_VARIABLE:
9e730a78 1570 if (!IsPhpWordChar(ch)) {
d134f170 1571 styler.ColourTo(i - 1, SCE_HPHP_VARIABLE);
b8b0e402
RD
1572 if (isoperator(ch))
1573 state = SCE_HPHP_OPERATOR;
1574 else
65ec6247 1575 state = SCE_HPHP_DEFAULT;
d134f170
RD
1576 }
1577 break;
1578 case SCE_HPHP_COMMENT:
1579 if (ch == '/' && chPrev == '*') {
1580 styler.ColourTo(i, StateToPrint);
1581 state = SCE_HPHP_DEFAULT;
1582 }
1583 break;
1584 case SCE_HPHP_COMMENTLINE:
f6bcfd97 1585 if (ch == '\r' || ch == '\n') {
d134f170
RD
1586 styler.ColourTo(i - 1, StateToPrint);
1587 state = SCE_HPHP_DEFAULT;
f6bcfd97 1588 }
d134f170
RD
1589 break;
1590 case SCE_HPHP_HSTRING:
591d01be 1591 if (ch == '\\' && (phpStringDelimiter[0] == '\"' || chNext == '$' || chNext == '{')) {
65ec6247
RD
1592 // skip the next char
1593 i++;
591d01be
RD
1594 } else if (((ch == '{' && chNext == '$') || (ch == '$' && chNext == '{'))
1595 && IsPhpWordStart(chNext2)) {
1596 styler.ColourTo(i - 1, StateToPrint);
1597 state = SCE_HPHP_COMPLEX_VARIABLE;
9e730a78 1598 } else if (ch == '$' && IsPhpWordStart(chNext)) {
b8b0e402 1599 styler.ColourTo(i - 1, StateToPrint);
65ec6247 1600 state = SCE_HPHP_HSTRING_VARIABLE;
591d01be
RD
1601 } else if (styler.Match(i, phpStringDelimiter)) {
1602 if (strlen(phpStringDelimiter) > 1)
1603 i += strlen(phpStringDelimiter) - 1;
d134f170
RD
1604 styler.ColourTo(i, StateToPrint);
1605 state = SCE_HPHP_DEFAULT;
f6bcfd97 1606 }
d134f170
RD
1607 break;
1608 case SCE_HPHP_SIMPLESTRING:
65ec6247
RD
1609 if (ch == '\\') {
1610 // skip the next char
1611 i++;
1612 } else if (ch == '\'') {
d134f170
RD
1613 styler.ColourTo(i, StateToPrint);
1614 state = SCE_HPHP_DEFAULT;
f6bcfd97 1615 }
d134f170 1616 break;
65ec6247 1617 case SCE_HPHP_HSTRING_VARIABLE:
9e730a78 1618 if (!IsPhpWordChar(ch)) {
b8b0e402 1619 styler.ColourTo(i - 1, StateToPrint);
65ec6247
RD
1620 i--; // strange but it works
1621 state = SCE_HPHP_HSTRING;
1622 }
1623 break;
591d01be
RD
1624 case SCE_HPHP_COMPLEX_VARIABLE:
1625 if (ch == '}') {
1626 styler.ColourTo(i, StateToPrint);
1627 state = SCE_HPHP_HSTRING;
1628 }
1629 break;
65ec6247 1630 case SCE_HPHP_OPERATOR:
b8b0e402 1631 case SCE_HPHP_DEFAULT:
d134f170 1632 styler.ColourTo(i - 1, StateToPrint);
a33203cb 1633 if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) {
d134f170
RD
1634 state = SCE_HPHP_NUMBER;
1635 } else if (iswordstart(ch)) {
1636 state = SCE_HPHP_WORD;
1637 } else if (ch == '/' && chNext == '*') {
1638 i++;
1639 state = SCE_HPHP_COMMENT;
1640 } else if (ch == '/' && chNext == '/') {
1641 i++;
1642 state = SCE_HPHP_COMMENTLINE;
1643 } else if (ch == '#') {
1644 state = SCE_HPHP_COMMENTLINE;
1645 } else if (ch == '\"') {
1646 state = SCE_HPHP_HSTRING;
591d01be
RD
1647 strcpy(phpStringDelimiter, "\"");
1648 } else if (styler.Match(i, "<<<")) {
1649 state = SCE_HPHP_HSTRING;
1650 i = FindPhpStringDelimiter(phpStringDelimiter, sizeof(phpStringDelimiter), i + 3, lengthDoc, styler);
d134f170
RD
1651 } else if (ch == '\'') {
1652 state = SCE_HPHP_SIMPLESTRING;
9e730a78 1653 } else if (ch == '$' && IsPhpWordStart(chNext)) {
d134f170 1654 state = SCE_HPHP_VARIABLE;
65ec6247
RD
1655 } else if (isoperator(ch)) {
1656 state = SCE_HPHP_OPERATOR;
1657 } else if ((state == SCE_HPHP_OPERATOR) && (isspacechar(ch))) {
1658 state = SCE_HPHP_DEFAULT;
f6bcfd97 1659 }
d134f170
RD
1660 break;
1661 ///////////// end - PHP state handling
f6bcfd97 1662 }
d134f170 1663
65ec6247
RD
1664 // Some of the above terminated their lexeme but since the same character starts
1665 // the same class again, only reenter if non empty segment.
b8b0e402 1666
65ec6247 1667 bool nonEmptySegment = i >= static_cast<int>(styler.GetStartSegment());
f6bcfd97 1668 if (state == SCE_HB_DEFAULT) { // One of the above succeeded
65ec6247 1669 if ((ch == '\"') && (nonEmptySegment)) {
f6bcfd97
BP
1670 state = SCE_HB_STRING;
1671 } else if (ch == '\'') {
1672 state = SCE_HB_COMMENTLINE;
1673 } else if (iswordstart(ch)) {
1674 state = SCE_HB_WORD;
1675 } else if (isoperator(ch)) {
1676 styler.ColourTo(i, SCE_HB_DEFAULT);
1677 }
d134f170 1678 } else if (state == SCE_HBA_DEFAULT) { // One of the above succeeded
65ec6247 1679 if ((ch == '\"') && (nonEmptySegment)) {
f6bcfd97
BP
1680 state = SCE_HBA_STRING;
1681 } else if (ch == '\'') {
1682 state = SCE_HBA_COMMENTLINE;
1683 } else if (iswordstart(ch)) {
1684 state = SCE_HBA_WORD;
1685 } else if (isoperator(ch)) {
1686 styler.ColourTo(i, SCE_HBA_DEFAULT);
1687 }
d134f170 1688 } else if (state == SCE_HJ_DEFAULT) { // One of the above succeeded
f6bcfd97
BP
1689 if (ch == '/' && chNext == '*') {
1690 if (styler.SafeGetCharAt(i + 2) == '*')
1691 state = SCE_HJ_COMMENTDOC;
1692 else
1693 state = SCE_HJ_COMMENT;
1694 } else if (ch == '/' && chNext == '/') {
1695 state = SCE_HJ_COMMENTLINE;
65ec6247 1696 } else if ((ch == '\"') && (nonEmptySegment)) {
f6bcfd97 1697 state = SCE_HJ_DOUBLESTRING;
b8b0e402 1698 } else if ((ch == '\'') && (nonEmptySegment)) {
f6bcfd97
BP
1699 state = SCE_HJ_SINGLESTRING;
1700 } else if (iswordstart(ch)) {
1701 state = SCE_HJ_WORD;
1702 } else if (isoperator(ch)) {
65ec6247 1703 styler.ColourTo(i, statePrintForState(SCE_HJ_SYMBOLS, inScriptType));
f6bcfd97
BP
1704 }
1705 }
f6bcfd97 1706 }
d134f170
RD
1707
1708 StateToPrint = statePrintForState(state, inScriptType);
9e730a78 1709 styler.ColourTo(lengthDoc - 1, StateToPrint);
d134f170
RD
1710
1711 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
1712 if (fold) {
1713 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
d134f170 1714 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
d134f170 1715 }
f6bcfd97
BP
1716}
1717
1a2fb4cd
RD
1718static bool isASPScript(int state) {
1719 return
1720 (state >= SCE_HJA_START && state <= SCE_HJA_REGEX) ||
1721 (state >= SCE_HBA_START && state <= SCE_HBA_STRINGEOL) ||
1722 (state >= SCE_HPA_DEFAULT && state <= SCE_HPA_IDENTIFIER);
1723}
1724
1725static void ColouriseHBAPiece(StyleContext &sc, WordList *keywordlists[]) {
1726 WordList &keywordsVBS = *keywordlists[2];
1727 if (sc.state == SCE_HBA_WORD) {
1728 if (!IsAWordChar(sc.ch)) {
1729 char s[100];
1730 sc.GetCurrentLowered(s, sizeof(s));
1731 if (keywordsVBS.InList(s)) {
1732 if (strcmp(s, "rem") == 0) {
1733 sc.ChangeState(SCE_HBA_COMMENTLINE);
1734 if (sc.atLineEnd) {
1735 sc.SetState(SCE_HBA_DEFAULT);
1736 }
1737 } else {
1738 sc.SetState(SCE_HBA_DEFAULT);
1739 }
1740 } else {
1741 sc.ChangeState(SCE_HBA_IDENTIFIER);
1742 sc.SetState(SCE_HBA_DEFAULT);
1743 }
1744 }
1745 } else if (sc.state == SCE_HBA_NUMBER) {
1746 if (!IsAWordChar(sc.ch)) {
1747 sc.SetState(SCE_HBA_DEFAULT);
1748 }
1749 } else if (sc.state == SCE_HBA_STRING) {
1750 if (sc.ch == '\"') {
1751 sc.ForwardSetState(SCE_HBA_DEFAULT);
1752 } else if (sc.ch == '\r' || sc.ch == '\n') {
1753 sc.ChangeState(SCE_HBA_STRINGEOL);
1754 sc.ForwardSetState(SCE_HBA_DEFAULT);
1755 }
1756 } else if (sc.state == SCE_HBA_COMMENTLINE) {
1757 if (sc.ch == '\r' || sc.ch == '\n') {
1758 sc.SetState(SCE_HBA_DEFAULT);
1759 }
1760 }
1761
1762 if (sc.state == SCE_HBA_DEFAULT) {
1763 if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
1764 sc.SetState(SCE_HBA_NUMBER);
1765 } else if (IsAWordStart(sc.ch)) {
1766 sc.SetState(SCE_HBA_WORD);
1767 } else if (sc.ch == '\'') {
1768 sc.SetState(SCE_HBA_COMMENTLINE);
1769 } else if (sc.ch == '\"') {
1770 sc.SetState(SCE_HBA_STRING);
1771 }
1772 }
1773}
1774
1775static void ColouriseHTMLPiece(StyleContext &sc, WordList *keywordlists[]) {
1776 WordList &keywordsTags = *keywordlists[0];
1777 if (sc.state == SCE_H_COMMENT) {
1778 if (sc.Match("-->")) {
1779 sc.Forward();
1780 sc.Forward();
1781 sc.ForwardSetState(SCE_H_DEFAULT);
1782 }
1783 } else if (sc.state == SCE_H_ENTITY) {
1784 if (sc.ch == ';') {
1785 sc.ForwardSetState(SCE_H_DEFAULT);
591d01be
RD
1786 } else if (sc.ch != '#' && (sc.ch < 0x80) && !isalnum(sc.ch) // Should check that '#' follows '&', but it is unlikely anyway...
1787 && sc.ch != '.' && sc.ch != '-' && sc.ch != '_' && sc.ch != ':') { // valid in XML
1a2fb4cd
RD
1788 sc.ChangeState(SCE_H_TAGUNKNOWN);
1789 sc.SetState(SCE_H_DEFAULT);
1790 }
1791 } else if (sc.state == SCE_H_TAGUNKNOWN) {
1792 if (!ishtmlwordchar(static_cast<char>(sc.ch)) && !((sc.ch == '/') && (sc.chPrev == '<')) && sc.ch != '[') {
1793 char s[100];
1794 sc.GetCurrentLowered(s, sizeof(s));
1795 if (s[1] == '/') {
1796 if (keywordsTags.InList(s + 2)) {
1797 sc.ChangeState(SCE_H_TAG);
1798 }
1799 } else {
1800 if (keywordsTags.InList(s + 1)) {
1801 sc.ChangeState(SCE_H_TAG);
1802 }
1803 }
1804 if (sc.ch == '>') {
1805 sc.ForwardSetState(SCE_H_DEFAULT);
1806 } else if (sc.Match('/', '>')) {
1807 sc.SetState(SCE_H_TAGEND);
1808 sc.Forward();
1809 sc.ForwardSetState(SCE_H_DEFAULT);
1810 } else {
1811 sc.SetState(SCE_H_OTHER);
1812 }
1813 }
1814 } else if (sc.state == SCE_H_ATTRIBUTE) {
1815 if (!ishtmlwordchar(static_cast<char>(sc.ch))) {
1816 char s[100];
1817 sc.GetCurrentLowered(s, sizeof(s));
1818 if (!keywordsTags.InList(s)) {
1819 sc.ChangeState(SCE_H_ATTRIBUTEUNKNOWN);
1820 }
1821 sc.SetState(SCE_H_OTHER);
1822 }
1823 } else if (sc.state == SCE_H_OTHER) {
1824 if (sc.ch == '>') {
1825 sc.SetState(SCE_H_TAG);
1826 sc.ForwardSetState(SCE_H_DEFAULT);
1827 } else if (sc.Match('/', '>')) {
1828 sc.SetState(SCE_H_TAG);
1829 sc.Forward();
1830 sc.ForwardSetState(SCE_H_DEFAULT);
1831 } else if (sc.chPrev == '=') {
1832 sc.SetState(SCE_H_VALUE);
1833 }
1834 } else if (sc.state == SCE_H_DOUBLESTRING) {
1835 if (sc.ch == '\"') {
1836 sc.ForwardSetState(SCE_H_OTHER);
1837 }
1838 } else if (sc.state == SCE_H_SINGLESTRING) {
1839 if (sc.ch == '\'') {
1840 sc.ForwardSetState(SCE_H_OTHER);
1841 }
1842 } else if (sc.state == SCE_H_NUMBER) {
1843 if (!IsADigit(sc.ch)) {
1844 sc.SetState(SCE_H_OTHER);
1845 }
1846 }
1847
1848 if (sc.state == SCE_H_DEFAULT) {
1849 if (sc.ch == '<') {
1850 if (sc.Match("<!--"))
1851 sc.SetState(SCE_H_COMMENT);
1852 else
1853 sc.SetState(SCE_H_TAGUNKNOWN);
1854 } else if (sc.ch == '&') {
1855 sc.SetState(SCE_H_ENTITY);
1856 }
1857 } else if ((sc.state == SCE_H_OTHER) || (sc.state == SCE_H_VALUE)) {
9e730a78 1858 if (sc.ch == '\"' && sc.chPrev == '=') {
1a2fb4cd 1859 sc.SetState(SCE_H_DOUBLESTRING);
9e730a78 1860 } else if (sc.ch == '\'' && sc.chPrev == '=') {
1a2fb4cd
RD
1861 sc.SetState(SCE_H_SINGLESTRING);
1862 } else if (IsADigit(sc.ch)) {
1863 sc.SetState(SCE_H_NUMBER);
1864 } else if (sc.ch == '>') {
1865 sc.SetState(SCE_H_TAG);
1866 sc.ForwardSetState(SCE_H_DEFAULT);
1867 } else if (ishtmlwordchar(static_cast<char>(sc.ch))) {
1868 sc.SetState(SCE_H_ATTRIBUTE);
1869 }
1870 }
1871}
1872
1873static void ColouriseASPPiece(StyleContext &sc, WordList *keywordlists[]) {
1874 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1875 if ((sc.state == SCE_H_ASPAT || isASPScript(sc.state)) && sc.Match('%', '>')) {
1876 sc.SetState(SCE_H_ASP);
1877 sc.Forward();
1878 sc.ForwardSetState(SCE_H_DEFAULT);
1879 }
1880
1881 // Handle some ASP script
1882 if (sc.state >= SCE_HBA_START && sc.state <= SCE_HBA_STRINGEOL) {
1883 ColouriseHBAPiece(sc, keywordlists);
1884 } else if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
1885 ColouriseHTMLPiece(sc, keywordlists);
1886 }
1887
1888 // Enter new sc.state
1889 if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
1890 if (sc.Match('<', '%')) {
1891 if (sc.state == SCE_H_TAGUNKNOWN)
1892 sc.ChangeState(SCE_H_ASP);
1893 else
1894 sc.SetState(SCE_H_ASP);
1895 sc.Forward();
1896 sc.Forward();
1897 if (sc.ch == '@') {
1898 sc.ForwardSetState(SCE_H_ASPAT);
1899 } else {
1900 if (sc.ch == '=') {
1901 sc.Forward();
1902 }
1903 sc.SetState(SCE_HBA_DEFAULT);
1904 }
1905 }
1906 }
1907}
1908
1909static void ColouriseASPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
1910 Accessor &styler) {
1911 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
1912 StyleContext sc(startPos, length, initStyle, styler, 0x7f);
1913 for (; sc.More(); sc.Forward()) {
1914 ColouriseASPPiece(sc, keywordlists);
1915 }
1916 sc.Complete();
1917}
1918
1919static void ColourisePHPPiece(StyleContext &sc, WordList *keywordlists[]) {
1920 // Possibly exit current state to either SCE_H_DEFAULT or SCE_HBA_DEFAULT
1921 if (sc.state >= SCE_HPHP_DEFAULT && sc.state <= SCE_HPHP_OPERATOR) {
1922 if (!isPHPStringState(sc.state) &&
1923 (sc.state != SCE_HPHP_COMMENT) &&
1924 (sc.Match('?', '>'))) {
1925 sc.SetState(SCE_H_QUESTION);
1926 sc.Forward();
1927 sc.ForwardSetState(SCE_H_DEFAULT);
1928 }
1929 }
1930
1931 if (sc.state >= SCE_H_DEFAULT && sc.state <= SCE_H_SGML_BLOCK_DEFAULT) {
1932 ColouriseHTMLPiece(sc, keywordlists);
1933 }
1934
1935 // Handle some PHP script
1936 if (sc.state == SCE_HPHP_WORD) {
9e730a78 1937 if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
1a2fb4cd
RD
1938 sc.SetState(SCE_HPHP_DEFAULT);
1939 }
1940 } else if (sc.state == SCE_HPHP_COMMENTLINE) {
1941 if (sc.ch == '\r' || sc.ch == '\n') {
1942 sc.SetState(SCE_HPHP_DEFAULT);
1943 }
1944 } else if (sc.state == SCE_HPHP_COMMENT) {
1945 if (sc.Match('*', '/')) {
1946 sc.Forward();
1947 sc.Forward();
1948 sc.SetState(SCE_HPHP_DEFAULT);
1949 }
1950 } else if (sc.state == SCE_HPHP_HSTRING) {
1951 if (sc.ch == '\"') {
1952 sc.ForwardSetState(SCE_HPHP_DEFAULT);
1953 }
1954 } else if (sc.state == SCE_HPHP_SIMPLESTRING) {
1955 if (sc.ch == '\'') {
1956 sc.ForwardSetState(SCE_HPHP_DEFAULT);
1957 }
1958 } else if (sc.state == SCE_HPHP_VARIABLE) {
9e730a78 1959 if (!IsPhpWordChar(static_cast<char>(sc.ch))) {
1a2fb4cd
RD
1960 sc.SetState(SCE_HPHP_DEFAULT);
1961 }
1962 } else if (sc.state == SCE_HPHP_OPERATOR) {
1963 sc.SetState(SCE_HPHP_DEFAULT);
1964 }
1965
1966 // Enter new sc.state
1967 if ((sc.state == SCE_H_DEFAULT) || (sc.state == SCE_H_TAGUNKNOWN)) {
1968 if (sc.Match("<?php")) {
1969 sc.SetState(SCE_H_QUESTION);
1970 sc.Forward();
1971 sc.Forward();
1972 sc.Forward();
1973 sc.Forward();
1974 sc.Forward();
1975 sc.SetState(SCE_HPHP_DEFAULT);
1976 }
1977 }
1978 if (sc.state == SCE_HPHP_DEFAULT) {
9e730a78 1979 if (IsPhpWordStart(static_cast<char>(sc.ch))) {
1a2fb4cd
RD
1980 sc.SetState(SCE_HPHP_WORD);
1981 } else if (sc.ch == '#') {
1982 sc.SetState(SCE_HPHP_COMMENTLINE);
1983 } else if (sc.Match("<!--")) {
1984 sc.SetState(SCE_HPHP_COMMENTLINE);
1985 } else if (sc.Match('/', '/')) {
1986 sc.SetState(SCE_HPHP_COMMENTLINE);
1987 } else if (sc.Match('/', '*')) {
1988 sc.SetState(SCE_HPHP_COMMENT);
1989 } else if (sc.ch == '\"') {
1990 sc.SetState(SCE_HPHP_HSTRING);
1991 } else if (sc.ch == '\'') {
1992 sc.SetState(SCE_HPHP_SIMPLESTRING);
9e730a78 1993 } else if (sc.ch == '$' && IsPhpWordStart(static_cast<char>(sc.chNext))) {
1a2fb4cd
RD
1994 sc.SetState(SCE_HPHP_VARIABLE);
1995 } else if (isoperator(static_cast<char>(sc.ch))) {
1996 sc.SetState(SCE_HPHP_OPERATOR);
1997 }
1998 }
1999}
2000
2001static void ColourisePHPDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
2002 Accessor &styler) {
2003 // Lexer for HTML requires more lexical states (7 bits worth) than most lexers
2004 StyleContext sc(startPos, length, initStyle, styler, 0x7f);
2005 for (; sc.More(); sc.Forward()) {
2006 ColourisePHPPiece(sc, keywordlists);
2007 }
2008 sc.Complete();
2009}
2010
1e9bafca
RD
2011static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
2012 Accessor &styler) {
2013 if(startPos == 0) initStyle = SCE_HPHP_DEFAULT;
2014 ColouriseHyperTextDoc(startPos,length,initStyle,keywordlists,styler);
2015}
2016
a834585d
RD
2017static const char * const htmlWordListDesc[] = {
2018 "HTML elements and attributes",
2019 "JavaScript keywords",
2020 "VBScript keywords",
2021 "Python keywords",
2022 "PHP keywords",
2023 "SGML and DTD keywords",
2024 0,
2025};
2026
1e9bafca
RD
2027static const char * const phpscriptWordListDesc[] = {
2028 "", //Unused
2029 "", //Unused
2030 "", //Unused
2031 "", //Unused
2032 "PHP keywords",
2033 "", //Unused
2034 0,
2035};
2036
2037LexerModule lmHTML(SCLEX_HTML, ColouriseHyperTextDoc, "hypertext", 0, htmlWordListDesc, 7);
2038LexerModule lmXML(SCLEX_XML, ColouriseHyperTextDoc, "xml", 0, htmlWordListDesc, 7);
2039// SCLEX_ASP and SCLEX_PHP should not be used in new code: use SCLEX_HTML instead.
2040LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc, 7);
2041LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc, 7);
2042LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 7);