PageRenderTime 64ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/LuaStudio/scintilla/src/LexHTML.cxx

http://starworld.googlecode.com/
C++ | 2091 lines | 1902 code | 103 blank | 86 comment | 1391 complexity | 33b444f017a56a50c99d0fc3c717c1db MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1

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

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