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