OSDN Git Service

Add SCI Edit to GitBlameView
[tortoisegit/TortoiseGitJp.git] / ext / scintilla / src / LexFlagship.cxx
1 // Scintilla source code edit control\r
2 /** @file LexFlagShip.cxx\r
3  ** Lexer for FlagShip \r
4  ** (Syntactically compatible to other XBase dialects, like dBase, Clipper, Fox etc.)\r
5  **/\r
6 // Copyright 2005 by Randy Butler\r
7 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>\r
8 // The License.txt file describes the conditions under which this software may be distributed.\r
9 \r
10 #include <stdlib.h>\r
11 #include <string.h>\r
12 #include <ctype.h>\r
13 #include <stdio.h>\r
14 #include <stdarg.h>\r
15 \r
16 #include "Platform.h"\r
17 \r
18 #include "PropSet.h"\r
19 #include "Accessor.h"\r
20 #include "StyleContext.h"\r
21 #include "KeyWords.h"\r
22 #include "Scintilla.h"\r
23 #include "SciLexer.h"\r
24 \r
25 #ifdef SCI_NAMESPACE\r
26 using namespace Scintilla;\r
27 #endif\r
28 \r
29 static bool IsFlagShipComment(Accessor &styler, int pos, int len) {\r
30         return len>0 && styler[pos]=='\'';\r
31 }\r
32 \r
33 static inline bool IsTypeCharacter(int ch) {\r
34         return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$';\r
35 }\r
36 \r
37 // Extended to accept accented characters\r
38 static inline bool IsAWordChar(int ch) {\r
39         return ch >= 0x80 ||\r
40                (isalnum(ch) || ch == '.' || ch == '_');\r
41 }\r
42 \r
43 static inline bool IsAWordStart(int ch) {\r
44         return ch >= 0x80 ||\r
45                (isalnum(ch) || ch == '_');\r
46 }\r
47 \r
48 static inline bool IsADateCharacter(const int ch) {\r
49         return (ch < 0x80) &&\r
50                 (isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t');\r
51 }\r
52 \r
53 \r
54 static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle,\r
55                            WordList *keywordlists[], Accessor &styler) {\r
56 \r
57         //bool FSScriptSyntax = true;\r
58         WordList &keywords = *keywordlists[0];\r
59         WordList &keywords2 = *keywordlists[1];\r
60         WordList &keywords3 = *keywordlists[2];\r
61         WordList &keywords4 = *keywordlists[3];\r
62 \r
63         styler.StartAt(startPos);\r
64 \r
65         int visibleChars = 0;\r
66 \r
67         StyleContext sc(startPos, length, initStyle, styler);\r
68 \r
69         for (; sc.More(); sc.Forward()) {\r
70 \r
71                 if (sc.state == SCE_FS_OPERATOR) {\r
72                         sc.SetState(SCE_FS_DEFAULT);\r
73                 } else if (sc.state == SCE_FS_IDENTIFIER) {\r
74                         if (!IsAWordChar(sc.ch)) {\r
75                                 char s[100];\r
76                                 sc.GetCurrentLowered(s, sizeof(s));\r
77                                 if (keywords.InList(s)) {\r
78                                         sc.ChangeState(SCE_FS_KEYWORD);\r
79                                 } else if (keywords2.InList(s)) {\r
80                                         sc.ChangeState(SCE_FS_KEYWORD2);\r
81                                 } else if (keywords3.InList(s)) {\r
82                                         sc.ChangeState(SCE_FS_KEYWORD3);\r
83                                 } else if (keywords4.InList(s)) {\r
84                                         sc.ChangeState(SCE_FS_KEYWORD4);\r
85                                 }// Else, it is really an identifier...\r
86                                 sc.SetState(SCE_FS_DEFAULT);\r
87                         }\r
88                 } else if (sc.state == SCE_FS_NUMBER) {\r
89                         if (!IsAWordChar(sc.ch)) {\r
90                                 sc.SetState(SCE_FS_DEFAULT);\r
91                         }\r
92                 } else if (sc.state == SCE_FS_STRING) {\r
93                         // VB doubles quotes to preserve them, so just end this string\r
94                         // state now as a following quote will start again\r
95                         if (sc.ch == '\"') {\r
96                                 if (tolower(sc.chNext) == 'c') {\r
97                                         sc.Forward();\r
98                                 }\r
99                                 sc.ForwardSetState(SCE_FS_DEFAULT);\r
100                         } else if (sc.atLineEnd) {\r
101                                 sc.ChangeState(SCE_FS_STRINGEOL);\r
102                                 sc.ForwardSetState(SCE_FS_DEFAULT);\r
103                         }\r
104                 } else if (sc.state == SCE_FS_COMMENT) {\r
105                         if (sc.Match('*', '/')) {   // new code\r
106                                 sc.Forward();\r
107                                 sc.ForwardSetState(SCE_FS_DEFAULT);\r
108                         //if (sc.atLineEnd) {       // old code\r
109                         //      sc.SetState(SCE_FS_DEFAULT);\r
110                         }\r
111                 } else if (sc.state == SCE_FS_COMMENTLINE) {  //new code\r
112                         if (sc.ch == '\r' || sc.ch == '\n') {\r
113                                 sc.SetState(SCE_FS_DEFAULT);\r
114                                 visibleChars = 0;\r
115                         }\r
116                 } else if (sc.state == SCE_FS_PREPROCESSOR) {\r
117                         if (sc.atLineEnd) {\r
118                                 sc.SetState(SCE_FS_DEFAULT);\r
119                         }\r
120                 } else if (sc.state == SCE_FS_DATE) {\r
121                         if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) {\r
122                                 sc.ForwardSetState(SCE_FS_DEFAULT);\r
123                         }\r
124                 }\r
125 \r
126                 // Determine if a new state should be entered.\r
127                 if (sc.state == SCE_FS_DEFAULT) {\r
128                         if (sc.Match('/', '*')) {  // New code\r
129                                 sc.SetState(SCE_FS_COMMENT);\r
130                                 sc.Forward();   // Eat the * so it isn't used for the end of the comment\r
131                         //if (sc.ch == '\'') {  // Old code\r
132                         //      sc.SetState(SCE_FS_COMMENT); // old code\r
133                         } else if (sc.Match('/', '/')) { // New code\r
134                                 sc.SetState(SCE_FS_COMMENTLINE);\r
135                         } else if (sc.ch == '\"') {\r
136                                 sc.SetState(SCE_FS_STRING);\r
137                         } else if (sc.ch == '#' && visibleChars == 0) {\r
138                                 // Preprocessor commands are alone on their line\r
139                                 sc.SetState(SCE_FS_PREPROCESSOR);\r
140                         } else if (sc.ch == '#') {\r
141                                 int n = 1;\r
142                                 int chSeek = ' ';\r
143                                 while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) {\r
144                                         chSeek = sc.GetRelative(n);\r
145                                         n++;\r
146                                 }\r
147                                 if (IsADigit(chSeek)) {\r
148                                         sc.SetState(SCE_FS_DATE);\r
149                                 } else {\r
150                                         sc.SetState(SCE_FS_OPERATOR);\r
151                                 }\r
152                         } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {\r
153                                 sc.SetState(SCE_FS_NUMBER);\r
154                         } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {\r
155                                 sc.SetState(SCE_FS_NUMBER);\r
156                         } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {\r
157                                 sc.SetState(SCE_FS_NUMBER);\r
158                         } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {\r
159                                 sc.SetState(SCE_FS_IDENTIFIER);\r
160                         } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {\r
161                                 sc.SetState(SCE_FS_OPERATOR);\r
162                         }\r
163                 }\r
164 \r
165                 if (sc.atLineEnd) {\r
166                         visibleChars = 0;\r
167                 }\r
168                 if (!IsASpace(sc.ch)) {\r
169                         visibleChars++;\r
170                 }\r
171         }\r
172         sc.Complete();\r
173 }\r
174 \r
175 static void FoldFlagShipDoc(unsigned int startPos, int length, int,\r
176                                                    WordList *[], Accessor &styler) {\r
177 \r
178         int endPos = startPos + length;\r
179 \r
180         // Backtrack to previous line in case need to fix its fold status\r
181         int lineCurrent = styler.GetLine(startPos);\r
182         if (startPos > 0) {\r
183                 if (lineCurrent > 0) {\r
184                         lineCurrent--;\r
185                         startPos = styler.LineStart(lineCurrent);\r
186                 }\r
187         }\r
188         int spaceFlags = 0;\r
189         int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsFlagShipComment);\r
190         char chNext = styler[startPos];\r
191         for (int i = startPos; i < endPos; i++) {\r
192                 char ch = chNext;\r
193                 chNext = styler.SafeGetCharAt(i + 1);\r
194 \r
195                 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {\r
196                         int lev = indentCurrent;\r
197                         int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsFlagShipComment);\r
198                         if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {\r
199                                 // Only non whitespace lines can be headers\r
200                                 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {\r
201                                         lev |= SC_FOLDLEVELHEADERFLAG;\r
202                                 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {\r
203                                         // Line after is blank so check the next - maybe should continue further?\r
204                                         int spaceFlags2 = 0;\r
205                                         int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsFlagShipComment);\r
206                                         if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {\r
207                                                 lev |= SC_FOLDLEVELHEADERFLAG;\r
208                                         }\r
209                                 }\r
210                         }\r
211                         indentCurrent = indentNext;\r
212                         styler.SetLevel(lineCurrent, lev);\r
213                         lineCurrent++;\r
214                 }\r
215         }\r
216 }\r
217 \r
218 \r
219 static const char * const FSWordListDesc[] = {\r
220         "Keywords",\r
221         "functions",\r
222         "user2",\r
223         "user3",\r
224         0\r
225 };\r
226 \r
227 LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc);\r
228 \r
229 \r
230 \r