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