OSDN Git Service

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