PageRenderTime 57ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/scintilla/lexers/LexHTML.cxx

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