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