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