]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexPython.cxx
don't do anything in SetBackgroundColour() if colour is invalid
[wxWidgets.git] / src / stc / scintilla / src / LexPython.cxx
1 // SciTE - Scintilla based Text Editor
2 // LexPython.cxx - lexer for Python
3 // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
4 // The License.txt file describes the conditions under which this software may be distributed.
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdarg.h>
11
12 #include "Platform.h"
13
14 #include "PropSet.h"
15 #include "Accessor.h"
16 #include "KeyWords.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
19
20 static void ClassifyWordPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
21 char s[100];
22 bool wordIsNumber = isdigit(styler[start]);
23 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
24 s[i] = styler[start + i];
25 s[i + 1] = '\0';
26 }
27 char chAttr = SCE_P_IDENTIFIER;
28 if (0 == strcmp(prevWord, "class"))
29 chAttr = SCE_P_CLASSNAME;
30 else if (0 == strcmp(prevWord, "def"))
31 chAttr = SCE_P_DEFNAME;
32 else if (wordIsNumber)
33 chAttr = SCE_P_NUMBER;
34 else if (keywords.InList(s))
35 chAttr = SCE_P_WORD;
36 // make sure that dot-qualifiers inside the word are lexed correct
37 else for (unsigned int i = 0; i < end - start + 1; i++) {
38 if (styler[start + i] == '.') {
39 styler.ColourTo(start + i - 1, chAttr);
40 styler.ColourTo(start + i, SCE_P_OPERATOR);
41 }
42 }
43 styler.ColourTo(end, chAttr);
44 strcpy(prevWord, s);
45 }
46
47 static bool IsPyComment(Accessor &styler, int pos, int len) {
48 return len>0 && styler[pos]=='#';
49 }
50
51 static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
52 WordList *keywordlists[], Accessor &styler) {
53
54 int lengthDoc = startPos + length;
55
56 // Backtrack to previous line in case need to fix its fold status or tab whinging
57 int lineCurrent = styler.GetLine(startPos);
58 if (startPos > 0) {
59 if (lineCurrent > 0) {
60 lineCurrent--;
61 startPos = styler.LineStart(lineCurrent);
62 if (startPos == 0)
63 initStyle = SCE_P_DEFAULT;
64 else
65 initStyle = styler.StyleAt(startPos-1);
66 }
67 }
68
69 // Python uses a different mask because bad indentation is marked by oring with 32
70 styler.StartAt(startPos, 127);
71
72 WordList &keywords = *keywordlists[0];
73
74 bool fold = styler.GetPropertyInt("fold");
75 int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
76 char prevWord[200];
77 prevWord[0] = '\0';
78 if (length == 0)
79 return ;
80 int spaceFlags = 0;
81
82 int state = initStyle & 31;
83
84 int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
85 if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
86 indentCurrent |= SC_FOLDLEVELWHITEFLAG;
87
88 char chPrev = ' ';
89 char chPrev2 = ' ';
90 char chNext = styler[startPos];
91 styler.StartSegment(startPos);
92 bool atStartLine = true;
93 for (int i = startPos; i < lengthDoc; i++) {
94
95 if (atStartLine) {
96 char chBad = static_cast<char>(64);
97 char chGood = static_cast<char>(0);
98 char chFlags = chGood;
99 if (whingeLevel == 1) {
100 chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood;
101 } else if (whingeLevel == 2) {
102 chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood;
103 } else if (whingeLevel == 3) {
104 chFlags = (spaceFlags & wsSpace) ? chBad : chGood;
105 } else if (whingeLevel == 4) {
106 chFlags = (spaceFlags & wsTab) ? chBad : chGood;
107 }
108 styler.SetFlags(chFlags, static_cast<char>(state));
109 atStartLine = false;
110 }
111
112 char ch = chNext;
113 chNext = styler.SafeGetCharAt(i + 1);
114 char chNext2 = styler.SafeGetCharAt(i + 2);
115
116 if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
117 if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
118 // Perform colourisation of white space and triple quoted strings at end of each line to allow
119 // tab marking to work inside white space and triple quoted strings
120 styler.ColourTo(i, state);
121 }
122
123 int lev = indentCurrent;
124 int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsPyComment);
125 if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
126 indentNext |= SC_FOLDLEVELWHITEFLAG;
127 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
128 // Only non whitespace lines can be headers
129 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
130 lev |= SC_FOLDLEVELHEADERFLAG;
131 } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
132 // Line after is blank so check the next - maybe should continue further?
133 int spaceFlags2 = 0;
134 int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsPyComment);
135 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
136 lev |= SC_FOLDLEVELHEADERFLAG;
137 }
138 }
139 }
140 indentCurrent = indentNext;
141 if (fold) {
142 styler.SetLevel(lineCurrent, lev);
143 }
144 lineCurrent++;
145 atStartLine = true;
146 }
147
148 if (styler.IsLeadByte(ch)) {
149 chNext = styler.SafeGetCharAt(i + 2);
150 chPrev = ' ';
151 chPrev2 = ' ';
152 i += 1;
153 continue;
154 }
155
156 if (state == SCE_P_STRINGEOL) {
157 if (ch != '\r' && ch != '\n') {
158 styler.ColourTo(i - 1, state);
159 state = SCE_P_DEFAULT;
160 }
161 }
162 if (state == SCE_P_DEFAULT) {
163 if (iswordstart(ch)) {
164 styler.ColourTo(i - 1, state);
165 state = SCE_P_WORD;
166 } else if (ch == '#') {
167 styler.ColourTo(i - 1, state);
168 state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
169 } else if (ch == '\"') {
170 styler.ColourTo(i - 1, state);
171 if (chNext == '\"' && chNext2 == '\"') {
172 i += 2;
173 state = SCE_P_TRIPLEDOUBLE;
174 ch = ' ';
175 chPrev = ' ';
176 chNext = styler.SafeGetCharAt(i + 1);
177 } else {
178 state = SCE_P_STRING;
179 }
180 } else if (ch == '\'') {
181 styler.ColourTo(i - 1, state);
182 if (chNext == '\'' && chNext2 == '\'') {
183 i += 2;
184 state = SCE_P_TRIPLE;
185 ch = ' ';
186 chPrev = ' ';
187 chNext = styler.SafeGetCharAt(i + 1);
188 } else {
189 state = SCE_P_CHARACTER;
190 }
191 } else if (isoperator(ch)) {
192 styler.ColourTo(i - 1, state);
193 styler.ColourTo(i, SCE_P_OPERATOR);
194 }
195 } else if (state == SCE_P_WORD) {
196 if (!iswordchar(ch)) {
197 ClassifyWordPy(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
198 state = SCE_P_DEFAULT;
199 if (ch == '#') {
200 state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
201 } else if (ch == '\"') {
202 if (chNext == '\"' && chNext2 == '\"') {
203 i += 2;
204 state = SCE_P_TRIPLEDOUBLE;
205 ch = ' ';
206 chPrev = ' ';
207 chNext = styler.SafeGetCharAt(i + 1);
208 } else {
209 state = SCE_P_STRING;
210 }
211 } else if (ch == '\'') {
212 if (chNext == '\'' && chNext2 == '\'') {
213 i += 2;
214 state = SCE_P_TRIPLE;
215 ch = ' ';
216 chPrev = ' ';
217 chNext = styler.SafeGetCharAt(i + 1);
218 } else {
219 state = SCE_P_CHARACTER;
220 }
221 } else if (isoperator(ch)) {
222 styler.ColourTo(i, SCE_P_OPERATOR);
223 }
224 }
225 } else {
226 if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) {
227 if (ch == '\r' || ch == '\n') {
228 styler.ColourTo(i - 1, state);
229 state = SCE_P_DEFAULT;
230 }
231 } else if (state == SCE_P_STRING) {
232 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
233 styler.ColourTo(i - 1, state);
234 state = SCE_P_STRINGEOL;
235 } else if (ch == '\\') {
236 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
237 i++;
238 ch = chNext;
239 chNext = styler.SafeGetCharAt(i + 1);
240 }
241 } else if (ch == '\"') {
242 styler.ColourTo(i, state);
243 state = SCE_P_DEFAULT;
244 }
245 } else if (state == SCE_P_CHARACTER) {
246 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
247 styler.ColourTo(i - 1, state);
248 state = SCE_P_STRINGEOL;
249 } else if (ch == '\\') {
250 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
251 i++;
252 ch = chNext;
253 chNext = styler.SafeGetCharAt(i + 1);
254 }
255 } else if (ch == '\'') {
256 styler.ColourTo(i, state);
257 state = SCE_P_DEFAULT;
258 }
259 } else if (state == SCE_P_TRIPLE) {
260 if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
261 styler.ColourTo(i, state);
262 state = SCE_P_DEFAULT;
263 }
264 } else if (state == SCE_P_TRIPLEDOUBLE) {
265 if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
266 styler.ColourTo(i, state);
267 state = SCE_P_DEFAULT;
268 }
269 }
270 }
271 chPrev2 = chPrev;
272 chPrev = ch;
273 }
274 if (state == SCE_P_WORD) {
275 ClassifyWordPy(styler.GetStartSegment(), lengthDoc, keywords, styler, prevWord);
276 } else {
277 styler.ColourTo(lengthDoc, state);
278 }
279 }
280
281 LexerModule lmPython(SCLEX_PYTHON, ColourisePyDoc);