Gitweb links:

...log 
http://git.netsurf-browser.org/libcss.git/shortlog/754b9b2aab51d9a8b1eaf42d481d20711643256a
...commit 
http://git.netsurf-browser.org/libcss.git/commit/754b9b2aab51d9a8b1eaf42d481d20711643256a
...tree 
http://git.netsurf-browser.org/libcss.git/tree/754b9b2aab51d9a8b1eaf42d481d20711643256a

The branch, tlsa/jmb/mq has been updated
  discards  07bc34bff0eb4745dd623037f6161e2c66f9e540 (commit)
  discards  88513f5561b4220e4bd9f8833cb245cb4215be5a (commit)
  discards  6b6e91508ad8f6f6b746bfbe8e3f8fe3de1a91ed (commit)
  discards  4d073754f51d5e7633556887ccb88bfed7a39627 (commit)
  discards  7fcc6d364c866d71f9f6beb2bdee88e8ba8dcfd5 (commit)
  discards  4f74a21e3116d5eb3d6b15bba34df872afb1f0be (commit)
  discards  bc6888a7f66c54457135270cfdb84e28da38d6ca (commit)
  discards  9b7593678b581163cfd3eb0c20c05719b519edca (commit)
  discards  64dac37c10bd73be79570b5941d19a3d0f2fa307 (commit)
  discards  eb086b1edd9736175a5a40cfebb015380d3efeb3 (commit)
  discards  c2c02f2c827f8d8357d75b237c08ac3aee4922ba (commit)
  discards  96617c34a7c1368e5c6e5239683b2970afdfcc0c (commit)
  discards  5a2c24fcf6188c59269e5dd20d132c33177d6238 (commit)
  discards  bedec4801750f20d3b30c18da414c3fcc7f11320 (commit)
  discards  6d8cbc150c46c0a5a57548d45d1a95f6298821a1 (commit)
  discards  c34d7ed171c0dcaaf97fad52b8cf3ed2d6193eb1 (commit)
  discards  c9b33b9fd0b4bf50ef8a9a0f4c599d28c8a1efc4 (commit)
  discards  ee76c7549ce7b3abc5f0deba969db6efc6f59ec8 (commit)
  discards  070ad0dd26a9e8856cddf6e3e5544ebc5e472f56 (commit)
  discards  53bc671f3c8118d349b73cda6e342c6e7e99f8f9 (commit)
  discards  fd3f9c08d60c47644c486fb857eb9fbdb6031a4d (commit)
       via  754b9b2aab51d9a8b1eaf42d481d20711643256a (commit)
       via  402942982db97e9995a91715e21f26e23c15360c (commit)
       via  95379c707aae2e8266ffba9bfac6fd7a68fd5381 (commit)
       via  8a27e65cda95305f6b684f341c985142de7603a2 (commit)
       via  729d354c1c50698c1d08c925cd4e67b0f548691f (commit)
       via  f76745d277cf7fa6bae70bf0b5cff404c0c1fd6a (commit)
       via  6d01409022ba0a02f40dd9ebb7b247bd66a83017 (commit)
       via  fa185a120a6dfdc77ba68beefff42fa24474a04b (commit)
       via  70355dd6c235dff2a8b4dd22be6efd129a30eb95 (commit)
       via  eb4ae979e6ee8a51fb360bd5addcd479bd8121c8 (commit)
       via  0b11761524f50052e8f58f89f8a6be5e737fc5be (commit)
       via  951c66846cebb683b2edb65b7318a0dfc4c4ca00 (commit)
       via  c3006e4bbbe99c927532557d2cd6fa9b9e7e379b (commit)
       via  3847e0611bfc81ef2a53d1b3a2207785dfe202da (commit)
       via  7ba6e00f28bec3efb16c86481f27fb9e22f093ef (commit)
       via  7d990ee1d8eb3aa9db21a862743c116bc935f524 (commit)
       via  c0cab85092b0c836afd30969cc9aae0594a2afdb (commit)
       via  03ad0999ec3f0f8503ddd773097b0fa746f3702b (commit)
       via  323bb9a5dc5a8bf103a6d943b3253b77f8ff90db (commit)
       via  7bd7f0d5132adddf3f642a46b06c61d019f9f0de (commit)
       via  21955293e6769732a671d700e3b3862dd6c3a901 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (07bc34bff0eb4745dd623037f6161e2c66f9e540)
            \
             N -- N -- N (754b9b2aab51d9a8b1eaf42d481d20711643256a)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=754b9b2aab51d9a8b1eaf42d481d20711643256a
