LexCLW.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. // Scintilla source code edit control
  2. /** @file LexClw.cxx
  3. ** Lexer for Clarion.
  4. ** 2004/12/17 Updated Lexer
  5. **/
  6. // Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
  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 <stdio.h>
  11. #include <stdarg.h>
  12. #include <assert.h>
  13. #include <ctype.h>
  14. #include "ILexer.h"
  15. #include "Scintilla.h"
  16. #include "SciLexer.h"
  17. #include "WordList.h"
  18. #include "LexAccessor.h"
  19. #include "Accessor.h"
  20. #include "StyleContext.h"
  21. #include "CharacterSet.h"
  22. #include "LexerModule.h"
  23. #ifdef SCI_NAMESPACE
  24. using namespace Scintilla;
  25. #endif
  26. // Is an end of line character
  27. inline bool IsEOL(const int ch) {
  28. return(ch == '\n');
  29. }
  30. // Convert character to uppercase
  31. static char CharacterUpper(char chChar) {
  32. if (chChar < 'a' || chChar > 'z') {
  33. return(chChar);
  34. }
  35. else {
  36. return(static_cast<char>(chChar - 'a' + 'A'));
  37. }
  38. }
  39. // Convert string to uppercase
  40. static void StringUpper(char *szString) {
  41. while (*szString) {
  42. *szString = CharacterUpper(*szString);
  43. szString++;
  44. }
  45. }
  46. // Is a label start character
  47. inline bool IsALabelStart(const int iChar) {
  48. return(isalpha(iChar) || iChar == '_');
  49. }
  50. // Is a label character
  51. inline bool IsALabelCharacter(const int iChar) {
  52. return(isalnum(iChar) || iChar == '_' || iChar == ':');
  53. }
  54. // Is the character is a ! and the the next character is not a !
  55. inline bool IsACommentStart(const int iChar) {
  56. return(iChar == '!');
  57. }
  58. // Is the character a Clarion hex character (ABCDEF)
  59. inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
  60. // Case insensitive.
  61. if (!bCaseSensitive) {
  62. if (strchr("ABCDEFabcdef", iChar) != NULL) {
  63. return(true);
  64. }
  65. }
  66. // Case sensitive
  67. else {
  68. if (strchr("ABCDEF", iChar) != NULL) {
  69. return(true);
  70. }
  71. }
  72. return(false);
  73. }
  74. // Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
  75. inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
  76. // Case insensitive.
  77. if (!bCaseSensitive) {
  78. // If character is a numeric base character
  79. if (strchr("BOHboh", iChar) != NULL) {
  80. return(true);
  81. }
  82. }
  83. // Case sensitive
  84. else {
  85. // If character is a numeric base character
  86. if (strchr("BOH", iChar) != NULL) {
  87. return(true);
  88. }
  89. }
  90. return(false);
  91. }
  92. // Set the correct numeric constant state
  93. inline bool SetNumericConstantState(StyleContext &scDoc) {
  94. int iPoints = 0; // Point counter
  95. char cNumericString[512]; // Numeric string buffer
  96. // Buffer the current numberic string
  97. scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
  98. // Loop through the string until end of string (NULL termination)
  99. for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) {
  100. // Depending on the character
  101. switch (cNumericString[iIndex]) {
  102. // Is a . (point)
  103. case '.' :
  104. // Increment point counter
  105. iPoints++;
  106. break;
  107. default :
  108. break;
  109. }
  110. }
  111. // If points found (can be more than one for improper formatted number
  112. if (iPoints > 0) {
  113. return(true);
  114. }
  115. // Else no points found
  116. else {
  117. return(false);
  118. }
  119. }
  120. // Get the next word in uppercase from the current position (keyword lookahead)
  121. inline bool GetNextWordUpper(Accessor &styler, Sci_PositionU uiStartPos, Sci_Position iLength, char *cWord) {
  122. Sci_PositionU iIndex = 0; // Buffer Index
  123. // Loop through the remaining string from the current position
  124. for (Sci_Position iOffset = uiStartPos; iOffset < iLength; iOffset++) {
  125. // Get the character from the buffer using the offset
  126. char cCharacter = styler[iOffset];
  127. if (IsEOL(cCharacter)) {
  128. break;
  129. }
  130. // If the character is alphabet character
  131. if (isalpha(cCharacter)) {
  132. // Add UPPERCASE character to the word buffer
  133. cWord[iIndex++] = CharacterUpper(cCharacter);
  134. }
  135. }
  136. // Add null termination
  137. cWord[iIndex] = '\0';
  138. // If no word was found
  139. if (iIndex == 0) {
  140. // Return failure
  141. return(false);
  142. }
  143. // Else word was found
  144. else {
  145. // Return success
  146. return(true);
  147. }
  148. }
  149. // Clarion Language Colouring Procedure
  150. static void ColouriseClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
  151. int iParenthesesLevel = 0; // Parenthese Level
  152. int iColumn1Label = false; // Label starts in Column 1
  153. WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords
  154. WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives
  155. WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions
  156. WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions
  157. WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types
  158. WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes
  159. WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates
  160. WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels)
  161. WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels)
  162. const char wlProcReservedKeywordList[] =
  163. "PROCEDURE FUNCTION";
  164. WordList wlProcReservedKeywords;
  165. wlProcReservedKeywords.Set(wlProcReservedKeywordList);
  166. const char wlCompilerKeywordList[] =
  167. "COMPILE OMIT";
  168. WordList wlCompilerKeywords;
  169. wlCompilerKeywords.Set(wlCompilerKeywordList);
  170. const char wlLegacyStatementsList[] =
  171. "BOF EOF FUNCTION POINTER SHARE";
  172. WordList wlLegacyStatements;
  173. wlLegacyStatements.Set(wlLegacyStatementsList);
  174. StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
  175. // lex source code
  176. for (; scDoc.More(); scDoc.Forward())
  177. {
  178. //
  179. // Determine if the current state should terminate.
  180. //
  181. // Label State Handling
  182. if (scDoc.state == SCE_CLW_LABEL) {
  183. // If the character is not a valid label
  184. if (!IsALabelCharacter(scDoc.ch)) {
  185. // If the character is a . (dot syntax)
  186. if (scDoc.ch == '.') {
  187. // Turn off column 1 label flag as label now cannot be reserved work
  188. iColumn1Label = false;
  189. // Uncolour the . (dot) to default state, move forward one character,
  190. // and change back to the label state.
  191. scDoc.SetState(SCE_CLW_DEFAULT);
  192. scDoc.Forward();
  193. scDoc.SetState(SCE_CLW_LABEL);
  194. }
  195. // Else check label
  196. else {
  197. char cLabel[512]; // Label buffer
  198. // Buffer the current label string
  199. scDoc.GetCurrent(cLabel,sizeof(cLabel));
  200. // If case insensitive, convert string to UPPERCASE to match passed keywords.
  201. if (!bCaseSensitive) {
  202. StringUpper(cLabel);
  203. }
  204. // Else if UPPERCASE label string is in the Clarion compiler keyword list
  205. if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){
  206. // change the label to error state
  207. scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
  208. }
  209. // Else if UPPERCASE label string is in the Clarion reserved keyword list
  210. else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){
  211. // change the label to error state
  212. scDoc.ChangeState(SCE_CLW_ERROR);
  213. }
  214. // Else if UPPERCASE label string is
  215. else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) {
  216. char cWord[512]; // Word buffer
  217. // Get the next word from the current position
  218. if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) {
  219. // If the next word is a procedure reserved word
  220. if (wlProcReservedKeywords.InList(cWord)) {
  221. // Change the label to error state
  222. scDoc.ChangeState(SCE_CLW_ERROR);
  223. }
  224. }
  225. }
  226. // Else if label string is in the compiler directive keyword list
  227. else if (wlCompilerDirectives.InList(cLabel)) {
  228. // change the state to compiler directive state
  229. scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
  230. }
  231. // Terminate the label state and set to default state
  232. scDoc.SetState(SCE_CLW_DEFAULT);
  233. }
  234. }
  235. }
  236. // Keyword State Handling
  237. else if (scDoc.state == SCE_CLW_KEYWORD) {
  238. // If character is : (colon)
  239. if (scDoc.ch == ':') {
  240. char cEquate[512]; // Equate buffer
  241. // Move forward to include : (colon) in buffer
  242. scDoc.Forward();
  243. // Buffer the equate string
  244. scDoc.GetCurrent(cEquate,sizeof(cEquate));
  245. // If case insensitive, convert string to UPPERCASE to match passed keywords.
  246. if (!bCaseSensitive) {
  247. StringUpper(cEquate);
  248. }
  249. // If statement string is in the equate list
  250. if (wlStandardEquates.InList(cEquate)) {
  251. // Change to equate state
  252. scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
  253. }
  254. }
  255. // If the character is not a valid label character
  256. else if (!IsALabelCharacter(scDoc.ch)) {
  257. char cStatement[512]; // Statement buffer
  258. // Buffer the statement string
  259. scDoc.GetCurrent(cStatement,sizeof(cStatement));
  260. // If case insensitive, convert string to UPPERCASE to match passed keywords.
  261. if (!bCaseSensitive) {
  262. StringUpper(cStatement);
  263. }
  264. // If statement string is in the Clarion keyword list
  265. if (wlClarionKeywords.InList(cStatement)) {
  266. // Change the statement string to the Clarion keyword state
  267. scDoc.ChangeState(SCE_CLW_KEYWORD);
  268. }
  269. // Else if statement string is in the compiler directive keyword list
  270. else if (wlCompilerDirectives.InList(cStatement)) {
  271. // Change the statement string to the compiler directive state
  272. scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
  273. }
  274. // Else if statement string is in the runtime expressions keyword list
  275. else if (wlRuntimeExpressions.InList(cStatement)) {
  276. // Change the statement string to the runtime expressions state
  277. scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS);
  278. }
  279. // Else if statement string is in the builtin procedures and functions keyword list
  280. else if (wlBuiltInProcsFuncs.InList(cStatement)) {
  281. // Change the statement string to the builtin procedures and functions state
  282. scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
  283. }
  284. // Else if statement string is in the tructures and data types keyword list
  285. else if (wlStructsDataTypes.InList(cStatement)) {
  286. // Change the statement string to the structures and data types state
  287. scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
  288. }
  289. // Else if statement string is in the procedure attribute keyword list
  290. else if (wlAttributes.InList(cStatement)) {
  291. // Change the statement string to the procedure attribute state
  292. scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
  293. }
  294. // Else if statement string is in the standard equate keyword list
  295. else if (wlStandardEquates.InList(cStatement)) {
  296. // Change the statement string to the standard equate state
  297. scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
  298. }
  299. // Else if statement string is in the deprecated or legacy keyword list
  300. else if (wlLegacyStatements.InList(cStatement)) {
  301. // Change the statement string to the standard equate state
  302. scDoc.ChangeState(SCE_CLW_DEPRECATED);
  303. }
  304. // Else the statement string doesn't match any work list
  305. else {
  306. // Change the statement string to the default state
  307. scDoc.ChangeState(SCE_CLW_DEFAULT);
  308. }
  309. // Terminate the keyword state and set to default state
  310. scDoc.SetState(SCE_CLW_DEFAULT);
  311. }
  312. }
  313. // String State Handling
  314. else if (scDoc.state == SCE_CLW_STRING) {
  315. // If the character is an ' (single quote)
  316. if (scDoc.ch == '\'') {
  317. // Set the state to default and move forward colouring
  318. // the ' (single quote) as default state
  319. // terminating the string state
  320. scDoc.SetState(SCE_CLW_DEFAULT);
  321. scDoc.Forward();
  322. }
  323. // If the next character is an ' (single quote)
  324. if (scDoc.chNext == '\'') {
  325. // Move forward one character and set to default state
  326. // colouring the next ' (single quote) as default state
  327. // terminating the string state
  328. scDoc.ForwardSetState(SCE_CLW_DEFAULT);
  329. scDoc.Forward();
  330. }
  331. }
  332. // Picture String State Handling
  333. else if (scDoc.state == SCE_CLW_PICTURE_STRING) {
  334. // If the character is an ( (open parenthese)
  335. if (scDoc.ch == '(') {
  336. // Increment the parenthese level
  337. iParenthesesLevel++;
  338. }
  339. // Else if the character is a ) (close parenthese)
  340. else if (scDoc.ch == ')') {
  341. // If the parenthese level is set to zero
  342. // parentheses matched
  343. if (!iParenthesesLevel) {
  344. scDoc.SetState(SCE_CLW_DEFAULT);
  345. }
  346. // Else parenthese level is greater than zero
  347. // still looking for matching parentheses
  348. else {
  349. // Decrement the parenthese level
  350. iParenthesesLevel--;
  351. }
  352. }
  353. }
  354. // Standard Equate State Handling
  355. else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) {
  356. if (!isalnum(scDoc.ch)) {
  357. scDoc.SetState(SCE_CLW_DEFAULT);
  358. }
  359. }
  360. // Integer Constant State Handling
  361. else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) {
  362. // If the character is not a digit (0-9)
  363. // or character is not a hexidecimal character (A-F)
  364. // or character is not a . (point)
  365. // or character is not a numberic base character (B,O,H)
  366. if (!(isdigit(scDoc.ch)
  367. || IsAHexCharacter(scDoc.ch, bCaseSensitive)
  368. || scDoc.ch == '.'
  369. || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
  370. // If the number was a real
  371. if (SetNumericConstantState(scDoc)) {
  372. // Colour the matched string to the real constant state
  373. scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
  374. }
  375. // Else the number was an integer
  376. else {
  377. // Colour the matched string to an integer constant state
  378. scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT);
  379. }
  380. // Terminate the integer constant state and set to default state
  381. scDoc.SetState(SCE_CLW_DEFAULT);
  382. }
  383. }
  384. //
  385. // Determine if a new state should be entered.
  386. //
  387. // Beginning of Line Handling
  388. if (scDoc.atLineStart) {
  389. // Reset the column 1 label flag
  390. iColumn1Label = false;
  391. // If column 1 character is a label start character
  392. if (IsALabelStart(scDoc.ch)) {
  393. // Label character is found in column 1
  394. // so set column 1 label flag and clear last column 1 label
  395. iColumn1Label = true;
  396. // Set the state to label
  397. scDoc.SetState(SCE_CLW_LABEL);
  398. }
  399. // else if character is a space or tab
  400. else if (IsASpace(scDoc.ch)){
  401. // Set to default state
  402. scDoc.SetState(SCE_CLW_DEFAULT);
  403. }
  404. // else if comment start (!) or is an * (asterisk)
  405. else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
  406. // then set the state to comment.
  407. scDoc.SetState(SCE_CLW_COMMENT);
  408. }
  409. // else the character is a ? (question mark)
  410. else if (scDoc.ch == '?') {
  411. // Change to the compiler directive state, move forward,
  412. // colouring the ? (question mark), change back to default state.
  413. scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
  414. scDoc.Forward();
  415. scDoc.SetState(SCE_CLW_DEFAULT);
  416. }
  417. // else an invalid character in column 1
  418. else {
  419. // Set to error state
  420. scDoc.SetState(SCE_CLW_ERROR);
  421. }
  422. }
  423. // End of Line Handling
  424. else if (scDoc.atLineEnd) {
  425. // Reset to the default state at the end of each line.
  426. scDoc.SetState(SCE_CLW_DEFAULT);
  427. }
  428. // Default Handling
  429. else {
  430. // If in default state
  431. if (scDoc.state == SCE_CLW_DEFAULT) {
  432. // If is a letter could be a possible statement
  433. if (isalpha(scDoc.ch)) {
  434. // Set the state to Clarion Keyword and verify later
  435. scDoc.SetState(SCE_CLW_KEYWORD);
  436. }
  437. // else is a number
  438. else if (isdigit(scDoc.ch)) {
  439. // Set the state to Integer Constant and verify later
  440. scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
  441. }
  442. // else if the start of a comment or a | (line continuation)
  443. else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
  444. // then set the state to comment.
  445. scDoc.SetState(SCE_CLW_COMMENT);
  446. }
  447. // else if the character is a ' (single quote)
  448. else if (scDoc.ch == '\'') {
  449. // If the character is also a ' (single quote)
  450. // Embedded Apostrophe
  451. if (scDoc.chNext == '\'') {
  452. // Move forward colouring it as default state
  453. scDoc.ForwardSetState(SCE_CLW_DEFAULT);
  454. }
  455. else {
  456. // move to the next character and then set the state to comment.
  457. scDoc.ForwardSetState(SCE_CLW_STRING);
  458. }
  459. }
  460. // else the character is an @ (ampersand)
  461. else if (scDoc.ch == '@') {
  462. // Case insensitive.
  463. if (!bCaseSensitive) {
  464. // If character is a valid picture token character
  465. if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) {
  466. // Set to the picture string state
  467. scDoc.SetState(SCE_CLW_PICTURE_STRING);
  468. }
  469. }
  470. // Case sensitive
  471. else {
  472. // If character is a valid picture token character
  473. if (strchr("DEKNPST", scDoc.chNext) != NULL) {
  474. // Set the picture string state
  475. scDoc.SetState(SCE_CLW_PICTURE_STRING);
  476. }
  477. }
  478. }
  479. }
  480. }
  481. }
  482. // lexing complete
  483. scDoc.Complete();
  484. }
  485. // Clarion Language Case Sensitive Colouring Procedure
  486. static void ColouriseClarionDocSensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
  487. ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
  488. }
  489. // Clarion Language Case Insensitive Colouring Procedure
  490. static void ColouriseClarionDocInsensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
  491. ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
  492. }
  493. // Fill Buffer
  494. static void FillBuffer(Sci_PositionU uiStart, Sci_PositionU uiEnd, Accessor &accStyler, char *szBuffer, Sci_PositionU uiLength) {
  495. Sci_PositionU uiPos = 0;
  496. while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) {
  497. szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos]));
  498. uiPos++;
  499. }
  500. szBuffer[uiPos] = '\0';
  501. }
  502. // Classify Clarion Fold Point
  503. static int ClassifyClarionFoldPoint(int iLevel, const char* szString) {
  504. if (!(isdigit(szString[0]) || (szString[0] == '.'))) {
  505. if (strcmp(szString, "PROCEDURE") == 0) {
  506. // iLevel = SC_FOLDLEVELBASE + 1;
  507. }
  508. else if (strcmp(szString, "MAP") == 0 ||
  509. strcmp(szString,"ACCEPT") == 0 ||
  510. strcmp(szString,"BEGIN") == 0 ||
  511. strcmp(szString,"CASE") == 0 ||
  512. strcmp(szString,"EXECUTE") == 0 ||
  513. strcmp(szString,"IF") == 0 ||
  514. strcmp(szString,"ITEMIZE") == 0 ||
  515. strcmp(szString,"INTERFACE") == 0 ||
  516. strcmp(szString,"JOIN") == 0 ||
  517. strcmp(szString,"LOOP") == 0 ||
  518. strcmp(szString,"MODULE") == 0 ||
  519. strcmp(szString,"RECORD") == 0) {
  520. iLevel++;
  521. }
  522. else if (strcmp(szString, "APPLICATION") == 0 ||
  523. strcmp(szString, "CLASS") == 0 ||
  524. strcmp(szString, "DETAIL") == 0 ||
  525. strcmp(szString, "FILE") == 0 ||
  526. strcmp(szString, "FOOTER") == 0 ||
  527. strcmp(szString, "FORM") == 0 ||
  528. strcmp(szString, "GROUP") == 0 ||
  529. strcmp(szString, "HEADER") == 0 ||
  530. strcmp(szString, "INTERFACE") == 0 ||
  531. strcmp(szString, "MENU") == 0 ||
  532. strcmp(szString, "MENUBAR") == 0 ||
  533. strcmp(szString, "OLE") == 0 ||
  534. strcmp(szString, "OPTION") == 0 ||
  535. strcmp(szString, "QUEUE") == 0 ||
  536. strcmp(szString, "REPORT") == 0 ||
  537. strcmp(szString, "SHEET") == 0 ||
  538. strcmp(szString, "TAB") == 0 ||
  539. strcmp(szString, "TOOLBAR") == 0 ||
  540. strcmp(szString, "VIEW") == 0 ||
  541. strcmp(szString, "WINDOW") == 0) {
  542. iLevel++;
  543. }
  544. else if (strcmp(szString, "END") == 0 ||
  545. strcmp(szString, "UNTIL") == 0 ||
  546. strcmp(szString, "WHILE") == 0) {
  547. iLevel--;
  548. }
  549. }
  550. return(iLevel);
  551. }
  552. // Clarion Language Folding Procedure
  553. static void FoldClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *[], Accessor &accStyler) {
  554. Sci_PositionU uiEndPos = uiStartPos + iLength;
  555. Sci_Position iLineCurrent = accStyler.GetLine(uiStartPos);
  556. int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK;
  557. int iLevelCurrent = iLevelPrev;
  558. char chNext = accStyler[uiStartPos];
  559. int iStyle = iInitStyle;
  560. int iStyleNext = accStyler.StyleAt(uiStartPos);
  561. int iVisibleChars = 0;
  562. Sci_Position iLastStart = 0;
  563. for (Sci_PositionU uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) {
  564. char chChar = chNext;
  565. chNext = accStyler.SafeGetCharAt(uiPos + 1);
  566. int iStylePrev = iStyle;
  567. iStyle = iStyleNext;
  568. iStyleNext = accStyler.StyleAt(uiPos + 1);
  569. bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n');
  570. if (iStylePrev == SCE_CLW_DEFAULT) {
  571. if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) {
  572. // Store last word start point.
  573. iLastStart = uiPos;
  574. }
  575. }
  576. if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) {
  577. if(iswordchar(chChar) && !iswordchar(chNext)) {
  578. char chBuffer[100];
  579. FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer));
  580. iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer);
  581. // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) {
  582. // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE);
  583. // iLevelPrev = SC_FOLDLEVELBASE;
  584. // }
  585. }
  586. }
  587. if (bEOL) {
  588. int iLevel = iLevelPrev;
  589. if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0))
  590. iLevel |= SC_FOLDLEVELHEADERFLAG;
  591. if (iLevel != accStyler.LevelAt(iLineCurrent)) {
  592. accStyler.SetLevel(iLineCurrent,iLevel);
  593. }
  594. iLineCurrent++;
  595. iLevelPrev = iLevelCurrent;
  596. iVisibleChars = 0;
  597. }
  598. if (!isspacechar(chChar))
  599. iVisibleChars++;
  600. }
  601. // Fill in the real level of the next line, keeping the current flags
  602. // as they will be filled in later.
  603. int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  604. accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext);
  605. }
  606. // Word List Descriptions
  607. static const char * const rgWordListDescriptions[] = {
  608. "Clarion Keywords",
  609. "Compiler Directives",
  610. "Built-in Procedures and Functions",
  611. "Runtime Expressions",
  612. "Structure and Data Types",
  613. "Attributes",
  614. "Standard Equates",
  615. "Reserved Words (Labels)",
  616. "Reserved Words (Procedure Labels)",
  617. 0,
  618. };
  619. // Case Sensitive Clarion Language Lexer
  620. LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
  621. // Case Insensitive Clarion Language Lexer
  622. LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);