30
30
static inline bool IsAWordChar(const unsigned int ch) {
31
return (isalnum(ch) || ch == '-' || ch == '_' || ch >= 161); // _ is not in fact correct CSS word-character
32
* The CSS spec allows "ISO 10646 characters U+00A1 and higher" to be treated as word chars.
33
* Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee
34
* that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher
36
return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_';
34
inline bool IsCssOperator(const char ch) {
39
inline bool IsCssOperator(const int ch) {
40
if (!((ch < 0x80) && isalnum(ch)) &&
36
41
(ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' ||
37
42
ch == '.' || ch == '#' || ch == '!' || ch == '@' ||
46
51
static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
47
WordList &keywords = *keywordlists[0];
52
WordList &css1Props = *keywordlists[0];
48
53
WordList &pseudoClasses = *keywordlists[1];
49
WordList &keywords2 = *keywordlists[2];
54
WordList &css2Props = *keywordlists[2];
55
WordList &css3Props = *keywordlists[3];
56
WordList &pseudoElements = *keywordlists[4];
57
WordList &exProps = *keywordlists[5];
58
WordList &exPseudoClasses = *keywordlists[6];
59
WordList &exPseudoElements = *keywordlists[7];
51
61
StyleContext sc(startPos, length, initStyle, styler);
53
63
int lastState = -1; // before operator
54
64
int lastStateC = -1; // before comment
55
65
int op = ' '; // last operator
66
int opPrev = ' '; // last operator
57
68
for (; sc.More(); sc.Forward()) {
58
69
if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) {
64
75
if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) {
65
76
if (lastStateC == SCE_CSS_OPERATOR) {
66
77
op = styler.SafeGetCharAt(i-1);
78
opPrev = styler.SafeGetCharAt(i-2);
68
80
lastState = styler.StyleAt(i-1);
69
81
if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
101
113
unsigned int i = startPos;
102
114
op = styler.SafeGetCharAt(i-1);
115
opPrev = styler.SafeGetCharAt(i-2);
104
117
lastState = styler.StyleAt(i-1);
105
118
if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
111
124
if (lastState == SCE_CSS_DEFAULT)
112
125
sc.SetState(SCE_CSS_DIRECTIVE);
115
if (lastState == SCE_CSS_DEFAULT)
116
sc.SetState(SCE_CSS_TAG);
120
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_CLASS
121
|| lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
129
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
130
lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
122
131
sc.SetState(SCE_CSS_DEFAULT);
125
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
126
lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
134
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
135
lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
127
136
sc.SetState(SCE_CSS_ATTRIBUTE);
140
149
if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT ||
141
lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2)
150
lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_IDENTIFIER3)
142
151
sc.SetState(SCE_CSS_DEFAULT);
154
if (lastState == SCE_CSS_PSEUDOCLASS)
155
sc.SetState(SCE_CSS_TAG);
156
else if (lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)
157
sc.SetState(SCE_CSS_EXTENDED_PSEUDOCLASS);
160
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
161
lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
162
lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT)
163
sc.SetState(SCE_CSS_TAG);
145
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
146
lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
166
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
167
lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
168
lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT)
147
169
sc.SetState(SCE_CSS_PSEUDOCLASS);
148
else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_UNKNOWN_IDENTIFIER)
170
else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 ||
171
lastState == SCE_CSS_IDENTIFIER3 || lastState == SCE_CSS_EXTENDED_IDENTIFIER ||
172
lastState == SCE_CSS_UNKNOWN_IDENTIFIER)
149
173
sc.SetState(SCE_CSS_VALUE);
152
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
153
lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
176
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
177
lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
154
178
sc.SetState(SCE_CSS_CLASS);
157
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
158
lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
181
if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID ||
182
lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
159
183
sc.SetState(SCE_CSS_ID);
162
188
if (lastState == SCE_CSS_TAG)
163
189
sc.SetState(SCE_CSS_DEFAULT);
210
if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) {
211
sc.SetState(SCE_CSS_TAG);
184
215
if (IsAWordChar(sc.chPrev) && (
185
sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2
186
|| sc.state == SCE_CSS_UNKNOWN_IDENTIFIER
187
|| sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
188
|| sc.state == SCE_CSS_IMPORTANT
216
sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2 ||
217
sc.state == SCE_CSS_IDENTIFIER3 || sc.state == SCE_CSS_EXTENDED_IDENTIFIER ||
218
sc.state == SCE_CSS_UNKNOWN_IDENTIFIER ||
219
sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT ||
220
sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT ||
221
sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS ||
222
sc.state == SCE_CSS_IMPORTANT
191
225
sc.GetCurrentLowered(s, sizeof(s));
195
229
switch (sc.state) {
196
230
case SCE_CSS_IDENTIFIER:
197
if (!keywords.InList(s2)) {
198
if (keywords2.InList(s2)) {
199
sc.ChangeState(SCE_CSS_IDENTIFIER2);
201
sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
231
case SCE_CSS_IDENTIFIER2:
232
case SCE_CSS_IDENTIFIER3:
233
case SCE_CSS_EXTENDED_IDENTIFIER:
205
234
case SCE_CSS_UNKNOWN_IDENTIFIER:
206
if (keywords.InList(s2))
235
if (css1Props.InList(s2))
207
236
sc.ChangeState(SCE_CSS_IDENTIFIER);
208
else if (keywords2.InList(s2))
237
else if (css2Props.InList(s2))
209
238
sc.ChangeState(SCE_CSS_IDENTIFIER2);
239
else if (css3Props.InList(s2))
240
sc.ChangeState(SCE_CSS_IDENTIFIER3);
241
else if (exProps.InList(s2))
242
sc.ChangeState(SCE_CSS_EXTENDED_IDENTIFIER);
244
sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
211
246
case SCE_CSS_PSEUDOCLASS:
212
if (!pseudoClasses.InList(s2))
213
sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
247
case SCE_CSS_PSEUDOELEMENT:
248
case SCE_CSS_EXTENDED_PSEUDOCLASS:
249
case SCE_CSS_EXTENDED_PSEUDOELEMENT:
215
250
case SCE_CSS_UNKNOWN_PSEUDOCLASS:
216
if (pseudoClasses.InList(s2))
251
if (op == ':' && opPrev != ':' && pseudoClasses.InList(s2))
217
252
sc.ChangeState(SCE_CSS_PSEUDOCLASS);
253
else if (opPrev == ':' && pseudoElements.InList(s2))
254
sc.ChangeState(SCE_CSS_PSEUDOELEMENT);
255
else if ((op == ':' || (op == '(' && lastState == SCE_CSS_EXTENDED_PSEUDOCLASS)) && opPrev != ':' && exPseudoClasses.InList(s2))
256
sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOCLASS);
257
else if (opPrev == ':' && exPseudoElements.InList(s2))
258
sc.ChangeState(SCE_CSS_EXTENDED_PSEUDOELEMENT);
260
sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
219
262
case SCE_CSS_IMPORTANT:
220
263
if (strcmp(s2, "important") != 0)
226
if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || sc.state == SCE_CSS_ID))
269
if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (
270
sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_ID ||
271
(sc.ch != '(' && sc.ch != ')' && ( /* This line of the condition makes it possible to extend pseudo-classes with parentheses */
272
sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT ||
273
sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT ||
274
sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
227
277
sc.SetState(SCE_CSS_TAG);
229
279
if (sc.Match('/', '*')) {
233
283
} else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) {
234
284
sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
235
} else if (IsCssOperator(static_cast<char>(sc.ch))
285
} else if (IsCssOperator(sc.ch)
236
286
&& (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']')
237
287
&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
238
288
&& (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{')
300
351
static const char * const cssWordListDesc[] = {
357
"Browser-Specific CSS Properties",
358
"Browser-Specific Pseudo-classes",
359
"Browser-Specific Pseudo-elements",