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