commit 754b9b2aab51d9a8b1eaf42d481d20711643256a
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Fix range parsing.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index ffddf64..8f4391b 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -227,7 +227,7 @@ static css_error mq_parse_range(css_language *c,
        if (name_or_value->type == CSS_TOKEN_NUMBER &&
                        tokenIsChar(parserutils_vector_peek(vector, *ctx), 
'/')) {
                /* ratio */
-               error = mq_parse_ratio(vector, ctx, token, &ratio);
+               error = mq_parse_ratio(vector, ctx, name_or_value, &ratio);
                if (error != CSS_OK) {
                        return error;
                }


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=402942982db97e9995a91715e21f26e23c15360c
commit 402942982db97e9995a91715e21f26e23c15360c
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Client media specification structure.

diff --git a/include/libcss/types.h b/include/libcss/types.h
index c5e9cce..d7450e5 100644
--- a/include/libcss/types.h
+++ b/include/libcss/types.h
@@ -116,6 +116,132 @@ typedef enum css_unit {
 } css_unit;
 
 /**
+ * Media orienations
+ */
+typedef enum css_media_orientation {
+       CSS_MEDIA_ORIENTATION_PORTRAIT  = 0,
+       CSS_MEDIA_ORIENTATION_LANDSCAPE = 1
+} css_media_orientation;
+
+/**
+ * Media scans
+ */
+typedef enum css_media_scan {
+       CSS_MEDIA_SCAN_PROGRESSIVE = 0,
+       CSS_MEDIA_SCAN_INTERLACE   = 1
+} css_media_scan;
+
+/**
+ * Media update-frequencies
+ */
+typedef enum css_media_update_frequency {
+       CSS_MEDIA_UPDATE_FREQUENCY_NORMAL = 0,
+       CSS_MEDIA_UPDATE_FREQUENCY_SLOW   = 1,
+       CSS_MEDIA_UPDATE_FREQUENCY_NONE   = 2
+} css_media_update_frequency;
+
+/**
+ * Media block overflows
+ */
+typedef enum css_media_overflow_block {
+       CSS_MEDIA_OVERFLOW_BLOCK_NONE           = 0,
+       CSS_MEDIA_OVERFLOW_BLOCK_SCROLL         = 1,
+       CSS_MEDIA_OVERFLOW_BLOCK_OPTIONAL_PAGED = 2,
+       CSS_MEDIA_OVERFLOW_BLOCK_PAGED          = 3
+} css_media_overflow_block;
+
+/**
+ * Media inline overflows
+ */
+typedef enum css_media_overflow_inline {
+       CSS_MEDIA_OVERFLOW_INLINE_NONE   = 0,
+       CSS_MEDIA_OVERFLOW_INLINE_SCROLL = 1
+} css_media_overflow_inline;
+
+/**
+ * Media pointers
+ */
+typedef enum css_media_pointer {
+       CSS_MEDIA_POINTER_NONE   = 0,
+       CSS_MEDIA_POINTER_COARSE = 1,
+       CSS_MEDIA_POINTER_FINE   = 2
+} css_media_pointer;
+
+/**
+ * Media hovers
+ */
+typedef enum css_media_hover {
+       CSS_MEDIA_HOVER_NONE      = 0,
+       CSS_MEDIA_HOVER_ON_DEMAND = 1,
+       CSS_MEDIA_HOVER_HOVER     = 2
+} css_media_hover;
+
+/**
+ * Media light-levels
+ */
+typedef enum css_media_light_level {
+       CSS_MEDIA_LIGHT_LEVEL_NORMAL = 0,
+       CSS_MEDIA_LIGHT_LEVEL_DIM    = 1,
+       CSS_MEDIA_LIGHT_LEVEL_WASHED = 2
+} css_media_light_level;
+
+/**
+ * Media scriptings
+ */
+typedef enum css_media_scripting {
+       CSS_MEDIA_SCRIPTING_NONE         = 0,
+       CSS_MEDIA_SCRIPTING_INITIAL_ONLY = 1,
+       CSS_MEDIA_SCRIPTING_ENABLED      = 2
+} css_media_scripting;
+
+typedef struct css_media_length {
+       css_fixed value;
+       css_unit unit;
+} css_media_length;
+
+typedef struct css_media_resolution {
+       css_fixed value;
+       css_unit unit;
+} css_media_resolution;
+
+/**
+ * Media specification
+ */
+typedef struct css_media {
+       /* Screen / Device media features */
+       css_media_length      width;
+       css_media_length      height;
+       css_fixed             aspect_ratio;
+       css_media_orientation orientation;
+
+       /* Display quality media features */
+       css_media_resolution       resolution;
+       css_media_scan             scan;
+       css_fixed                  grid; /** boolean: {0|1} */
+       css_media_update_frequency frequency;
+       css_media_overflow_block   overflow_block;
+       css_media_overflow_inline  overflow_inline;
+
+       /* Color media features */
+       css_fixed color;      /* colour bpp (0 for monochrome) */
+       css_fixed color_index;
+       css_fixed monochrome; /* monochrome bpp (0 for colour) */
+       css_fixed inverted_colors; /** boolean: {0|1} */
+
+       /* Interaction media features */
+       css_media_pointer pointer;
+       css_media_pointer any_pointer;
+       css_media_hover   hover;
+       css_media_hover   any_hover;
+
+       /* Environmental media features */
+       css_media_light_level light_level;
+
+       /* Scripting media features */
+       css_media_scripting scripting;
+} css_media;
+
+/**
  * Type of a qualified name
  */
 typedef struct css_qname {


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=95379c707aae2e8266ffba9bfac6fd7a68fd5381
commit 95379c707aae2e8266ffba9bfac6fd7a68fd5381
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Code style: Use spaces for alignment.

diff --git a/include/libcss/types.h b/include/libcss/types.h
index 4f35737..c5e9cce 100644
--- a/include/libcss/types.h
+++ b/include/libcss/types.h
@@ -60,10 +60,10 @@ typedef enum css_media_type {
        CSS_MEDIA_TTY               = (1 << 8),
        CSS_MEDIA_TV                = (1 << 9),
        CSS_MEDIA_ALL               = CSS_MEDIA_AURAL | CSS_MEDIA_BRAILLE |
-                                      CSS_MEDIA_EMBOSSED | CSS_MEDIA_HANDHELD |
-                                      CSS_MEDIA_PRINT | CSS_MEDIA_PROJECTION |
-                                      CSS_MEDIA_SCREEN | CSS_MEDIA_SPEECH |
-                                      CSS_MEDIA_TTY | CSS_MEDIA_TV
+                                     CSS_MEDIA_EMBOSSED | CSS_MEDIA_HANDHELD |
+                                     CSS_MEDIA_PRINT | CSS_MEDIA_PROJECTION |
+                                     CSS_MEDIA_SCREEN | CSS_MEDIA_SPEECH |
+                                     CSS_MEDIA_TTY | CSS_MEDIA_TV
 } css_media_type;
 
 /**


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=8a27e65cda95305f6b684f341c985142de7603a2
commit 8a27e65cda95305f6b684f341c985142de7603a2
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Add error-path resource cleanup.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 1fa66d6..ffddf64 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -369,8 +369,7 @@ static css_error mq_parse_range(css_language *c,
                        /* num/dim/ident */
                        error = mq_populate_value(&result->value2, token);
                        if (error != CSS_OK) {
-                               /* TODO: clean up result properly? */
-                               free(result);
+                               css_mq_feature_destroy(result);
                                return error;
                        }
                }
@@ -481,7 +480,7 @@ static css_error mq_parse_media_feature(css_language *c,
 
        token = parserutils_vector_iterate(vector, ctx);
        if (tokenIsChar(token, ')') == false) {
-               /* TODO: clean up result */
+               css_mq_feature_destroy(result);
                return CSS_INVALID;
        }
 
@@ -644,7 +643,7 @@ static css_error mq_parse_media_in_parens(css_language *c,
 
                        result = malloc(sizeof(*result));
                        if (result == NULL) {
-                               /* TODO: clean up cond */
+                               css__mq_cond_destroy(cond);
                                return CSS_NOMEM;
                        }
                        memset(result, 0, sizeof(*result));
@@ -661,7 +660,7 @@ static css_error mq_parse_media_in_parens(css_language *c,
                if (error == CSS_OK) {
                        result = malloc(sizeof(*result));
                        if (result == NULL) {
-                               /* TODO: clean up feature */
+                               css_mq_feature_destroy(feature);
                                return CSS_NOMEM;
                        }
                        memset(result, 0, sizeof(*result));
@@ -724,8 +723,7 @@ static css_error mq_parse_condition(css_language *c,
 
                error = mq_parse_media_in_parens(c, vector, ctx, 
&cond_or_feature);
                if (error != CSS_OK) {
-                       free(result->parts);
-                       free(result);
+                       css__mq_cond_destroy(result);
                        return CSS_INVALID;
                }
 
@@ -733,9 +731,8 @@ static css_error mq_parse_condition(css_language *c,
                result->parts->nparts = 1;
                result->parts->parts = malloc(sizeof(*result->parts->parts));
                if (result->parts->parts == NULL) {
-                       /* TODO: clean up cond_or_feature */
-                       free(result->parts);
-                       free(result);
+                       css__mq_cond_or_feature_destroy(cond_or_feature);
+                       css__mq_cond_destroy(result);
                        return CSS_NOMEM;
                }
                result->parts->parts[0] = cond_or_feature;
@@ -750,18 +747,15 @@ static css_error mq_parse_condition(css_language *c,
                        tokenIsChar(token, ',') == false) {
                error = mq_parse_media_in_parens(c, vector, ctx, 
&cond_or_feature);
                if (error != CSS_OK) {
-                       /* TODO: clean up result->parts->parts */
-                       free(result->parts);
-                       free(result);
+                       css__mq_cond_destroy(result);
                        return CSS_INVALID;
                }
 
                parts = realloc(result->parts->parts,
                                
(result->parts->nparts+1)*sizeof(*result->parts->parts));
                if (parts == NULL) {
-                       /* TODO: clean up result->parts->parts */
-                       free(result->parts);
-                       free(result);
+                       css__mq_cond_or_feature_destroy(cond_or_feature);
+                       css__mq_cond_destroy(result);
                        return CSS_NOMEM;
                }
                parts[result->parts->nparts] = cond_or_feature;
@@ -774,17 +768,13 @@ static css_error mq_parse_condition(css_language *c,
                if (token != NULL && tokenIsChar(token, ')') == false &&
                                tokenIsChar(token, ',') == false) {
                        if (token->type != CSS_TOKEN_IDENT) {
-                               /* TODO: clean up result->parts->parts */
-                               free(result->parts);
-                               free(result);
+                               css__mq_cond_destroy(result);
                                return CSS_INVALID;
                        } else if (lwc_string_caseless_isequal(token->idata,
                                        c->strings[AND], &match) == 
lwc_error_ok &&
                                        match) {
                                if (op != 0 && op != AND) {
-                                       /* TODO: clean up result->parts->parts 
*/
-                                       free(result->parts);
-                                       free(result);
+                                       css__mq_cond_destroy(result);
                                        return CSS_INVALID;
                                }
                                op = AND;
@@ -792,17 +782,13 @@ static css_error mq_parse_condition(css_language *c,
                                                c->strings[OR], &match) == 
lwc_error_ok &&
                                        match) {
                                if (permit_or == false || (op != 0 && op != 
OR)) {
-                                       /* TODO: clean up result->parts->parts 
*/
-                                       free(result->parts);
-                                       free(result);
+                                       css__mq_cond_destroy(result);
                                        return CSS_INVALID;
                                }
                                op = OR;
                        } else {
                                /* Neither AND nor OR */
-                               /* TODO: clean up result->parts->parts */
-                               free(result->parts);
-                               free(result);
+                               css__mq_cond_destroy(result);
                                return CSS_INVALID;
                        }
 
@@ -954,6 +940,8 @@ css_error css__mq_parse_media_list(css_language *c,
                error = mq_parse_media_query(c, vector, ctx, &query);
                if (error != CSS_OK) {
                        /* TODO: error recovery (see above) */
+                       css__mq_query_destroy(result);
+                       return error;
                } else {
                        if (result == NULL) {
                                result = last = query;


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=729d354c1c50698c1d08c925cd4e67b0f548691f
commit 729d354c1c50698c1d08c925cd4e67b0f548691f
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Add destruction functions.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 6692651..1fa66d6 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -17,6 +17,63 @@
 #include "parse/properties/utils.h"
 #include "utils/utils.h"
 
+static void css_mq_feature_destroy(css_mq_feature *feature)
+{
+       if (feature != NULL) {
+               lwc_string_unref(feature->name);
+               free(feature);
+       }
+}
+
+static void css__mq_cond_or_feature_destroy(
+               css_mq_cond_or_feature *cond_or_feature);
+
+static void css__mq_cond_parts_destroy(css_mq_cond_parts *cond_parts)
+{
+       if (cond_parts != NULL) {
+               for (uint32_t i = 0; i < cond_parts->nparts; i++) {
+                       css__mq_cond_or_feature_destroy(cond_parts->parts[i]);
+               }
+               free(cond_parts);
+       }
+}
+
+static void css__mq_cond_destroy(css_mq_cond *cond)
+{
+       if (cond != NULL) {
+               css__mq_cond_parts_destroy(cond->parts);
+               free(cond);
+       }
+}
+
+static void css__mq_cond_or_feature_destroy(
+               css_mq_cond_or_feature *cond_or_feature)
+{
+       if (cond_or_feature != NULL) {
+               switch (cond_or_feature->type) {
+               case CSS_MQ_FEATURE:
+                       css_mq_feature_destroy(cond_or_feature->data.feat);
+                       break;
+               case CSS_MQ_COND:
+                       css__mq_cond_destroy(cond_or_feature->data.cond);
+                       break;
+               }
+               free(cond_or_feature);
+       }
+}
+
+void css__mq_query_destroy(css_mq_query *media)
+{
+       while (media != NULL) {
+               css_mq_query *next = media->next;
+
+               css__mq_cond_destroy(media->cond);
+               free(media);
+
+               media = next;
+       }
+}
+
 static css_error mq_parse_condition(css_language *c,
                const parserutils_vector *vector, int *ctx,
                bool permit_or, css_mq_cond **cond);
diff --git a/src/parse/mq.h b/src/parse/mq.h
index ae0110b..77f8a8a 100644
--- a/src/parse/mq.h
+++ b/src/parse/mq.h
@@ -91,6 +91,6 @@ css_error css__mq_parse_media_list(css_language *c,
                const parserutils_vector *vector, int *ctx,
                css_mq_query **media);
 
-css_mq_query *css__mq_query_destroy(css_mq_query *media);
+void css__mq_query_destroy(css_mq_query *media);
 
 #endif


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=f76745d277cf7fa6bae70bf0b5cff404c0c1fd6a
commit f76745d277cf7fa6bae70bf0b5cff404c0c1fd6a
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Documentation: Add new units to bytecode docs.

diff --git a/docs/Bytecode b/docs/Bytecode
index f64656a..dd0f424 100644
--- a/docs/Bytecode
+++ b/docs/Bytecode
@@ -69,6 +69,7 @@ Length is a 32bit numeric value (as described above) and unit 
is as follows:
                        00000000 => deg
                        00000001 => grad
                        00000010 => rad
+                       00000011 => turn
 
        bit 10 set => time unit
                bits 11-31: MBZ
@@ -84,6 +85,14 @@ Length is a 32bit numeric value (as described above) and 
unit is as follows:
                        00000000 => Hz
                        00000001 => kHz
 
+       bit 12 set => resolution unit
+               bits 13-31: MBZ
+               bits 8-11 : MBZ
+               bits 0-7  :
+                       00000000 => dpi
+                       00000001 => dpcm
+                       00000010 => dppx
+
 CSS colours are stored as one 32bit value. See "Colour" for their format.
 
 Shorthand properties


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=6d01409022ba0a02f40dd9ebb7b247bd66a83017
commit 6d01409022ba0a02f40dd9ebb7b247bd66a83017
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Implement parsing <general-enclosed>.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 719e129..6692651 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -433,14 +433,111 @@ static css_error mq_parse_media_feature(css_language *c,
        return CSS_OK;
 }
 
+/*
+ * Consume any value
+ *
+ * CSS Syntax Module Level 3: 8.2
+ */
+static css_error mq_parse_consume_any_value(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               bool until, const char until_char)
+{
+       const css_token *token;
+       css_error error;
+
+       while (true) {
+               consumeWhitespace(vector, ctx);
+
+               token = parserutils_vector_iterate(vector, ctx);
+               if (token == NULL) {
+                       return CSS_INVALID;
+               }
+
+               switch (token->type) {
+               case CSS_TOKEN_INVALID_STRING:
+                       return CSS_INVALID;
+
+               case CSS_TOKEN_CHAR:
+                       if (until && tokenIsChar(token, until_char)) {
+                               /* Found matching close bracket */
+                               return CSS_OK;
+
+                       } else if (tokenIsChar(token, ')') ||
+                                  tokenIsChar(token, ']') ||
+                                  tokenIsChar(token, '}')) {
+                               /* Non-matching close bracket */
+                               return CSS_INVALID;
+                       }
+                       if (tokenIsChar(token, '(')) {
+                               /* Need to consume until matching bracket. */
+                               error = mq_parse_consume_any_value(
+                                               c, vector, ctx, true, ')');
+                               if (error != CSS_OK) {
+                                       return error;
+                               }
+                       } else if (tokenIsChar(token, '[')) {
+                               /* Need to consume until matching bracket. */
+                               error = mq_parse_consume_any_value(
+                                               c, vector, ctx, true, ']');
+                               if (error != CSS_OK) {
+                                       return error;
+                               }
+                       } else if (tokenIsChar(token, '{')) {
+                               /* Need to consume until matching bracket. */
+                               error = mq_parse_consume_any_value(
+                                               c, vector, ctx, true, '}');
+                               if (error != CSS_OK) {
+                                       return error;
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       return CSS_OK;
+}
+
 static css_error mq_parse_general_enclosed(css_language *c,
                const parserutils_vector *vector, int *ctx)
 {
+       const css_token *token;
+       css_error error;
+
        /* <general-enclosed> = [ <function-token> <any-value> ) ]
         *                    | ( <ident> <any-value> )
         */
 
-       /* TODO: implement */
+       token = parserutils_vector_iterate(vector, ctx);
+       if (token == NULL) {
+               return CSS_INVALID;
+       }
+
+       switch (token->type) {
+       case CSS_TOKEN_FUNCTION:
+               error = mq_parse_consume_any_value(c, vector, ctx, true, ')');
+               if (error != CSS_OK) {
+                       return error;
+               }
+
+               token = parserutils_vector_peek(vector, *ctx);
+               if (!tokenIsChar(token, ')')) {
+                       return CSS_INVALID;
+               }
+               break;
+
+       case CSS_TOKEN_IDENT:
+               error = mq_parse_consume_any_value(c, vector, ctx, false, '\0');
+               if (error != CSS_OK) {
+                       return error;
+               }
+               break;
+
+       default:
+               return CSS_INVALID;
+       }
 
        return CSS_OK;
 }


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=fa185a120a6dfdc77ba68beefff42fa24474a04b
commit fa185a120a6dfdc77ba68beefff42fa24474a04b
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Squash invalid use of unused variable warning.
    
    error: ‘last’ may be used uninitialized in this function 
[-Werror=maybe-uninitialized]

diff --git a/src/parse/mq.c b/src/parse/mq.c
index f587f8d..719e129 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -780,7 +780,7 @@ css_error css__mq_parse_media_list(css_language *c,
                const parserutils_vector *vector, int *ctx,
                css_mq_query **media)
 {
-       css_mq_query *result = NULL, *last;
+       css_mq_query *result = NULL, *last = NULL;
        const css_token *token;
        css_error error;
 
@@ -804,6 +804,7 @@ css_error css__mq_parse_media_list(css_language *c,
                        if (result == NULL) {
                                result = last = query;
                        } else {
+                               assert(last != NULL);
                                last->next = query;
                                last = query;
                        }


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=70355dd6c235dff2a8b4dd22be6efd129a30eb95
commit 70355dd6c235dff2a8b4dd22be6efd129a30eb95
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Add forward declaration of mq_parse_condition.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 932d6aa..f587f8d 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -17,6 +17,10 @@
 #include "parse/properties/utils.h"
 #include "utils/utils.h"
 
+static css_error mq_parse_condition(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               bool permit_or, css_mq_cond **cond);
+
 static css_error mq_parse_ratio(
                const parserutils_vector *vector, int *ctx,
                const css_token *numerator, css_fixed *ratio)


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=eb4ae979e6ee8a51fb360bd5addcd479bd8121c8
commit eb4ae979e6ee8a51fb360bd5addcd479bd8121c8
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: mq_parse_ratio doesn't need language object.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index f99d5b0..932d6aa 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -17,7 +17,7 @@
 #include "parse/properties/utils.h"
 #include "utils/utils.h"
 
-static css_error mq_parse_ratio(css_language *c,
+static css_error mq_parse_ratio(
                const parserutils_vector *vector, int *ctx,
                const css_token *numerator, css_fixed *ratio)
 {
@@ -166,7 +166,7 @@ static css_error mq_parse_range(css_language *c,
        if (name_or_value->type == CSS_TOKEN_NUMBER &&
                        tokenIsChar(parserutils_vector_peek(vector, *ctx), 
'/')) {
                /* ratio */
-               error = mq_parse_ratio(c, vector, ctx, token, &ratio);
+               error = mq_parse_ratio(vector, ctx, token, &ratio);
                if (error != CSS_OK) {
                        return error;
                }
@@ -213,7 +213,7 @@ static css_error mq_parse_range(css_language *c,
        if (value_or_name->type == CSS_TOKEN_NUMBER &&
                        tokenIsChar(parserutils_vector_peek(vector, *ctx), 
'/')) {
                /* ratio */
-               error = mq_parse_ratio(c, vector, ctx, token, &ratio);
+               error = mq_parse_ratio(vector, ctx, token, &ratio);
                if (error != CSS_OK) {
                        return error;
                }
@@ -260,7 +260,7 @@ static css_error mq_parse_range(css_language *c,
                if (value_or_name->type == CSS_TOKEN_NUMBER &&
                                tokenIsChar(parserutils_vector_peek(vector, 
*ctx), '/')) {
                        /* ratio */
-                       error = mq_parse_ratio(c, vector, ctx, token, &ratio2);
+                       error = mq_parse_ratio(vector, ctx, token, &ratio2);
                        if (error != CSS_OK) {
                                return error;
                        }
@@ -381,7 +381,7 @@ static css_error mq_parse_media_feature(css_language *c,
                                /* ratio */
                                css_fixed ratio;
 
-                               error = mq_parse_ratio(c, vector, ctx, token, 
&ratio);
+                               error = mq_parse_ratio(vector, ctx, token, 
&ratio);
                                if (error != CSS_OK) {
                                        free(result);
                                        return error;


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=0b11761524f50052e8f58f89f8a6be5e737fc5be
commit 0b11761524f50052e8f58f89f8a6be5e737fc5be
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Minor fixes.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 8bdd7a0..f99d5b0 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -82,8 +82,9 @@ static css_error mq_populate_value(css_mq_value *value,
                const char *data = lwc_string_data(token->idata);
                uint32_t unit = UNIT_PX;
                size_t consumed;
+               css_error error;
 
-               value->type == CSS_MQ_VALUE_TYPE_DIM;
+               value->type = CSS_MQ_VALUE_TYPE_DIM;
                value->data.dim.len = css__number_from_lwc_string(
                                token->idata, false, &consumed);
                error = css__parse_unit_keyword(data + consumed, len - consumed,
@@ -91,7 +92,7 @@ static css_error mq_populate_value(css_mq_value *value,
                if (error != CSS_OK) {
                        return error;
                }
-               value->data.dim.unit = temp_unit;
+               value->data.dim.unit = unit;
        } else if (token->type == CSS_TOKEN_IDENT) {
                value->type = CSS_MQ_VALUE_TYPE_IDENT;
                value->data.ident = lwc_string_ref(token->idata);
@@ -447,7 +448,7 @@ static css_error mq_parse_media_in_parens(css_language *c,
        const css_token *token;
        bool match;
        int old_ctx;
-       cond_or_feature *result = NULL;
+       css_mq_cond_or_feature *result = NULL;
        css_error error = CSS_OK;
 
        /* <media-in-parens> = ( <media-condition> ) | <media-feature> | 
<general-enclosed>
@@ -609,7 +610,7 @@ static css_error mq_parse_condition(css_language *c,
                result->parts->parts = parts;
                result->parts->nparts++;
 
-               consumeWhitespace(vector, token);
+               consumeWhitespace(vector, ctx);
 
                token = parserutils_vector_peek(vector, *ctx);
                if (token != NULL && tokenIsChar(token, ')') == false &&


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=951c66846cebb683b2edb65b7318a0dfc4c4ca00
commit 951c66846cebb683b2edb65b7318a0dfc4c4ca00
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Strings: Add 'infinite'.

diff --git a/src/parse/propstrings.c b/src/parse/propstrings.c
index dc32ce9..3c9401b 100644
--- a/src/parse/propstrings.c
+++ b/src/parse/propstrings.c
@@ -442,6 +442,7 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
        { "and", SLEN("and") },
        { "or", SLEN("or") },
        { "only", SLEN("only") },
+       { "infinite", SLEN("infinite") },
 
        { "aliceblue", SLEN("aliceblue") },
        { "antiquewhite", SLEN("antiquewhite") },
diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h
index 0d5d0be..24b681b 100644
--- a/src/parse/propstrings.h
+++ b/src/parse/propstrings.h
@@ -101,7 +101,7 @@ enum {
        AVOID_PAGE, AVOID_COLUMN, BALANCE, HORIZONTAL_TB, VERTICAL_RL,
        VERTICAL_LR, CONTENT_BOX, BORDER_BOX, STRETCH, INLINE_FLEX, FLEX_START,
        FLEX_END, SPACE_BETWEEN, SPACE_AROUND, SPACE_EVENLY, ROW, ROW_REVERSE,
-       COLUMN_REVERSE, WRAP_STRING, WRAP_REVERSE, AND, OR, ONLY,
+       COLUMN_REVERSE, WRAP_STRING, WRAP_REVERSE, AND, OR, ONLY, INFINITE,
 
        /* Named colours */
        FIRST_COLOUR,


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=c3006e4bbbe99c927532557d2cd6fa9b9e7e379b
commit c3006e4bbbe99c927532557d2cd6fa9b9e7e379b
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Include string.h for memset.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 48f4c41..8bdd7a0 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -7,6 +7,8 @@
 
 /* https://drafts.csswg.org/mediaqueries/ */
 
+#include <string.h>
+
 #include <libcss/fpmath.h>
 
 #include "stylesheet.h"


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=3847e0611bfc81ef2a53d1b3a2207785dfe202da
commit 3847e0611bfc81ef2a53d1b3a2207785dfe202da
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: Include stylesheet.h for css_style.

diff --git a/src/parse/mq.c b/src/parse/mq.c
index c557996..48f4c41 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -9,6 +9,7 @@
 
 #include <libcss/fpmath.h>
 
+#include "stylesheet.h"
 #include "bytecode/bytecode.h"
 #include "parse/mq.h"
 #include "parse/properties/utils.h"


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=7ba6e00f28bec3efb16c86481f27fb9e22f093ef
commit 7ba6e00f28bec3efb16c86481f27fb9e22f093ef
Author: John-Mark Bell <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: remainder of parser

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 96f70df..c557996 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -333,6 +333,8 @@ static css_error mq_parse_media_feature(css_language *c,
 
        /* ( already consumed */
 
+       consumeWhitespace(vector, ctx);
+
        name_or_value = parserutils_vector_iterate(vector, ctx);
        if (name_or_value == NULL)
                return CSS_INVALID;
@@ -423,42 +425,359 @@ static css_error mq_parse_media_feature(css_language *c,
        return CSS_OK;
 }
 
-static css_error mq_parse_media_in_parens()
+static css_error mq_parse_general_enclosed(css_language *c,
+               const parserutils_vector *vector, int *ctx)
 {
+       /* <general-enclosed> = [ <function-token> <any-value> ) ]
+        *                    | ( <ident> <any-value> )
+        */
+
+       /* TODO: implement */
+
+       return CSS_OK;
+}
+
+static css_error mq_parse_media_in_parens(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_mq_cond_or_feature **cond_or_feature)
+{
+       const css_token *token;
+       bool match;
+       int old_ctx;
+       cond_or_feature *result = NULL;
+       css_error error = CSS_OK;
+
        /* <media-in-parens> = ( <media-condition> ) | <media-feature> | 
<general-enclosed>
-        * <general-enclosed> = [ <function-token> <any-value> ) ] | ( <ident> 
<any-value> )
         */
 
        //LPAREN -> condition-or-feature
        //        "not" or LPAREN -> condition
        //        IDENT | NUMBER | DIMENSION | RATIO -> feature
 
+       token = parserutils_vector_iterate(vector, ctx);
+       if (token == NULL || tokenIsChar(token, '(') == false) {
+               return CSS_INVALID;
+       }
+
+       consumeWhitespace(vector, ctx);
+
+       token = parserutils_vector_peek(vector, *ctx);
+       if (token == NULL) {
+               return CSS_INVALID;
+       }
+
+       old_ctx = *ctx;
+
+       if (tokenIsChar(token, '(') || (token->type == CSS_TOKEN_IDENT &&
+                       lwc_string_caseless_isequal(token->idata,
+                               c->strings[NOT], &match) == lwc_error_ok &&
+                       match)) {
+               css_mq_cond *cond;
+               error = mq_parse_condition(c, vector, ctx, true, &cond);
+               if (error == CSS_OK) {
+                       token = parserutils_vector_iterate(vector, ctx);
+                       if (tokenIsChar(token, ')') == false) {
+                               return CSS_INVALID;
+                       }
+
+                       result = malloc(sizeof(*result));
+                       if (result == NULL) {
+                               /* TODO: clean up cond */
+                               return CSS_NOMEM;
+                       }
+                       memset(result, 0, sizeof(*result));
+                       result->type = CSS_MQ_COND;
+                       result->data.cond = cond;
+                       *cond_or_feature = result;
+                       return CSS_OK;
+               }
+       } else if (token->type == CSS_TOKEN_IDENT ||
+                       token->type == CSS_TOKEN_NUMBER ||
+                       token->type == CSS_TOKEN_DIMENSION) {
+               css_mq_feature *feature;
+               error = mq_parse_media_feature(c, vector, ctx, &feature);
+               if (error == CSS_OK) {
+                       result = malloc(sizeof(*result));
+                       if (result == NULL) {
+                               /* TODO: clean up feature */
+                               return CSS_NOMEM;
+                       }
+                       memset(result, 0, sizeof(*result));
+                       result->type = CSS_MQ_FEATURE;
+                       result->data.feat = feature;
+                       *cond_or_feature = result;
+                       return CSS_OK;
+               }
+       }
+
+       *ctx = old_ctx;
+       error = mq_parse_general_enclosed(c, vector, ctx);
+
+       return error;
 }
 
-static css_error mq_parse_condition()
+static css_error mq_parse_condition(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               bool permit_or, css_mq_cond **cond)
 {
+       const css_token *token;
+       bool match;
+       int op = 0; /* Will be AND | OR once we've had one */
+       css_mq_cond_or_feature *cond_or_feature, **parts;
+       css_mq_cond *result;
+       css_error error;
+
        /* <media-condition> = <media-not> | <media-in-parens> [ <media-and>* | 
<media-or>* ]
         * <media-condition-without-or> = <media-not> | <media-in-parens> 
<media-and>*
         * <media-not> = not <media-in-parens>
         * <media-and> = and <media-in-parens>
         * <media-or> = or <media-in-parens>
         */
+
+       token = parserutils_vector_peek(vector, *ctx);
+       if (token == NULL || tokenIsChar(token, '(') == false ||
+                       token->type != CSS_TOKEN_IDENT ||
+                       lwc_string_caseless_isequal(token->idata,
+                               c->strings[NOT], &match) != lwc_error_ok ||
+                       match == false) {
+               return CSS_INVALID;
+       }
+
+       result = malloc(sizeof(*result));
+       if (result == NULL) {
+               return CSS_NOMEM;
+       }
+       memset(result, 0, sizeof(*result));
+       result->parts = malloc(sizeof(*result->parts));
+       if (result->parts == NULL) {
+               free(result);
+               return CSS_NOMEM;
+       }
+       memset(result->parts, 0, sizeof(*result->parts));
+
+       if (tokenIsChar(token, '(') == false) {
+               /* Must be "not" */
+               parserutils_vector_iterate(vector, ctx);
+               consumeWhitespace(vector, ctx);
+
+               error = mq_parse_media_in_parens(c, vector, ctx, 
&cond_or_feature);
+               if (error != CSS_OK) {
+                       free(result->parts);
+                       free(result);
+                       return CSS_INVALID;
+               }
+
+               result->negate = 1;
+               result->parts->nparts = 1;
+               result->parts->parts = malloc(sizeof(*result->parts->parts));
+               if (result->parts->parts == NULL) {
+                       /* TODO: clean up cond_or_feature */
+                       free(result->parts);
+                       free(result);
+                       return CSS_NOMEM;
+               }
+               result->parts->parts[0] = cond_or_feature;
+
+               *cond = result;
+
+               return CSS_OK;
+       }
+
+       /* FOLLOW(media-condition) := RPAREN | COMMA | EOF */
+       while (token != NULL && tokenIsChar(token, ')') == false &&
+                       tokenIsChar(token, ',') == false) {
+               error = mq_parse_media_in_parens(c, vector, ctx, 
&cond_or_feature);
+               if (error != CSS_OK) {
+                       /* TODO: clean up result->parts->parts */
+                       free(result->parts);
+                       free(result);
+                       return CSS_INVALID;
+               }
+
+               parts = realloc(result->parts->parts,
+                               
(result->parts->nparts+1)*sizeof(*result->parts->parts));
+               if (parts == NULL) {
+                       /* TODO: clean up result->parts->parts */
+                       free(result->parts);
+                       free(result);
+                       return CSS_NOMEM;
+               }
+               parts[result->parts->nparts] = cond_or_feature;
+               result->parts->parts = parts;
+               result->parts->nparts++;
+
+               consumeWhitespace(vector, token);
+
+               token = parserutils_vector_peek(vector, *ctx);
+               if (token != NULL && tokenIsChar(token, ')') == false &&
+                               tokenIsChar(token, ',') == false) {
+                       if (token->type != CSS_TOKEN_IDENT) {
+                               /* TODO: clean up result->parts->parts */
+                               free(result->parts);
+                               free(result);
+                               return CSS_INVALID;
+                       } else if (lwc_string_caseless_isequal(token->idata,
+                                       c->strings[AND], &match) == 
lwc_error_ok &&
+                                       match) {
+                               if (op != 0 && op != AND) {
+                                       /* TODO: clean up result->parts->parts 
*/
+                                       free(result->parts);
+                                       free(result);
+                                       return CSS_INVALID;
+                               }
+                               op = AND;
+                       } else if (lwc_string_caseless_isequal(token->idata,
+                                               c->strings[OR], &match) == 
lwc_error_ok &&
+                                       match) {
+                               if (permit_or == false || (op != 0 && op != 
OR)) {
+                                       /* TODO: clean up result->parts->parts 
*/
+                                       free(result->parts);
+                                       free(result);
+                                       return CSS_INVALID;
+                               }
+                               op = OR;
+                       } else {
+                               /* Neither AND nor OR */
+                               /* TODO: clean up result->parts->parts */
+                               free(result->parts);
+                               free(result);
+                               return CSS_INVALID;
+                       }
+
+                       parserutils_vector_iterate(vector, ctx);
+                       consumeWhitespace(vector, ctx);
+               }
+       }
+
+       if (op == OR) {
+               result->op = 1;
+       }
+
+       *cond = result;
+
+       return CSS_OK;
 }
 
-css_error css__mq_parse_media_list(css_language *c,
+static css_error mq_parse_media_query(css_language *c,
                const parserutils_vector *vector, int *ctx,
-               css_mq_query **media)
+               css_mq_query **query)
 {
-       css_mq_query *ret = NULL;
        const css_token *token;
+       bool match, is_condition = false;
+       css_mq_query *result;
+       css_error error;
 
-       /* <media-query-list> = <media-query> [ COMMA <media-query> ]*
-        * <media-query> = <media-condition>
+       /* <media-query> = <media-condition>
         *               | [ not | only ]? <media-type> [ and 
<media-condition-without-or> ]?
         * <media-type> = <ident> (except "not", "and", "or", "only")
-        *
         */
 
+       // LPAREN -> media-condition
+       //    not LPAREN -> media-condition
+
+       consumeWhitespace(vector, ctx);
+
+       token = parserutils_vector_peek(vector, *ctx);
+       if (tokenIsChar(token, '(')) {
+               is_condition = true;
+       } else if (token->type == CSS_TOKEN_IDENT &&
+                       lwc_string_caseless_isequal(token->idata,
+                               c->strings[NOT], &match) == lwc_error_ok &&
+                               match) {
+               int old_ctx = *ctx;
+
+               parserutils_vector_iterate(vector, ctx);
+               consumeWhitespace(vector, ctx);
+
+               token = parserutils_vector_peek(vector, *ctx);
+               if (tokenIsChar(token, '(')) {
+                       is_condition = true;
+               }
+
+               *ctx = old_ctx;
+       }
+
+       result = malloc(sizeof(*result));
+       if (result == NULL) {
+               return CSS_NOMEM;
+       }
+       memset(result, 0, sizeof(*result));
+
+       if (is_condition) {
+               /* media-condition */
+               error = mq_parse_condition(c, vector, ctx, true, &result->cond);
+               if (error != CSS_OK) {
+                       free(result);
+                       return error;
+               }
+
+               *query = result;
+               return CSS_OK;
+       }
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (token == NULL || token->type != CSS_TOKEN_IDENT) {
+               free(result);
+               return CSS_INVALID;
+       }
+
+       if (lwc_string_caseless_isequal(token->idata,
+                       c->strings[NOT], &match) == lwc_error_ok &&
+                       match) {
+               result->negate_type = 1;
+               consumeWhitespace(vector, ctx);
+               token = parserutils_vector_iterate(vector, ctx);
+       } else if (lwc_string_caseless_isequal(token->idata,
+                       c->strings[ONLY], &match) == lwc_error_ok &&
+                       match) {
+               consumeWhitespace(vector, ctx);
+               token = parserutils_vector_iterate(vector, ctx);
+       }
+
+       if (token == NULL || token->type != CSS_TOKEN_IDENT) {
+               free(result);
+               return CSS_INVALID;
+       }
+
+       result->type = lwc_string_ref(token->idata);
+
+       consumeWhitespace(vector, ctx);
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (token != NULL) {
+               if (token->type != CSS_TOKEN_IDENT ||
+                               lwc_string_caseless_isequal(token->idata,
+                                       c->strings[AND], &match) != 
lwc_error_ok ||
+                               match == false) {
+                       lwc_string_unref(result->type);
+                       free(result);
+                       return CSS_INVALID;
+               }
+
+               consumeWhitespace(vector, ctx);
+
+               error = mq_parse_condition(c, vector, ctx, false, 
&result->cond);
+               if (error != CSS_OK) {
+                       lwc_string_unref(result->type);
+                       free(result);
+                       return error;
+               }
+       }
+
+       *query = result;
+       return CSS_OK;
+}
+
+css_error css__mq_parse_media_list(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_mq_query **media)
+{
+       css_mq_query *result = NULL, *last;
+       const css_token *token;
+       css_error error;
+
+       /* <media-query-list> = <media-query> [ COMMA <media-query> ]* */
+
        /* if {[(, push }]) to stack
         * if func, push ) to stack
         * on error, scan forward until stack is empty (or EOF), popping 
matching tokens off stack
@@ -466,78 +785,32 @@ css_error css__mq_parse_media_list(css_language *c,
         * if comma, consume, and start again from the next input token
         */
 
-       UNUSED(c);
-
-       token = parserutils_vector_iterate(vector, ctx);
-
+       token = parserutils_vector_peek(vector, *ctx);
        while (token != NULL) {
-               if (token->type != CSS_TOKEN_IDENT)
-                       return CSS_INVALID;
+               css_mq_query *query;
+
+               error = mq_parse_media_query(c, vector, ctx, &query);
+               if (error != CSS_OK) {
+                       /* TODO: error recovery (see above) */
+               } else {
+                       if (result == NULL) {
+                               result = last = query;
+                       } else {
+                               last->next = query;
+                               last = query;
+                       }
+               }
 
-#if 0
-               if (lwc_string_caseless_isequal(token->idata, 
c->strings[AURAL], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_AURAL;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[BRAILLE], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_BRAILLE;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[EMBOSSED], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_EMBOSSED;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[HANDHELD], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_HANDHELD;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[PRINT], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_PRINT;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[PROJECTION], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_PROJECTION;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[SCREEN], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_SCREEN;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[SPEECH], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_SPEECH;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[TTY], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_TTY;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[TV], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_TV;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[ALL], 
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_ALL;
-               } else
-                       return CSS_INVALID;
-#endif
                consumeWhitespace(vector, ctx);
 
                token = parserutils_vector_iterate(vector, ctx);
-               if (token != NULL && tokenIsChar(token, ',') == false)
-                       return CSS_INVALID;
-
-               consumeWhitespace(vector, ctx);
+               if (token != NULL && tokenIsChar(token, ',') == false) {
+                       /* Give up */
+                       break;
+               }
        }
 
-#if 0
-       /* If, after parsing the media list, we still have no media, 
-        * then it must be ALL. */
-       if (ret == 0)
-               ret = CSS_MEDIA_ALL;
-#endif
-
-       *media = ret;
+       *media = result;
 
        return CSS_OK;
 }
diff --git a/src/parse/mq.h b/src/parse/mq.h
index c5268c7..ae0110b 100644
--- a/src/parse/mq.h
+++ b/src/parse/mq.h
@@ -73,20 +73,18 @@ struct css_mq_cond_or_feature {
                CSS_MQ_COND
        } type;
        union {
-               css_mq_cond cond;
-               css_mq_feature feat;
+               css_mq_cond *cond;
+               css_mq_feature *feat;
        } data;
 };
 
 typedef struct css_mq_query {
        struct css_mq_query *next;
 
-       uint32_t negate_type : 1, /* set if "not type" */
-                cond_op     : 1; /* clear if "and", set if "or" */
+       uint32_t negate_type : 1; /* set if "not type" */
        lwc_string *type; /* or NULL */
 
-       uint32_t nconds;
-       css_mq_cond **conds;
+       css_mq_cond *cond;
 } css_mq_query;
 
 css_error css__mq_parse_media_list(css_language *c,


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=7d990ee1d8eb3aa9db21a862743c116bc935f524
commit 7d990ee1d8eb3aa9db21a862743c116bc935f524
Author: John-Mark Bell <[email protected]>
Commit: Michael Drake <[email protected]>

    Propstrings: add AND, ONLY, OR

diff --git a/src/parse/propstrings.c b/src/parse/propstrings.c
index bfd2965..dc32ce9 100644
--- a/src/parse/propstrings.c
+++ b/src/parse/propstrings.c
@@ -439,6 +439,9 @@ const stringmap_entry stringmap[LAST_KNOWN] = {
        { "column-reverse", SLEN("column-reverse") },
        { "wrap", SLEN("wrap") },
        { "wrap-reverse", SLEN("wrap-reverse") },
+       { "and", SLEN("and") },
+       { "or", SLEN("or") },
+       { "only", SLEN("only") },
 
        { "aliceblue", SLEN("aliceblue") },
        { "antiquewhite", SLEN("antiquewhite") },
diff --git a/src/parse/propstrings.h b/src/parse/propstrings.h
index 67eaa5f..0d5d0be 100644
--- a/src/parse/propstrings.h
+++ b/src/parse/propstrings.h
@@ -101,7 +101,7 @@ enum {
        AVOID_PAGE, AVOID_COLUMN, BALANCE, HORIZONTAL_TB, VERTICAL_RL,
        VERTICAL_LR, CONTENT_BOX, BORDER_BOX, STRETCH, INLINE_FLEX, FLEX_START,
        FLEX_END, SPACE_BETWEEN, SPACE_AROUND, SPACE_EVENLY, ROW, ROW_REVERSE,
-       COLUMN_REVERSE, WRAP_STRING, WRAP_REVERSE,
+       COLUMN_REVERSE, WRAP_STRING, WRAP_REVERSE, AND, OR, ONLY,
 
        /* Named colours */
        FIRST_COLOUR,


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=c0cab85092b0c836afd30969cc9aae0594a2afdb
commit c0cab85092b0c836afd30969cc9aae0594a2afdb
Author: John-Mark Bell <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: parse features

diff --git a/src/parse/mq.c b/src/parse/mq.c
index 5c9c7fa..96f70df 100644
--- a/src/parse/mq.c
+++ b/src/parse/mq.c
@@ -7,7 +7,443 @@
 
 /* https://drafts.csswg.org/mediaqueries/ */
 
+#include <libcss/fpmath.h>
+
+#include "bytecode/bytecode.h"
 #include "parse/mq.h"
+#include "parse/properties/utils.h"
+#include "utils/utils.h"
+
+static css_error mq_parse_ratio(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               const css_token *numerator, css_fixed *ratio)
+{
+       const css_token *token;
+       css_fixed num, den;
+       size_t num_len, den_len;
+
+       /* NUMBER ws* '/' ws* NUMBER */
+
+       /* numerator, ws* already consumed */
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (token == NULL || tokenIsChar(token, '/') == false) {
+               return CSS_INVALID;
+       }
+
+       consumeWhitespace(vector, ctx);
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (token == NULL || token->type != CSS_TOKEN_NUMBER) {
+               return CSS_INVALID;
+       }
+
+       num = css__number_from_lwc_string(numerator->idata, true, &num_len);
+       den = css__number_from_lwc_string(token->idata, true, &den_len);
+
+       *ratio = css_divide_fixed(num, den);
+
+       return CSS_OK;
+}
+
+static css_error mq_create_feature(
+               lwc_string *name,
+               css_mq_feature **feature)
+{
+       css_mq_feature *f;
+
+       f = malloc(sizeof(*f));
+       if (f == NULL) {
+               return CSS_NOMEM;
+       }
+
+       memset(f, 0, sizeof(*f));
+
+       f->name = lwc_string_ref(name);
+
+       *feature = f;
+
+       return CSS_OK;
+}
+
+static css_error mq_populate_value(css_mq_value *value,
+               const css_token *token)
+{
+       if (token->type == CSS_TOKEN_NUMBER) {
+               size_t num_len;
+               value->type = CSS_MQ_VALUE_TYPE_NUM;
+               value->data.num_or_ratio = css__number_from_lwc_string(
+                               token->idata, false, &num_len);
+       } else if (token->type == CSS_TOKEN_DIMENSION) {
+               size_t len = lwc_string_length(token->idata);
+               const char *data = lwc_string_data(token->idata);
+               uint32_t unit = UNIT_PX;
+               size_t consumed;
+
+               value->type == CSS_MQ_VALUE_TYPE_DIM;
+               value->data.dim.len = css__number_from_lwc_string(
+                               token->idata, false, &consumed);
+               error = css__parse_unit_keyword(data + consumed, len - consumed,
+                               &unit);
+               if (error != CSS_OK) {
+                       return error;
+               }
+               value->data.dim.unit = temp_unit;
+       } else if (token->type == CSS_TOKEN_IDENT) {
+               value->type = CSS_MQ_VALUE_TYPE_IDENT;
+               value->data.ident = lwc_string_ref(token->idata);
+       }
+
+       return CSS_OK;
+}
+
+static css_error mq_parse_op(const css_token *token,
+               css_mq_feature_op *op)
+{
+       size_t len;
+       const char *data;
+
+       if (token == NULL || token->type != CSS_TOKEN_CHAR)
+               return CSS_INVALID;
+
+       len = lwc_string_length(token->idata);
+       data = lwc_string_data(token->idata);
+
+       if (len == 2) {
+               if (strncasecmp(data, "<=", 2) == 0)
+                       *op = CSS_MQ_FEATURE_OP_LTE;
+               else if (strncasecmp(data, ">=", 2) == 0)
+                       *op = CSS_MQ_FEATURE_OP_GTE;
+               else
+                       return CSS_INVALID;
+       } else if (len == 1) {
+               if (*data == '<')
+                       *op = CSS_MQ_FEATURE_OP_LT;
+               else if (*data == '=')
+                       *op = CSS_MQ_FEATURE_OP_EQ;
+               else if (*data == '>')
+                       *op = CSS_MQ_FEATURE_OP_GT;
+               else
+                       return CSS_INVALID;
+       } else {
+               return CSS_INVALID;
+       }
+
+       return CSS_OK;
+}
+
+static css_error mq_parse_range(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               const css_token *name_or_value,
+               css_mq_feature **feature)
+{
+       const css_token *token, *value_or_name, *name = NULL, *value2 = NULL;
+       css_mq_feature *result;
+       css_mq_feature_op op, op2;
+       css_fixed ratio, ratio2;
+       bool name_first = false, value_is_ratio = false, value2_is_ratio = 
false, match;
+       css_error error;
+
+       /* <mf-range> = <mf-name> [ '<' | '>' ]? '='? <mf-value>
+        *            | <mf-value> [ '<' | '>' ]? '='? <mf-name>
+        *            | <mf-value> '<' '='? <mf-name> '<' '='? <mf-value>
+        *            | <mf-value> '>' '='? <mf-name> '>' '='? <mf-value>
+        */
+
+       if (name_or_value == NULL || (name_or_value->type != CSS_TOKEN_NUMBER &&
+                       name_or_value->type != CSS_TOKEN_DIMENSION &&
+                       name_or_value->type != CSS_TOKEN_IDENT)) {
+               return CSS_INVALID;
+       }
+
+       consumeWhitespace(vector, ctx);
+
+       /* Name-or-value */
+       if (name_or_value->type == CSS_TOKEN_NUMBER &&
+                       tokenIsChar(parserutils_vector_peek(vector, *ctx), 
'/')) {
+               /* ratio */
+               error = mq_parse_ratio(c, vector, ctx, token, &ratio);
+               if (error != CSS_OK) {
+                       return error;
+               }
+
+               consumeWhitespace(vector, ctx);
+
+               value_is_ratio = true;
+       } else if (name_or_value->type == CSS_TOKEN_IDENT &&
+                       lwc_string_caseless_isequal(name_or_value->idata,
+                               c->strings[INFINITE], &match) == lwc_error_ok 
&& 
+                       match == false) {
+               /* The only ident permitted for mf-value is 'infinite', thus 
must have name */
+               name = name_or_value;
+               name_first = true;
+       }
+
+       /* Op */
+       token = parserutils_vector_iterate(vector, ctx);
+       error = mq_parse_op(token, &op);
+       if (error != CSS_OK) {
+               return error;
+       }
+
+       consumeWhitespace(vector, ctx);
+
+       /* Value-or-name */
+       value_or_name = parserutils_vector_iterate(vector, ctx);
+       if (value_or_name == NULL || (value_or_name->type != CSS_TOKEN_NUMBER &&
+                       value_or_name->type != CSS_TOKEN_DIMENSION &&
+                       value_or_name->type != CSS_TOKEN_IDENT)) {
+               return CSS_INVALID;
+       }
+
+       if (name == NULL) {
+               if (value_or_name->type != CSS_TOKEN_IDENT) {
+                       return CSS_INVALID;
+               } else {
+                       name = value_or_name;
+               }
+       }
+
+       consumeWhitespace(vector, ctx);
+
+       if (value_or_name->type == CSS_TOKEN_NUMBER &&
+                       tokenIsChar(parserutils_vector_peek(vector, *ctx), 
'/')) {
+               /* ratio */
+               error = mq_parse_ratio(c, vector, ctx, token, &ratio);
+               if (error != CSS_OK) {
+                       return error;
+               }
+
+               consumeWhitespace(vector, ctx);
+
+               value_is_ratio = true;
+       }
+
+       token = parserutils_vector_peek(vector, *ctx);
+       if (name_first == false && token != NULL && tokenIsChar(token, ')') == 
false) {
+               /* Op2 */
+               token = parserutils_vector_iterate(vector, ctx);
+               error = mq_parse_op(token, &op2);
+               if (error != CSS_OK) {
+                       return error;
+               }
+
+               consumeWhitespace(vector, ctx);
+
+               /* Validate operators: must both be LT(E) or GT(E) */
+               if (op == CSS_MQ_FEATURE_OP_LT || op == CSS_MQ_FEATURE_OP_LTE) {
+                       if (op2 != CSS_MQ_FEATURE_OP_LT && op2 != 
CSS_MQ_FEATURE_OP_LTE) {
+                               return CSS_INVALID;
+                       }
+               } else if (op == CSS_MQ_FEATURE_OP_GT || op == 
CSS_MQ_FEATURE_OP_GTE) {
+                      if (op2 != CSS_MQ_FEATURE_OP_GT && op2 != 
CSS_MQ_FEATURE_OP_GTE) {
+                               return CSS_INVALID;
+                       }
+               } else {
+                       return CSS_INVALID;
+               }
+
+               /* Value2 */
+               value2 = parserutils_vector_iterate(vector, ctx);
+               if (value2 == NULL || (value2->type != CSS_TOKEN_NUMBER &&
+                               value2->type != CSS_TOKEN_DIMENSION &&
+                               value2->type != CSS_TOKEN_IDENT)) {
+                       return CSS_INVALID;
+               }
+
+               consumeWhitespace(vector, ctx);
+
+               if (value_or_name->type == CSS_TOKEN_NUMBER &&
+                               tokenIsChar(parserutils_vector_peek(vector, 
*ctx), '/')) {
+                       /* ratio */
+                       error = mq_parse_ratio(c, vector, ctx, token, &ratio2);
+                       if (error != CSS_OK) {
+                               return error;
+                       }
+
+                       consumeWhitespace(vector, ctx);
+
+                       value2_is_ratio = true;
+               }
+       }
+
+       error = mq_create_feature(name->idata, &result);
+       if (error != CSS_OK) {
+               return error;
+       }
+       if (name_first) {
+               /* Invert operator */
+               if (op == CSS_MQ_FEATURE_OP_LT) {
+                       op = CSS_MQ_FEATURE_OP_GTE;
+               } else if (op == CSS_MQ_FEATURE_OP_LTE) {
+                       op = CSS_MQ_FEATURE_OP_GT;
+               } else if (op == CSS_MQ_FEATURE_OP_GT) {
+                       op = CSS_MQ_FEATURE_OP_LTE;
+               } else if (op == CSS_MQ_FEATURE_OP_GTE) {
+                       op = CSS_MQ_FEATURE_OP_LT;
+               }
+       }
+       result->op = op;
+       if (value_is_ratio) {
+               result->value.type = CSS_MQ_VALUE_TYPE_RATIO;
+               result->value.data.num_or_ratio = ratio;
+       } else {
+               /* num/dim/ident */
+               error = mq_populate_value(&result->value, token);
+               if (error != CSS_OK) {
+                       free(result);
+                       return error;
+               }
+       }
+       if (value2 != NULL) {
+               result->op2 = op2;
+               if (value2_is_ratio) {
+                       result->value2.type = CSS_MQ_VALUE_TYPE_RATIO;
+                       result->value2.data.num_or_ratio = ratio;
+               } else {
+                       /* num/dim/ident */
+                       error = mq_populate_value(&result->value2, token);
+                       if (error != CSS_OK) {
+                               /* TODO: clean up result properly? */
+                               free(result);
+                               return error;
+                       }
+               }
+       }
+
+       *feature = result;
+
+       return CSS_OK;
+}
+
+static css_error mq_parse_media_feature(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_mq_feature **feature)
+{
+       const css_token *name_or_value, *token;
+       css_mq_feature *result;
+       css_error error;
+
+       /* <media-feature> = ( [ <mf-plain> | <mf-boolean> | <mf-range> ] )
+        * <mf-plain> = <mf-name> : <mf-value>
+        * <mf-boolean> = <mf-name>
+        * <mf-name> = <ident>
+        * <mf-value> = <number> | <dimension> | <ident> | <ratio>
+        */
+
+       /* ( already consumed */
+
+       name_or_value = parserutils_vector_iterate(vector, ctx);
+       if (name_or_value == NULL)
+               return CSS_INVALID;
+
+       if (name_or_value->type == CSS_TOKEN_IDENT) {
+               consumeWhitespace(vector, ctx);
+
+               token = parserutils_vector_peek(vector, *ctx);
+               if (tokenIsChar(token, ')')) {
+                       /* mf-boolean */
+                       error = mq_create_feature(name_or_value->idata, 
&result);
+                       if (error != CSS_OK) {
+                               return error;
+                       }
+
+                       result->op = CSS_MQ_FEATURE_OP_BOOL;
+               } else if (tokenIsChar(token, ':')) {
+                       /* mf-plain */
+                       parserutils_vector_iterate(vector, ctx);
+
+                       consumeWhitespace(vector, ctx);
+
+                       token = parserutils_vector_iterate(vector, ctx);
+                       if (token == NULL || (token->type != CSS_TOKEN_NUMBER &&
+                                       token->type != CSS_TOKEN_DIMENSION &&
+                                       token->type != CSS_TOKEN_IDENT)) {
+                               return CSS_INVALID;
+                       }
+
+                       consumeWhitespace(vector, ctx);
+
+                       error = mq_create_feature(name_or_value->idata, 
&result);
+                       if (error != CSS_OK) {
+                               return error;
+                       }
+                       result->op = CSS_MQ_FEATURE_OP_EQ;
+
+                       if (token->type == CSS_TOKEN_NUMBER &&
+                                       
tokenIsChar(parserutils_vector_peek(vector, *ctx), '/')) {
+                               /* ratio */
+                               css_fixed ratio;
+
+                               error = mq_parse_ratio(c, vector, ctx, token, 
&ratio);
+                               if (error != CSS_OK) {
+                                       free(result);
+                                       return error;
+                               }
+
+                               result->value.type = CSS_MQ_VALUE_TYPE_RATIO;
+                               result->value.data.num_or_ratio = ratio;
+                       } else {
+                               /* num/dim/ident */
+                               error = mq_populate_value(&result->value, 
token);
+                               if (error != CSS_OK) {
+                                       free(result);
+                                       return error;
+                               }
+                       }
+
+                       consumeWhitespace(vector, ctx);
+               } else {
+                       /* mf-range */
+                       error = mq_parse_range(c, vector, ctx, name_or_value, 
&result);
+                       if (error != CSS_OK) {
+                               return error;
+                       }
+
+                       consumeWhitespace(vector, ctx);
+               }
+       } else {
+               /* mf-range */
+               error = mq_parse_range(c, vector, ctx, name_or_value, &result);
+               if (error != CSS_OK) {
+                       return error;
+               }
+
+               consumeWhitespace(vector, ctx);
+       }
+
+       token = parserutils_vector_iterate(vector, ctx);
+       if (tokenIsChar(token, ')') == false) {
+               /* TODO: clean up result */
+               return CSS_INVALID;
+       }
+
+       *feature = result;
+
+       return CSS_OK;
+}
+
+static css_error mq_parse_media_in_parens()
+{
+       /* <media-in-parens> = ( <media-condition> ) | <media-feature> | 
<general-enclosed>
+        * <general-enclosed> = [ <function-token> <any-value> ) ] | ( <ident> 
<any-value> )
+        */
+
+       //LPAREN -> condition-or-feature
+       //        "not" or LPAREN -> condition
+       //        IDENT | NUMBER | DIMENSION | RATIO -> feature
+
+}
+
+static css_error mq_parse_condition()
+{
+       /* <media-condition> = <media-not> | <media-in-parens> [ <media-and>* | 
<media-or>* ]
+        * <media-condition-without-or> = <media-not> | <media-in-parens> 
<media-and>*
+        * <media-not> = not <media-in-parens>
+        * <media-and> = and <media-in-parens>
+        * <media-or> = or <media-in-parens>
+        */
+}
 
 css_error css__mq_parse_media_list(css_language *c,
                const parserutils_vector *vector, int *ctx,
@@ -16,7 +452,19 @@ css_error css__mq_parse_media_list(css_language *c,
        css_mq_query *ret = NULL;
        const css_token *token;
 
-       /* (IDENT ws (',' ws IDENT ws)* )? */
+       /* <media-query-list> = <media-query> [ COMMA <media-query> ]*
+        * <media-query> = <media-condition>
+        *               | [ not | only ]? <media-type> [ and 
<media-condition-without-or> ]?
+        * <media-type> = <ident> (except "not", "and", "or", "only")
+        *
+        */
+
+       /* if {[(, push }]) to stack
+        * if func, push ) to stack
+        * on error, scan forward until stack is empty (or EOF), popping 
matching tokens off stack
+        * if stack is empty, the next input token must be comma or EOF
+        * if comma, consume, and start again from the next input token
+        */
 
        UNUSED(c);
 
diff --git a/src/parse/mq.h b/src/parse/mq.h
index 7d62e8c..c5268c7 100644
--- a/src/parse/mq.h
+++ b/src/parse/mq.h
@@ -22,7 +22,7 @@ typedef struct {
                css_fixed num_or_ratio; /* Where ratio is the result of a/b */
                struct {
                        css_fixed len;
-                       css_unit unit;
+                       uint32_t unit;
                } dim;
                lwc_string *ident;
        } data;
@@ -31,8 +31,8 @@ typedef struct {
 /*
  * "name : value" is encoded as "name = value"
  * "name" is encoded by setting the operator to "bool"
- * "name op value" is encoded verbatim (with op2 set to "unused")
- * "value op name" inverts the operator to encode (i.e < becomes >=) (and sets 
op2 to "unused")
+ * "value op name" is encoded verbatim (with op2 set to "unused")
+ * "name op value" inverts the operator to encode (i.e < becomes >=) (and sets 
op2 to "unused")
  * "value op name op value" is encoded using op2 and value2
  */
 typedef enum {


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=03ad0999ec3f0f8503ddd773097b0fa746f3702b
commit 03ad0999ec3f0f8503ddd773097b0fa746f3702b
Author: John-Mark Bell <[email protected]>
Commit: Michael Drake <[email protected]>

    Units: parse new unit names

diff --git a/src/bytecode/bytecode.h b/src/bytecode/bytecode.h
index 422f141..22703f7 100644
--- a/src/bytecode/bytecode.h
+++ b/src/bytecode/bytecode.h
@@ -52,6 +52,7 @@ typedef enum unit {
        UNIT_DEG  = (1 << 9) + 0,
        UNIT_GRAD = (1 << 9) + 1,
        UNIT_RAD  = (1 << 9) + 2,
+       UNIT_TURN = (1 << 9) + 3,
 
        UNIT_TIME = (1 << 10),
        UNIT_MS   = (1 << 10) + 0,
@@ -59,7 +60,12 @@ typedef enum unit {
 
        UNIT_FREQ = (1 << 11),
        UNIT_HZ   = (1 << 11) + 0,
-       UNIT_KHZ  = (1 << 11) + 1
+       UNIT_KHZ  = (1 << 11) + 1,
+
+       UNIT_RESOLUTION = (1 << 12),
+       UNIT_DPI  = (1 << 12) + 0,
+       UNIT_DPCM = (1 << 12) + 1,
+       UNIT_DPPX = (1 << 12) + 2,
 } unit;
 
 typedef uint32_t colour;
diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c
index 76b406b..f9555d2 100644
--- a/src/parse/properties/utils.c
+++ b/src/parse/properties/utils.c
@@ -1007,6 +1007,12 @@ css_error css__parse_unit_keyword(const char *ptr, 
size_t len, uint32_t *unit)
        if (len == 4) {
                if (strncasecmp(ptr, "grad", 4) == 0)
                        *unit = UNIT_GRAD;
+               else if (strncasecmp(ptr, "turn", 4) == 0)
+                       *unit = UNIT_TURN;
+               else if (strncasecmp(ptr, "dppx", 4) == 0)
+                       *unit = UNIT_DPPX;
+               else if (strncasecmp(ptr, "dpcm", 4) == 0)
+                       *unit = UNIT_DPCM;
                else if (strncasecmp(ptr, "vmin", 4) == 0)
                        *unit = UNIT_VMIN;
                else if (strncasecmp(ptr, "vmax", 4) == 0)
@@ -1026,6 +1032,8 @@ css_error css__parse_unit_keyword(const char *ptr, size_t 
len, uint32_t *unit)
                        *unit = UNIT_REM;
                else if (strncasecmp(ptr, "rlh", 3) == 0)
                        *unit = UNIT_RLH;
+               else if (strncasecmp(ptr, "dpi", 3) == 0)
+                       *unit = UNIT_DPI;
                else
                        return CSS_INVALID;
        } else if (len == 2) {


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=323bb9a5dc5a8bf103a6d943b3253b77f8ff90db
commit 323bb9a5dc5a8bf103a6d943b3253b77f8ff90db
Author: John-Mark Bell <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: sort out object lifetimes

diff --git a/src/parse/language.c b/src/parse/language.c
index a5f57d3..c3b523d 100644
--- a/src/parse/language.c
+++ b/src/parse/language.c
@@ -416,8 +416,7 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                        lwc_string *url;
                        css_mq_query *media = NULL;
 
-                       /* any0 = (STRING | URI) ws
-                        *        (media query)? */
+                       /* any0 = (STRING | URI) ws (media query)? */
                        const css_token *uri =
                                parserutils_vector_iterate(vector, &ctx);
                        if (uri == NULL || (uri->type != CSS_TOKEN_STRING &&
@@ -435,7 +434,7 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                        error = css__stylesheet_rule_create(c->sheet,
                                        CSS_RULE_IMPORT, &rule);
                        if (error != CSS_OK) {
-                               css__mq_query_unref(media);
+                               css__mq_query_destroy(media);
                                return error;
                        }
 
@@ -444,8 +443,8 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                                        c->sheet->url,
                                        uri->idata, &url);
                        if (error != CSS_OK) {
-                               css__mq_query_unref(media);
                                css__stylesheet_rule_destroy(c->sheet, rule);
+                               css__mq_query_destroy(media);
                                return error;
                        }
 
@@ -454,8 +453,8 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                                        rule, url, media);
                        if (error != CSS_OK) {
                                lwc_string_unref(url);
-                               css__mq_query_unref(media);
                                css__stylesheet_rule_destroy(c->sheet, rule);
+                               css__mq_query_destroy(media);
                                return error;
                        }
 
@@ -465,16 +464,14 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                                                c->sheet, url);
                                if (error != CSS_OK) {
                                        lwc_string_unref(url);
-                                       css__mq_query_unref(media);
                                        css__stylesheet_rule_destroy(c->sheet,
                                                        rule);
                                        return error;
                                }
                        }
 
-                       /* No longer care about url or media */
+                       /* No longer care about url */
                        lwc_string_unref(url);
-                       css__mq_query_unref(media);
 
                        /* Add rule to sheet */
                        error = css__stylesheet_add_rule(c->sheet, rule, NULL);
@@ -542,26 +539,23 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                error = css__stylesheet_rule_create(c->sheet,
                                CSS_RULE_MEDIA, &rule);
                if (error != CSS_OK) {
-                       css__mq_query_unref(media);
+                       css__mq_query_destroy(media);
                        return error;
                }
 
                error = css__stylesheet_rule_set_media(c->sheet, rule, media);
                if (error != CSS_OK) {
                        css__stylesheet_rule_destroy(c->sheet, rule);
-                       css__mq_query_unref(media);
+                       css__mq_query_destroy(media);
                        return error;
                }
 
                error = css__stylesheet_add_rule(c->sheet, rule, NULL);
                if (error != CSS_OK) {
                        css__stylesheet_rule_destroy(c->sheet, rule);
-                       css__mq_query_unref(media);
                        return error;
                }
 
-               css__mq_query_unref(media);
-
                /* Rule is now owned by the sheet,
                 * so no need to destroy it */
 
diff --git a/src/parse/mq.h b/src/parse/mq.h
index eeb55da..7d62e8c 100644
--- a/src/parse/mq.h
+++ b/src/parse/mq.h
@@ -93,8 +93,6 @@ css_error css__mq_parse_media_list(css_language *c,
                const parserutils_vector *vector, int *ctx,
                css_mq_query **media);
 
-/** \todo is this necessary? */
-css_mq_query *css__mq_query_ref(css_mq_query *media);
-css_mq_query *css__mq_query_unref(css_mq_query *media);
+css_mq_query *css__mq_query_destroy(css_mq_query *media);
 
 #endif
diff --git a/src/stylesheet.c b/src/stylesheet.c
index b1801ed..22c7681 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -12,6 +12,7 @@
 #include "stylesheet.h"
 #include "bytecode/bytecode.h"
 #include "parse/language.h"
+#include "parse/mq.h"
 #include "utils/parserutilserror.h"
 #include "utils/utils.h"
 #include "select/dispatch.h"
@@ -1151,6 +1152,9 @@ css_error css__stylesheet_rule_destroy(css_stylesheet 
*sheet, css_rule *rule)
                css_rule_import *import = (css_rule_import *) rule;
 
                lwc_string_unref(import->url);
+               if (import->media != NULL) {
+                       css__mq_query_destroy(import->media);
+               }
 
                /* Do not destroy imported sheet: it is owned by the client */
        }
@@ -1160,6 +1164,10 @@ css_error css__stylesheet_rule_destroy(css_stylesheet 
*sheet, css_rule *rule)
                css_rule_media *media = (css_rule_media *) rule;
                css_rule *c, *d;
 
+               if (media->media != NULL) {
+                       css__mq_query_destroy(media->media);
+               }
+
                for (c = media->first_child; c != NULL; c = d) {
                        d = c->next;
 
@@ -1335,7 +1343,7 @@ css_error 
css__stylesheet_rule_set_nascent_import(css_stylesheet *sheet,
 
        /* Set the rule's sheet field */
        r->url = lwc_string_ref(url);
-       r->media = css__mq_query_ref(media);
+       r->media = media;
 
        return CSS_OK;
 }
@@ -1360,7 +1368,7 @@ css_error css__stylesheet_rule_set_media(css_stylesheet 
*sheet,
        assert(rule->type == CSS_RULE_MEDIA);
 
        /* Set the rule's media */
-       r->media = css__mq_query_ref(media);
+       r->media = media;
 
        return CSS_OK;
 }


commitdiff 
http://git.netsurf-browser.org/libcss.git/commit/?id=7bd7f0d5132adddf3f642a46b06c61d019f9f0de
commit 7bd7f0d5132adddf3f642a46b06c61d019f9f0de
Author: John-Mark Bell <[email protected]>
Commit: Michael Drake <[email protected]>

    Media Queries: datastructures and plumbing.
    
    No parse implementation as yet.
    
    Selection hasn't been updated, either. One item of note
    in that area is that a client currently provides the
    media for top-level sheets being added to a selection
    context. This probably needs to change to providing a
    lwc_string containing the verbatim media query from
    the containing document's import mechanism. That way,
    the internal representation of media queries can remain
    opaque to clients.

diff --git a/include/libcss/stylesheet.h b/include/libcss/stylesheet.h
index 68c4dfc..542f199 100644
--- a/include/libcss/stylesheet.h
+++ b/include/libcss/stylesheet.h
@@ -36,7 +36,6 @@ typedef css_error (*css_url_resolution_fn)(void *pw,
  * \param pw      Client data
  * \param parent  Stylesheet requesting the import
  * \param url     URL of the imported sheet
- * \param media   Applicable media for the imported sheet
  * \return CSS_OK on success, appropriate error otherwise
  *
  * \note This function will be invoked for notification purposes
@@ -46,7 +45,7 @@ typedef css_error (*css_url_resolution_fn)(void *pw,
  *       registration API.
  */
 typedef css_error (*css_import_notification_fn)(void *pw,
-               css_stylesheet *parent, lwc_string *url, uint64_t media);
+               css_stylesheet *parent, lwc_string *url);
 
 /**
  * Callback use to resolve system colour names to RGB values
@@ -145,7 +144,7 @@ css_error css_stylesheet_append_data(css_stylesheet *sheet,
 css_error css_stylesheet_data_done(css_stylesheet *sheet);
 
 css_error css_stylesheet_next_pending_import(css_stylesheet *parent,
-               lwc_string **url, uint64_t *media);
+               lwc_string **url);
 css_error css_stylesheet_register_import(css_stylesheet *parent,
                css_stylesheet *child);
 
diff --git a/src/parse/Makefile b/src/parse/Makefile
index 99f55d0..6d11096 100644
--- a/src/parse/Makefile
+++ b/src/parse/Makefile
@@ -1,4 +1,4 @@
 # Sources
-DIR_SOURCES := parse.c language.c important.c propstrings.c font_face.c
+DIR_SOURCES := parse.c language.c important.c propstrings.c font_face.c mq.c
 
 include $(NSBUILD)/Makefile.subdir
diff --git a/src/parse/language.c b/src/parse/language.c
index 9af2547..a5f57d3 100644
--- a/src/parse/language.c
+++ b/src/parse/language.c
@@ -15,6 +15,7 @@
 #include "parse/font_face.h"
 #include "parse/important.h"
 #include "parse/language.h"
+#include "parse/mq.h"
 #include "parse/parse.h"
 #include "parse/propstrings.h"
 #include "parse/properties/properties.h"
@@ -53,9 +54,6 @@ static css_error handleDeclaration(css_language *c,
                const parserutils_vector *vector);
 
 /* At-rule parsing */
-static css_error parseMediaList(css_language *c,
-               const parserutils_vector *vector, int *ctx,
-               uint64_t *media);
 static css_error addNamespace(css_language *c,
                lwc_string *prefix, lwc_string *uri);
 static css_error lookupNamespace(css_language *c,
@@ -416,10 +414,10 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                        match) {
                if (c->state <= IMPORT_PERMITTED) {
                        lwc_string *url;
-                       uint64_t media = 0;
+                       css_mq_query *media = NULL;
 
                        /* any0 = (STRING | URI) ws
-                        *        (IDENT ws (',' ws IDENT ws)* )? */
+                        *        (media query)? */
                        const css_token *uri =
                                parserutils_vector_iterate(vector, &ctx);
                        if (uri == NULL || (uri->type != CSS_TOKEN_STRING &&
@@ -429,21 +427,24 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                        consumeWhitespace(vector, &ctx);
 
                        /* Parse media list */
-                       error = parseMediaList(c, vector, &ctx, &media);
+                       error = css__mq_parse_media_list(c, vector, &ctx, 
&media);
                        if (error != CSS_OK)
                                return error;
 
                        /* Create rule */
                        error = css__stylesheet_rule_create(c->sheet,
                                        CSS_RULE_IMPORT, &rule);
-                       if (error != CSS_OK)
+                       if (error != CSS_OK) {
+                               css__mq_query_unref(media);
                                return error;
+                       }
 
                        /* Resolve import URI */
                        error = c->sheet->resolve(c->sheet->resolve_pw,
                                        c->sheet->url,
                                        uri->idata, &url);
                        if (error != CSS_OK) {
+                               css__mq_query_unref(media);
                                css__stylesheet_rule_destroy(c->sheet, rule);
                                return error;
                        }
@@ -453,6 +454,7 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                                        rule, url, media);
                        if (error != CSS_OK) {
                                lwc_string_unref(url);
+                               css__mq_query_unref(media);
                                css__stylesheet_rule_destroy(c->sheet, rule);
                                return error;
                        }
@@ -460,17 +462,19 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                        /* Inform client of need for import */
                        if (c->sheet->import != NULL) {
                                error = c->sheet->import(c->sheet->import_pw,
-                                               c->sheet, url, media);
+                                               c->sheet, url);
                                if (error != CSS_OK) {
                                        lwc_string_unref(url);
+                                       css__mq_query_unref(media);
                                        css__stylesheet_rule_destroy(c->sheet,
                                                        rule);
                                        return error;
                                }
                        }
 
-                       /* No longer care about url */
+                       /* No longer care about url or media */
                        lwc_string_unref(url);
+                       css__mq_query_unref(media);
 
                        /* Add rule to sheet */
                        error = css__stylesheet_add_rule(c->sheet, rule, NULL);
@@ -527,31 +531,37 @@ css_error handleStartAtRule(css_language *c, const 
parserutils_vector *vector)
                }
        } else if (lwc_string_caseless_isequal(atkeyword->idata, 
c->strings[MEDIA],
                        &match) == lwc_error_ok && match) {
-               uint64_t media = 0;
+               css_mq_query *media = NULL;
 
-               /* any0 = IDENT ws (',' ws IDENT ws)* */
+               /* any0 = media query */
 
-               error = parseMediaList(c, vector, &ctx, &media);
+               error = css__mq_parse_media_list(c, vector, &ctx, &media);
                if (error != CSS_OK)
                        return error;
 
                error = css__stylesheet_rule_create(c->sheet,
                                CSS_RULE_MEDIA, &rule);
-               if (error != CSS_OK)
+               if (error != CSS_OK) {
+                       css__mq_query_unref(media);
                        return error;
+               }
 
                error = css__stylesheet_rule_set_media(c->sheet, rule, media);
                if (error != CSS_OK) {
                        css__stylesheet_rule_destroy(c->sheet, rule);
+                       css__mq_query_unref(media);
                        return error;
                }
 
                error = css__stylesheet_add_rule(c->sheet, rule, NULL);
                if (error != CSS_OK) {
                        css__stylesheet_rule_destroy(c->sheet, rule);
+                       css__mq_query_unref(media);
                        return error;
                }
 
+               css__mq_query_unref(media);
+
                /* Rule is now owned by the sheet,
                 * so no need to destroy it */
 
@@ -795,85 +805,6 @@ css_error handleDeclaration(css_language *c, const 
parserutils_vector *vector)
  * At-rule parsing functions                                                 *
  
******************************************************************************/
 
-css_error parseMediaList(css_language *c,
-               const parserutils_vector *vector, int *ctx,
-               uint64_t *media)
-{
-       uint64_t ret = 0;
-       bool match = false;
-       const css_token *token;
-
-       token = parserutils_vector_iterate(vector, ctx);
-
-       while (token != NULL) {
-               if (token->type != CSS_TOKEN_IDENT)
-                       return CSS_INVALID;
-
-               if (lwc_string_caseless_isequal(token->idata, c->strings[AURAL],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_AURAL;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[BRAILLE],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_BRAILLE;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[EMBOSSED],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_EMBOSSED;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[HANDHELD],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_HANDHELD;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[PRINT],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_PRINT;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[PROJECTION],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_PROJECTION;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[SCREEN],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_SCREEN;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[SPEECH],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_SPEECH;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[TTY],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_TTY;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[TV],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_TV;
-               } else if (lwc_string_caseless_isequal(
-                               token->idata, c->strings[ALL],
-                               &match) == lwc_error_ok && match) {
-                       ret |= CSS_MEDIA_ALL;
-               } else
-                       return CSS_INVALID;
-
-               consumeWhitespace(vector, ctx);
-
-               token = parserutils_vector_iterate(vector, ctx);
-               if (token != NULL && tokenIsChar(token, ',') == false)
-                       return CSS_INVALID;
-
-               consumeWhitespace(vector, ctx);
-       }
-
-       /* If, after parsing the media list, we still have no media,
-        * then it must be ALL. */
-       if (ret == 0)
-               ret = CSS_MEDIA_ALL;
-
-       *media = ret;
-
-       return CSS_OK;
-}
-
 /**
  * Add a namespace mapping
  *
diff --git a/src/parse/mq.c b/src/parse/mq.c
new file mode 100644
index 0000000..5c9c7fa
--- /dev/null
+++ b/src/parse/mq.c
@@ -0,0 +1,96 @@
+/*
+ * This file is part of LibCSS.
+ * Licensed under the MIT License,
+ *               http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2016 John-Mark Bell <[email protected]>
+ */
+
+/* https://drafts.csswg.org/mediaqueries/ */
+
+#include "parse/mq.h"
+
+css_error css__mq_parse_media_list(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_mq_query **media)
+{
+       css_mq_query *ret = NULL;
+       const css_token *token;
+
+       /* (IDENT ws (',' ws IDENT ws)* )? */
+
+       UNUSED(c);
+
+       token = parserutils_vector_iterate(vector, ctx);
+
+       while (token != NULL) {
+               if (token->type != CSS_TOKEN_IDENT)
+                       return CSS_INVALID;
+
+#if 0
+               if (lwc_string_caseless_isequal(token->idata, 
c->strings[AURAL], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_AURAL;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[BRAILLE], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_BRAILLE;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[EMBOSSED], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_EMBOSSED;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[HANDHELD], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_HANDHELD;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[PRINT], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_PRINT;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[PROJECTION], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_PROJECTION;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[SCREEN], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_SCREEN;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[SPEECH], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_SPEECH;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[TTY], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_TTY;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[TV], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_TV;
+               } else if (lwc_string_caseless_isequal(
+                               token->idata, c->strings[ALL], 
+                               &match) == lwc_error_ok && match) {
+                       ret |= CSS_MEDIA_ALL;
+               } else
+                       return CSS_INVALID;
+#endif
+               consumeWhitespace(vector, ctx);
+
+               token = parserutils_vector_iterate(vector, ctx);
+               if (token != NULL && tokenIsChar(token, ',') == false)
+                       return CSS_INVALID;
+
+               consumeWhitespace(vector, ctx);
+       }
+
+#if 0
+       /* If, after parsing the media list, we still have no media, 
+        * then it must be ALL. */
+       if (ret == 0)
+               ret = CSS_MEDIA_ALL;
+#endif
+
+       *media = ret;
+
+       return CSS_OK;
+}
+
diff --git a/src/parse/mq.h b/src/parse/mq.h
new file mode 100644
index 0000000..eeb55da
--- /dev/null
+++ b/src/parse/mq.h
@@ -0,0 +1,100 @@
+/*
+ * This file is part of LibCSS.
+ * Licensed under the MIT License,
+ *               http://www.opensource.org/licenses/mit-license.php
+ * Copyright 2016 John-Mark Bell <[email protected]>
+ */
+
+#ifndef css_parse_mq_h_
+#define css_parse_mq_h_
+
+#include <parserutils/utils/vector.h>
+#include "parse/language.h"
+
+typedef struct {
+       enum {
+               CSS_MQ_VALUE_TYPE_NUM,
+               CSS_MQ_VALUE_TYPE_DIM,
+               CSS_MQ_VALUE_TYPE_IDENT,
+               CSS_MQ_VALUE_TYPE_RATIO
+       } type;
+       union {
+               css_fixed num_or_ratio; /* Where ratio is the result of a/b */
+               struct {
+                       css_fixed len;
+                       css_unit unit;
+               } dim;
+               lwc_string *ident;
+       } data;
+} css_mq_value;
+
+/*
+ * "name : value" is encoded as "name = value"
+ * "name" is encoded by setting the operator to "bool"
+ * "name op value" is encoded verbatim (with op2 set to "unused")
+ * "value op name" inverts the operator to encode (i.e < becomes >=) (and sets 
op2 to "unused")
+ * "value op name op value" is encoded using op2 and value2
+ */
+typedef enum {
+       CSS_MQ_FEATURE_OP_BOOL, /* op only */
+       CSS_MQ_FEATURE_OP_UNUSED = CSS_MQ_FEATURE_OP_BOOL, /* op2 only */
+
+       CSS_MQ_FEATURE_OP_LT,
+       CSS_MQ_FEATURE_OP_LTE,
+       CSS_MQ_FEATURE_OP_EQ, /* op only */
+       CSS_MQ_FEATURE_OP_GTE,
+       CSS_MQ_FEATURE_OP_GT
+} css_mq_feature_op;
+
+typedef struct {
+       lwc_string *name;
+       css_mq_feature_op op;
+       css_mq_feature_op op2;
+       css_mq_value value;
+       css_mq_value value2;
+} css_mq_feature;
+
+typedef struct css_mq_cond_or_feature css_mq_cond_or_feature;
+
+typedef struct {
+       uint32_t nparts;
+       css_mq_cond_or_feature **parts;
+} css_mq_cond_parts;
+
+typedef struct {
+       uint32_t negate : 1, /* set if "not" */
+                op     : 1; /* clear if "and", set if "or" */
+       css_mq_cond_parts *parts;
+} css_mq_cond;
+
+struct css_mq_cond_or_feature {
+       enum {
+               CSS_MQ_FEATURE,
+               CSS_MQ_COND
+       } type;
+       union {
+               css_mq_cond cond;
+               css_mq_feature feat;
+       } data;
+};
+
+typedef struct css_mq_query {
+       struct css_mq_query *next;
+
+       uint32_t negate_type : 1, /* set if "not type" */
+                cond_op     : 1; /* clear if "and", set if "or" */
+       lwc_string *type; /* or NULL */
+
+       uint32_t nconds;
+       css_mq_cond **conds;
+} css_mq_query;
+
+css_error css__mq_parse_media_list(css_language *c,
+               const parserutils_vector *vector, int *ctx,
+               css_mq_query **media);
+
+/** \todo is this necessary? */
+css_mq_query *css__mq_query_ref(css_mq_query *media);
+css_mq_query *css__mq_query_unref(css_mq_query *media);
+
+#endif
diff --git a/src/stylesheet.c b/src/stylesheet.c
index 7c6728b..b1801ed 100644
--- a/src/stylesheet.c
+++ b/src/stylesheet.c
@@ -377,8 +377,6 @@ css_error css_stylesheet_data_done(css_stylesheet *sheet)
  * \param parent  Parent stylesheet
  * \param url    Pointer to object to be populated with details of URL of
  *               imported stylesheet (potentially relative)
- * \param media          Pointer to location to receive applicable media types 
for
- *               imported sheet,
  * \return CSS_OK on success,
  *        CSS_INVALID if there are no pending imports remaining
  *
@@ -396,11 +394,11 @@ css_error css_stylesheet_data_done(css_stylesheet *sheet)
  * register an empty stylesheet with the parent in its place.
  */
 css_error css_stylesheet_next_pending_import(css_stylesheet *parent,
-               lwc_string **url, uint64_t *media)
+               lwc_string **url)
 {
        const css_rule *r;
 
-       if (parent == NULL || url == NULL || media == NULL)
+       if (parent == NULL || url == NULL)
                return CSS_BADPARM;
 
        for (r = parent->rule_list; r != NULL; r = r->next) {
@@ -413,7 +411,6 @@ css_error css_stylesheet_next_pending_import(css_stylesheet 
*parent,
 
                if (r->type == CSS_RULE_IMPORT && i->sheet == NULL) {
                        *url = lwc_string_ref(i->url);
-                       *media = i->media;
 
                        return CSS_OK;
                }
@@ -1326,7 +1323,7 @@ css_error css__stylesheet_rule_set_charset(css_stylesheet 
*sheet,
  */
 css_error css__stylesheet_rule_set_nascent_import(css_stylesheet *sheet,
                css_rule *rule, lwc_string *url,
-               uint64_t media)
+               css_mq_query *media)
 {
        css_rule_import *r = (css_rule_import *) rule;
 
@@ -1338,7 +1335,7 @@ css_error 
css__stylesheet_rule_set_nascent_import(css_stylesheet *sheet,
 
        /* Set the rule's sheet field */
        r->url = lwc_string_ref(url);
-       r->media = media;
+       r->media = css__mq_query_ref(media);
 
        return CSS_OK;
 }
@@ -1352,7 +1349,7 @@ css_error 
css__stylesheet_rule_set_nascent_import(css_stylesheet *sheet,
  * \return CSS_OK on success, appropriate error otherwise
  */
 css_error css__stylesheet_rule_set_media(css_stylesheet *sheet,
-               css_rule *rule, uint64_t media)
+               css_rule *rule, css_mq_query *media)
 {
        css_rule_media *r = (css_rule_media *) rule;
 
@@ -1363,7 +1360,7 @@ css_error css__stylesheet_rule_set_media(css_stylesheet 
*sheet,
        assert(rule->type == CSS_RULE_MEDIA);
 
        /* Set the rule's media */
-       r->media = media;
+       r->media = css__mq_query_ref(media);
 
        return CSS_OK;
 }
diff --git a/src/stylesheet.h b/src/stylesheet.h
index 18e077e..a44ad1f 100644
--- a/src/stylesheet.h
+++ b/src/stylesheet.h
@@ -20,6 +20,7 @@
 
 #include "bytecode/bytecode.h"
 #include "parse/parse.h"
+#include "parse/mq.h"
 #include "select/hash.h"
 
 typedef struct css_rule css_rule;
@@ -132,7 +133,7 @@ typedef struct css_rule_selector {
 typedef struct css_rule_media {
        css_rule base;
 
-       uint64_t media;
+       css_mq_query *media;
 
        css_rule *first_child;
        css_rule *last_child;
@@ -155,7 +156,7 @@ typedef struct css_rule_import {
        css_rule base;
 
        lwc_string *url;
-       uint64_t media;
+       css_mq_query *media;
 
        css_stylesheet *sheet;
 } css_rule_import;
@@ -268,10 +269,10 @@ css_error css__stylesheet_rule_set_charset(css_stylesheet 
*sheet,
                css_rule *rule, lwc_string *charset);
 
 css_error css__stylesheet_rule_set_nascent_import(css_stylesheet *sheet,
-               css_rule *rule, lwc_string *url, uint64_t media);
+               css_rule *rule, lwc_string *url, css_mq_query *media);
 
 css_error css__stylesheet_rule_set_media(css_stylesheet *sheet,
-               css_rule *rule, uint64_t media);
+               css_rule *rule, css_mq_query *media);
 
 css_error css__stylesheet_rule_set_page_selector(css_stylesheet *sheet,
                css_rule *rule, css_selector *sel);


-----------------------------------------------------------------------

Summary of changes:


-- 
Cascading Style Sheets library

_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to