1 /*
2  * This file is part of LibCSS.
3  * Licensed under the MIT License,
4  *                http://www.opensource.org/licenses/mit-license.php
5  * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
6  */
7 
8 #include <assert.h>
9 
10 #include "bytecode/bytecode.h"
11 #include "bytecode/opcodes.h"
12 #include "parse/important.h"
13 
14 /**
15  * Parse !important
16  *
17  * \param c       Parsing context
18  * \param vector  Vector of tokens to process
19  * \param ctx     Pointer to vector iteration context
20  * \param result  Pointer to location to receive result
21  * \return CSS_OK on success,
22  *         CSS_INVALID if "S* ! S* important" is not at the start of the vector
23  *
24  * Post condition: \a *ctx is updated with the next token to process
25  *                 If the input is invalid, then \a *ctx remains unchanged.
26  */
css__parse_important(css_language * c,const parserutils_vector * vector,int * ctx,uint8_t * result)27 css_error css__parse_important(css_language *c,
28 		const parserutils_vector *vector, int *ctx,
29 		uint8_t *result)
30 {
31 	int orig_ctx = *ctx;
32 	bool match = false;
33 	const css_token *token;
34 
35 	consumeWhitespace(vector, ctx);
36 
37 	token = parserutils_vector_iterate(vector, ctx);
38 	if (token != NULL && tokenIsChar(token, '!')) {
39 		consumeWhitespace(vector, ctx);
40 
41 		token = parserutils_vector_iterate(vector, ctx);
42 		if (token == NULL || token->type != CSS_TOKEN_IDENT) {
43 			*ctx = orig_ctx;
44 			return CSS_INVALID;
45 		}
46 
47 		if (lwc_string_caseless_isequal(token->idata, c->strings[IMPORTANT],
48 				&match) == lwc_error_ok && match) {
49 			*result |= FLAG_IMPORTANT;
50 		} else {
51 			*ctx = orig_ctx;
52 			return CSS_INVALID;
53 		}
54 	} else if (token != NULL) {
55 		*ctx = orig_ctx;
56 		return CSS_INVALID;
57 	}
58 
59 	return CSS_OK;
60 }
61 
62 /**
63  * Make a style important
64  *
65  * \param style  The style to modify
66  */
css__make_style_important(css_style * style)67 void css__make_style_important(css_style *style)
68 {
69 	css_code_t *bytecode = style->bytecode;
70 	uint32_t length = style->used;
71 	uint32_t offset = 0;
72 
73 	while (offset < length) {
74 		opcode_t op;
75 		uint8_t flags;
76 		uint32_t value;
77 		css_code_t opv = bytecode[offset];
78 
79 		/* Extract opv components, setting important flag */
80 		op = getOpcode(opv);
81 		flags = getFlags(opv) | FLAG_IMPORTANT;
82 		value = getValue(opv);
83 
84 		/* Write OPV back to bytecode */
85 		bytecode[offset] = buildOPV(op, flags, value);
86 
87 		offset++;
88 
89 		/* Advance past any property-specific data */
90 		if (isInherit(opv) == false) {
91 			switch (op) {
92 			case CSS_PROP_AZIMUTH:
93 				if ((value & ~AZIMUTH_BEHIND) == AZIMUTH_ANGLE)
94 					offset += 2; /* length + units */
95 				break;
96 
97 			case CSS_PROP_BORDER_TOP_COLOR:
98 			case CSS_PROP_BORDER_RIGHT_COLOR:
99 			case CSS_PROP_BORDER_BOTTOM_COLOR:
100 			case CSS_PROP_BORDER_LEFT_COLOR:
101 			case CSS_PROP_BACKGROUND_COLOR:
102 			case CSS_PROP_COLUMN_RULE_COLOR:
103 				assert(BACKGROUND_COLOR_SET ==
104 				       (enum op_background_color)BORDER_COLOR_SET);
105 				assert(BACKGROUND_COLOR_SET ==
106 				       (enum op_background_color)COLUMN_RULE_COLOR_SET);
107 
108 				if (value == BACKGROUND_COLOR_SET)
109 					offset++; /* colour */
110 				break;
111 
112 			case CSS_PROP_BACKGROUND_IMAGE:
113 			case CSS_PROP_CUE_AFTER:
114 			case CSS_PROP_CUE_BEFORE:
115 			case CSS_PROP_LIST_STYLE_IMAGE:
116 				assert(BACKGROUND_IMAGE_URI ==
117 				       (enum op_background_image)CUE_AFTER_URI);
118 				assert(BACKGROUND_IMAGE_URI ==
119 				       (enum op_background_image)CUE_BEFORE_URI);
120 				assert(BACKGROUND_IMAGE_URI ==
121 				       (enum op_background_image)LIST_STYLE_IMAGE_URI);
122 
123 				if (value == BACKGROUND_IMAGE_URI)
124 					offset++; /* string table entry */
125 				break;
126 
127 			case CSS_PROP_BACKGROUND_POSITION:
128 				if ((value & 0xf0) == BACKGROUND_POSITION_HORZ_SET)
129 					offset += 2; /* length + units */
130 
131 				if ((value & 0x0f) == BACKGROUND_POSITION_VERT_SET)
132 					offset += 2; /* length + units */
133 				break;
134 
135 			case CSS_PROP_BORDER_SPACING:
136 				if (value == BORDER_SPACING_SET)
137 					offset += 4; /* two length + units */
138 				break;
139 
140 			case CSS_PROP_BORDER_TOP_WIDTH:
141 			case CSS_PROP_BORDER_RIGHT_WIDTH:
142 			case CSS_PROP_BORDER_BOTTOM_WIDTH:
143 			case CSS_PROP_BORDER_LEFT_WIDTH:
144 			case CSS_PROP_OUTLINE_WIDTH:
145 			case CSS_PROP_COLUMN_RULE_WIDTH:
146 				assert(BORDER_WIDTH_SET ==
147 				       (enum op_border_width)OUTLINE_WIDTH_SET);
148 				assert(BORDER_WIDTH_SET ==
149 				       (enum op_border_width)COLUMN_RULE_WIDTH_SET);
150 
151 				if (value == BORDER_WIDTH_SET)
152 					offset += 2; /* length + units */
153 				break;
154 
155 			case CSS_PROP_MARGIN_TOP:
156 			case CSS_PROP_MARGIN_RIGHT:
157 			case CSS_PROP_MARGIN_BOTTOM:
158 			case CSS_PROP_MARGIN_LEFT:
159 			case CSS_PROP_BOTTOM:
160 			case CSS_PROP_LEFT:
161 			case CSS_PROP_RIGHT:
162 			case CSS_PROP_TOP:
163 			case CSS_PROP_HEIGHT:
164 			case CSS_PROP_WIDTH:
165 			case CSS_PROP_COLUMN_WIDTH:
166 			case CSS_PROP_COLUMN_GAP:
167 				assert(BOTTOM_SET == (enum op_bottom)LEFT_SET);
168 				assert(BOTTOM_SET == (enum op_bottom)RIGHT_SET);
169 				assert(BOTTOM_SET == (enum op_bottom)TOP_SET);
170 				assert(BOTTOM_SET == (enum op_bottom)HEIGHT_SET);
171 				assert(BOTTOM_SET == (enum op_bottom)MARGIN_SET);
172 				assert(BOTTOM_SET == (enum op_bottom)WIDTH_SET);
173 				assert(BOTTOM_SET == (enum op_bottom)COLUMN_WIDTH_SET);
174 				assert(BOTTOM_SET == (enum op_bottom)COLUMN_GAP_SET);
175 
176 				if (value == BOTTOM_SET)
177 					offset += 2; /* length + units */
178 				break;
179 
180 			case CSS_PROP_CLIP:
181 				if ((value & CLIP_SHAPE_MASK) == CLIP_SHAPE_RECT) {
182 					if ((value & CLIP_RECT_TOP_AUTO) == 0)
183 						offset += 2; /* length + units */
184 
185 					if ((value & CLIP_RECT_RIGHT_AUTO) == 0)
186 						offset += 2; /* length + units */
187 
188 					if ((value & CLIP_RECT_BOTTOM_AUTO) == 0)
189 						offset += 2; /* length + units */
190 
191 					if ((value & CLIP_RECT_LEFT_AUTO) == 0)
192 						offset += 2; /* length + units */
193 
194 				}
195 				break;
196 
197 			case CSS_PROP_COLOR:
198 				if (value == COLOR_SET)
199 					offset++; /* colour */
200 				break;
201 
202 			case CSS_PROP_COLUMN_COUNT:
203 				if (value == COLUMN_COUNT_SET)
204 					offset++; /* colour */
205 				break;
206 
207 			case CSS_PROP_CONTENT:
208 				while (value != CONTENT_NORMAL &&
209 						value != CONTENT_NONE) {
210 					switch (value & 0xff) {
211 					case CONTENT_COUNTER:
212 					case CONTENT_URI:
213 					case CONTENT_ATTR:
214 					case CONTENT_STRING:
215 						offset++; /* string table entry */
216 						break;
217 
218 					case CONTENT_COUNTERS:
219 						offset+=2; /* two string entries */
220 						break;
221 
222 					case CONTENT_OPEN_QUOTE:
223 					case CONTENT_CLOSE_QUOTE:
224 					case CONTENT_NO_OPEN_QUOTE:
225 					case CONTENT_NO_CLOSE_QUOTE:
226 						break;
227 					}
228 
229 					value = bytecode[offset];
230 				        offset++;
231 				}
232 				break;
233 
234 			case CSS_PROP_COUNTER_INCREMENT:
235 			case CSS_PROP_COUNTER_RESET:
236 				assert(COUNTER_INCREMENT_NONE ==
237 				       (enum op_counter_increment)COUNTER_RESET_NONE);
238 
239 				while (value != COUNTER_INCREMENT_NONE) {
240 					offset+=2; /* string + integer */
241 
242 					value = bytecode[offset];
243 				        offset++;
244 				}
245 				break;
246 
247 			case CSS_PROP_CURSOR:
248 				while (value == CURSOR_URI) {
249 					offset++; /* string table entry */
250 
251 					value = bytecode[offset];
252 				        offset++;
253 				}
254 				break;
255 
256 			case CSS_PROP_ELEVATION:
257 				if (value == ELEVATION_ANGLE)
258 					offset += 2; /* length + units */
259 				break;
260 
261 			case CSS_PROP_FLEX_BASIS:
262 				if (value == FLEX_BASIS_SET)
263 					offset += 2; /* length + units */
264 				break;
265 
266 			case CSS_PROP_FLEX_GROW:
267 				if (value == FLEX_GROW_SET)
268 					offset++; /* value */
269 				break;
270 
271 			case CSS_PROP_FLEX_SHRINK:
272 				if (value == FLEX_SHRINK_SET)
273 					offset++; /* value */
274 				break;
275 
276 			case CSS_PROP_FONT_FAMILY:
277 				while (value != FONT_FAMILY_END) {
278 					switch (value) {
279 					case FONT_FAMILY_STRING:
280 					case FONT_FAMILY_IDENT_LIST:
281 						offset++; /* string table entry */
282 						break;
283 					}
284 
285 					value = bytecode[offset];
286 				        offset++;
287 				}
288 				break;
289 
290 			case CSS_PROP_FONT_SIZE:
291 				if (value == FONT_SIZE_DIMENSION)
292 					offset += 2; /* length + units */
293 				break;
294 
295 			case CSS_PROP_LETTER_SPACING:
296 			case CSS_PROP_WORD_SPACING:
297 				assert(LETTER_SPACING_SET ==
298 				       (enum op_letter_spacing)WORD_SPACING_SET);
299 
300 				if (value == LETTER_SPACING_SET)
301 					offset += 2; /* length + units */
302 				break;
303 
304 			case CSS_PROP_LINE_HEIGHT:
305 				switch (value) {
306 				case LINE_HEIGHT_NUMBER:
307 					offset++; /* value */
308 					break;
309 
310 				case LINE_HEIGHT_DIMENSION:
311 					offset += 2; /* length + units */
312 					break;
313 				}
314 				break;
315 
316 			case CSS_PROP_MAX_HEIGHT:
317 			case CSS_PROP_MAX_WIDTH:
318 				assert(MAX_HEIGHT_SET ==
319 				       (enum op_max_height)MAX_WIDTH_SET);
320 
321 				if (value == MAX_HEIGHT_SET)
322 					offset += 2; /* length + units */
323 				break;
324 
325 			case CSS_PROP_PADDING_TOP:
326 			case CSS_PROP_PADDING_RIGHT:
327 			case CSS_PROP_PADDING_BOTTOM:
328 			case CSS_PROP_PADDING_LEFT:
329 			case CSS_PROP_MIN_HEIGHT:
330 			case CSS_PROP_MIN_WIDTH:
331 			case CSS_PROP_PAUSE_AFTER:
332 			case CSS_PROP_PAUSE_BEFORE:
333 			case CSS_PROP_TEXT_INDENT:
334 				assert(MIN_HEIGHT_SET == (enum op_min_height)MIN_WIDTH_SET);
335 				assert(MIN_HEIGHT_SET == (enum op_min_height)PADDING_SET);
336 				assert(MIN_HEIGHT_SET == (enum op_min_height)PAUSE_AFTER_SET);
337 				assert(MIN_HEIGHT_SET == (enum op_min_height)PAUSE_BEFORE_SET);
338 				assert(MIN_HEIGHT_SET == (enum op_min_height)TEXT_INDENT_SET);
339 
340 				if (value == MIN_HEIGHT_SET)
341 					offset += 2; /* length + units */
342 				break;
343 
344 			case CSS_PROP_OPACITY:
345 				if (value == OPACITY_SET)
346 					offset++; /* value */
347 				break;
348 
349 			case CSS_PROP_ORDER:
350 				if (value == ORDER_SET)
351 					offset++; /* value */
352 				break;
353 
354 			case CSS_PROP_ORPHANS:
355 			case CSS_PROP_PITCH_RANGE:
356 			case CSS_PROP_RICHNESS:
357 			case CSS_PROP_STRESS:
358 			case CSS_PROP_WIDOWS:
359 				assert(ORPHANS_SET == (enum op_orphans)PITCH_RANGE_SET);
360 				assert(ORPHANS_SET == (enum op_orphans)RICHNESS_SET);
361 				assert(ORPHANS_SET == (enum op_orphans)STRESS_SET);
362 				assert(ORPHANS_SET == (enum op_orphans)WIDOWS_SET);
363 
364 				if (value == ORPHANS_SET)
365 					offset++; /* value */
366 				break;
367 
368 			case CSS_PROP_OUTLINE_COLOR:
369 				if (value == OUTLINE_COLOR_SET)
370 					offset++; /* color */
371 				break;
372 
373 			case CSS_PROP_PITCH:
374 				if (value == PITCH_FREQUENCY)
375 					offset += 2; /* length + units */
376 				break;
377 
378 			case CSS_PROP_PLAY_DURING:
379 				if (value & PLAY_DURING_URI)
380 					offset++; /* string table entry */
381 				break;
382 
383 			case CSS_PROP_QUOTES:
384 				while (value != QUOTES_NONE) {
385 					offset += 2; /* two string table entries */
386 
387 					value = bytecode[offset];
388 				        offset++;
389 				}
390 				break;
391 
392 			case CSS_PROP_SPEECH_RATE:
393 				if (value == SPEECH_RATE_SET)
394 					offset++; /* rate */
395 				break;
396 
397 			case CSS_PROP_VERTICAL_ALIGN:
398 				if (value == VERTICAL_ALIGN_SET)
399 					offset += 2; /* length + units */
400 				break;
401 
402 			case CSS_PROP_VOICE_FAMILY:
403 				while (value != VOICE_FAMILY_END) {
404 					switch (value) {
405 					case VOICE_FAMILY_STRING:
406 					case VOICE_FAMILY_IDENT_LIST:
407 						offset++; /* string table entry */
408 						break;
409 					}
410 
411 					value = bytecode[offset];
412 				        offset++;
413 				}
414 				break;
415 
416 			case CSS_PROP_VOLUME:
417 				switch (value) {
418 				case VOLUME_NUMBER:
419 					offset++; /* value */
420 					break;
421 
422 				case VOLUME_DIMENSION:
423 					offset += 2; /* value + units */
424 					break;
425 				}
426 				break;
427 
428 			case CSS_PROP_Z_INDEX:
429 				if (value == Z_INDEX_SET)
430 					offset++; /* z index */
431 				break;
432 
433 			default:
434 				break;
435 			}
436 		}
437 	}
438 
439 }
440 
441