PageRenderTime 56ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/notepad++/scintilla/src/LexHTML.cxx

http://creativity86.googlecode.com/
C++ | 1913 lines | 1746 code | 90 blank | 77 comment | 1242 complexity | f60b0bddf82e238227cfd0129671c464 MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file