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

/wx.mod/wxscintilla.mod/src/scintilla/src/LexOthers.cxx

http://wxmax.googlecode.com/
C++ | 1162 lines | 921 code | 66 blank | 175 comment | 552 complexity | 599f4ea53b836af0463d8fe2fc42f6f9 MD5 | raw file
Possible License(s): Unlicense, GPL-2.0
  1. // Scintilla source code edit control
  2. /** @file LexOthers.cxx
  3. ** Lexers for batch files, diff results, properties files, make files and error lists.
  4. ** Also lexer for LaTeX documents.
  5. **/
  6. // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
  7. // The License.txt file describes the conditions under which this software may be distributed.
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <stdio.h>
  12. #include <stdarg.h>
  13. #include "Platform.h"
  14. #include "PropSet.h"
  15. #include "Accessor.h"
  16. #include "KeyWords.h"
  17. #include "Scintilla.h"
  18. #include "SciLexer.h"
  19. #ifdef SCI_NAMESPACE
  20. using namespace Scintilla;
  21. #endif
  22. static bool Is0To9(char ch) {
  23. return (ch >= '0') && (ch <= '9');
  24. }
  25. static bool Is1To9(char ch) {
  26. return (ch >= '1') && (ch <= '9');
  27. }
  28. static inline bool AtEOL(Accessor &styler, unsigned int i) {
  29. return (styler[i] == '\n') ||
  30. ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
  31. }
  32. // Tests for BATCH Operators
  33. static bool IsBOperator(char ch) {
  34. return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') ||
  35. (ch == '|') || (ch == '?') || (ch == '*');
  36. }
  37. // Tests for BATCH Separators
  38. static bool IsBSeparator(char ch) {
  39. return (ch == '\\') || (ch == '.') || (ch == ';') ||
  40. (ch == '\"') || (ch == '\'') || (ch == '/') || (ch == ')');
  41. }
  42. static void ColouriseBatchLine(
  43. char *lineBuffer,
  44. unsigned int lengthLine,
  45. unsigned int startLine,
  46. unsigned int endPos,
  47. WordList *keywordlists[],
  48. Accessor &styler) {
  49. unsigned int offset = 0; // Line Buffer Offset
  50. unsigned int enVarEnd; // Environment Variable End point
  51. unsigned int cmdLoc; // External Command / Program Location
  52. char wordBuffer[81]; // Word Buffer - large to catch long paths
  53. unsigned int wbl; // Word Buffer Length
  54. unsigned int wbo; // Word Buffer Offset - also Special Keyword Buffer Length
  55. WordList &keywords = *keywordlists[0]; // Internal Commands
  56. WordList &keywords2 = *keywordlists[1]; // External Commands (optional)
  57. // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
  58. // Toggling Regular Keyword Checking off improves readability
  59. // Other Regular Keywords and External Commands / Programs might also benefit from toggling
  60. // Need a more robust algorithm to properly toggle Regular Keyword Checking
  61. bool continueProcessing = true; // Used to toggle Regular Keyword Checking
  62. // Special Keywords are those that allow certain characters without whitespace after the command
  63. // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
  64. // Special Keyword Buffer used to determine if the first n characters is a Keyword
  65. char sKeywordBuffer[10]; // Special Keyword Buffer
  66. bool sKeywordFound; // Exit Special Keyword for-loop if found
  67. // Skip initial spaces
  68. while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
  69. offset++;
  70. }
  71. // Colorize Default Text
  72. styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
  73. // Set External Command / Program Location
  74. cmdLoc = offset;
  75. // Check for Fake Label (Comment) or Real Label - return if found
  76. if (lineBuffer[offset] == ':') {
  77. if (lineBuffer[offset + 1] == ':') {
  78. // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
  79. styler.ColourTo(endPos, SCE_BAT_COMMENT);
  80. } else {
  81. // Colorize Real Label
  82. styler.ColourTo(endPos, SCE_BAT_LABEL);
  83. }
  84. return;
  85. // Check for Drive Change (Drive Change is internal command) - return if found
  86. } else if ((isalpha(lineBuffer[offset])) &&
  87. (lineBuffer[offset + 1] == ':') &&
  88. ((isspacechar(lineBuffer[offset + 2])) ||
  89. (((lineBuffer[offset + 2] == '\\')) &&
  90. (isspacechar(lineBuffer[offset + 3]))))) {
  91. // Colorize Regular Keyword
  92. styler.ColourTo(endPos, SCE_BAT_WORD);
  93. return;
  94. }
  95. // Check for Hide Command (@ECHO OFF/ON)
  96. if (lineBuffer[offset] == '@') {
  97. styler.ColourTo(startLine + offset, SCE_BAT_HIDE);
  98. offset++;
  99. // Check for Argument (%n) or Environment Variable (%x...%)
  100. } else if (lineBuffer[offset] == '%') {
  101. enVarEnd = offset + 1;
  102. // Search end of word for second % (can be a long path)
  103. while ((enVarEnd < lengthLine) &&
  104. (!isspacechar(lineBuffer[enVarEnd])) &&
  105. (lineBuffer[enVarEnd] != '%') &&
  106. (!IsBOperator(lineBuffer[enVarEnd])) &&
  107. (!IsBSeparator(lineBuffer[enVarEnd]))) {
  108. enVarEnd++;
  109. }
  110. // Check for Argument (%n)
  111. if ((Is0To9(lineBuffer[offset + 1])) &&
  112. (lineBuffer[enVarEnd] != '%')) {
  113. // Colorize Argument
  114. styler.ColourTo(startLine + offset + 1, SCE_BAT_IDENTIFIER);
  115. offset += 2;
  116. // Check for External Command / Program
  117. if (offset < lengthLine && !isspacechar(lineBuffer[offset])) {
  118. cmdLoc = offset;
  119. }
  120. // Check for Environment Variable (%x...%)
  121. } else if ((lineBuffer[offset + 1] != '%') &&
  122. (lineBuffer[enVarEnd] == '%')) {
  123. offset = enVarEnd;
  124. // Colorize Environment Variable
  125. styler.ColourTo(startLine + offset, SCE_BAT_IDENTIFIER);
  126. offset++;
  127. // Check for External Command / Program
  128. if (offset < lengthLine && !isspacechar(lineBuffer[offset])) {
  129. cmdLoc = offset;
  130. }
  131. }
  132. }
  133. // Skip next spaces
  134. while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
  135. offset++;
  136. }
  137. // Read remainder of line word-at-a-time or remainder-of-word-at-a-time
  138. while (offset < lengthLine) {
  139. if (offset > startLine) {
  140. // Colorize Default Text
  141. styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
  142. }
  143. // Copy word from Line Buffer into Word Buffer
  144. wbl = 0;
  145. for (; offset < lengthLine && wbl < 80 &&
  146. !isspacechar(lineBuffer[offset]); wbl++, offset++) {
  147. wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
  148. }
  149. wordBuffer[wbl] = '\0';
  150. wbo = 0;
  151. // Check for Comment - return if found
  152. if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
  153. styler.ColourTo(endPos, SCE_BAT_COMMENT);
  154. return;
  155. }
  156. // Check for Separator
  157. if (IsBSeparator(wordBuffer[0])) {
  158. // Check for External Command / Program
  159. if ((cmdLoc == offset - wbl) &&
  160. ((wordBuffer[0] == ':') ||
  161. (wordBuffer[0] == '\\') ||
  162. (wordBuffer[0] == '.'))) {
  163. // Reset Offset to re-process remainder of word
  164. offset -= (wbl - 1);
  165. // Colorize External Command / Program
  166. if (!keywords2) {
  167. styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
  168. } else if (keywords2.InList(wordBuffer)) {
  169. styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
  170. } else {
  171. styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
  172. }
  173. // Reset External Command / Program Location
  174. cmdLoc = offset;
  175. } else {
  176. // Reset Offset to re-process remainder of word
  177. offset -= (wbl - 1);
  178. // Colorize Default Text
  179. styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
  180. }
  181. // Check for Regular Keyword in list
  182. } else if ((keywords.InList(wordBuffer)) &&
  183. (continueProcessing)) {
  184. // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
  185. if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) ||
  186. (CompareCaseInsensitive(wordBuffer, "goto") == 0) ||
  187. (CompareCaseInsensitive(wordBuffer, "prompt") == 0) ||
  188. (CompareCaseInsensitive(wordBuffer, "set") == 0)) {
  189. continueProcessing = false;
  190. }
  191. // Identify External Command / Program Location for ERRORLEVEL, and EXIST
  192. if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) ||
  193. (CompareCaseInsensitive(wordBuffer, "exist") == 0)) {
  194. // Reset External Command / Program Location
  195. cmdLoc = offset;
  196. // Skip next spaces
  197. while ((cmdLoc < lengthLine) &&
  198. (isspacechar(lineBuffer[cmdLoc]))) {
  199. cmdLoc++;
  200. }
  201. // Skip comparison
  202. while ((cmdLoc < lengthLine) &&
  203. (!isspacechar(lineBuffer[cmdLoc]))) {
  204. cmdLoc++;
  205. }
  206. // Skip next spaces
  207. while ((cmdLoc < lengthLine) &&
  208. (isspacechar(lineBuffer[cmdLoc]))) {
  209. cmdLoc++;
  210. }
  211. // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
  212. } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) ||
  213. (CompareCaseInsensitive(wordBuffer, "do") == 0) ||
  214. (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) ||
  215. (CompareCaseInsensitive(wordBuffer, "lh") == 0)) {
  216. // Reset External Command / Program Location
  217. cmdLoc = offset;
  218. // Skip next spaces
  219. while ((cmdLoc < lengthLine) &&
  220. (isspacechar(lineBuffer[cmdLoc]))) {
  221. cmdLoc++;
  222. }
  223. }
  224. // Colorize Regular keyword
  225. styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);
  226. // No need to Reset Offset
  227. // Check for Special Keyword in list, External Command / Program, or Default Text
  228. } else if ((wordBuffer[0] != '%') &&
  229. (!IsBOperator(wordBuffer[0])) &&
  230. (continueProcessing)) {
  231. // Check for Special Keyword
  232. // Affected Commands are in Length range 2-6
  233. // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
  234. sKeywordFound = false;
  235. for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) {
  236. wbo = 0;
  237. // Copy Keyword Length from Word Buffer into Special Keyword Buffer
  238. for (; wbo < keywordLength; wbo++) {
  239. sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]);
  240. }
  241. sKeywordBuffer[wbo] = '\0';
  242. // Check for Special Keyword in list
  243. if ((keywords.InList(sKeywordBuffer)) &&
  244. ((IsBOperator(wordBuffer[wbo])) ||
  245. (IsBSeparator(wordBuffer[wbo])))) {
  246. sKeywordFound = true;
  247. // ECHO requires no further Regular Keyword Checking
  248. if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) {
  249. continueProcessing = false;
  250. }
  251. // Colorize Special Keyword as Regular Keyword
  252. styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD);
  253. // Reset Offset to re-process remainder of word
  254. offset -= (wbl - wbo);
  255. }
  256. }
  257. // Check for External Command / Program or Default Text
  258. if (!sKeywordFound) {
  259. wbo = 0;
  260. // Check for External Command / Program
  261. if (cmdLoc == offset - wbl) {
  262. // Read up to %, Operator or Separator
  263. while ((wbo < wbl) &&
  264. (wordBuffer[wbo] != '%') &&
  265. (!IsBOperator(wordBuffer[wbo])) &&
  266. (!IsBSeparator(wordBuffer[wbo]))) {
  267. wbo++;
  268. }
  269. // Reset External Command / Program Location
  270. cmdLoc = offset - (wbl - wbo);
  271. // Reset Offset to re-process remainder of word
  272. offset -= (wbl - wbo);
  273. // CHOICE requires no further Regular Keyword Checking
  274. if (CompareCaseInsensitive(wordBuffer, "choice") == 0) {
  275. continueProcessing = false;
  276. }
  277. // Check for START (and its switches) - What follows is External Command \ Program
  278. if (CompareCaseInsensitive(wordBuffer, "start") == 0) {
  279. // Reset External Command / Program Location
  280. cmdLoc = offset;
  281. // Skip next spaces
  282. while ((cmdLoc < lengthLine) &&
  283. (isspacechar(lineBuffer[cmdLoc]))) {
  284. cmdLoc++;
  285. }
  286. // Reset External Command / Program Location if command switch detected
  287. if (lineBuffer[cmdLoc] == '/') {
  288. // Skip command switch
  289. while ((cmdLoc < lengthLine) &&
  290. (!isspacechar(lineBuffer[cmdLoc]))) {
  291. cmdLoc++;
  292. }
  293. // Skip next spaces
  294. while ((cmdLoc < lengthLine) &&
  295. (isspacechar(lineBuffer[cmdLoc]))) {
  296. cmdLoc++;
  297. }
  298. }
  299. }
  300. // Colorize External Command / Program
  301. if (!keywords2) {
  302. styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
  303. } else if (keywords2.InList(wordBuffer)) {
  304. styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
  305. } else {
  306. styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
  307. }
  308. // No need to Reset Offset
  309. // Check for Default Text
  310. } else {
  311. // Read up to %, Operator or Separator
  312. while ((wbo < wbl) &&
  313. (wordBuffer[wbo] != '%') &&
  314. (!IsBOperator(wordBuffer[wbo])) &&
  315. (!IsBSeparator(wordBuffer[wbo]))) {
  316. wbo++;
  317. }
  318. // Colorize Default Text
  319. styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
  320. // Reset Offset to re-process remainder of word
  321. offset -= (wbl - wbo);
  322. }
  323. }
  324. // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
  325. } else if (wordBuffer[0] == '%') {
  326. // Colorize Default Text
  327. styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
  328. wbo++;
  329. // Search to end of word for second % (can be a long path)
  330. while ((wbo < wbl) &&
  331. (wordBuffer[wbo] != '%') &&
  332. (!IsBOperator(wordBuffer[wbo])) &&
  333. (!IsBSeparator(wordBuffer[wbo]))) {
  334. wbo++;
  335. }
  336. // Check for Argument (%n)
  337. if ((Is0To9(wordBuffer[1])) &&
  338. (wordBuffer[wbo] != '%')) {
  339. // Check for External Command / Program
  340. if (cmdLoc == offset - wbl) {
  341. cmdLoc = offset - (wbl - 2);
  342. }
  343. // Colorize Argument
  344. styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER);
  345. // Reset Offset to re-process remainder of word
  346. offset -= (wbl - 2);
  347. // Check for Environment Variable (%x...%)
  348. } else if ((wordBuffer[1] != '%') &&
  349. (wordBuffer[wbo] == '%')) {
  350. wbo++;
  351. // Check for External Command / Program
  352. if (cmdLoc == offset - wbl) {
  353. cmdLoc = offset - (wbl - wbo);
  354. }
  355. // Colorize Environment Variable
  356. styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
  357. // Reset Offset to re-process remainder of word
  358. offset -= (wbl - wbo);
  359. // Check for Local Variable (%%a)
  360. } else if (
  361. (wbl > 2) &&
  362. (wordBuffer[1] == '%') &&
  363. (wordBuffer[2] != '%') &&
  364. (!IsBOperator(wordBuffer[2])) &&
  365. (!IsBSeparator(wordBuffer[2]))) {
  366. // Check for External Command / Program
  367. if (cmdLoc == offset - wbl) {
  368. cmdLoc = offset - (wbl - 3);
  369. }
  370. // Colorize Local Variable
  371. styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER);
  372. // Reset Offset to re-process remainder of word
  373. offset -= (wbl - 3);
  374. }
  375. // Check for Operator
  376. } else if (IsBOperator(wordBuffer[0])) {
  377. // Colorize Default Text
  378. styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
  379. // Check for Comparison Operator
  380. if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) {
  381. // Identify External Command / Program Location for IF
  382. cmdLoc = offset;
  383. // Skip next spaces
  384. while ((cmdLoc < lengthLine) &&
  385. (isspacechar(lineBuffer[cmdLoc]))) {
  386. cmdLoc++;
  387. }
  388. // Colorize Comparison Operator
  389. styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR);
  390. // Reset Offset to re-process remainder of word
  391. offset -= (wbl - 2);
  392. // Check for Pipe Operator
  393. } else if (wordBuffer[0] == '|') {
  394. // Reset External Command / Program Location
  395. cmdLoc = offset - wbl + 1;
  396. // Skip next spaces
  397. while ((cmdLoc < lengthLine) &&
  398. (isspacechar(lineBuffer[cmdLoc]))) {
  399. cmdLoc++;
  400. }
  401. // Colorize Pipe Operator
  402. styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
  403. // Reset Offset to re-process remainder of word
  404. offset -= (wbl - 1);
  405. // Check for Other Operator
  406. } else {
  407. // Check for > Operator
  408. if (wordBuffer[0] == '>') {
  409. // Turn Keyword and External Command / Program checking back on
  410. continueProcessing = true;
  411. }
  412. // Colorize Other Operator
  413. styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
  414. // Reset Offset to re-process remainder of word
  415. offset -= (wbl - 1);
  416. }
  417. // Check for Default Text
  418. } else {
  419. // Read up to %, Operator or Separator
  420. while ((wbo < wbl) &&
  421. (wordBuffer[wbo] != '%') &&
  422. (!IsBOperator(wordBuffer[wbo])) &&
  423. (!IsBSeparator(wordBuffer[wbo]))) {
  424. wbo++;
  425. }
  426. // Colorize Default Text
  427. styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
  428. // Reset Offset to re-process remainder of word
  429. offset -= (wbl - wbo);
  430. }
  431. // Skip next spaces - nothing happens if Offset was Reset
  432. while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
  433. offset++;
  434. }
  435. }
  436. // Colorize Default Text for remainder of line - currently not lexed
  437. styler.ColourTo(endPos, SCE_BAT_DEFAULT);
  438. }
  439. static void ColouriseBatchDoc(
  440. unsigned int startPos,
  441. int length,
  442. int /*initStyle*/,
  443. WordList *keywordlists[],
  444. Accessor &styler) {
  445. char lineBuffer[1024];
  446. styler.StartAt(startPos);
  447. styler.StartSegment(startPos);
  448. unsigned int linePos = 0;
  449. unsigned int startLine = startPos;
  450. for (unsigned int i = startPos; i < startPos + length; i++) {
  451. lineBuffer[linePos++] = styler[i];
  452. if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
  453. // End of line (or of line buffer) met, colourise it
  454. lineBuffer[linePos] = '\0';
  455. ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler);
  456. linePos = 0;
  457. startLine = i + 1;
  458. }
  459. }
  460. if (linePos > 0) { // Last line does not have ending characters
  461. lineBuffer[linePos] = '\0';
  462. ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1,
  463. keywordlists, styler);
  464. }
  465. }
  466. static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) {
  467. // It is needed to remember the current state to recognize starting
  468. // comment lines before the first "diff " or "--- ". If a real
  469. // difference starts then each line starting with ' ' is a whitespace
  470. // otherwise it is considered a comment (Only in..., Binary file...)
  471. if (0 == strncmp(lineBuffer, "diff ", 5)) {
  472. styler.ColourTo(endLine, SCE_DIFF_COMMAND);
  473. } else if (0 == strncmp(lineBuffer, "--- ", 4)) {
  474. // In a context diff, --- appears in both the header and the position markers
  475. if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
  476. styler.ColourTo(endLine, SCE_DIFF_POSITION);
  477. else
  478. styler.ColourTo(endLine, SCE_DIFF_HEADER);
  479. } else if (0 == strncmp(lineBuffer, "+++ ", 4)) {
  480. // I don't know of any diff where "+++ " is a position marker, but for
  481. // consistency, do the same as with "--- " and "*** ".
  482. if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
  483. styler.ColourTo(endLine, SCE_DIFF_POSITION);
  484. else
  485. styler.ColourTo(endLine, SCE_DIFF_HEADER);
  486. } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff
  487. styler.ColourTo(endLine, SCE_DIFF_HEADER);
  488. } else if (0 == strncmp(lineBuffer, "***", 3)) {
  489. // In a context diff, *** appears in both the header and the position markers.
  490. // Also ******** is a chunk header, but here it's treated as part of the
  491. // position marker since there is no separate style for a chunk header.
  492. if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/'))
  493. styler.ColourTo(endLine, SCE_DIFF_POSITION);
  494. else if (lineBuffer[3] == '*')
  495. styler.ColourTo(endLine, SCE_DIFF_POSITION);
  496. else
  497. styler.ColourTo(endLine, SCE_DIFF_HEADER);
  498. } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib
  499. styler.ColourTo(endLine, SCE_DIFF_HEADER);
  500. } else if (lineBuffer[0] == '@') {
  501. styler.ColourTo(endLine, SCE_DIFF_POSITION);
  502. } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') {
  503. styler.ColourTo(endLine, SCE_DIFF_POSITION);
  504. } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') {
  505. styler.ColourTo(endLine, SCE_DIFF_DELETED);
  506. } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') {
  507. styler.ColourTo(endLine, SCE_DIFF_ADDED);
  508. } else if (lineBuffer[0] != ' ') {
  509. styler.ColourTo(endLine, SCE_DIFF_COMMENT);
  510. } else {
  511. styler.ColourTo(endLine, SCE_DIFF_DEFAULT);
  512. }
  513. }
  514. static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
  515. char lineBuffer[1024];
  516. styler.StartAt(startPos);
  517. styler.StartSegment(startPos);
  518. unsigned int linePos = 0;
  519. for (unsigned int i = startPos; i < startPos + length; i++) {
  520. lineBuffer[linePos++] = styler[i];
  521. if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
  522. // End of line (or of line buffer) met, colourise it
  523. lineBuffer[linePos] = '\0';
  524. ColouriseDiffLine(lineBuffer, i, styler);
  525. linePos = 0;
  526. }
  527. }
  528. if (linePos > 0) { // Last line does not have ending characters
  529. ColouriseDiffLine(lineBuffer, startPos + length - 1, styler);
  530. }
  531. }
  532. static void FoldDiffDoc(unsigned int startPos, int length, int, WordList*[], Accessor &styler) {
  533. int curLine = styler.GetLine(startPos);
  534. int prevLevel = SC_FOLDLEVELBASE;
  535. if (curLine > 0)
  536. prevLevel = styler.LevelAt(curLine-1);
  537. int curLineStart = styler.LineStart(curLine);
  538. do {
  539. int nextLevel = prevLevel;
  540. if (prevLevel & SC_FOLDLEVELHEADERFLAG)
  541. nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1;
  542. int lineType = styler.StyleAt(curLineStart);
  543. if (lineType == SCE_DIFF_COMMAND)
  544. nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG;
  545. else if (lineType == SCE_DIFF_HEADER) {
  546. nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG;
  547. } else if (lineType == SCE_DIFF_POSITION)
  548. nextLevel = (SC_FOLDLEVELBASE + 3) | SC_FOLDLEVELHEADERFLAG;
  549. if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel))
  550. styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG);
  551. styler.SetLevel(curLine, nextLevel);
  552. prevLevel = nextLevel;
  553. curLineStart = styler.LineStart(++curLine);
  554. } while (static_cast<int>(startPos) + length > curLineStart);
  555. }
  556. static void ColourisePropsLine(
  557. char *lineBuffer,
  558. unsigned int lengthLine,
  559. unsigned int startLine,
  560. unsigned int endPos,
  561. Accessor &styler) {
  562. unsigned int i = 0;
  563. while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces
  564. i++;
  565. if (i < lengthLine) {
  566. if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
  567. styler.ColourTo(endPos, SCE_PROPS_COMMENT);
  568. } else if (lineBuffer[i] == '[') {
  569. styler.ColourTo(endPos, SCE_PROPS_SECTION);
  570. } else if (lineBuffer[i] == '@') {
  571. styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL);
  572. if (lineBuffer[++i] == '=')
  573. styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
  574. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  575. } else {
  576. // Search for the '=' character
  577. while ((i < lengthLine) && (lineBuffer[i] != '='))
  578. i++;
  579. if ((i < lengthLine) && (lineBuffer[i] == '=')) {
  580. styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY);
  581. styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
  582. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  583. } else {
  584. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  585. }
  586. }
  587. } else {
  588. styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
  589. }
  590. }
  591. static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
  592. char lineBuffer[1024];
  593. styler.StartAt(startPos);
  594. styler.StartSegment(startPos);
  595. unsigned int linePos = 0;
  596. unsigned int startLine = startPos;
  597. for (unsigned int i = startPos; i < startPos + length; i++) {
  598. lineBuffer[linePos++] = styler[i];
  599. if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
  600. // End of line (or of line buffer) met, colourise it
  601. lineBuffer[linePos] = '\0';
  602. ColourisePropsLine(lineBuffer, linePos, startLine, i, styler);
  603. linePos = 0;
  604. startLine = i + 1;
  605. }
  606. }
  607. if (linePos > 0) { // Last line does not have ending characters
  608. ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
  609. }
  610. }
  611. // adaption by ksc, using the "} else {" trick of 1.53
  612. // 030721
  613. static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
  614. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  615. unsigned int endPos = startPos + length;
  616. int visibleChars = 0;
  617. int lineCurrent = styler.GetLine(startPos);
  618. char chNext = styler[startPos];
  619. int styleNext = styler.StyleAt(startPos);
  620. bool headerPoint = false;
  621. int lev;
  622. for (unsigned int i = startPos; i < endPos; i++) {
  623. char ch = chNext;
  624. chNext = styler[i+1];
  625. int style = styleNext;
  626. styleNext = styler.StyleAt(i + 1);
  627. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  628. if (style == SCE_PROPS_SECTION) {
  629. headerPoint = true;
  630. }
  631. if (atEOL) {
  632. lev = SC_FOLDLEVELBASE;
  633. if (lineCurrent > 0) {
  634. int levelPrevious = styler.LevelAt(lineCurrent - 1);
  635. if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
  636. lev = SC_FOLDLEVELBASE + 1;
  637. } else {
  638. lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
  639. }
  640. }
  641. if (headerPoint) {
  642. lev = SC_FOLDLEVELBASE;
  643. }
  644. if (visibleChars == 0 && foldCompact)
  645. lev |= SC_FOLDLEVELWHITEFLAG;
  646. if (headerPoint) {
  647. lev |= SC_FOLDLEVELHEADERFLAG;
  648. }
  649. if (lev != styler.LevelAt(lineCurrent)) {
  650. styler.SetLevel(lineCurrent, lev);
  651. }
  652. lineCurrent++;
  653. visibleChars = 0;
  654. headerPoint = false;
  655. }
  656. if (!isspacechar(ch))
  657. visibleChars++;
  658. }
  659. if (lineCurrent > 0) {
  660. int levelPrevious = styler.LevelAt(lineCurrent - 1);
  661. if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
  662. lev = SC_FOLDLEVELBASE + 1;
  663. } else {
  664. lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
  665. }
  666. } else {
  667. lev = SC_FOLDLEVELBASE;
  668. }
  669. int flagsNext = styler.LevelAt(lineCurrent);
  670. styler.SetLevel(lineCurrent, lev | flagsNext & ~SC_FOLDLEVELNUMBERMASK);
  671. }
  672. static void ColouriseMakeLine(
  673. char *lineBuffer,
  674. unsigned int lengthLine,
  675. unsigned int startLine,
  676. unsigned int endPos,
  677. Accessor &styler) {
  678. unsigned int i = 0;
  679. int lastNonSpace = -1;
  680. unsigned int state = SCE_MAKE_DEFAULT;
  681. bool bSpecial = false;
  682. // check for a tab character in column 0 indicating a command
  683. bool bCommand = false;
  684. if ((lengthLine > 0) && (lineBuffer[0] == '\t'))
  685. bCommand = true;
  686. // Skip initial spaces
  687. while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
  688. i++;
  689. }
  690. if (lineBuffer[i] == '#') { // Comment
  691. styler.ColourTo(endPos, SCE_MAKE_COMMENT);
  692. return;
  693. }
  694. if (lineBuffer[i] == '!') { // Special directive
  695. styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
  696. return;
  697. }
  698. while (i < lengthLine) {
  699. if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') {
  700. styler.ColourTo(startLine + i - 1, state);
  701. state = SCE_MAKE_IDENTIFIER;
  702. } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') {
  703. styler.ColourTo(startLine + i, state);
  704. state = SCE_MAKE_DEFAULT;
  705. }
  706. // skip identifier and target styling if this is a command line
  707. if (!bSpecial && !bCommand) {
  708. if (lineBuffer[i] == ':') {
  709. if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) {
  710. // it's a ':=', so style as an identifier
  711. if (lastNonSpace >= 0)
  712. styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
  713. styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
  714. styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR);
  715. } else {
  716. // We should check that no colouring was made since the beginning of the line,
  717. // to avoid colouring stuff like /OUT:file
  718. if (lastNonSpace >= 0)
  719. styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
  720. styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
  721. styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
  722. }
  723. bSpecial = true; // Only react to the first ':' of the line
  724. state = SCE_MAKE_DEFAULT;
  725. } else if (lineBuffer[i] == '=') {
  726. if (lastNonSpace >= 0)
  727. styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
  728. styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
  729. styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
  730. bSpecial = true; // Only react to the first '=' of the line
  731. state = SCE_MAKE_DEFAULT;
  732. }
  733. }
  734. if (!isspacechar(lineBuffer[i])) {
  735. lastNonSpace = i;
  736. }
  737. i++;
  738. }
  739. if (state == SCE_MAKE_IDENTIFIER) {
  740. styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended
  741. } else {
  742. styler.ColourTo(endPos, SCE_MAKE_DEFAULT);
  743. }
  744. }
  745. static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
  746. char lineBuffer[1024];
  747. styler.StartAt(startPos);
  748. styler.StartSegment(startPos);
  749. unsigned int linePos = 0;
  750. unsigned int startLine = startPos;
  751. for (unsigned int i = startPos; i < startPos + length; i++) {
  752. lineBuffer[linePos++] = styler[i];
  753. if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
  754. // End of line (or of line buffer) met, colourise it
  755. lineBuffer[linePos] = '\0';
  756. ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler);
  757. linePos = 0;
  758. startLine = i + 1;
  759. }
  760. }
  761. if (linePos > 0) { // Last line does not have ending characters
  762. ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
  763. }
  764. }
  765. static bool strstart(const char *haystack, const char *needle) {
  766. return strncmp(haystack, needle, strlen(needle)) == 0;
  767. }
  768. static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine) {
  769. if (lineBuffer[0] == '>') {
  770. // Command or return status
  771. return SCE_ERR_CMD;
  772. } else if (lineBuffer[0] == '<') {
  773. // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
  774. return SCE_ERR_DEFAULT;
  775. } else if (lineBuffer[0] == '!') {
  776. return SCE_ERR_DIFF_CHANGED;
  777. } else if (lineBuffer[0] == '+') {
  778. if (strstart(lineBuffer, "+++ ")) {
  779. return SCE_ERR_DIFF_MESSAGE;
  780. } else {
  781. return SCE_ERR_DIFF_ADDITION;
  782. }
  783. } else if (lineBuffer[0] == '-') {
  784. if (strstart(lineBuffer, "--- ")) {
  785. return SCE_ERR_DIFF_MESSAGE;
  786. } else {
  787. return SCE_ERR_DIFF_DELETION;
  788. }
  789. } else if (strstart(lineBuffer, "cf90-")) {
  790. // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
  791. return SCE_ERR_ABSF;
  792. } else if (strstart(lineBuffer, "fortcom:")) {
  793. // Intel Fortran Compiler v8.0 error/warning message
  794. return SCE_ERR_IFORT;
  795. } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
  796. return SCE_ERR_PYTHON;
  797. } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
  798. return SCE_ERR_PHP;
  799. } else if ((strstart(lineBuffer, "Error ") ||
  800. strstart(lineBuffer, "Warning ")) &&
  801. strstr(lineBuffer, " at (") &&
  802. strstr(lineBuffer, ") : ") &&
  803. (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
  804. // Intel Fortran Compiler error/warning message
  805. return SCE_ERR_IFC;
  806. } else if (strstart(lineBuffer, "Error ")) {
  807. // Borland error message
  808. return SCE_ERR_BORLAND;
  809. } else if (strstart(lineBuffer, "Warning ")) {
  810. // Borland warning message
  811. return SCE_ERR_BORLAND;
  812. } else if (strstr(lineBuffer, "at line " ) &&
  813. (strstr(lineBuffer, "at line " ) < (lineBuffer + lengthLine)) &&
  814. strstr(lineBuffer, "file ") &&
  815. (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) {
  816. // Lua 4 error message
  817. return SCE_ERR_LUA;
  818. } else if (strstr(lineBuffer, " at " ) &&
  819. (strstr(lineBuffer, " at " ) < (lineBuffer + lengthLine)) &&
  820. strstr(lineBuffer, " line ") &&
  821. (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) &&
  822. (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
  823. // perl error message
  824. return SCE_ERR_PERL;
  825. } else if ((memcmp(lineBuffer, " at ", 6) == 0) &&
  826. strstr(lineBuffer, ":line ")) {
  827. // A .NET traceback
  828. return SCE_ERR_NET;
  829. } else if (strstart(lineBuffer, "Line ") &&
  830. strstr(lineBuffer, ", file ")) {
  831. // Essential Lahey Fortran error message
  832. return SCE_ERR_ELF;
  833. } else if (strstart(lineBuffer, "line ") &&
  834. strstr(lineBuffer, " column ")) {
  835. // HTML tidy style: line 42 column 1
  836. return SCE_ERR_TIDY;
  837. } else if (strstart(lineBuffer, "\tat ") &&
  838. strstr(lineBuffer, "(") &&
  839. strstr(lineBuffer, ".java:")) {
  840. // Java stack back trace
  841. return SCE_ERR_JAVA_STACK;
  842. } else {
  843. // Look for one of the following formats:
  844. // GCC: <filename>:<line>:<message>
  845. // Microsoft: <filename>(<line>) :<message>
  846. // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
  847. // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
  848. // Microsoft: <filename>(<line>,<column>)<message>
  849. // CTags: \t<message>
  850. // Lua 5 traceback: \t<filename>:<line>:<message>
  851. bool initialTab = (lineBuffer[0] == '\t');
  852. enum { stInitial,
  853. stGccStart, stGccDigit, stGcc,
  854. stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet,
  855. stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags,
  856. stUnrecognized
  857. } state = stInitial;
  858. for (unsigned int i = 0; i < lengthLine; i++) {
  859. char ch = lineBuffer[i];
  860. char chNext = ' ';
  861. if ((i + 1) < lengthLine)
  862. chNext = lineBuffer[i + 1];
  863. if (state == stInitial) {
  864. if (ch == ':') {
  865. // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
  866. if ((chNext != '\\') && (chNext != '/')) {
  867. // This check is not completely accurate as may be on
  868. // GTK+ with a file name that includes ':'.
  869. state = stGccStart;
  870. }
  871. } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
  872. // May be Microsoft
  873. // Check against '0' often removes phone numbers
  874. state = stMsStart;
  875. } else if ((ch == '\t') && (!initialTab)) {
  876. // May be CTags
  877. state = stCtagsStart;
  878. }
  879. } else if (state == stGccStart) { // <filename>:
  880. state = Is1To9(ch) ? stGccDigit : stUnrecognized;
  881. } else if (state == stGccDigit) { // <filename>:<line>
  882. if (ch == ':') {
  883. state = stGcc; // :9.*: is GCC
  884. break;
  885. } else if (!Is0To9(ch)) {
  886. state = stUnrecognized;
  887. }
  888. } else if (state == stMsStart) { // <filename>(
  889. state = Is0To9(ch) ? stMsDigit : stUnrecognized;
  890. } else if (state == stMsDigit) { // <filename>(<line>
  891. if (ch == ',') {
  892. state = stMsDigitComma;
  893. } else if (ch == ')') {
  894. state = stMsBracket;
  895. } else if ((ch != ' ') && !Is0To9(ch)) {
  896. state = stUnrecognized;
  897. }
  898. } else if (state == stMsBracket) { // <filename>(<line>)
  899. if ((ch == ' ') && (chNext == ':')) {
  900. state = stMsVc;
  901. } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) {
  902. // Possibly Delphi.. don't test against chNext as it's one of the strings below.
  903. char word[512];
  904. unsigned int j, chPos;
  905. unsigned numstep;
  906. chPos = 0;
  907. if (ch == ' ')
  908. numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
  909. else
  910. numstep = 2; // otherwise add 2.
  911. for (j = i + numstep; j < lengthLine && isalpha(lineBuffer[j]) && chPos < sizeof(word) - 1; j++)
  912. word[chPos++] = lineBuffer[j];
  913. word[chPos] = 0;
  914. if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") ||
  915. !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") ||
  916. !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) {
  917. state = stMsVc;
  918. } else
  919. state = stUnrecognized;
  920. } else {
  921. state = stUnrecognized;
  922. }
  923. } else if (state == stMsDigitComma) { // <filename>(<line>,
  924. if (ch == ')') {
  925. state = stMsDotNet;
  926. break;
  927. } else if ((ch != ' ') && !Is0To9(ch)) {
  928. state = stUnrecognized;
  929. }
  930. } else if (state == stCtagsStart) {
  931. if ((lineBuffer[i - 1] == '\t') &&
  932. ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) {
  933. state = stCtags;
  934. break;
  935. } else if ((ch == '/') && (lineBuffer[i + 1] == '^')) {
  936. state = stCtagsStartString;
  937. }
  938. } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) {
  939. state = stCtagsStringDollar;
  940. break;
  941. }
  942. }
  943. if (state == stGcc) {
  944. return SCE_ERR_GCC;
  945. } else if ((state == stMsVc) || (state == stMsDotNet)) {
  946. return SCE_ERR_MS;
  947. } else if ((state == stCtagsStringDollar) || (state == stCtags)) {
  948. return SCE_ERR_CTAG;
  949. } else {
  950. return SCE_ERR_DEFAULT;
  951. }
  952. }
  953. }
  954. static void ColouriseErrorListLine(
  955. char *lineBuffer,
  956. unsigned int lengthLine,
  957. unsigned int endPos,
  958. Accessor &styler) {
  959. styler.ColourTo(endPos, RecogniseErrorListLine(lineBuffer, lengthLine));
  960. }
  961. static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
  962. char lineBuffer[10000];
  963. styler.StartAt(startPos);
  964. styler.StartSegment(startPos);
  965. unsigned int linePos = 0;
  966. for (unsigned int i = startPos; i < startPos + length; i++) {
  967. lineBuffer[linePos++] = styler[i];
  968. if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
  969. // End of line (or of line buffer) met, colourise it
  970. lineBuffer[linePos] = '\0';
  971. ColouriseErrorListLine(lineBuffer, linePos, i, styler);
  972. linePos = 0;
  973. }
  974. }
  975. if (linePos > 0) { // Last line does not have ending characters
  976. ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler);
  977. }
  978. }
  979. static int isSpecial(char s) {
  980. return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') ||
  981. (s == '\"') || (s == '`') || (s == '^') || (s == '~');
  982. }
  983. static int isTag(int start, Accessor &styler) {
  984. char s[6];
  985. unsigned int i = 0, e = 1;
  986. while (i < 5 && e) {
  987. s[i] = styler[start + i];
  988. i++;
  989. e = styler[start + i] != '{';
  990. }
  991. s[i] = '\0';
  992. return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0);
  993. }
  994. static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
  995. WordList *[], Accessor &styler) {
  996. styler.StartAt(startPos);
  997. int state = initStyle;
  998. char chNext = styler[startPos];
  999. styler.StartSegment(startPos);
  1000. int lengthDoc = startPos + length;
  1001. for (int i = startPos; i < lengthDoc; i++) {
  1002. char ch = chNext;
  1003. chNext = styler.SafeGetCharAt(i + 1);
  1004. if (styler.IsLeadByte(ch)) {
  1005. chNext = styler.SafeGetCharAt(i + 2);
  1006. i++;
  1007. continue;
  1008. }
  1009. switch (state) {
  1010. case SCE_L_DEFAULT :
  1011. switch (ch) {
  1012. case '\\' :
  1013. styler.ColourTo(i - 1, state);
  1014. if (isSpecial(styler[i + 1])) {
  1015. styler.ColourTo(i + 1, SCE_L_COMMAND);
  1016. i++;
  1017. chNext = styler.SafeGetCharAt(i + 1);
  1018. } else {
  1019. if (isTag(i + 1, styler))
  1020. state = SCE_L_TAG;
  1021. else
  1022. state = SCE_L_COMMAND;
  1023. }
  1024. break;
  1025. case '$' :
  1026. styler.ColourTo(i - 1, state);
  1027. state = SCE_L_MATH;
  1028. if (chNext == '$') {
  1029. i++;
  1030. chNext = styler.SafeGetCharAt(i + 1);
  1031. }
  1032. break;
  1033. case '%' :
  1034. styler.ColourTo(i - 1, state);
  1035. state = SCE_L_COMMENT;
  1036. break;
  1037. }
  1038. break;
  1039. case SCE_L_COMMAND :
  1040. if (chNext == '[' || chNext == '{' || chNext == '}' ||
  1041. chNext == ' ' || chNext == '\r' || chNext == '\n') {
  1042. styler.ColourTo(i, state);
  1043. state = SCE_L_DEFAULT;
  1044. i++;
  1045. chNext = styler.SafeGetCharAt(i + 1);
  1046. }
  1047. break;
  1048. case SCE_L_TAG :
  1049. if (ch == '}') {
  1050. styler.ColourTo(i, state);
  1051. state = SCE_L_DEFAULT;
  1052. }
  1053. break;
  1054. case SCE_L_MATH :
  1055. if (ch == '$') {
  1056. if (chNext == '$') {
  1057. i++;
  1058. chNext = styler.SafeGetCharAt(i + 1);
  1059. }
  1060. styler.ColourTo(i, state);
  1061. state = SCE_L_DEFAULT;
  1062. }
  1063. break;
  1064. case SCE_L_COMMENT :
  1065. if (ch == '\r' || ch == '\n') {
  1066. styler.ColourTo(i - 1, state);
  1067. state = SCE_L_DEFAULT;
  1068. }
  1069. }
  1070. }
  1071. styler.ColourTo(lengthDoc-1, state);
  1072. }
  1073. static const char * const batchWordListDesc[] = {
  1074. "Internal Commands",
  1075. "External Commands",
  1076. 0
  1077. };
  1078. static const char * const emptyWordListDesc[] = {
  1079. 0
  1080. };
  1081. static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
  1082. Accessor &styler) {
  1083. // Null language means all style bytes are 0 so just mark the end - no need to fill in.
  1084. if (length > 0) {
  1085. styler.StartAt(startPos + length - 1);
  1086. styler.StartSegment(startPos + length - 1);
  1087. styler.ColourTo(startPos + length - 1, 0);
  1088. }
  1089. }
  1090. LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc);
  1091. LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc);
  1092. LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);
  1093. LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);
  1094. LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
  1095. LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
  1096. LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");