PageRenderTime 65ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/cssed-0.4.0/scintilla/src/LexHTML.cxx

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

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