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