Gitweb links:

...log 
http://git.netsurf-browser.org/libcss.git/shortlog/6a5b31af1ac53832e47784efa1445302e0debc81
...commit 
http://git.netsurf-browser.org/libcss.git/commit/6a5b31af1ac53832e47784efa1445302e0debc81
...tree 
http://git.netsurf-browser.org/libcss.git/tree/6a5b31af1ac53832e47784efa1445302e0debc81

The branch, tlsa/jmb/mq has been updated
  discards  9c62650cce8c9f45ae8fd2fa4f93e0234a1a76a9 (commit)
  discards  38328ce3cca58eac03047c3f6edaa15b3dbc1c0e (commit)
  discards  6a80dbac1309eaca000d7bf79a69c7f897e018fb (commit)
  discards  b087a200323a651a479357907038a1983d8127c8 (commit)
  discards  842ae56d81e1e90f393be44201c9b83b9d7b5f92 (commit)
  discards  a4d73071ae2d810107defe8c209687b12dac003a (commit)
  discards  84d60a9fd17a4192924fd11040a310737e850438 (commit)
  discards  7ac9d1d20ea5be2326651108083a23277523157b (commit)
  discards  8e1278e738f5736ea083dadaecd8603a3048c558 (commit)
  discards  bcfdbe274523b9cb51a1d92dee26dbadcecc23f4 (commit)
  discards  c97512eb3dcf012f0a0088075f45d51cb4acf59d (commit)
  discards  3f241d9b69f4283c7c98b43fc4b1eeba1fc158c7 (commit)
  discards  8e2a1fd146c662ea34ff9cba3e7e87cff106122a (commit)
  discards  0032d2c2b313c7c4afdd3866e72c38c440726a0e (commit)
  discards  1c867d67f998f647e96408a6aa221ff952c4da50 (commit)
  discards  aa99505f8fb7612162e25f0a0d032d354ee1cd7a (commit)
  discards  dd272fe8cc3144370e14a69acb5476c7d5568190 (commit)
  discards  3c5cf48de6e3a582e20ec2ddfe8f710d351e712c (commit)
  discards  1ab22bb288f76db50bf68357d0b630554e7c7bcc (commit)
       via  6a5b31af1ac53832e47784efa1445302e0debc81 (commit)
       via  d7325b02515d29e68c54b3d97b3d7b62916ab9a4 (commit)
       via  33e1e87382c1aeec33b4d14e8711d87dcb6a9a44 (commit)
       via  9e49a87068cdaa394f7f8811408d12ca896261d3 (commit)
       via  8f4d112c4cb99917856bda00e30fd75d96d883a7 (commit)
       via  613edbebf1a01a19b9a31aab212071b1bf6c6c3f (commit)
       via  80a1d238b83308c8020c26921b5d8f9182267666 (commit)
       via  681c2b96239f6cfb5af42212dc6efe8dc1c5bb33 (commit)
       via  14768c22a04d1d28893073c4f705d1f3126083cd (commit)
       via  4215e1270efa09c591bb84e51667f0bed8290ad0 (commit)
       via  982880cc8211f53fff47dd0fa28ae20ef6c71754 (commit)
       via  610ec2225c901f9e183e7042f7de7063b7fe93d1 (commit)
       via  075ba1af88067cd902b724ab6ec2c2975a8b1efa (commit)
       via  37e77f8891690b0fe7b2d8580e171ebf3d6f8562 (commit)
       via  9a01f6d9f10d3494b947e099e7dbee35f13321b6 (commit)
       via  65e7a455f2b70daffeac7dfc238f16d34b5af218 (commit)
       via  0512243a988c10e4b9e2a8519a3b0fc4e0d5917b (commit)
       via  7ee44ebb8aa76b7a1154bd2af7b65fc3602e613c (commit)
       via  68f9a335c4695202dfeec00ef3ebb3933787d8a7 (commit)
       via  9897ed69e624afe2241111f489b4213ec8d567da (commit)
       via  eb6f8ac03b2df2b0871b584c84aee01a71169c3d (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 (9c62650cce8c9f45ae8fd2fa4f93e0234a1a76a9)
            \
             N -- N -- N (6a5b31af1ac53832e47784efa1445302e0debc81)

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=6a5b31af1ac53832e47784efa1445302e0debc81
commit 6a5b31af1ac53832e47784efa1445302e0debc81
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=d7325b02515d29e68c54b3d97b3d7b62916ab9a4
commit d7325b02515d29e68c54b3d97b3d7b62916ab9a4
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=33e1e87382c1aeec33b4d14e8711d87dcb6a9a44
commit 33e1e87382c1aeec33b4d14e8711d87dcb6a9a44
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=9e49a87068cdaa394f7f8811408d12ca896261d3
commit 9e49a87068cdaa394f7f8811408d12ca896261d3
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=8f4d112c4cb99917856bda00e30fd75d96d883a7
commit 8f4d112c4cb99917856bda00e30fd75d96d883a7
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=613edbebf1a01a19b9a31aab212071b1bf6c6c3f
commit 613edbebf1a01a19b9a31aab212071b1bf6c6c3f
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=80a1d238b83308c8020c26921b5d8f9182267666
commit 80a1d238b83308c8020c26921b5d8f9182267666
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=681c2b96239f6cfb5af42212dc6efe8dc1c5bb33
commit 681c2b96239f6cfb5af42212dc6efe8dc1c5bb33
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=14768c22a04d1d28893073c4f705d1f3126083cd
commit 14768c22a04d1d28893073c4f705d1f3126083cd
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=4215e1270efa09c591bb84e51667f0bed8290ad0
commit 4215e1270efa09c591bb84e51667f0bed8290ad0
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=982880cc8211f53fff47dd0fa28ae20ef6c71754
commit 982880cc8211f53fff47dd0fa28ae20ef6c71754
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=610ec2225c901f9e183e7042f7de7063b7fe93d1
commit 610ec2225c901f9e183e7042f7de7063b7fe93d1
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=075ba1af88067cd902b724ab6ec2c2975a8b1efa
commit 075ba1af88067cd902b724ab6ec2c2975a8b1efa
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=37e77f8891690b0fe7b2d8580e171ebf3d6f8562
commit 37e77f8891690b0fe7b2d8580e171ebf3d6f8562
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=9a01f6d9f10d3494b947e099e7dbee35f13321b6
commit 9a01f6d9f10d3494b947e099e7dbee35f13321b6
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=65e7a455f2b70daffeac7dfc238f16d34b5af218
commit 65e7a455f2b70daffeac7dfc238f16d34b5af218
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=0512243a988c10e4b9e2a8519a3b0fc4e0d5917b
commit 0512243a988c10e4b9e2a8519a3b0fc4e0d5917b
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=7ee44ebb8aa76b7a1154bd2af7b65fc3602e613c
commit 7ee44ebb8aa76b7a1154bd2af7b65fc3602e613c
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=68f9a335c4695202dfeec00ef3ebb3933787d8a7
commit 68f9a335c4695202dfeec00ef3ebb3933787d8a7
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=9897ed69e624afe2241111f489b4213ec8d567da
commit 9897ed69e624afe2241111f489b4213ec8d567da
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);


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

    Selection: Unify rule good for media helper.

