LexGui4Cli.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Scintilla source code edit control
  2. // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
  3. /*
  4. This is the Lexer for Gui4Cli, included in SciLexer.dll
  5. - by d. Keletsekis, 2/10/2003
  6. To add to SciLexer.dll:
  7. 1. Add the values below to INCLUDE\Scintilla.iface
  8. 2. Run the scripts/HFacer.py script
  9. 3. Run the scripts/LexGen.py script
  10. val SCE_GC_DEFAULT=0
  11. val SCE_GC_COMMENTLINE=1
  12. val SCE_GC_COMMENTBLOCK=2
  13. val SCE_GC_GLOBAL=3
  14. val SCE_GC_EVENT=4
  15. val SCE_GC_ATTRIBUTE=5
  16. val SCE_GC_CONTROL=6
  17. val SCE_GC_COMMAND=7
  18. val SCE_GC_STRING=8
  19. val SCE_GC_OPERATOR=9
  20. */
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include <stdarg.h>
  25. #include <assert.h>
  26. #include <ctype.h>
  27. #include "ILexer.h"
  28. #include "Scintilla.h"
  29. #include "SciLexer.h"
  30. #include "WordList.h"
  31. #include "LexAccessor.h"
  32. #include "Accessor.h"
  33. #include "StyleContext.h"
  34. #include "CharacterSet.h"
  35. #include "LexerModule.h"
  36. #ifdef SCI_NAMESPACE
  37. using namespace Scintilla;
  38. #endif
  39. #define debug Platform::DebugPrintf
  40. static inline bool IsAWordChar(const int ch) {
  41. return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\');
  42. }
  43. inline bool isGCOperator(int ch)
  44. { if (isalnum(ch))
  45. return false;
  46. // '.' left out as it is used to make up numbers
  47. if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
  48. ch == '(' || ch == ')' || ch == '=' || ch == '%' ||
  49. ch == '[' || ch == ']' || ch == '<' || ch == '>' ||
  50. ch == ',' || ch == ';' || ch == ':')
  51. return true;
  52. return false;
  53. }
  54. #define isSpace(x) ((x)==' ' || (x)=='\t')
  55. #define isNL(x) ((x)=='\n' || (x)=='\r')
  56. #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
  57. #define BUFFSIZE 500
  58. #define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
  59. static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
  60. StyleContext *sc, char *buff, Sci_Position length, int)
  61. {
  62. Sci_Position c = 0;
  63. while (sc->More() && isSpaceOrNL(sc->ch))
  64. { sc->Forward();
  65. }
  66. styler.ColourTo(sc->currentPos - 1, sc->state);
  67. if (!IsAWordChar(sc->ch)) // comment, marker, etc..
  68. return;
  69. while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
  70. { buff[c] = static_cast<char>(sc->ch);
  71. ++c; sc->Forward();
  72. }
  73. buff[c] = '\0';
  74. char *p = buff;
  75. while (*p) // capitalize..
  76. { if (islower(*p)) *p = static_cast<char>(toupper(*p));
  77. ++p;
  78. }
  79. WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user
  80. WordList &kEvent = *keywordlists[1];
  81. WordList &kAttribute = *keywordlists[2];
  82. WordList &kControl = *keywordlists[3];
  83. WordList &kCommand = *keywordlists[4];
  84. int state = 0;
  85. // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
  86. // debug ("line = %d, level = %d", line, level);
  87. if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL;
  88. else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE;
  89. else if (kControl.InList(buff)) state = SCE_GC_CONTROL;
  90. else if (kCommand.InList(buff)) state = SCE_GC_COMMAND;
  91. else if (kEvent.InList(buff)) state = SCE_GC_EVENT;
  92. if (state)
  93. { sc->ChangeState(state);
  94. styler.ColourTo(sc->currentPos - 1, sc->state);
  95. sc->ChangeState(SCE_GC_DEFAULT);
  96. }
  97. else
  98. { sc->ChangeState(SCE_GC_DEFAULT);
  99. styler.ColourTo(sc->currentPos - 1, sc->state);
  100. }
  101. }
  102. // Main colorizing function called by Scintilla
  103. static void
  104. ColouriseGui4CliDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
  105. WordList *keywordlists[], Accessor &styler)
  106. {
  107. styler.StartAt(startPos);
  108. Sci_Position currentline = styler.GetLine(startPos);
  109. int quotestart = 0, oldstate;
  110. styler.StartSegment(startPos);
  111. bool noforward;
  112. char buff[BUFFSIZE+1]; // buffer for command name
  113. StyleContext sc(startPos, length, initStyle, styler);
  114. buff[0] = '\0'; // cbuff = 0;
  115. if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word..
  116. colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
  117. while (sc.More())
  118. { noforward = 0;
  119. switch (sc.ch)
  120. {
  121. case '/':
  122. if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
  123. break;
  124. if (sc.chNext == '/') // line comment
  125. { sc.SetState (SCE_GC_COMMENTLINE);
  126. sc.Forward();
  127. styler.ColourTo(sc.currentPos, sc.state);
  128. }
  129. else if (sc.chNext == '*') // block comment
  130. { sc.SetState(SCE_GC_COMMENTBLOCK);
  131. sc.Forward();
  132. styler.ColourTo(sc.currentPos, sc.state);
  133. }
  134. else
  135. styler.ColourTo(sc.currentPos, sc.state);
  136. break;
  137. case '*': // end of comment block, or operator..
  138. if (sc.state == SCE_GC_STRING)
  139. break;
  140. if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
  141. { sc.Forward();
  142. styler.ColourTo(sc.currentPos, sc.state);
  143. sc.ChangeState (SCE_GC_DEFAULT);
  144. }
  145. else
  146. styler.ColourTo(sc.currentPos, sc.state);
  147. break;
  148. case '\'': case '\"': // strings..
  149. if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
  150. break;
  151. if (sc.state == SCE_GC_STRING)
  152. { if (sc.ch == quotestart) // match same quote char..
  153. { styler.ColourTo(sc.currentPos, sc.state);
  154. sc.ChangeState(SCE_GC_DEFAULT);
  155. quotestart = 0;
  156. } }
  157. else
  158. { styler.ColourTo(sc.currentPos - 1, sc.state);
  159. sc.ChangeState(SCE_GC_STRING);
  160. quotestart = sc.ch;
  161. }
  162. break;
  163. case ';': // end of commandline character
  164. if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
  165. sc.state != SCE_GC_STRING)
  166. {
  167. styler.ColourTo(sc.currentPos - 1, sc.state);
  168. styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
  169. sc.ChangeState(SCE_GC_DEFAULT);
  170. sc.Forward();
  171. colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
  172. noforward = 1; // don't move forward - already positioned at next char..
  173. }
  174. break;
  175. case '+': case '-': case '=': case '!': // operators..
  176. case '<': case '>': case '&': case '|': case '$':
  177. if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
  178. sc.state != SCE_GC_STRING)
  179. {
  180. styler.ColourTo(sc.currentPos - 1, sc.state);
  181. styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
  182. sc.ChangeState(SCE_GC_DEFAULT);
  183. }
  184. break;
  185. case '\\': // escape - same as operator, but also mark in strings..
  186. if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
  187. {
  188. oldstate = sc.state;
  189. styler.ColourTo(sc.currentPos - 1, sc.state);
  190. sc.Forward(); // mark also the next char..
  191. styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
  192. sc.ChangeState(oldstate);
  193. }
  194. break;
  195. case '\n': case '\r':
  196. ++currentline;
  197. if (sc.state == SCE_GC_COMMENTLINE)
  198. { styler.ColourTo(sc.currentPos, sc.state);
  199. sc.ChangeState (SCE_GC_DEFAULT);
  200. }
  201. else if (sc.state != SCE_GC_COMMENTBLOCK)
  202. { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
  203. noforward = 1; // don't move forward - already positioned at next char..
  204. }
  205. break;
  206. // case ' ': case '\t':
  207. // default :
  208. }
  209. if (!noforward) sc.Forward();
  210. }
  211. sc.Complete();
  212. }
  213. // Main folding function called by Scintilla - (based on props (.ini) files function)
  214. static void FoldGui4Cli(Sci_PositionU startPos, Sci_Position length, int,
  215. WordList *[], Accessor &styler)
  216. {
  217. bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
  218. Sci_PositionU endPos = startPos + length;
  219. int visibleChars = 0;
  220. Sci_Position lineCurrent = styler.GetLine(startPos);
  221. char chNext = styler[startPos];
  222. int styleNext = styler.StyleAt(startPos);
  223. bool headerPoint = false;
  224. for (Sci_PositionU i = startPos; i < endPos; i++)
  225. {
  226. char ch = chNext;
  227. chNext = styler[i+1];
  228. int style = styleNext;
  229. styleNext = styler.StyleAt(i + 1);
  230. bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
  231. if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL)
  232. { headerPoint = true; // fold at events and globals
  233. }
  234. if (atEOL)
  235. { int lev = SC_FOLDLEVELBASE+1;
  236. if (headerPoint)
  237. lev = SC_FOLDLEVELBASE;
  238. if (visibleChars == 0 && foldCompact)
  239. lev |= SC_FOLDLEVELWHITEFLAG;
  240. if (headerPoint)
  241. lev |= SC_FOLDLEVELHEADERFLAG;
  242. if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct
  243. { styler.SetLevel(lineCurrent, lev);
  244. }
  245. lineCurrent++; // re-initialize our flags
  246. visibleChars = 0;
  247. headerPoint = false;
  248. }
  249. if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
  250. visibleChars++;
  251. }
  252. int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
  253. int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
  254. styler.SetLevel(lineCurrent, lev | flagsNext);
  255. }
  256. // I have no idea what these are for.. probably accessible by some message.
  257. static const char * const gui4cliWordListDesc[] = {
  258. "Globals", "Events", "Attributes", "Control", "Commands",
  259. 0
  260. };
  261. // Declare language & pass our function pointers to Scintilla
  262. LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc);
  263. #undef debug