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