diff --git a/src/select/hash.c b/src/select/hash.c
index dce4065..92457d8 100644
--- a/src/select/hash.c
+++ b/src/select/hash.c
@@ -10,6 +10,7 @@
 
 #include "stylesheet.h"
 #include "select/hash.h"
+#include "select/mq.h"
 #include "utils/utils.h"
 
 #undef PRINT_CHAIN_BLOOM_DETAILS
@@ -106,36 +107,6 @@ static inline bool _chain_good_for_element_name(const 
css_selector *selector,
        return true;
 }
 
-/**
- * Test whether the rule applies for current media.
- *
- * \param rule         Rule to test
- * \meaid media                Current media type(s)
- * \return true iff chain's rule applies for media
- */
-static inline bool _rule_good_for_media(const css_rule *rule, uint64_t media)
-{
-       bool applies = true;
-       const css_rule *ancestor = rule;
-
-       while (ancestor != NULL) {
-               const css_rule_media *m = (const css_rule_media *) ancestor;
-
-               if (ancestor->type == CSS_RULE_MEDIA &&
-                               (m->media & media) == 0) {
-                       applies = false;
-                       break;
-               }
-
-               if (ancestor->ptype != CSS_RULE_PARENT_STYLESHEET)
-                       ancestor = ancestor->parent;
-               else
-                       ancestor = NULL;
-       }
-
-       return applies;
-}
-
 
 /**
  * Create a hash
@@ -396,7 +367,7 @@ css_error css__selector_hash_find(css_selector_hash *hash,
                                if (css_bloom_in_bloom(
                                                head->sel_chain_bloom,
                                                req->node_bloom) &&
-                                   _rule_good_for_media(head->sel->rule,
+                                   mq_rule_good_for_media(head->sel->rule,
                                                req->media)) {
                                        /* Found a match */
                                        break;
