PageRenderTime 50ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/code/ryzom/client/src/lua_ide_dll_nevrax/source/scintilla/LexHTML.cxx

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