@@ -474,7 +445,7 @@ css_error 
css__selector_hash_find_by_class(css_selector_hash *hash,
                                                        head->sel,
                                                        &(req->qname),
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -554,7 +525,7 @@ css_error css__selector_hash_find_by_id(css_selector_hash 
*hash,
                                                        head->sel,
                                                        &req->qname,
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -605,7 +576,7 @@ css_error 
css__selector_hash_find_universal(css_selector_hash *hash,
                            css_bloom_in_bloom(
                                        head->sel_chain_bloom,
                                        req->node_bloom) &&
-                           _rule_good_for_media(head->sel->rule,
+                           mq_rule_good_for_media(head->sel->rule,
                                        req->media)) {
                                /* Found a match */
                                break;
@@ -949,7 +920,7 @@ css_error _iterate_elements(
                                if (css_bloom_in_bloom(
                                                head->sel_chain_bloom,
                                                req->node_bloom) &&
-                                   _rule_good_for_media(head->sel->rule,
+                                   mq_rule_good_for_media(head->sel->rule,
                                                req->media)) {
                                        /* Found a match */
                                        break;
@@ -1008,7 +979,7 @@ css_error _iterate_classes(
                                                        head->sel,
                                                        &(req->qname),
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -1069,7 +1040,7 @@ css_error _iterate_ids(
                                                        head->sel,
                                                        &req->qname,
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -1113,7 +1084,7 @@ css_error _iterate_universal(
                            css_bloom_in_bloom(
                                        head->sel_chain_bloom,
                                        req->node_bloom) &&
-                           _rule_good_for_media(head->sel->rule,
+                           mq_rule_good_for_media(head->sel->rule,
                                        req->media)) {
                                /* Found a match */
                                break;
diff --git a/src/select/select.c b/src/select/select.c
index 6b5225a..644369a 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -19,6 +19,7 @@
 #include "select/computed.h"
 #include "select/dispatch.h"
 #include "select/hash.h"
+#include "select/mq.h"
 #include "select/propset.h"
 #include "select/font_face.h"
 #include "select/select.h"
@@ -1885,34 +1886,11 @@ css_error select_from_sheet(css_select_ctx *ctx, const 
css_stylesheet *sheet,
        return CSS_OK;
 }
 
-static inline bool _rule_applies_to_media(const css_rule *rule, uint64_t media)
-{
-       bool applies = true;
-       const css_rule *ancestor = rule;
-
-       while (ancestor != NULL) {
-               const css_rule_media *m = (const css_rule_media *) ancestor;
-
-               if (ancestor->type == CSS_RULE_MEDIA &&
-                               (m->media & media) == 0) {
-                       applies = false;
-                       break;
-               }
-
-               if (ancestor->ptype != CSS_RULE_PARENT_STYLESHEET)
-                       ancestor = ancestor->parent;
-               else
-                       ancestor = NULL;
-       }
-
-       return applies;
-}
-
 static css_error _select_font_face_from_rule(
                const css_rule_font_face *rule, css_origin origin,
                css_select_font_faces_state *state)
 {
-       if (_rule_applies_to_media((const css_rule *) rule, state->media)) {
+       if (mq_rule_good_for_media((const css_rule *) rule, state->media)) {
                bool correct_family = false;
 
                if (lwc_string_isequal(


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

Summary of changes:
 src/parse/mq.c      |    2 +-
 src/select/hash.c   |   47 +++++++++--------------------------------------
 src/select/select.c |   26 ++------------------------
 3 files changed, 12 insertions(+), 63 deletions(-)

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;
                }
diff --git a/src/select/hash.c b/src/select/hash.c
index dce4065..92457d8 100644
--- a/src/select/hash.c
+++ b/src/select/hash.c
@@ -10,6 +10,7 @@
 
 #include "stylesheet.h"
 #include "select/hash.h"
+#include "select/mq.h"
 #include "utils/utils.h"
 
 #undef PRINT_CHAIN_BLOOM_DETAILS
@@ -106,36 +107,6 @@ static inline bool _chain_good_for_element_name(const 
css_selector *selector,
        return true;
 }
 
-/**
- * Test whether the rule applies for current media.
- *
- * \param rule         Rule to test
- * \meaid media                Current media type(s)
- * \return true iff chain's rule applies for media
- */
-static inline bool _rule_good_for_media(const css_rule *rule, uint64_t media)
-{
-       bool applies = true;
-       const css_rule *ancestor = rule;
-
-       while (ancestor != NULL) {
-               const css_rule_media *m = (const css_rule_media *) ancestor;
-
-               if (ancestor->type == CSS_RULE_MEDIA &&
-                               (m->media & media) == 0) {
-                       applies = false;
-                       break;
-               }
-
-               if (ancestor->ptype != CSS_RULE_PARENT_STYLESHEET)
-                       ancestor = ancestor->parent;
-               else
-                       ancestor = NULL;
-       }
-
-       return applies;
-}
-
 
 /**
  * Create a hash
@@ -396,7 +367,7 @@ css_error css__selector_hash_find(css_selector_hash *hash,
                                if (css_bloom_in_bloom(
                                                head->sel_chain_bloom,
                                                req->node_bloom) &&
-                                   _rule_good_for_media(head->sel->rule,
+                                   mq_rule_good_for_media(head->sel->rule,
                                                req->media)) {
                                        /* Found a match */
                                        break;
@@ -474,7 +445,7 @@ css_error 
css__selector_hash_find_by_class(css_selector_hash *hash,
                                                        head->sel,
                                                        &(req->qname),
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -554,7 +525,7 @@ css_error css__selector_hash_find_by_id(css_selector_hash 
*hash,
                                                        head->sel,
                                                        &req->qname,
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -605,7 +576,7 @@ css_error 
css__selector_hash_find_universal(css_selector_hash *hash,
                            css_bloom_in_bloom(
                                        head->sel_chain_bloom,
                                        req->node_bloom) &&
-                           _rule_good_for_media(head->sel->rule,
+                           mq_rule_good_for_media(head->sel->rule,
                                        req->media)) {
                                /* Found a match */
                                break;
@@ -949,7 +920,7 @@ css_error _iterate_elements(
                                if (css_bloom_in_bloom(
                                                head->sel_chain_bloom,
                                                req->node_bloom) &&
-                                   _rule_good_for_media(head->sel->rule,
+                                   mq_rule_good_for_media(head->sel->rule,
                                                req->media)) {
                                        /* Found a match */
                                        break;
@@ -1008,7 +979,7 @@ css_error _iterate_classes(
                                                        head->sel,
                                                        &(req->qname),
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -1069,7 +1040,7 @@ css_error _iterate_ids(
                                                        head->sel,
                                                        &req->qname,
                                                        req->uni) &&
-                                           _rule_good_for_media(
+                                           mq_rule_good_for_media(
                                                        head->sel->rule,
                                                        req->media)) {
                                                /* Found a match */
@@ -1113,7 +1084,7 @@ css_error _iterate_universal(
                            css_bloom_in_bloom(
                                        head->sel_chain_bloom,
                                        req->node_bloom) &&
-                           _rule_good_for_media(head->sel->rule,
+                           mq_rule_good_for_media(head->sel->rule,
                                        req->media)) {
                                /* Found a match */
                                break;
diff --git a/src/select/select.c b/src/select/select.c
index 6b5225a..644369a 100644
--- a/src/select/select.c
+++ b/src/select/select.c
@@ -19,6 +19,7 @@
 #include "select/computed.h"
 #include "select/dispatch.h"
 #include "select/hash.h"
+#include "select/mq.h"
 #include "select/propset.h"
 #include "select/font_face.h"
 #include "select/select.h"
@@ -1885,34 +1886,11 @@ css_error select_from_sheet(css_select_ctx *ctx, const 
css_stylesheet *sheet,
        return CSS_OK;
 }
 
-static inline bool _rule_applies_to_media(const css_rule *rule, uint64_t media)
-{
-       bool applies = true;
-       const css_rule *ancestor = rule;
-
-       while (ancestor != NULL) {
-               const css_rule_media *m = (const css_rule_media *) ancestor;
-
-               if (ancestor->type == CSS_RULE_MEDIA &&
-                               (m->media & media) == 0) {
-                       applies = false;
-                       break;
-               }
-
-               if (ancestor->ptype != CSS_RULE_PARENT_STYLESHEET)
-                       ancestor = ancestor->parent;
-               else
-                       ancestor = NULL;
-       }
-
-       return applies;
-}
-
 static css_error _select_font_face_from_rule(
                const css_rule_font_face *rule, css_origin origin,
                css_select_font_faces_state *state)
 {
-       if (_rule_applies_to_media((const css_rule *) rule, state->media)) {
+       if (mq_rule_good_for_media((const css_rule *) rule, state->media)) {
                bool correct_family = false;
 
                if (lwc_string_isequal(


-- 
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