Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/2264285f780c2d83de80f...
...commit
http://git.netsurf-browser.org/netsurf.git/commit/2264285f780c2d83de80fff...
...tree
http://git.netsurf-browser.org/netsurf.git/tree/2264285f780c2d83de80fff8e...
The branch, tlsa/shared-styles has been updated
discards d68406e9c9b317ed461ea9b0ad4af20268ba238d (commit)
discards 2a8ce59c0e5b74449f8d9a1dc535c966fb3352d8 (commit)
discards f6750060c39eb36e888e293d1fe6ed0b7e5a7cbc (commit)
discards 73c7cdc5fadcda7a562fbf34bf84e394c59e7534 (commit)
discards e612366e1f50be4559349a3bc754fc875b5af330 (commit)
via 2264285f780c2d83de80fff8eee7da0369a577e5 (commit)
via 6fa628350b2e97eb5cd843cd9dff2defac59da92 (commit)
via 5ddfb29ce27cf567abd89488657498da61fc5204 (commit)
via 31b7916841963da78e250c5e861da371f0b78e41 (commit)
via c1b6253891e9689cff9f20ba663506d78f6a7204 (commit)
via 4137739b8ae3829d679b59a0894d1189a4e776d4 (commit)
via c92726d3aa05e7fd3ffb00a2b115c61e42c6270d (commit)
via 180a8f452e0904bdcd6ee7c47a31877e1625bde4 (commit)
via b42a910ed91c91da71e53b4efb9889aa46938aee (commit)
via 9fe01f09c879bd75c369ea064be519adaf3d9837 (commit)
via b41b672fe5228be936715254003132ee21843242 (commit)
via f7ebec7142321c0d97789015d8185c5b0cacda0c (commit)
via 5e24a802b073f2905a983d743dc5363915467d53 (commit)
via 47fa0bf7a2f214a580546e88e9c77cf530905d7b (commit)
via af71481a5f4b0ddb9d5ca55187981dfe9ae2558c (commit)
via 4c2d40b35eb1d3b3dc9237c609806b84f7d4b97d (commit)
via c659e115854b60960ddf62117977cbbbbd45d3ef (commit)
via 6d474e74e6a967563ea1b85f4d8576ebc41153f1 (commit)
via 479b8acce8cdc4009c83aaed2849fe48528d4603 (commit)
via 5ad337a7b5b4793dfebc8a4d333f8995f6c8877b (commit)
via 6fbe30c617158e40827a055f7c5c1527eb886672 (commit)
via 045b254c157025a177ae8b7db36462305b1c5c50 (commit)
via 0feb291c2e3041004b676ddd56301beaf78851a5 (commit)
via bf6d56c7fe14029ed1a04111bfa1bc53414707c2 (commit)
via 28be6d2d79ba87cc231f28ce25525dd2ae60e5ed (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 (d68406e9c9b317ed461ea9b0ad4af20268ba238d)
\
N -- N -- N (2264285f780c2d83de80fff8eee7da0369a577e5)
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/netsurf.git/commit/?id=2264285f780c2d83de8...
commit 2264285f780c2d83de80fff8eee7da0369a577e5
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Update to use libcss API which allows interned partial styles.
diff --git a/css/select.c b/css/select.c
index c9e5f7e..a4225cb 100644
--- a/css/select.c
+++ b/css/select.c
@@ -252,6 +252,7 @@ static void nscss_dom_user_data_handler(dom_node_operation operation,
css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
uint64_t media, const css_stylesheet *inline_style)
{
+ css_computed_style *composed;
css_select_results *styles;
int pseudo_element;
css_error error;
@@ -273,11 +274,16 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node
*n,
error = css_computed_style_compose(ctx->parent_style,
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
nscss_compute_font_size, NULL,
- &(styles->styles[CSS_PSEUDO_ELEMENT_NONE]));
+ &composed);
if (error != CSS_OK) {
css_select_results_destroy(styles);
return NULL;
}
+
+ /* Replace select_results style with composed style */
+ css_computed_style_destroy(
+ styles->styles[CSS_PSEUDO_ELEMENT_NONE]);
+ styles->styles[CSS_PSEUDO_ELEMENT_NONE] = composed;
}
for (pseudo_element = CSS_PSEUDO_ELEMENT_NONE + 1;
@@ -300,40 +306,20 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node
*n,
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
styles->styles[pseudo_element],
nscss_compute_font_size, NULL,
- &(styles->styles[pseudo_element]));
+ &composed);
if (error != CSS_OK) {
/* TODO: perhaps this shouldn't be quite so
* catastrophic? */
css_select_results_destroy(styles);
return NULL;
}
- }
-
- return styles;
-}
-
-/**
- * Get an initial style
- *
- * \param ctx CSS selection context
- * \return Pointer to partial computed style, or NULL on failure
- */
-static css_computed_style *nscss_get_initial_style(nscss_select_ctx *ctx)
-{
- css_computed_style *style;
- css_error error;
- error = css_computed_style_create(&style);
- if (error != CSS_OK)
- return NULL;
-
- error = css_computed_style_initialise(style, &selection_handler, ctx);
- if (error != CSS_OK) {
- css_computed_style_destroy(style);
- return NULL;
+ /* Replace select_results style with composed style */
+ css_computed_style_destroy(styles->styles[pseudo_element]);
+ styles->styles[pseudo_element] = composed;
}
- return style;
+ return styles;
}
/**
@@ -346,21 +332,26 @@ static css_computed_style *nscss_get_initial_style(nscss_select_ctx
*ctx)
css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
const css_computed_style *parent)
{
- css_computed_style *partial;
+ css_computed_style *partial, *composed;
css_error error;
- partial = nscss_get_initial_style(ctx);
- if (partial == NULL)
+ error = css_select_default_style(ctx->ctx,
+ &selection_handler, ctx, &partial);
+ if (error != CSS_OK) {
return NULL;
+ }
+ /* TODO: Do we really need to compose? Initial style shouldn't
+ * have any inherited properties. */
error = css_computed_style_compose(parent, partial,
- nscss_compute_font_size, NULL, &partial);
+ nscss_compute_font_size, NULL, &composed);
+ css_computed_style_destroy(partial);
if (error != CSS_OK) {
- css_computed_style_destroy(partial);
+ css_computed_style_destroy(composed);
return NULL;
}
- return partial;
+ return composed;
}
/**
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=6fa628350b2e97eb5cd...
commit 6fa628350b2e97eb5cd843cd9dff2defac59da92
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Remove duplicate branch.
diff --git a/css/hints.c b/css/hints.c
index c8f5ebb..066212e 100644
--- a/css/hints.c
+++ b/css/hints.c
@@ -1578,14 +1578,6 @@ static css_error node_presentational_hint_color(
return CSS_PROPERTY_NOT_SET;
}
}
- } else if (dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_body)) {
- err = dom_element_get_attribute(node,
- corestring_dom_text, &color);
- if ((err != DOM_NO_ERR) || (color == NULL)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
} else {
err = dom_element_get_attribute(node,
corestring_dom_color, &color);
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=5ddfb29ce27cf567abd...
commit 5ddfb29ce27cf567abd89488657498da61fc5204
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Tidy cellpadding hint handling.
diff --git a/css/hints.c b/css/hints.c
index 059b42b..c8f5ebb 100644
--- a/css/hints.c
+++ b/css/hints.c
@@ -832,7 +832,6 @@ static css_error node_presentational_hint_padding_trbl(
{
dom_string *name;
dom_exception exc;
- dom_string *cellpadding = NULL;
css_error result = CSS_PROPERTY_NOT_SET;
exc = dom_node_get_node_name(node, &name);
@@ -843,6 +842,8 @@ static css_error node_presentational_hint_padding_trbl(
dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
css_qname qs;
dom_node *tablenode = NULL;
+ dom_string *cellpadding = NULL;
+
qs.ns = NULL;
qs.name = lwc_string_ref(corestring_lwc_table);
if (named_ancestor_node(ctx, node, &qs,
@@ -866,20 +867,20 @@ static css_error node_presentational_hint_padding_trbl(
/* No need to unref tablenode, named_ancestor_node does not
* return a reffed node to the CSS
*/
- }
-
- dom_string_unref(name);
- if (cellpadding != NULL) {
- if (parse_dimension(dom_string_data(cellpadding), false,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- hint->status = CSS_PADDING_SET;
- result = CSS_OK;
+ if (cellpadding != NULL) {
+ if (parse_dimension(dom_string_data(cellpadding), false,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->status = CSS_PADDING_SET;
+ result = CSS_OK;
+ }
+ dom_string_unref(cellpadding);
}
- dom_string_unref(cellpadding);
}
+ dom_string_unref(name);
+
return result;
}
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=31b7916841963da78e2...
commit 31b7916841963da78e250c5e861da371f0b78e41
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Split out presentational hints handling.
diff --git a/css/Makefile b/css/Makefile
index 1280d57..127dbaa 100644
--- a/css/Makefile
+++ b/css/Makefile
@@ -1,5 +1,5 @@
# CSS sources
-S_CSS := css.c dump.c internal.c select.c utils.c
+S_CSS := css.c dump.c internal.c hints.c select.c utils.c
S_CSS := $(addprefix css/,$(S_CSS))
diff --git a/css/hints.c b/css/hints.c
new file mode 100644
index 0000000..059b42b
--- /dev/null
+++ b/css/hints.c
@@ -0,0 +1,1794 @@
+/*
+ * Copyright 2009 John-Mark Bell <jmb(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf,
http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <strings.h>
+
+#include "utils/nsoption.h"
+#include "utils/corestrings.h"
+#include "utils/log.h"
+#include "utils/nsurl.h"
+#include "utils/utils.h"
+
+#include "css/hints.h"
+#include "css/select.h"
+
+/******************************************************************************
+ * Utility functions *
+ ******************************************************************************/
+
+/**
+ * Determine if a given character is whitespace
+ *
+ * \param c Character to consider
+ * \return true if character is whitespace, false otherwise
+ */
+static bool isWhitespace(char c)
+{
+ return c == ' ' || c == '\t' || c == '\f' || c == '\r'
|| c == '\n';
+}
+
+/**
+ * Determine if a given character is a valid hex digit
+ *
+ * \param c Character to consider
+ * \return true if character is a valid hex digit, false otherwise
+ */
+static bool isHex(char c)
+{
+ return ('0' <= c && c <= '9') ||
+ ('A' <= (c & ~0x20) && (c & ~0x20) <= 'F');
+}
+
+/**
+ * Convert a character representing a hex digit to the corresponding hex value
+ *
+ * \param c Character to convert
+ * \return Hex value represented by character
+ *
+ * \note This function assumes an ASCII-compatible character set
+ */
+static uint8_t charToHex(char c)
+{
+ /* 0-9 */
+ c -= '0';
+
+ /* A-F */
+ if (c > 9)
+ c -= 'A' - '9' - 1;
+
+ /* a-f */
+ if (c > 15)
+ c -= 'a' - 'A';
+
+ return c;
+}
+
+
+/******************************************************************************
+ * Common parsing functions *
+ ******************************************************************************/
+
+/**
+ * Parse a number string
+ *
+ * \param data Data to parse (NUL-terminated)
+ * \param maybe_negative Negative numbers permitted
+ * \param real Floating point numbers permitted
+ * \param value Pointer to location to receive numeric value
+ * \param consumed Pointer to location to receive number of input
+ * bytes consumed
+ * \return true on success, false on invalid input
+ */
+static bool parse_number(const char *data, bool maybe_negative, bool real,
+ css_fixed *value, size_t *consumed)
+{
+ size_t len;
+ const uint8_t *ptr;
+ int32_t intpart = 0;
+ int32_t fracpart = 0;
+ int32_t pwr = 1;
+ int sign = 1;
+
+ *consumed = 0;
+
+ len = strlen(data);
+ ptr = (const uint8_t *) data;
+
+ if (len == 0)
+ return false;
+
+ /* Skip leading whitespace */
+ while (len > 0 && isWhitespace(ptr[0])) {
+ len--;
+ ptr++;
+ }
+
+ if (len == 0)
+ return false;
+
+ /* Extract sign, if any */
+ if (ptr[0] == '+') {
+ len--;
+ ptr++;
+ } else if (ptr[0] == '-' && maybe_negative) {
+ sign = -1;
+ len--;
+ ptr++;
+ }
+
+ if (len == 0)
+ return false;
+
+ /* Must have a digit [0,9] */
+ if ('0' > ptr[0] || ptr[0] > '9')
+ return false;
+
+ /* Now extract intpart, assuming base 10 */
+ while (len > 0) {
+ /* Stop on first non-digit */
+ if (ptr[0] < '0' || '9' < ptr[0])
+ break;
+
+ /* Prevent overflow of 'intpart'; proper clamping below */
+ if (intpart < (1 << 22)) {
+ intpart *= 10;
+ intpart += ptr[0] - '0';
+ }
+ ptr++;
+ len--;
+ }
+
+ /* And fracpart, again, assuming base 10 */
+ if (real && len > 1 && ptr[0] == '.' &&
+ ('0' <= ptr[1] && ptr[1] <= '9')) {
+ ptr++;
+ len--;
+
+ while (len > 0) {
+ if (ptr[0] < '0' || '9' < ptr[0])
+ break;
+
+ if (pwr < 1000000) {
+ pwr *= 10;
+ fracpart *= 10;
+ fracpart += ptr[0] - '0';
+ }
+ ptr++;
+ len--;
+ }
+
+ fracpart = ((1 << 10) * fracpart + pwr/2) / pwr;
+ if (fracpart >= (1 << 10)) {
+ intpart++;
+ fracpart &= (1 << 10) - 1;
+ }
+ }
+
+ if (sign > 0) {
+ /* If the result is larger than we can represent,
+ * then clamp to the maximum value we can store. */
+ if (intpart >= (1 << 21)) {
+ intpart = (1 << 21) - 1;
+ fracpart = (1 << 10) - 1;
+ }
+ } else {
+ /* If the negated result is smaller than we can represent
+ * then clamp to the minimum value we can store. */
+ if (intpart >= (1 << 21)) {
+ intpart = -(1 << 21);
+ fracpart = 0;
+ } else {
+ intpart = -intpart;
+ if (fracpart) {
+ fracpart = (1 << 10) - fracpart;
+ intpart--;
+ }
+ }
+ }
+
+ *value = (intpart << 10) | fracpart;
+
+ *consumed = ptr - (const uint8_t *) data;
+
+ return true;
+}
+
+/**
+ * Parse a dimension string
+ *
+ * \param data Data to parse (NUL-terminated)
+ * \param strict Whether to enforce strict parsing rules
+ * \param length Pointer to location to receive dimension's length
+ * \param unit Pointer to location to receive dimension's unit
+ * \return true on success, false on invalid input
+ */
+static bool parse_dimension(const char *data, bool strict, css_fixed *length,
+ css_unit *unit)
+{
+ size_t len;
+ size_t read;
+ css_fixed value;
+
+ len = strlen(data);
+
+ if (parse_number(data, false, true, &value, &read) == false)
+ return false;
+
+ if (strict && value < INTTOFIX(1))
+ return false;
+
+ *length = value;
+
+ if (len > read && data[read] == '%')
+ *unit = CSS_UNIT_PCT;
+ else
+ *unit = CSS_UNIT_PX;
+
+ return true;
+}
+
+/**
+ * Mapping of colour name to CSS color
+ */
+struct colour_map {
+ const char *name;
+ css_color color;
+};
+
+/**
+ * Name comparator for named colour matching
+ *
+ * \param a Name to match
+ * \param b Colour map entry to consider
+ * \return 0 on match,
+ * < 0 if a < b,
+ * > 0 if b > a.
+ */
+static int cmp_colour_name(const void *a, const void *b)
+{
+ const char *aa = a;
+ const struct colour_map *bb = b;
+
+ return strcasecmp(aa, bb->name);
+}
+
+/**
+ * Parse a named colour
+ *
+ * \param name Name to parse
+ * \param result Pointer to location to receive css_color
+ * \return true on success, false on invalid input
+ */
+static bool parse_named_colour(const char *name, css_color *result)
+{
+ static const struct colour_map named_colours[] = {
+ { "aliceblue", 0xfff0f8ff },
+ { "antiquewhite", 0xfffaebd7 },
+ { "aqua", 0xff00ffff },
+ { "aquamarine", 0xff7fffd4 },
+ { "azure", 0xfff0ffff },
+ { "beige", 0xfff5f5dc },
+ { "bisque", 0xffffe4c4 },
+ { "black", 0xff000000 },
+ { "blanchedalmond", 0xffffebcd },
+ { "blue", 0xff0000ff },
+ { "blueviolet", 0xff8a2be2 },
+ { "brown", 0xffa52a2a },
+ { "burlywood", 0xffdeb887 },
+ { "cadetblue", 0xff5f9ea0 },
+ { "chartreuse", 0xff7fff00 },
+ { "chocolate", 0xffd2691e },
+ { "coral", 0xffff7f50 },
+ { "cornflowerblue", 0xff6495ed },
+ { "cornsilk", 0xfffff8dc },
+ { "crimson", 0xffdc143c },
+ { "cyan", 0xff00ffff },
+ { "darkblue", 0xff00008b },
+ { "darkcyan", 0xff008b8b },
+ { "darkgoldenrod", 0xffb8860b },
+ { "darkgray", 0xffa9a9a9 },
+ { "darkgreen", 0xff006400 },
+ { "darkgrey", 0xffa9a9a9 },
+ { "darkkhaki", 0xffbdb76b },
+ { "darkmagenta", 0xff8b008b },
+ { "darkolivegreen", 0xff556b2f },
+ { "darkorange", 0xffff8c00 },
+ { "darkorchid", 0xff9932cc },
+ { "darkred", 0xff8b0000 },
+ { "darksalmon", 0xffe9967a },
+ { "darkseagreen", 0xff8fbc8f },
+ { "darkslateblue", 0xff483d8b },
+ { "darkslategray", 0xff2f4f4f },
+ { "darkslategrey", 0xff2f4f4f },
+ { "darkturquoise", 0xff00ced1 },
+ { "darkviolet", 0xff9400d3 },
+ { "deeppink", 0xffff1493 },
+ { "deepskyblue", 0xff00bfff },
+ { "dimgray", 0xff696969 },
+ { "dimgrey", 0xff696969 },
+ { "dodgerblue", 0xff1e90ff },
+ { "feldspar", 0xffd19275 },
+ { "firebrick", 0xffb22222 },
+ { "floralwhite", 0xfffffaf0 },
+ { "forestgreen", 0xff228b22 },
+ { "fuchsia", 0xffff00ff },
+ { "gainsboro", 0xffdcdcdc },
+ { "ghostwhite", 0xfff8f8ff },
+ { "gold", 0xffffd700 },
+ { "goldenrod", 0xffdaa520 },
+ { "gray", 0xff808080 },
+ { "green", 0xff008000 },
+ { "greenyellow", 0xffadff2f },
+ { "grey", 0xff808080 },
+ { "honeydew", 0xfff0fff0 },
+ { "hotpink", 0xffff69b4 },
+ { "indianred", 0xffcd5c5c },
+ { "indigo", 0xff4b0082 },
+ { "ivory", 0xfffffff0 },
+ { "khaki", 0xfff0e68c },
+ { "lavender", 0xffe6e6fa },
+ { "lavenderblush", 0xfffff0f5 },
+ { "lawngreen", 0xff7cfc00 },
+ { "lemonchiffon", 0xfffffacd },
+ { "lightblue", 0xffadd8e6 },
+ { "lightcoral", 0xfff08080 },
+ { "lightcyan", 0xffe0ffff },
+ { "lightgoldenrodyellow", 0xfffafad2 },
+ { "lightgray", 0xffd3d3d3 },
+ { "lightgreen", 0xff90ee90 },
+ { "lightgrey", 0xffd3d3d3 },
+ { "lightpink", 0xffffb6c1 },
+ { "lightsalmon", 0xffffa07a },
+ { "lightseagreen", 0xff20b2aa },
+ { "lightskyblue", 0xff87cefa },
+ { "lightslateblue", 0xff8470ff },
+ { "lightslategray", 0xff778899 },
+ { "lightslategrey", 0xff778899 },
+ { "lightsteelblue", 0xffb0c4de },
+ { "lightyellow", 0xffffffe0 },
+ { "lime", 0xff00ff00 },
+ { "limegreen", 0xff32cd32 },
+ { "linen", 0xfffaf0e6 },
+ { "magenta", 0xffff00ff },
+ { "maroon", 0xff800000 },
+ { "mediumaquamarine", 0xff66cdaa },
+ { "mediumblue", 0xff0000cd },
+ { "mediumorchid", 0xffba55d3 },
+ { "mediumpurple", 0xff9370db },
+ { "mediumseagreen", 0xff3cb371 },
+ { "mediumslateblue", 0xff7b68ee },
+ { "mediumspringgreen", 0xff00fa9a },
+ { "mediumturquoise", 0xff48d1cc },
+ { "mediumvioletred", 0xffc71585 },
+ { "midnightblue", 0xff191970 },
+ { "mintcream", 0xfff5fffa },
+ { "mistyrose", 0xffffe4e1 },
+ { "moccasin", 0xffffe4b5 },
+ { "navajowhite", 0xffffdead },
+ { "navy", 0xff000080 },
+ { "oldlace", 0xfffdf5e6 },
+ { "olive", 0xff808000 },
+ { "olivedrab", 0xff6b8e23 },
+ { "orange", 0xffffa500 },
+ { "orangered", 0xffff4500 },
+ { "orchid", 0xffda70d6 },
+ { "palegoldenrod", 0xffeee8aa },
+ { "palegreen", 0xff98fb98 },
+ { "paleturquoise", 0xffafeeee },
+ { "palevioletred", 0xffdb7093 },
+ { "papayawhip", 0xffffefd5 },
+ { "peachpuff", 0xffffdab9 },
+ { "peru", 0xffcd853f },
+ { "pink", 0xffffc0cb },
+ { "plum", 0xffdda0dd },
+ { "powderblue", 0xffb0e0e6 },
+ { "purple", 0xff800080 },
+ { "red", 0xffff0000 },
+ { "rosybrown", 0xffbc8f8f },
+ { "royalblue", 0xff4169e1 },
+ { "saddlebrown", 0xff8b4513 },
+ { "salmon", 0xfffa8072 },
+ { "sandybrown", 0xfff4a460 },
+ { "seagreen", 0xff2e8b57 },
+ { "seashell", 0xfffff5ee },
+ { "sienna", 0xffa0522d },
+ { "silver", 0xffc0c0c0 },
+ { "skyblue", 0xff87ceeb },
+ { "slateblue", 0xff6a5acd },
+ { "slategray", 0xff708090 },
+ { "slategrey", 0xff708090 },
+ { "snow", 0xfffffafa },
+ { "springgreen", 0xff00ff7f },
+ { "steelblue", 0xff4682b4 },
+ { "tan", 0xffd2b48c },
+ { "teal", 0xff008080 },
+ { "thistle", 0xffd8bfd8 },
+ { "tomato", 0xffff6347 },
+ { "turquoise", 0xff40e0d0 },
+ { "violet", 0xffee82ee },
+ { "violetred", 0xffd02090 },
+ { "wheat", 0xfff5deb3 },
+ { "white", 0xffffffff },
+ { "whitesmoke", 0xfff5f5f5 },
+ { "yellow", 0xffffff00 },
+ { "yellowgreen", 0xff9acd32 }
+ };
+ const struct colour_map *entry;
+
+ entry = bsearch(name, named_colours,
+ sizeof(named_colours) / sizeof(named_colours[0]),
+ sizeof(named_colours[0]),
+ cmp_colour_name);
+
+ if (entry != NULL)
+ *result = entry->color;
+
+ return entry != NULL;
+}
+
+/**
+ * Parser for colours specified in attribute values.
+ *
+ * \param data Data to parse (NUL-terminated)
+ * \param result Pointer to location to receive resulting css_color
+ * \return true on success, false on invalid input
+ */
+bool nscss_parse_colour(const char *data, css_color *result)
+{
+ size_t len = strlen(data);
+ uint8_t r, g, b;
+
+ /* 2 */
+ if (len == 0)
+ return false;
+
+ /* 3 */
+ if (len == SLEN("transparent") && strcasecmp(data,
"transparent") == 0)
+ return false;
+
+ /* 4 */
+ if (parse_named_colour(data, result))
+ return true;
+
+ /** \todo Implement HTML5's utterly insane legacy colour parsing */
+
+ if (data[0] == '#') {
+ data++;
+ len--;
+ }
+
+ if (len == 3 && isHex(data[0]) && isHex(data[1]) &&
isHex(data[2])) {
+ r = charToHex(data[0]);
+ g = charToHex(data[1]);
+ b = charToHex(data[2]);
+
+ r |= (r << 4);
+ g |= (g << 4);
+ b |= (b << 4);
+
+ *result = (0xff << 24) | (r << 16) | (g << 8) | b;
+
+ return true;
+ } else if (len == 6 && isHex(data[0]) && isHex(data[1]) &&
+ isHex(data[2]) && isHex(data[3]) && isHex(data[4]) &&
+ isHex(data[5])) {
+ r = (charToHex(data[0]) << 4) | charToHex(data[1]);
+ g = (charToHex(data[2]) << 4) | charToHex(data[3]);
+ b = (charToHex(data[4]) << 4) | charToHex(data[5]);
+
+ *result = (0xff << 24) | (r << 16) | (g << 8) | b;
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Parse a font \@size attribute
+ *
+ * \param size Data to parse (NUL-terminated)
+ * \param val Pointer to location to receive enum value
+ * \param len Pointer to location to receive length
+ * \param unit Pointer to location to receive unit
+ * \return True on success, false on failure
+ */
+static bool parse_font_size(const char *size, uint8_t *val,
+ css_fixed *len, css_unit *unit)
+{
+ static const uint8_t size_map[] = {
+ CSS_FONT_SIZE_XX_SMALL,
+ CSS_FONT_SIZE_SMALL,
+ CSS_FONT_SIZE_MEDIUM,
+ CSS_FONT_SIZE_LARGE,
+ CSS_FONT_SIZE_X_LARGE,
+ CSS_FONT_SIZE_XX_LARGE,
+ CSS_FONT_SIZE_DIMENSION /* xxx-large (see below) */
+ };
+
+ const char *p = size;
+ char mode;
+ int value = 0;
+
+ /* Skip whitespace */
+ while (*p != '\0' && isWhitespace(*p))
+ p++;
+
+ mode = *p;
+
+ /* Skip +/- */
+ if (mode == '+' || mode == '-')
+ p++;
+
+ /* Need at least one digit */
+ if (*p < '0' || *p > '9') {
+ return false;
+ }
+
+ /* Consume digits, computing value */
+ while ('0' <= *p && *p <= '9') {
+ value = value * 10 + (*p - '0');
+ p++;
+ }
+
+ /* Resolve relative sizes */
+ if (mode == '+')
+ value += 3;
+ else if (mode == '-')
+ value = 3 - value;
+
+ /* Clamp to range [1,7] */
+ if (value < 1)
+ value = 1;
+ else if (value > 7)
+ value = 7;
+
+ if (value == 7) {
+ /* Manufacture xxx-large */
+ *len = FDIV(FMUL(INTTOFIX(3), INTTOFIX(nsoption_int(font_size))),
+ F_10);
+ } else {
+ /* Len is irrelevant */
+ *len = 0;
+ }
+
+ *unit = CSS_UNIT_PT;
+ *val = size_map[value - 1];
+
+ return true;
+}
+
+
+/******************************************************************************
+ * Presentational hint handlers *
+ ******************************************************************************/
+
+static css_error node_presentational_hint_vertical_align(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_string *valign = NULL;
+ dom_exception err;
+
+ err = dom_node_get_node_name(node, &name);
+ if (err != DOM_NO_ERR)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_col) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_thead) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_tbody) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_tfoot) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_valign, &valign);
+ if (err != DOM_NO_ERR || valign == NULL) {
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_top)) {
+ hint->status = CSS_VERTICAL_ALIGN_TOP;
+ } else if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_middle)) {
+ hint->status = CSS_VERTICAL_ALIGN_MIDDLE;
+ } else if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_bottom)) {
+ hint->status = CSS_VERTICAL_ALIGN_BOTTOM;
+ } else if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_baseline)) {
+ hint->status = CSS_VERTICAL_ALIGN_BASELINE;
+ } else {
+ dom_string_unref(valign);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(valign);
+ dom_string_unref(name);
+
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_applet) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_embed) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_iframe) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_img) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_object)) {
+ /** \todo input[type=image][align=*] - $11.3.3 */
+ err = dom_element_get_attribute(node,
+ corestring_dom_align, &valign);
+ if (err != DOM_NO_ERR || valign == NULL) {
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_top)) {
+ hint->status = CSS_VERTICAL_ALIGN_TOP;
+ } else if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_bottom) ||
+ dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_baseline)) {
+ hint->status = CSS_VERTICAL_ALIGN_BASELINE;
+ } else if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_texttop)) {
+ hint->status = CSS_VERTICAL_ALIGN_TEXT_TOP;
+ } else if (dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_absmiddle) ||
+ dom_string_caseless_lwc_isequal(valign,
+ corestring_lwc_abscenter)) {
+ hint->status = CSS_VERTICAL_ALIGN_MIDDLE;
+ } else {
+ dom_string_unref(valign);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(valign);
+ dom_string_unref(name);
+
+ return CSS_OK;
+ }
+
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_text_align(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_string *align = NULL;
+ dom_exception err;
+
+ err = dom_node_get_node_name(node, &name);
+ if (err != DOM_NO_ERR)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_p) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_h1) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_h2) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_h3) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_h4) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_h5) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_h6)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_align, &align);
+ if (err != DOM_NO_ERR || align == NULL) {
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_left)) {
+ hint->status = CSS_TEXT_ALIGN_LEFT;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_center)) {
+ hint->status = CSS_TEXT_ALIGN_CENTER;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_right)) {
+ hint->status = CSS_TEXT_ALIGN_RIGHT;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_justify)) {
+ hint->status = CSS_TEXT_ALIGN_JUSTIFY;
+ } else {
+ dom_string_unref(align);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(align);
+ dom_string_unref(name);
+
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_center)) {
+ hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
+
+ dom_string_unref(name);
+
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_caption)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_align, &align);
+ if (err != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (align == NULL || dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_center)) {
+ hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_left)) {
+ hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_right)) {
+ hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_justify)) {
+ hint->status = CSS_TEXT_ALIGN_JUSTIFY;
+ } else {
+ dom_string_unref(align);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (align != NULL)
+ dom_string_unref(align);
+ dom_string_unref(name);
+
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_div) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_thead) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_tbody) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_tfoot) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_tr) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_th)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_align, &align);
+ if (err != DOM_NO_ERR || align == NULL) {
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_center)) {
+ hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_left)) {
+ hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_right)) {
+ hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_justify)) {
+ hint->status = CSS_TEXT_ALIGN_JUSTIFY;
+ } else {
+ dom_string_unref(align);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(align);
+ dom_string_unref(name);
+
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_table)) {
+ /* Tables usually reset alignment */
+ hint->status = CSS_TEXT_ALIGN_INHERIT_IF_NON_MAGIC;
+
+ dom_string_unref(name);
+
+ return CSS_OK;
+ } else {
+ dom_string_unref(name);
+
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+}
+
+static css_error node_presentational_hint_padding_trbl(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_exception exc;
+ dom_string *cellpadding = NULL;
+ css_error result = CSS_PROPERTY_NOT_SET;
+
+ exc = dom_node_get_node_name(node, &name);
+ if (exc != DOM_NO_ERR)
+ return CSS_BADPARM;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
+ css_qname qs;
+ dom_node *tablenode = NULL;
+ qs.ns = NULL;
+ qs.name = lwc_string_ref(corestring_lwc_table);
+ if (named_ancestor_node(ctx, node, &qs,
+ (void *)&tablenode) != CSS_OK) {
+ /* Didn't find, or had error */
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ lwc_string_unref(qs.name);
+
+ if (tablenode != NULL) {
+ exc = dom_element_get_attribute(tablenode,
+ corestring_dom_cellpadding,
+ &cellpadding);
+ if (exc != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return CSS_BADPARM;
+ }
+ }
+ /* No need to unref tablenode, named_ancestor_node does not
+ * return a reffed node to the CSS
+ */
+ }
+
+ dom_string_unref(name);
+
+ if (cellpadding != NULL) {
+ if (parse_dimension(dom_string_data(cellpadding), false,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->status = CSS_PADDING_SET;
+ result = CSS_OK;
+ }
+ dom_string_unref(cellpadding);
+ }
+
+ return result;
+}
+
+static css_error node_presentational_hint_margin_rl(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint,
+ uint32_t property)
+{
+ dom_string *n;
+ dom_exception exc;
+
+ exc = dom_node_get_node_name(node, &n);
+ if (exc != DOM_NO_ERR)
+ return CSS_BADPARM;
+
+ if (dom_string_caseless_lwc_isequal(n, corestring_lwc_img) ||
+ dom_string_caseless_lwc_isequal(n, corestring_lwc_applet)) {
+ dom_string_unref(n);
+ exc = dom_element_get_attribute(node,
+ corestring_dom_hspace, &n);
+ if (exc != DOM_NO_ERR) {
+ return CSS_BADPARM;
+ }
+
+ if (n == NULL)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (parse_dimension(dom_string_data(n), false,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->status = CSS_MARGIN_SET;
+ } else {
+ dom_string_unref(n);
+ return CSS_PROPERTY_NOT_SET;
+ }
+ dom_string_unref(n);
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_table) ||
+ dom_string_caseless_lwc_isequal(n, corestring_lwc_align)) {
+ dom_string_unref(n);
+ exc = dom_element_get_attribute(node,
+ corestring_dom_align, &n);
+ if (exc != DOM_NO_ERR) {
+ return CSS_BADPARM;
+ }
+
+ if (n == NULL)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (dom_string_caseless_lwc_isequal(n,
+ corestring_lwc_center) ||
+ dom_string_caseless_lwc_isequal(n,
+ corestring_lwc_abscenter) ||
+ dom_string_caseless_lwc_isequal(n,
+ corestring_lwc_middle) ||
+ dom_string_caseless_lwc_isequal(n,
+ corestring_lwc_absmiddle)) {
+ hint->status = CSS_MARGIN_AUTO;
+ } else {
+ dom_string_unref(n);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(n);
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_hr)) {
+ dom_string_unref(n);
+ exc = dom_element_get_attribute(node,
+ corestring_dom_align, &n);
+ if (exc != DOM_NO_ERR)
+ return CSS_BADPARM;
+
+ if (n == NULL)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (dom_string_caseless_lwc_isequal(n,
+ corestring_lwc_left)) {
+ if (property == CSS_PROP_MARGIN_LEFT) {
+ hint->data.length.value = 0;
+ hint->data.length.unit = CSS_UNIT_PX;
+ hint->status = CSS_MARGIN_SET;
+ } else {
+ hint->status = CSS_MARGIN_AUTO;
+ }
+ } else if (dom_string_caseless_lwc_isequal(n,
+ corestring_lwc_center)) {
+ hint->status = CSS_MARGIN_AUTO;
+ } else if (dom_string_caseless_lwc_isequal(n,
+ corestring_lwc_right)) {
+ if (property == CSS_PROP_MARGIN_RIGHT) {
+ hint->data.length.value = 0;
+ hint->data.length.unit = CSS_UNIT_PX;
+ hint->status = CSS_MARGIN_SET;
+ } else {
+ hint->status = CSS_MARGIN_AUTO;
+ }
+ } else {
+ dom_string_unref(n);
+ return CSS_PROPERTY_NOT_SET;
+ }
+ dom_string_unref(n);
+
+ return CSS_OK;
+ }
+
+ dom_string_unref(n);
+
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_margin_tb(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name, *vspace = NULL;
+ dom_exception exc;
+
+ exc = dom_node_get_node_name(node, &name);
+ if (exc != DOM_NO_ERR)
+ return CSS_BADPARM;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_img) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) {
+ exc = dom_element_get_attribute(node, corestring_dom_vspace,
+ &vspace);
+ if (exc != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return CSS_BADPARM;
+ }
+ }
+
+ dom_string_unref(name);
+
+ if (vspace == NULL)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (parse_dimension(dom_string_data(vspace), false,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->status = CSS_MARGIN_SET;
+ } else {
+ dom_string_unref(vspace);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(vspace);
+
+ return CSS_OK;
+}
+
+static css_error node_presentational_hint_border_trbl_width(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_exception exc;
+ dom_string *width = NULL;
+ bool is_table_cell = false;
+
+ exc = dom_node_get_node_name(node, &name);
+ if (exc != DOM_NO_ERR)
+ return CSS_BADPARM;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
+ css_qname qs;
+ dom_node *tablenode = NULL;
+ qs.ns = NULL;
+ qs.name = lwc_string_ref(corestring_lwc_table);
+ if (named_ancestor_node(ctx, node, &qs,
+ (void *)&tablenode) != CSS_OK) {
+ /* Didn't find, or had error */
+ lwc_string_unref(qs.name);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ lwc_string_unref(qs.name);
+ if (tablenode != NULL) {
+ exc = dom_element_get_attribute(tablenode,
+ corestring_dom_border, &width);
+ if (exc != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return CSS_BADPARM;
+ }
+ }
+ /* No need to unref tablenode, named_ancestor_node does not
+ * return a reffed node to the CSS
+ */
+ is_table_cell = true;
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_table)) {
+ exc = dom_element_get_attribute(node, corestring_dom_border,
+ &width);
+ if (exc != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return CSS_BADPARM;
+ }
+ }
+
+ dom_string_unref(name);
+
+ if (width == NULL)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (parse_dimension(dom_string_data(width), false,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ if (is_table_cell &&
+ INTTOFIX(0) !=
+ hint->data.length.value) {
+ hint->data.length.value = INTTOFIX(1);
+ hint->data.length.unit = CSS_UNIT_PX;
+ }
+ hint->status = CSS_BORDER_WIDTH_WIDTH;
+ } else {
+ dom_string_unref(width);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(width);
+
+ return CSS_OK;
+}
+
+static css_error node_presentational_hint_border_trbl_style(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_exception exc;
+
+ exc = dom_node_get_node_name(node, &name);
+ if (exc != DOM_NO_ERR)
+ return CSS_BADPARM;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
+ css_qname qs;
+ dom_node *tablenode = NULL;
+ qs.ns = NULL;
+ qs.name = lwc_string_ref(corestring_lwc_table);
+
+ if (named_ancestor_node(ctx, node, &qs,
+ (void *)&tablenode) != CSS_OK) {
+ /* Didn't find, or had error */
+ lwc_string_unref(qs.name);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ lwc_string_unref(qs.name);
+
+ if (tablenode != NULL) {
+ bool has_border = false;
+
+ exc = dom_element_has_attribute(tablenode,
+ corestring_dom_border,
+ &has_border);
+ if (exc != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return CSS_BADPARM;
+ }
+
+ if (has_border) {
+ hint->status = CSS_BORDER_STYLE_INSET;
+ dom_string_unref(name);
+ return CSS_OK;
+ }
+ }
+ /* No need to unref tablenode, named_ancestor_node does not
+ * return a reffed node to the CSS
+ */
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_table)) {
+ bool has_border = false;
+
+ exc = dom_element_has_attribute(node,
+ corestring_dom_border,
+ &has_border);
+ if (exc != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return CSS_BADPARM;
+ }
+
+ if (has_border) {
+ hint->status = CSS_BORDER_STYLE_OUTSET;
+ dom_string_unref(name);
+ return CSS_OK;
+ }
+ }
+
+ dom_string_unref(name);
+
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_border_trbl_color(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_string *bordercolor = NULL;
+ dom_exception err;
+
+ err = dom_node_get_node_name(node, &name);
+ if (err != DOM_NO_ERR)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
+ css_qname qs;
+ dom_node *tablenode = NULL;
+ qs.ns = NULL;
+ qs.name = lwc_string_ref(corestring_lwc_table);
+
+ if (named_ancestor_node(ctx, node, &qs,
+ (void *)&tablenode) != CSS_OK) {
+ /* Didn't find, or had error */
+ lwc_string_unref(qs.name);
+ dom_string_unref(name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ lwc_string_unref(qs.name);
+
+ if (tablenode != NULL) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_bordercolor,
+ &bordercolor);
+ }
+ /* No need to unref tablenode, named_ancestor_node does not
+ * return a reffed node to the CSS
+ */
+
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_table)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_bordercolor,
+ &bordercolor);
+ }
+
+ dom_string_unref(name);
+
+ if ((err != DOM_NO_ERR) || (bordercolor == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (nscss_parse_colour((const char *)dom_string_data(bordercolor),
+ &hint->data.color)) {
+ hint->status = CSS_BORDER_COLOR_COLOR;
+ dom_string_unref(bordercolor);
+ return CSS_OK;
+ }
+
+ dom_string_unref(bordercolor);
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_border_spacing(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_exception err;
+ dom_string *node_name = NULL;
+ dom_string *cellspacing = NULL;
+
+ err = dom_node_get_node_name(node, &node_name);
+ if ((err != DOM_NO_ERR) || (node_name == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (!dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_table)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(node_name);
+
+ err = dom_element_get_attribute(node,
+ corestring_dom_cellspacing, &cellspacing);
+ if ((err != DOM_NO_ERR) || (cellspacing == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+
+ if (parse_dimension((const char *)dom_string_data(cellspacing),
+ false,
+ &hint->data.position.h.value,
+ &hint->data.position.h.unit)) {
+
+ hint->data.position.v = hint->data.position.h;
+ hint->status = CSS_BORDER_SPACING_SET;
+
+ dom_string_unref(cellspacing);
+ return CSS_OK;
+ }
+
+ dom_string_unref(cellspacing);
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_width(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_string *width = NULL;
+ dom_exception err;
+ bool textarea = false;
+ bool input = false;
+
+ err = dom_node_get_node_name(node, &name);
+ if (err != DOM_NO_ERR)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_hr) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_img) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_object) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_table) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_th) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_width, &width);
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_textarea)) {
+ textarea = true;
+ err = dom_element_get_attribute(node,
+ corestring_dom_cols, &width);
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_input)) {
+ input = true;
+ err = dom_element_get_attribute(node,
+ corestring_dom_size, &width);
+ }
+
+ dom_string_unref(name);
+
+ if ((err != DOM_NO_ERR) || (width == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (parse_dimension((const char *)dom_string_data(width),
+ false,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->status = CSS_WIDTH_SET;
+ dom_string_unref(width);
+
+ if (textarea) {
+ hint->data.length.unit = CSS_UNIT_EX;
+ }
+
+ if (input) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_type, &width);
+ if (err != DOM_NO_ERR) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if ((width == NULL) ||
+ dom_string_caseless_lwc_isequal(width,
+ corestring_lwc_text) ||
+ dom_string_caseless_lwc_isequal(width,
+ corestring_lwc_search) ||
+ dom_string_caseless_lwc_isequal(width,
+ corestring_lwc_file) ||
+ dom_string_caseless_lwc_isequal(width,
+ corestring_lwc_password)) {
+ hint->data.length.unit = CSS_UNIT_EX;
+ }
+ dom_string_unref(width);
+ }
+
+ return CSS_OK;
+ }
+
+ dom_string_unref(width);
+ return CSS_PROPERTY_NOT_SET;
+
+}
+
+static css_error node_presentational_hint_height(nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_string *name;
+ dom_string *height = NULL;
+ dom_exception err;
+ bool textarea = false;
+
+ err = dom_node_get_node_name(node, &name);
+ if (err != DOM_NO_ERR)
+ return CSS_PROPERTY_NOT_SET;
+
+ if (dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_th) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_img) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_object) ||
+ dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_height, &height);
+ } else if (dom_string_caseless_lwc_isequal(name,
+ corestring_lwc_textarea)) {
+ textarea = true;
+ err = dom_element_get_attribute(node,
+ corestring_dom_rows, &height);
+ }
+
+ dom_string_unref(name);
+
+ if ((err != DOM_NO_ERR) || (height == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (parse_dimension((const char *)dom_string_data(height),
+ false,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ hint->status = CSS_HEIGHT_SET;
+
+ if (textarea) {
+ hint->data.length.unit = CSS_UNIT_EM;
+ }
+
+ dom_string_unref(height);
+ return CSS_OK;
+ }
+
+ dom_string_unref(height);
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_font_size(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_exception err;
+ dom_string *node_name = NULL;
+ dom_string *size;
+
+ err = dom_node_get_node_name(node, &node_name);
+ if ((err != DOM_NO_ERR) || (node_name == NULL)) {
+ return CSS_NOMEM;
+ }
+
+ if (!dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_font)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(node_name);
+
+ err = dom_element_get_attribute(node, corestring_dom_size, &size);
+ if ((err != DOM_NO_ERR) || (size == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (parse_font_size((const char *)dom_string_data(size),
+ &hint->status,
+ &hint->data.length.value,
+ &hint->data.length.unit)) {
+ dom_string_unref(size);
+ return CSS_OK;
+ }
+
+ dom_string_unref(size);
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_float(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_exception err;
+ dom_string *node_name = NULL;
+ dom_string *align;
+
+ err = dom_node_get_node_name(node, &node_name);
+ if ((err != DOM_NO_ERR) || (node_name == NULL)) {
+ return CSS_NOMEM;
+ }
+
+ /** \todo input[type=image][align=*] - $11.3.3 */
+ if (!dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_table) &&
+ !dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_applet) &&
+ !dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_embed) &&
+ !dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_iframe) &&
+ !dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_img) &&
+ !dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_object)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(node_name);
+
+ err = dom_element_get_attribute(node, corestring_dom_align, &align);
+ if ((err != DOM_NO_ERR) || (align == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_left)) {
+ hint->status = CSS_FLOAT_LEFT;
+ dom_string_unref(align);
+ return CSS_OK;
+ } else if (dom_string_caseless_lwc_isequal(align,
+ corestring_lwc_right)) {
+ hint->status = CSS_FLOAT_RIGHT;
+ dom_string_unref(align);
+ return CSS_OK;
+ }
+
+ dom_string_unref(align);
+
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_color(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ css_error error;
+ dom_exception err;
+ dom_string *node_name = NULL;
+ dom_string *color;
+
+ err = dom_node_get_node_name(node, &node_name);
+ if ((err != DOM_NO_ERR) || (node_name == NULL)) {
+ return CSS_NOMEM;
+ }
+
+ if (dom_string_caseless_lwc_isequal(node_name, corestring_lwc_a)) {
+ /* find body node */
+ css_qname qs;
+ dom_node *bodynode = NULL;
+ bool is_visited;
+
+ qs.ns = NULL;
+ qs.name = lwc_string_ref(corestring_lwc_body);
+ if (named_ancestor_node(ctx, node, &qs,
+ (void *)&bodynode) != CSS_OK) {
+ /* Didn't find, or had error */
+ lwc_string_unref(qs.name);
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ lwc_string_unref(qs.name);
+
+ /* deal with missing body ancestor */
+ if (bodynode == NULL) {
+ dom_string_unref(node_name);
+ return CSS_BADPARM;
+ }
+
+ error = node_is_visited(ctx, node, &is_visited);
+ if (error != CSS_OK)
+ return error;
+
+ if (is_visited) {
+ err = dom_element_get_attribute(bodynode,
+ corestring_dom_vlink, &color);
+ if ((err != DOM_NO_ERR) || (color == NULL)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+ } else {
+ err = dom_element_get_attribute(bodynode,
+ corestring_dom_link, &color);
+ if ((err != DOM_NO_ERR) || (color == NULL)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+ }
+ } else if (dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_body)) {
+ err = dom_element_get_attribute(node,
+ corestring_dom_text, &color);
+ if ((err != DOM_NO_ERR) || (color == NULL)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+ } else {
+ err = dom_element_get_attribute(node,
+ corestring_dom_color, &color);
+ if ((err != DOM_NO_ERR) || (color == NULL)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+ }
+
+ if (!nscss_parse_colour((const char *)dom_string_data(color),
+ &hint->data.color)) {
+ dom_string_unref(color);
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ hint->status = CSS_COLOR_COLOR;
+
+ dom_string_unref(color);
+ dom_string_unref(node_name);
+
+ return CSS_OK;
+}
+
+static css_error node_presentational_hint_caption_side(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_exception err;
+ dom_string *node_name = NULL;
+ dom_string *align = NULL;
+
+ err = dom_node_get_node_name(node, &node_name);
+ if ((err != DOM_NO_ERR) || (node_name == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (!dom_string_caseless_lwc_isequal(node_name,
+ corestring_lwc_caption)) {
+ dom_string_unref(node_name);
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ dom_string_unref(node_name);
+
+ err = dom_element_get_attribute(node, corestring_dom_align, &align);
+ if ((err != DOM_NO_ERR) || (align == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (dom_string_caseless_lwc_isequal(align, corestring_lwc_bottom)) {
+ hint->status = CSS_CAPTION_SIDE_BOTTOM;
+ dom_string_unref(align);
+ return CSS_OK;
+ }
+
+ dom_string_unref(align);
+
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_background_color(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_exception err;
+ dom_string *bgcolor;
+
+ err = dom_element_get_attribute(node,
+ corestring_dom_bgcolor, &bgcolor);
+ if ((err != DOM_NO_ERR) || (bgcolor == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ if (nscss_parse_colour((const char *)dom_string_data(bgcolor),
+ &hint->data.color)) {
+ hint->status = CSS_BACKGROUND_COLOR_COLOR;
+ dom_string_unref(bgcolor);
+ return CSS_OK;
+ }
+
+ dom_string_unref(bgcolor);
+
+ return CSS_PROPERTY_NOT_SET;
+}
+
+static css_error node_presentational_hint_background_image(
+ nscss_select_ctx *ctx,
+ dom_node *node,
+ css_hint *hint)
+{
+ dom_exception err;
+ dom_string *atr_val;
+ nserror error;
+ nsurl *url;
+ lwc_string *iurl;
+ lwc_error lerror;
+
+ err = dom_element_get_attribute(node,
+ corestring_dom_background, &atr_val);
+ if ((err != DOM_NO_ERR) || (atr_val == NULL)) {
+ return CSS_PROPERTY_NOT_SET;
+ }
+
+ error = nsurl_join(ctx->base_url,
+ (const char *)dom_string_data(atr_val), &url);
+
+ dom_string_unref(atr_val);
+
+ if (error != NSERROR_OK) {
+ return CSS_NOMEM;
+ }
+
+ lerror = lwc_intern_string(nsurl_access(url),
+ nsurl_length(url), &iurl);
+
+ nsurl_unref(url);
+
+ if (lerror == lwc_error_oom) {
+ return CSS_NOMEM;
+ }
+
+ if (lerror == lwc_error_ok) {
+ hint->data.string = iurl;
+ hint->status = CSS_BACKGROUND_IMAGE_IMAGE;
+ return CSS_OK;
+ }
+
+ return CSS_PROPERTY_NOT_SET;
+}
+
+/* Exported function, documeted in css/hints.h */
+css_error node_presentational_hint(void *pw, void *node,
+ uint32_t property, css_hint *hint)
+{
+
+ switch (property) {
+ case CSS_PROP_BACKGROUND_IMAGE:
+ return node_presentational_hint_background_image(pw, node, hint);
+
+ case CSS_PROP_BACKGROUND_COLOR:
+ return node_presentational_hint_background_color(pw, node, hint);
+ case CSS_PROP_CAPTION_SIDE:
+ return node_presentational_hint_caption_side(pw, node, hint);
+
+ case CSS_PROP_COLOR:
+ return node_presentational_hint_color(pw, node, hint);
+
+ case CSS_PROP_FLOAT:
+ return node_presentational_hint_float(pw, node, hint);
+
+ case CSS_PROP_FONT_SIZE:
+ return node_presentational_hint_font_size(pw, node, hint);
+
+ case CSS_PROP_HEIGHT:
+ return node_presentational_hint_height(pw, node, hint);
+
+ case CSS_PROP_WIDTH:
+ return node_presentational_hint_width(pw, node, hint);
+
+ case CSS_PROP_BORDER_SPACING:
+ return node_presentational_hint_border_spacing(pw, node, hint);
+
+ case CSS_PROP_BORDER_TOP_COLOR :
+ case CSS_PROP_BORDER_RIGHT_COLOR :
+ case CSS_PROP_BORDER_BOTTOM_COLOR :
+ case CSS_PROP_BORDER_LEFT_COLOR :
+ return node_presentational_hint_border_trbl_color(pw, node, hint);
+
+ case CSS_PROP_BORDER_TOP_STYLE :
+ case CSS_PROP_BORDER_RIGHT_STYLE :
+ case CSS_PROP_BORDER_BOTTOM_STYLE :
+ case CSS_PROP_BORDER_LEFT_STYLE :
+ return node_presentational_hint_border_trbl_style(pw, node, hint);
+
+ case CSS_PROP_BORDER_TOP_WIDTH :
+ case CSS_PROP_BORDER_RIGHT_WIDTH :
+ case CSS_PROP_BORDER_BOTTOM_WIDTH :
+ case CSS_PROP_BORDER_LEFT_WIDTH :
+ return node_presentational_hint_border_trbl_width(pw, node, hint);
+
+ case CSS_PROP_MARGIN_TOP :
+ case CSS_PROP_MARGIN_BOTTOM :
+ return node_presentational_hint_margin_tb(pw, node, hint);
+
+ case CSS_PROP_MARGIN_RIGHT:
+ case CSS_PROP_MARGIN_LEFT:
+ return node_presentational_hint_margin_rl(pw, node, hint, property);
+
+ case CSS_PROP_PADDING_TOP:
+ case CSS_PROP_PADDING_RIGHT :
+ case CSS_PROP_PADDING_BOTTOM :
+ case CSS_PROP_PADDING_LEFT:
+ return node_presentational_hint_padding_trbl(pw, node, hint);
+
+ case CSS_PROP_TEXT_ALIGN:
+ return node_presentational_hint_text_align(pw, node, hint);
+
+ case CSS_PROP_VERTICAL_ALIGN:
+ return node_presentational_hint_vertical_align(pw, node, hint);
+ }
+
+ return CSS_PROPERTY_NOT_SET;
+}
+
diff --git a/css/hints.h b/css/hints.h
new file mode 100644
index 0000000..68d4c10
--- /dev/null
+++ b/css/hints.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 John-Mark Bell <jmb(a)netsurf-browser.org>
+ *
+ * This file is part of NetSurf,
http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <
http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_CSS_HINTS_H_
+#define NETSURF_CSS_HINTS_H_
+
+#include <stdint.h>
+
+#include "css/css.h"
+
+
+
+
+/**
+ * Callback to retrieve presentational hints for a node
+ *
+ * \param pw HTML document
+ * \param node DOM node
+ * \param property CSS property to retrieve
+ * \param hint Pointer to hint object to populate
+ * \return CSS_OK on success,
+ * CSS_PROPERTY_NOT_SET if there is no hint for the requested property,
+ * CSS_NOMEM on memory exhaustion.
+ */
+css_error node_presentational_hint(
+ void *pw,
+ void *node,
+ uint32_t property,
+ css_hint *hint);
+
+bool nscss_parse_colour(const char *data, css_color *result);
+
+#endif
diff --git a/css/select.c b/css/select.c
index 85c32b5..c9e5f7e 100644
--- a/css/select.c
+++ b/css/select.c
@@ -17,28 +17,23 @@
*/
#include <assert.h>
-#include <stdbool.h>
#include <string.h>
#include <strings.h>
-#include "content/content_protected.h"
#include "content/urldb.h"
#include "desktop/system_colour.h"
#include "utils/nsoption.h"
#include "utils/corestrings.h"
#include "utils/log.h"
-#include "utils/utils.h"
#include "css/internal.h"
+#include "css/hints.h"
#include "css/select.h"
-#include "css/utils.h"
static css_error node_name(void *pw, void *node, css_qname *qname);
static css_error node_classes(void *pw, void *node,
lwc_string ***classes, uint32_t *n_classes);
static css_error node_id(void *pw, void *node, lwc_string **id);
-static css_error named_ancestor_node(void *pw, void *node,
- const css_qname *qname, void **ancestor);
static css_error named_parent_node(void *pw, void *node,
const css_qname *qname, void **parent);
static css_error named_sibling_node(void *pw, void *node,
@@ -78,7 +73,6 @@ static css_error node_count_siblings(void *pw, void *node,
bool same_name, bool after, int32_t *count);
static css_error node_is_empty(void *pw, void *node, bool *match);
static css_error node_is_link(void *pw, void *node, bool *match);
-static css_error node_is_visited(void *pw, void *node, bool *match);
static css_error node_is_hover(void *pw, void *node, bool *match);
static css_error node_is_active(void *pw, void *node, bool *match);
static css_error node_is_focus(void *pw, void *node, bool *match);
@@ -88,8 +82,6 @@ static css_error node_is_checked(void *pw, void *node, bool *match);
static css_error node_is_target(void *pw, void *node, bool *match);
static css_error node_is_lang(void *pw, void *node,
lwc_string *lang, bool *match);
-static css_error node_presentational_hint(void *pw, void *node,
- uint32_t property, css_hint *hint);
static css_error ua_default_for_property(void *pw, uint32_t property,
css_hint *hint);
static css_error set_libcss_node_data(void *pw, void *node,
@@ -97,18 +89,9 @@ static css_error set_libcss_node_data(void *pw, void *node,
static css_error get_libcss_node_data(void *pw, void *node,
void **libcss_node_data);
-static int cmp_colour_name(const void *a, const void *b);
-static bool parse_named_colour(const char *data, css_color *result);
-static bool parse_dimension(const char *data, bool strict,
- css_fixed *length, css_unit *unit);
-static bool parse_number(const char *data, bool non_negative, bool real,
- css_fixed *value, size_t *consumed);
-static bool parse_font_size(const char *size, uint8_t *val,
- css_fixed *len, css_unit *unit);
+static css_error nscss_compute_font_size(void *pw, const css_hint *parent,
+ css_hint *size);
-static bool isWhitespace(char c);
-static bool isHex(char c);
-static uint8_t charToHex(char c);
/**
* Selection callback table for libcss
@@ -465,64 +448,6 @@ css_error nscss_compute_font_size(void *pw, const css_hint *parent,
return CSS_OK;
}
-/**
- * Parser for colours specified in attribute values.
- *
- * \param data Data to parse (NUL-terminated)
- * \param result Pointer to location to receive resulting css_color
- * \return true on success, false on invalid input
- */
-bool nscss_parse_colour(const char *data, css_color *result)
-{
- size_t len = strlen(data);
- uint8_t r, g, b;
-
- /* 2 */
- if (len == 0)
- return false;
-
- /* 3 */
- if (len == SLEN("transparent") && strcasecmp(data,
"transparent") == 0)
- return false;
-
- /* 4 */
- if (parse_named_colour(data, result))
- return true;
-
- /** \todo Implement HTML5's utterly insane legacy colour parsing */
-
- if (data[0] == '#') {
- data++;
- len--;
- }
-
- if (len == 3 && isHex(data[0]) && isHex(data[1]) &&
isHex(data[2])) {
- r = charToHex(data[0]);
- g = charToHex(data[1]);
- b = charToHex(data[2]);
-
- r |= (r << 4);
- g |= (g << 4);
- b |= (b << 4);
-
- *result = (0xff << 24) | (r << 16) | (g << 8) | b;
-
- return true;
- } else if (len == 6 && isHex(data[0]) && isHex(data[1]) &&
- isHex(data[2]) && isHex(data[3]) && isHex(data[4]) &&
- isHex(data[5])) {
- r = (charToHex(data[0]) << 4) | charToHex(data[1]);
- g = (charToHex(data[2]) << 4) | charToHex(data[3]);
- b = (charToHex(data[4]) << 4) | charToHex(data[5]);
-
- *result = (0xff << 24) | (r << 16) | (g << 8) | b;
-
- return true;
- }
-
- return false;
-}
-
/******************************************************************************
* Style selection callbacks *
******************************************************************************/
@@ -1844,1794 +1769,86 @@ css_error node_is_lang(void *pw, void *node,
return CSS_OK;
}
-static css_error
-node_presentational_hint_vertical_align(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_string *name;
- dom_string *valign = NULL;
- dom_exception err;
-
- err = dom_node_get_node_name(node, &name);
- if (err != DOM_NO_ERR)
- return CSS_PROPERTY_NOT_SET;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_col) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_thead) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_tbody) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_tfoot) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
- err = dom_element_get_attribute(node,
- corestring_dom_valign, &valign);
- if (err != DOM_NO_ERR || valign == NULL) {
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_top)) {
- hint->status = CSS_VERTICAL_ALIGN_TOP;
- } else if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_middle)) {
- hint->status = CSS_VERTICAL_ALIGN_MIDDLE;
- } else if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_bottom)) {
- hint->status = CSS_VERTICAL_ALIGN_BOTTOM;
- } else if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_baseline)) {
- hint->status = CSS_VERTICAL_ALIGN_BASELINE;
- } else {
- dom_string_unref(valign);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(valign);
- dom_string_unref(name);
-
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_applet) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_embed) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_iframe) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_img) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_object)) {
- /** \todo input[type=image][align=*] - $11.3.3 */
- err = dom_element_get_attribute(node,
- corestring_dom_align, &valign);
- if (err != DOM_NO_ERR || valign == NULL) {
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_top)) {
- hint->status = CSS_VERTICAL_ALIGN_TOP;
- } else if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_bottom) ||
- dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_baseline)) {
- hint->status = CSS_VERTICAL_ALIGN_BASELINE;
- } else if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_texttop)) {
- hint->status = CSS_VERTICAL_ALIGN_TEXT_TOP;
- } else if (dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_absmiddle) ||
- dom_string_caseless_lwc_isequal(valign,
- corestring_lwc_abscenter)) {
- hint->status = CSS_VERTICAL_ALIGN_MIDDLE;
- } else {
- dom_string_unref(valign);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(valign);
- dom_string_unref(name);
-
- return CSS_OK;
- }
-
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_text_align(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
+/**
+ * Callback to retrieve the User-Agent defaults for a CSS property.
+ *
+ * \param pw HTML document
+ * \param property Property to retrieve defaults for
+ * \param hint Pointer to hint object to populate
+ * \return CSS_OK on success,
+ * CSS_INVALID if the property should not have a user-agent default.
+ */
+css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint)
{
- dom_string *name;
- dom_string *align = NULL;
- dom_exception err;
-
- err = dom_node_get_node_name(node, &name);
- if (err != DOM_NO_ERR)
- return CSS_PROPERTY_NOT_SET;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_p) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_h1) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_h2) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_h3) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_h4) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_h5) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_h6)) {
- err = dom_element_get_attribute(node,
- corestring_dom_align, &align);
- if (err != DOM_NO_ERR || align == NULL) {
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_left)) {
- hint->status = CSS_TEXT_ALIGN_LEFT;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_center)) {
- hint->status = CSS_TEXT_ALIGN_CENTER;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_right)) {
- hint->status = CSS_TEXT_ALIGN_RIGHT;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_justify)) {
- hint->status = CSS_TEXT_ALIGN_JUSTIFY;
- } else {
- dom_string_unref(align);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(align);
- dom_string_unref(name);
-
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_center)) {
- hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
-
- dom_string_unref(name);
-
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_caption)) {
- err = dom_element_get_attribute(node,
- corestring_dom_align, &align);
- if (err != DOM_NO_ERR) {
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (align == NULL || dom_string_caseless_lwc_isequal(align,
- corestring_lwc_center)) {
- hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_left)) {
- hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_right)) {
- hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_justify)) {
- hint->status = CSS_TEXT_ALIGN_JUSTIFY;
- } else {
- dom_string_unref(align);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (align != NULL)
- dom_string_unref(align);
- dom_string_unref(name);
-
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_div) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_thead) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_tbody) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_tfoot) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_tr) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name,
- corestring_lwc_th)) {
- err = dom_element_get_attribute(node,
- corestring_dom_align, &align);
- if (err != DOM_NO_ERR || align == NULL) {
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_center)) {
- hint->status = CSS_TEXT_ALIGN_LIBCSS_CENTER;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_left)) {
- hint->status = CSS_TEXT_ALIGN_LIBCSS_LEFT;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_right)) {
- hint->status = CSS_TEXT_ALIGN_LIBCSS_RIGHT;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_justify)) {
- hint->status = CSS_TEXT_ALIGN_JUSTIFY;
- } else {
- dom_string_unref(align);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
+ if (property == CSS_PROP_COLOR) {
+ hint->data.color = 0xff000000;
+ hint->status = CSS_COLOR_COLOR;
+ } else if (property == CSS_PROP_FONT_FAMILY) {
+ hint->data.strings = NULL;
+ switch (nsoption_int(font_default)) {
+ case PLOT_FONT_FAMILY_SANS_SERIF:
+ hint->status = CSS_FONT_FAMILY_SANS_SERIF;
+ break;
+ case PLOT_FONT_FAMILY_SERIF:
+ hint->status = CSS_FONT_FAMILY_SERIF;
+ break;
+ case PLOT_FONT_FAMILY_MONOSPACE:
+ hint->status = CSS_FONT_FAMILY_MONOSPACE;
+ break;
+ case PLOT_FONT_FAMILY_CURSIVE:
+ hint->status = CSS_FONT_FAMILY_CURSIVE;
+ break;
+ case PLOT_FONT_FAMILY_FANTASY:
+ hint->status = CSS_FONT_FAMILY_FANTASY;
+ break;
}
-
- dom_string_unref(align);
- dom_string_unref(name);
-
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_table)) {
- /* Tables usually reset alignment */
- hint->status = CSS_TEXT_ALIGN_INHERIT_IF_NON_MAGIC;
-
- dom_string_unref(name);
-
- return CSS_OK;
+ } else if (property == CSS_PROP_QUOTES) {
+ /** \todo Not exactly useful :) */
+ hint->data.strings = NULL;
+ hint->status = CSS_QUOTES_NONE;
+ } else if (property == CSS_PROP_VOICE_FAMILY) {
+ /** \todo Fix this when we have voice-family done */
+ hint->data.strings = NULL;
+ hint->status = 0;
} else {
- dom_string_unref(name);
-
- return CSS_PROPERTY_NOT_SET;
- }
-
-}
-
-static css_error
-node_presentational_hint_padding_trbl(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_string *name;
- dom_exception exc;
- dom_string *cellpadding = NULL;
- css_error result = CSS_PROPERTY_NOT_SET;
-
- exc = dom_node_get_node_name(node, &name);
- if (exc != DOM_NO_ERR)
- return CSS_BADPARM;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
- css_qname qs;
- dom_node *tablenode = NULL;
- qs.ns = NULL;
- qs.name = lwc_string_ref(corestring_lwc_table);
- if (named_ancestor_node(ctx, node, &qs,
- (void *)&tablenode) != CSS_OK) {
- /* Didn't find, or had error */
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- lwc_string_unref(qs.name);
-
- if (tablenode != NULL) {
- exc = dom_element_get_attribute(tablenode,
- corestring_dom_cellpadding,
- &cellpadding);
- if (exc != DOM_NO_ERR) {
- dom_string_unref(name);
- return CSS_BADPARM;
- }
- }
- /* No need to unref tablenode, named_ancestor_node does not
- * return a reffed node to the CSS
- */
+ return CSS_INVALID;
}
-
- dom_string_unref(name);
- if (cellpadding != NULL) {
- if (parse_dimension(dom_string_data(cellpadding), false,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- hint->status = CSS_PADDING_SET;
- result = CSS_OK;
- }
- dom_string_unref(cellpadding);
- }
-
- return result;
+ return CSS_OK;
}
-static css_error
-node_presentational_hint_margin_rl(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint,
- uint32_t property)
+css_error set_libcss_node_data(void *pw, void *node, void *libcss_node_data)
{
- dom_string *n;
- dom_exception exc;
-
- exc = dom_node_get_node_name(node, &n);
- if (exc != DOM_NO_ERR)
- return CSS_BADPARM;
-
- if (dom_string_caseless_lwc_isequal(n, corestring_lwc_img) ||
- dom_string_caseless_lwc_isequal(n, corestring_lwc_applet)) {
- dom_string_unref(n);
- exc = dom_element_get_attribute(node,
- corestring_dom_hspace, &n);
- if (exc != DOM_NO_ERR) {
- return CSS_BADPARM;
- }
-
- if (n == NULL)
- return CSS_PROPERTY_NOT_SET;
-
- if (parse_dimension(dom_string_data(n), false,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- hint->status = CSS_MARGIN_SET;
- } else {
- dom_string_unref(n);
- return CSS_PROPERTY_NOT_SET;
- }
- dom_string_unref(n);
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_table) ||
- dom_string_caseless_lwc_isequal(n, corestring_lwc_align)) {
- dom_string_unref(n);
- exc = dom_element_get_attribute(node,
- corestring_dom_align, &n);
- if (exc != DOM_NO_ERR) {
- return CSS_BADPARM;
- }
-
- if (n == NULL)
- return CSS_PROPERTY_NOT_SET;
-
- if (dom_string_caseless_lwc_isequal(n,
- corestring_lwc_center) ||
- dom_string_caseless_lwc_isequal(n,
- corestring_lwc_abscenter) ||
- dom_string_caseless_lwc_isequal(n,
- corestring_lwc_middle) ||
- dom_string_caseless_lwc_isequal(n,
- corestring_lwc_absmiddle)) {
- hint->status = CSS_MARGIN_AUTO;
- } else {
- dom_string_unref(n);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(n);
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(n, corestring_lwc_hr)) {
- dom_string_unref(n);
- exc = dom_element_get_attribute(node,
- corestring_dom_align, &n);
- if (exc != DOM_NO_ERR)
- return CSS_BADPARM;
-
- if (n == NULL)
- return CSS_PROPERTY_NOT_SET;
-
- if (dom_string_caseless_lwc_isequal(n,
- corestring_lwc_left)) {
- if (property == CSS_PROP_MARGIN_LEFT) {
- hint->data.length.value = 0;
- hint->data.length.unit = CSS_UNIT_PX;
- hint->status = CSS_MARGIN_SET;
- } else {
- hint->status = CSS_MARGIN_AUTO;
- }
- } else if (dom_string_caseless_lwc_isequal(n,
- corestring_lwc_center)) {
- hint->status = CSS_MARGIN_AUTO;
- } else if (dom_string_caseless_lwc_isequal(n,
- corestring_lwc_right)) {
- if (property == CSS_PROP_MARGIN_RIGHT) {
- hint->data.length.value = 0;
- hint->data.length.unit = CSS_UNIT_PX;
- hint->status = CSS_MARGIN_SET;
- } else {
- hint->status = CSS_MARGIN_AUTO;
- }
- } else {
- dom_string_unref(n);
- return CSS_PROPERTY_NOT_SET;
- }
- dom_string_unref(n);
-
- return CSS_OK;
- }
-
- dom_string_unref(n);
-
- return CSS_PROPERTY_NOT_SET;
-}
+ dom_node *n = node;
+ dom_exception err;
+ void *old_node_data;
-static css_error
-node_presentational_hint_margin_tb(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_string *name, *vspace = NULL;
- dom_exception exc;
-
- exc = dom_node_get_node_name(node, &name);
- if (exc != DOM_NO_ERR)
- return CSS_BADPARM;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_img) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) {
- exc = dom_element_get_attribute(node, corestring_dom_vspace,
- &vspace);
- if (exc != DOM_NO_ERR) {
- dom_string_unref(name);
- return CSS_BADPARM;
- }
- }
-
- dom_string_unref(name);
-
- if (vspace == NULL)
- return CSS_PROPERTY_NOT_SET;
-
- if (parse_dimension(dom_string_data(vspace), false,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- hint->status = CSS_MARGIN_SET;
- } else {
- dom_string_unref(vspace);
- return CSS_PROPERTY_NOT_SET;
+ /* Set this node's node data */
+ err = dom_node_set_user_data(n,
+ corestring_dom___ns_key_libcss_node_data,
+ libcss_node_data, nscss_dom_user_data_handler,
+ (void *) &old_node_data);
+ if (err != DOM_NO_ERR) {
+ return CSS_NOMEM;
}
- dom_string_unref(vspace);
+ assert(old_node_data == NULL);
return CSS_OK;
}
-static css_error
-node_presentational_hint_border_trbl_width(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
+css_error get_libcss_node_data(void *pw, void *node, void **libcss_node_data)
{
- dom_string *name;
- dom_exception exc;
- dom_string *width = NULL;
- bool is_table_cell = false;
-
- exc = dom_node_get_node_name(node, &name);
- if (exc != DOM_NO_ERR)
- return CSS_BADPARM;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
- css_qname qs;
- dom_node *tablenode = NULL;
- qs.ns = NULL;
- qs.name = lwc_string_ref(corestring_lwc_table);
- if (named_ancestor_node(ctx, node, &qs,
- (void *)&tablenode) != CSS_OK) {
- /* Didn't find, or had error */
- lwc_string_unref(qs.name);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- lwc_string_unref(qs.name);
- if (tablenode != NULL) {
- exc = dom_element_get_attribute(tablenode,
- corestring_dom_border, &width);
- if (exc != DOM_NO_ERR) {
- dom_string_unref(name);
- return CSS_BADPARM;
- }
- }
- /* No need to unref tablenode, named_ancestor_node does not
- * return a reffed node to the CSS
- */
- is_table_cell = true;
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_table)) {
- exc = dom_element_get_attribute(node, corestring_dom_border,
- &width);
- if (exc != DOM_NO_ERR) {
- dom_string_unref(name);
- return CSS_BADPARM;
- }
- }
-
- dom_string_unref(name);
-
- if (width == NULL)
- return CSS_PROPERTY_NOT_SET;
-
- if (parse_dimension(dom_string_data(width), false,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- if (is_table_cell &&
- INTTOFIX(0) !=
- hint->data.length.value) {
- hint->data.length.value = INTTOFIX(1);
- hint->data.length.unit = CSS_UNIT_PX;
- }
- hint->status = CSS_BORDER_WIDTH_WIDTH;
- } else {
- dom_string_unref(width);
- return CSS_PROPERTY_NOT_SET;
- }
+ dom_node *n = node;
+ dom_exception err;
- dom_string_unref(width);
+ /* Get this node's node data */
+ err = dom_node_get_user_data(n,
+ corestring_dom___ns_key_libcss_node_data,
+ libcss_node_data);
+ if (err != DOM_NO_ERR) {
+ return CSS_NOMEM;
+ }
return CSS_OK;
}
-
-static css_error
-node_presentational_hint_border_trbl_style(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_string *name;
- dom_exception exc;
-
- exc = dom_node_get_node_name(node, &name);
- if (exc != DOM_NO_ERR)
- return CSS_BADPARM;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
- css_qname qs;
- dom_node *tablenode = NULL;
- qs.ns = NULL;
- qs.name = lwc_string_ref(corestring_lwc_table);
-
- if (named_ancestor_node(ctx, node, &qs,
- (void *)&tablenode) != CSS_OK) {
- /* Didn't find, or had error */
- lwc_string_unref(qs.name);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- lwc_string_unref(qs.name);
-
- if (tablenode != NULL) {
- bool has_border = false;
-
- exc = dom_element_has_attribute(tablenode,
- corestring_dom_border,
- &has_border);
- if (exc != DOM_NO_ERR) {
- dom_string_unref(name);
- return CSS_BADPARM;
- }
-
- if (has_border) {
- hint->status = CSS_BORDER_STYLE_INSET;
- dom_string_unref(name);
- return CSS_OK;
- }
- }
- /* No need to unref tablenode, named_ancestor_node does not
- * return a reffed node to the CSS
- */
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_table)) {
- bool has_border = false;
-
- exc = dom_element_has_attribute(node,
- corestring_dom_border,
- &has_border);
- if (exc != DOM_NO_ERR) {
- dom_string_unref(name);
- return CSS_BADPARM;
- }
-
- if (has_border) {
- hint->status = CSS_BORDER_STYLE_OUTSET;
- dom_string_unref(name);
- return CSS_OK;
- }
- }
-
- dom_string_unref(name);
-
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_border_trbl_color(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_string *name;
- dom_string *bordercolor = NULL;
- dom_exception err;
-
- err = dom_node_get_node_name(node, &name);
- if (err != DOM_NO_ERR)
- return CSS_PROPERTY_NOT_SET;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_th)) {
- css_qname qs;
- dom_node *tablenode = NULL;
- qs.ns = NULL;
- qs.name = lwc_string_ref(corestring_lwc_table);
-
- if (named_ancestor_node(ctx, node, &qs,
- (void *)&tablenode) != CSS_OK) {
- /* Didn't find, or had error */
- lwc_string_unref(qs.name);
- dom_string_unref(name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- lwc_string_unref(qs.name);
-
- if (tablenode != NULL) {
- err = dom_element_get_attribute(node,
- corestring_dom_bordercolor,
- &bordercolor);
- }
- /* No need to unref tablenode, named_ancestor_node does not
- * return a reffed node to the CSS
- */
-
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_table)) {
- err = dom_element_get_attribute(node,
- corestring_dom_bordercolor,
- &bordercolor);
- }
-
- dom_string_unref(name);
-
- if ((err != DOM_NO_ERR) || (bordercolor == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (nscss_parse_colour((const char *)dom_string_data(bordercolor),
- &hint->data.color)) {
- hint->status = CSS_BORDER_COLOR_COLOR;
- dom_string_unref(bordercolor);
- return CSS_OK;
- }
-
- dom_string_unref(bordercolor);
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_border_spacing(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_exception err;
- dom_string *node_name = NULL;
- dom_string *cellspacing = NULL;
-
- err = dom_node_get_node_name(node, &node_name);
- if ((err != DOM_NO_ERR) || (node_name == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (!dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_table)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(node_name);
-
- err = dom_element_get_attribute(node,
- corestring_dom_cellspacing, &cellspacing);
- if ((err != DOM_NO_ERR) || (cellspacing == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
-
- if (parse_dimension((const char *)dom_string_data(cellspacing),
- false,
- &hint->data.position.h.value,
- &hint->data.position.h.unit)) {
-
- hint->data.position.v = hint->data.position.h;
- hint->status = CSS_BORDER_SPACING_SET;
-
- dom_string_unref(cellspacing);
- return CSS_OK;
- }
-
- dom_string_unref(cellspacing);
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_width(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_string *name;
- dom_string *width = NULL;
- dom_exception err;
- bool textarea = false;
- bool input = false;
-
- err = dom_node_get_node_name(node, &name);
- if (err != DOM_NO_ERR)
- return CSS_PROPERTY_NOT_SET;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_hr) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_img) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_object) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_table) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_th) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) {
- err = dom_element_get_attribute(node,
- corestring_dom_width, &width);
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_textarea)) {
- textarea = true;
- err = dom_element_get_attribute(node,
- corestring_dom_cols, &width);
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_input)) {
- input = true;
- err = dom_element_get_attribute(node,
- corestring_dom_size, &width);
- }
-
- dom_string_unref(name);
-
- if ((err != DOM_NO_ERR) || (width == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (parse_dimension((const char *)dom_string_data(width),
- false,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- hint->status = CSS_WIDTH_SET;
- dom_string_unref(width);
-
- if (textarea) {
- hint->data.length.unit = CSS_UNIT_EX;
- }
-
- if (input) {
- err = dom_element_get_attribute(node,
- corestring_dom_type, &width);
- if (err != DOM_NO_ERR) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if ((width == NULL) ||
- dom_string_caseless_lwc_isequal(width,
- corestring_lwc_text) ||
- dom_string_caseless_lwc_isequal(width,
- corestring_lwc_search) ||
- dom_string_caseless_lwc_isequal(width,
- corestring_lwc_file) ||
- dom_string_caseless_lwc_isequal(width,
- corestring_lwc_password)) {
- hint->data.length.unit = CSS_UNIT_EX;
- }
- dom_string_unref(width);
- }
-
- return CSS_OK;
- }
-
- dom_string_unref(width);
- return CSS_PROPERTY_NOT_SET;
-
-}
-
-static css_error
-node_presentational_hint_height(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_string *name;
- dom_string *height = NULL;
- dom_exception err;
- bool textarea = false;
-
- err = dom_node_get_node_name(node, &name);
- if (err != DOM_NO_ERR)
- return CSS_PROPERTY_NOT_SET;
-
- if (dom_string_caseless_lwc_isequal(name, corestring_lwc_iframe) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_td) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_th) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_tr) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_img) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_object) ||
- dom_string_caseless_lwc_isequal(name, corestring_lwc_applet)) {
- err = dom_element_get_attribute(node,
- corestring_dom_height, &height);
- } else if (dom_string_caseless_lwc_isequal(name,
- corestring_lwc_textarea)) {
- textarea = true;
- err = dom_element_get_attribute(node,
- corestring_dom_rows, &height);
- }
-
- dom_string_unref(name);
-
- if ((err != DOM_NO_ERR) || (height == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (parse_dimension((const char *)dom_string_data(height),
- false,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- hint->status = CSS_HEIGHT_SET;
-
- if (textarea) {
- hint->data.length.unit = CSS_UNIT_EM;
- }
-
- dom_string_unref(height);
- return CSS_OK;
- }
-
- dom_string_unref(height);
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_font_size(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_exception err;
- dom_string *node_name = NULL;
- dom_string *size;
-
- err = dom_node_get_node_name(node, &node_name);
- if ((err != DOM_NO_ERR) || (node_name == NULL)) {
- return CSS_NOMEM;
- }
-
- if (!dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_font)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(node_name);
-
- err = dom_element_get_attribute(node, corestring_dom_size, &size);
- if ((err != DOM_NO_ERR) || (size == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (parse_font_size((const char *)dom_string_data(size),
- &hint->status,
- &hint->data.length.value,
- &hint->data.length.unit)) {
- dom_string_unref(size);
- return CSS_OK;
- }
-
- dom_string_unref(size);
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_float(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_exception err;
- dom_string *node_name = NULL;
- dom_string *align;
-
- err = dom_node_get_node_name(node, &node_name);
- if ((err != DOM_NO_ERR) || (node_name == NULL)) {
- return CSS_NOMEM;
- }
-
- /** \todo input[type=image][align=*] - $11.3.3 */
- if (!dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_table) &&
- !dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_applet) &&
- !dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_embed) &&
- !dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_iframe) &&
- !dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_img) &&
- !dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_object)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(node_name);
-
- err = dom_element_get_attribute(node, corestring_dom_align, &align);
- if ((err != DOM_NO_ERR) || (align == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_left)) {
- hint->status = CSS_FLOAT_LEFT;
- dom_string_unref(align);
- return CSS_OK;
- } else if (dom_string_caseless_lwc_isequal(align,
- corestring_lwc_right)) {
- hint->status = CSS_FLOAT_RIGHT;
- dom_string_unref(align);
- return CSS_OK;
- }
-
- dom_string_unref(align);
-
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_color(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- css_error error;
- dom_exception err;
- dom_string *node_name = NULL;
- dom_string *color;
-
- err = dom_node_get_node_name(node, &node_name);
- if ((err != DOM_NO_ERR) || (node_name == NULL)) {
- return CSS_NOMEM;
- }
-
- if (dom_string_caseless_lwc_isequal(node_name, corestring_lwc_a)) {
- /* find body node */
- css_qname qs;
- dom_node *bodynode = NULL;
- bool is_visited;
-
- qs.ns = NULL;
- qs.name = lwc_string_ref(corestring_lwc_body);
- if (named_ancestor_node(ctx, node, &qs,
- (void *)&bodynode) != CSS_OK) {
- /* Didn't find, or had error */
- lwc_string_unref(qs.name);
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- lwc_string_unref(qs.name);
-
- /* deal with missing body ancestor */
- if (bodynode == NULL) {
- dom_string_unref(node_name);
- return CSS_BADPARM;
- }
-
- error = node_is_visited(ctx, node, &is_visited);
- if (error != CSS_OK)
- return error;
-
- if (is_visited) {
- err = dom_element_get_attribute(bodynode,
- corestring_dom_vlink, &color);
- if ((err != DOM_NO_ERR) || (color == NULL)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
- } else {
- err = dom_element_get_attribute(bodynode,
- corestring_dom_link, &color);
- if ((err != DOM_NO_ERR) || (color == NULL)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
- }
- } else if (dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_body)) {
- err = dom_element_get_attribute(node,
- corestring_dom_text, &color);
- if ((err != DOM_NO_ERR) || (color == NULL)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
- } else {
- err = dom_element_get_attribute(node,
- corestring_dom_color, &color);
- if ((err != DOM_NO_ERR) || (color == NULL)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
- }
-
- if (!nscss_parse_colour((const char *)dom_string_data(color),
- &hint->data.color)) {
- dom_string_unref(color);
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- hint->status = CSS_COLOR_COLOR;
-
- dom_string_unref(color);
- dom_string_unref(node_name);
-
- return CSS_OK;
-}
-
-static css_error
-node_presentational_hint_caption_side(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_exception err;
- dom_string *node_name = NULL;
- dom_string *align = NULL;
-
- err = dom_node_get_node_name(node, &node_name);
- if ((err != DOM_NO_ERR) || (node_name == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (!dom_string_caseless_lwc_isequal(node_name,
- corestring_lwc_caption)) {
- dom_string_unref(node_name);
- return CSS_PROPERTY_NOT_SET;
- }
-
- dom_string_unref(node_name);
-
- err = dom_element_get_attribute(node, corestring_dom_align, &align);
- if ((err != DOM_NO_ERR) || (align == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (dom_string_caseless_lwc_isequal(align, corestring_lwc_bottom)) {
- hint->status = CSS_CAPTION_SIDE_BOTTOM;
- dom_string_unref(align);
- return CSS_OK;
- }
-
- dom_string_unref(align);
-
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_background_color(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_exception err;
- dom_string *bgcolor;
-
- err = dom_element_get_attribute(node,
- corestring_dom_bgcolor, &bgcolor);
- if ((err != DOM_NO_ERR) || (bgcolor == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- if (nscss_parse_colour((const char *)dom_string_data(bgcolor),
- &hint->data.color)) {
- hint->status = CSS_BACKGROUND_COLOR_COLOR;
- dom_string_unref(bgcolor);
- return CSS_OK;
- }
-
- dom_string_unref(bgcolor);
-
- return CSS_PROPERTY_NOT_SET;
-}
-
-static css_error
-node_presentational_hint_background_image(nscss_select_ctx *ctx,
- dom_node *node,
- css_hint *hint)
-{
- dom_exception err;
- dom_string *atr_val;
- nserror error;
- nsurl *url;
- lwc_string *iurl;
- lwc_error lerror;
-
- err = dom_element_get_attribute(node,
- corestring_dom_background, &atr_val);
- if ((err != DOM_NO_ERR) || (atr_val == NULL)) {
- return CSS_PROPERTY_NOT_SET;
- }
-
- error = nsurl_join(ctx->base_url,
- (const char *)dom_string_data(atr_val), &url);
-
- dom_string_unref(atr_val);
-
- if (error != NSERROR_OK) {
- return CSS_NOMEM;
- }
-
- lerror = lwc_intern_string(nsurl_access(url),
- nsurl_length(url), &iurl);
-
- nsurl_unref(url);
-
- if (lerror == lwc_error_oom) {
- return CSS_NOMEM;
- }
-
- if (lerror == lwc_error_ok) {
- hint->data.string = iurl;
- hint->status = CSS_BACKGROUND_IMAGE_IMAGE;
- return CSS_OK;
- }
-
- return CSS_PROPERTY_NOT_SET;
-}
-
-/**
- * Callback to retrieve presentational hints for a node
- *
- * \param pw HTML document
- * \param node DOM node
- * \param property CSS property to retrieve
- * \param hint Pointer to hint object to populate
- * \return CSS_OK on success,
- * CSS_PROPERTY_NOT_SET if there is no hint for the requested property,
- * CSS_NOMEM on memory exhaustion.
- */
-css_error node_presentational_hint(void *pw, void *node,
- uint32_t property, css_hint *hint)
-{
-
- switch (property) {
- case CSS_PROP_BACKGROUND_IMAGE:
- return node_presentational_hint_background_image(pw, node, hint);
-
- case CSS_PROP_BACKGROUND_COLOR:
- return node_presentational_hint_background_color(pw, node, hint);
- case CSS_PROP_CAPTION_SIDE:
- return node_presentational_hint_caption_side(pw, node, hint);
-
- case CSS_PROP_COLOR:
- return node_presentational_hint_color(pw, node, hint);
-
- case CSS_PROP_FLOAT:
- return node_presentational_hint_float(pw, node, hint);
-
- case CSS_PROP_FONT_SIZE:
- return node_presentational_hint_font_size(pw, node, hint);
-
- case CSS_PROP_HEIGHT:
- return node_presentational_hint_height(pw, node, hint);
-
- case CSS_PROP_WIDTH:
- return node_presentational_hint_width(pw, node, hint);
-
- case CSS_PROP_BORDER_SPACING:
- return node_presentational_hint_border_spacing(pw, node, hint);
-
- case CSS_PROP_BORDER_TOP_COLOR :
- case CSS_PROP_BORDER_RIGHT_COLOR :
- case CSS_PROP_BORDER_BOTTOM_COLOR :
- case CSS_PROP_BORDER_LEFT_COLOR :
- return node_presentational_hint_border_trbl_color(pw, node, hint);
-
- case CSS_PROP_BORDER_TOP_STYLE :
- case CSS_PROP_BORDER_RIGHT_STYLE :
- case CSS_PROP_BORDER_BOTTOM_STYLE :
- case CSS_PROP_BORDER_LEFT_STYLE :
- return node_presentational_hint_border_trbl_style(pw, node, hint);
-
- case CSS_PROP_BORDER_TOP_WIDTH :
- case CSS_PROP_BORDER_RIGHT_WIDTH :
- case CSS_PROP_BORDER_BOTTOM_WIDTH :
- case CSS_PROP_BORDER_LEFT_WIDTH :
- return node_presentational_hint_border_trbl_width(pw, node, hint);
-
- case CSS_PROP_MARGIN_TOP :
- case CSS_PROP_MARGIN_BOTTOM :
- return node_presentational_hint_margin_tb(pw, node, hint);
-
- case CSS_PROP_MARGIN_RIGHT:
- case CSS_PROP_MARGIN_LEFT:
- return node_presentational_hint_margin_rl(pw, node, hint, property);
-
- case CSS_PROP_PADDING_TOP:
- case CSS_PROP_PADDING_RIGHT :
- case CSS_PROP_PADDING_BOTTOM :
- case CSS_PROP_PADDING_LEFT:
- return node_presentational_hint_padding_trbl(pw, node, hint);
-
- case CSS_PROP_TEXT_ALIGN:
- return node_presentational_hint_text_align(pw, node, hint);
-
- case CSS_PROP_VERTICAL_ALIGN:
- return node_presentational_hint_vertical_align(pw, node, hint);
- }
-
- return CSS_PROPERTY_NOT_SET;
-}
-
-/**
- * Callback to retrieve the User-Agent defaults for a CSS property.
- *
- * \param pw HTML document
- * \param property Property to retrieve defaults for
- * \param hint Pointer to hint object to populate
- * \return CSS_OK on success,
- * CSS_INVALID if the property should not have a user-agent default.
- */
-css_error ua_default_for_property(void *pw, uint32_t property, css_hint *hint)
-{
- if (property == CSS_PROP_COLOR) {
- hint->data.color = 0xff000000;
- hint->status = CSS_COLOR_COLOR;
- } else if (property == CSS_PROP_FONT_FAMILY) {
- hint->data.strings = NULL;
- switch (nsoption_int(font_default)) {
- case PLOT_FONT_FAMILY_SANS_SERIF:
- hint->status = CSS_FONT_FAMILY_SANS_SERIF;
- break;
- case PLOT_FONT_FAMILY_SERIF:
- hint->status = CSS_FONT_FAMILY_SERIF;
- break;
- case PLOT_FONT_FAMILY_MONOSPACE:
- hint->status = CSS_FONT_FAMILY_MONOSPACE;
- break;
- case PLOT_FONT_FAMILY_CURSIVE:
- hint->status = CSS_FONT_FAMILY_CURSIVE;
- break;
- case PLOT_FONT_FAMILY_FANTASY:
- hint->status = CSS_FONT_FAMILY_FANTASY;
- break;
- }
- } else if (property == CSS_PROP_QUOTES) {
- /** \todo Not exactly useful :) */
- hint->data.strings = NULL;
- hint->status = CSS_QUOTES_NONE;
- } else if (property == CSS_PROP_VOICE_FAMILY) {
- /** \todo Fix this when we have voice-family done */
- hint->data.strings = NULL;
- hint->status = 0;
- } else {
- return CSS_INVALID;
- }
-
- return CSS_OK;
-}
-
-css_error set_libcss_node_data(void *pw, void *node, void *libcss_node_data)
-{
- dom_node *n = node;
- dom_exception err;
- void *old_node_data;
-
- /* Set this node's node data */
- err = dom_node_set_user_data(n,
- corestring_dom___ns_key_libcss_node_data,
- libcss_node_data, nscss_dom_user_data_handler,
- (void *) &old_node_data);
- if (err != DOM_NO_ERR) {
- return CSS_NOMEM;
- }
-
- assert(old_node_data == NULL);
-
- return CSS_OK;
-}
-
-css_error get_libcss_node_data(void *pw, void *node, void **libcss_node_data)
-{
- dom_node *n = node;
- dom_exception err;
-
- /* Get this node's node data */
- err = dom_node_get_user_data(n,
- corestring_dom___ns_key_libcss_node_data,
- libcss_node_data);
- if (err != DOM_NO_ERR) {
- return CSS_NOMEM;
- }
-
- return CSS_OK;
-}
-
-/**
- * Mapping of colour name to CSS color
- */
-struct colour_map {
- const char *name;
- css_color color;
-};
-
-/**
- * Name comparator for named colour matching
- *
- * \param a Name to match
- * \param b Colour map entry to consider
- * \return 0 on match,
- * < 0 if a < b,
- * > 0 if b > a.
- */
-int cmp_colour_name(const void *a, const void *b)
-{
- const char *aa = a;
- const struct colour_map *bb = b;
-
- return strcasecmp(aa, bb->name);
-}
-
-/**
- * Parse a named colour
- *
- * \param name Name to parse
- * \param result Pointer to location to receive css_color
- * \return true on success, false on invalid input
- */
-bool parse_named_colour(const char *name, css_color *result)
-{
- static const struct colour_map named_colours[] = {
- { "aliceblue", 0xfff0f8ff },
- { "antiquewhite", 0xfffaebd7 },
- { "aqua", 0xff00ffff },
- { "aquamarine", 0xff7fffd4 },
- { "azure", 0xfff0ffff },
- { "beige", 0xfff5f5dc },
- { "bisque", 0xffffe4c4 },
- { "black", 0xff000000 },
- { "blanchedalmond", 0xffffebcd },
- { "blue", 0xff0000ff },
- { "blueviolet", 0xff8a2be2 },
- { "brown", 0xffa52a2a },
- { "burlywood", 0xffdeb887 },
- { "cadetblue", 0xff5f9ea0 },
- { "chartreuse", 0xff7fff00 },
- { "chocolate", 0xffd2691e },
- { "coral", 0xffff7f50 },
- { "cornflowerblue", 0xff6495ed },
- { "cornsilk", 0xfffff8dc },
- { "crimson", 0xffdc143c },
- { "cyan", 0xff00ffff },
- { "darkblue", 0xff00008b },
- { "darkcyan", 0xff008b8b },
- { "darkgoldenrod", 0xffb8860b },
- { "darkgray", 0xffa9a9a9 },
- { "darkgreen", 0xff006400 },
- { "darkgrey", 0xffa9a9a9 },
- { "darkkhaki", 0xffbdb76b },
- { "darkmagenta", 0xff8b008b },
- { "darkolivegreen", 0xff556b2f },
- { "darkorange", 0xffff8c00 },
- { "darkorchid", 0xff9932cc },
- { "darkred", 0xff8b0000 },
- { "darksalmon", 0xffe9967a },
- { "darkseagreen", 0xff8fbc8f },
- { "darkslateblue", 0xff483d8b },
- { "darkslategray", 0xff2f4f4f },
- { "darkslategrey", 0xff2f4f4f },
- { "darkturquoise", 0xff00ced1 },
- { "darkviolet", 0xff9400d3 },
- { "deeppink", 0xffff1493 },
- { "deepskyblue", 0xff00bfff },
- { "dimgray", 0xff696969 },
- { "dimgrey", 0xff696969 },
- { "dodgerblue", 0xff1e90ff },
- { "feldspar", 0xffd19275 },
- { "firebrick", 0xffb22222 },
- { "floralwhite", 0xfffffaf0 },
- { "forestgreen", 0xff228b22 },
- { "fuchsia", 0xffff00ff },
- { "gainsboro", 0xffdcdcdc },
- { "ghostwhite", 0xfff8f8ff },
- { "gold", 0xffffd700 },
- { "goldenrod", 0xffdaa520 },
- { "gray", 0xff808080 },
- { "green", 0xff008000 },
- { "greenyellow", 0xffadff2f },
- { "grey", 0xff808080 },
- { "honeydew", 0xfff0fff0 },
- { "hotpink", 0xffff69b4 },
- { "indianred", 0xffcd5c5c },
- { "indigo", 0xff4b0082 },
- { "ivory", 0xfffffff0 },
- { "khaki", 0xfff0e68c },
- { "lavender", 0xffe6e6fa },
- { "lavenderblush", 0xfffff0f5 },
- { "lawngreen", 0xff7cfc00 },
- { "lemonchiffon", 0xfffffacd },
- { "lightblue", 0xffadd8e6 },
- { "lightcoral", 0xfff08080 },
- { "lightcyan", 0xffe0ffff },
- { "lightgoldenrodyellow", 0xfffafad2 },
- { "lightgray", 0xffd3d3d3 },
- { "lightgreen", 0xff90ee90 },
- { "lightgrey", 0xffd3d3d3 },
- { "lightpink", 0xffffb6c1 },
- { "lightsalmon", 0xffffa07a },
- { "lightseagreen", 0xff20b2aa },
- { "lightskyblue", 0xff87cefa },
- { "lightslateblue", 0xff8470ff },
- { "lightslategray", 0xff778899 },
- { "lightslategrey", 0xff778899 },
- { "lightsteelblue", 0xffb0c4de },
- { "lightyellow", 0xffffffe0 },
- { "lime", 0xff00ff00 },
- { "limegreen", 0xff32cd32 },
- { "linen", 0xfffaf0e6 },
- { "magenta", 0xffff00ff },
- { "maroon", 0xff800000 },
- { "mediumaquamarine", 0xff66cdaa },
- { "mediumblue", 0xff0000cd },
- { "mediumorchid", 0xffba55d3 },
- { "mediumpurple", 0xff9370db },
- { "mediumseagreen", 0xff3cb371 },
- { "mediumslateblue", 0xff7b68ee },
- { "mediumspringgreen", 0xff00fa9a },
- { "mediumturquoise", 0xff48d1cc },
- { "mediumvioletred", 0xffc71585 },
- { "midnightblue", 0xff191970 },
- { "mintcream", 0xfff5fffa },
- { "mistyrose", 0xffffe4e1 },
- { "moccasin", 0xffffe4b5 },
- { "navajowhite", 0xffffdead },
- { "navy", 0xff000080 },
- { "oldlace", 0xfffdf5e6 },
- { "olive", 0xff808000 },
- { "olivedrab", 0xff6b8e23 },
- { "orange", 0xffffa500 },
- { "orangered", 0xffff4500 },
- { "orchid", 0xffda70d6 },
- { "palegoldenrod", 0xffeee8aa },
- { "palegreen", 0xff98fb98 },
- { "paleturquoise", 0xffafeeee },
- { "palevioletred", 0xffdb7093 },
- { "papayawhip", 0xffffefd5 },
- { "peachpuff", 0xffffdab9 },
- { "peru", 0xffcd853f },
- { "pink", 0xffffc0cb },
- { "plum", 0xffdda0dd },
- { "powderblue", 0xffb0e0e6 },
- { "purple", 0xff800080 },
- { "red", 0xffff0000 },
- { "rosybrown", 0xffbc8f8f },
- { "royalblue", 0xff4169e1 },
- { "saddlebrown", 0xff8b4513 },
- { "salmon", 0xfffa8072 },
- { "sandybrown", 0xfff4a460 },
- { "seagreen", 0xff2e8b57 },
- { "seashell", 0xfffff5ee },
- { "sienna", 0xffa0522d },
- { "silver", 0xffc0c0c0 },
- { "skyblue", 0xff87ceeb },
- { "slateblue", 0xff6a5acd },
- { "slategray", 0xff708090 },
- { "slategrey", 0xff708090 },
- { "snow", 0xfffffafa },
- { "springgreen", 0xff00ff7f },
- { "steelblue", 0xff4682b4 },
- { "tan", 0xffd2b48c },
- { "teal", 0xff008080 },
- { "thistle", 0xffd8bfd8 },
- { "tomato", 0xffff6347 },
- { "turquoise", 0xff40e0d0 },
- { "violet", 0xffee82ee },
- { "violetred", 0xffd02090 },
- { "wheat", 0xfff5deb3 },
- { "white", 0xffffffff },
- { "whitesmoke", 0xfff5f5f5 },
- { "yellow", 0xffffff00 },
- { "yellowgreen", 0xff9acd32 }
- };
- const struct colour_map *entry;
-
- entry = bsearch(name, named_colours,
- sizeof(named_colours) / sizeof(named_colours[0]),
- sizeof(named_colours[0]),
- cmp_colour_name);
-
- if (entry != NULL)
- *result = entry->color;
-
- return entry != NULL;
-}
-
-/**
- * Parse a dimension string
- *
- * \param data Data to parse (NUL-terminated)
- * \param strict Whether to enforce strict parsing rules
- * \param length Pointer to location to receive dimension's length
- * \param unit Pointer to location to receive dimension's unit
- * \return true on success, false on invalid input
- */
-bool parse_dimension(const char *data, bool strict, css_fixed *length,
- css_unit *unit)
-{
- size_t len;
- size_t read;
- css_fixed value;
-
- len = strlen(data);
-
- if (parse_number(data, false, true, &value, &read) == false)
- return false;
-
- if (strict && value < INTTOFIX(1))
- return false;
-
- *length = value;
-
- if (len > read && data[read] == '%')
- *unit = CSS_UNIT_PCT;
- else
- *unit = CSS_UNIT_PX;
-
- return true;
-}
-
-/**
- * Parse a number string
- *
- * \param data Data to parse (NUL-terminated)
- * \param maybe_negative Negative numbers permitted
- * \param real Floating point numbers permitted
- * \param value Pointer to location to receive numeric value
- * \param consumed Pointer to location to receive number of input
- * bytes consumed
- * \return true on success, false on invalid input
- */
-bool parse_number(const char *data, bool maybe_negative, bool real,
- css_fixed *value, size_t *consumed)
-{
- size_t len;
- const uint8_t *ptr;
- int32_t intpart = 0;
- int32_t fracpart = 0;
- int32_t pwr = 1;
- int sign = 1;
-
- *consumed = 0;
-
- len = strlen(data);
- ptr = (const uint8_t *) data;
-
- if (len == 0)
- return false;
-
- /* Skip leading whitespace */
- while (len > 0 && isWhitespace(ptr[0])) {
- len--;
- ptr++;
- }
-
- if (len == 0)
- return false;
-
- /* Extract sign, if any */
- if (ptr[0] == '+') {
- len--;
- ptr++;
- } else if (ptr[0] == '-' && maybe_negative) {
- sign = -1;
- len--;
- ptr++;
- }
-
- if (len == 0)
- return false;
-
- /* Must have a digit [0,9] */
- if ('0' > ptr[0] || ptr[0] > '9')
- return false;
-
- /* Now extract intpart, assuming base 10 */
- while (len > 0) {
- /* Stop on first non-digit */
- if (ptr[0] < '0' || '9' < ptr[0])
- break;
-
- /* Prevent overflow of 'intpart'; proper clamping below */
- if (intpart < (1 << 22)) {
- intpart *= 10;
- intpart += ptr[0] - '0';
- }
- ptr++;
- len--;
- }
-
- /* And fracpart, again, assuming base 10 */
- if (real && len > 1 && ptr[0] == '.' &&
- ('0' <= ptr[1] && ptr[1] <= '9')) {
- ptr++;
- len--;
-
- while (len > 0) {
- if (ptr[0] < '0' || '9' < ptr[0])
- break;
-
- if (pwr < 1000000) {
- pwr *= 10;
- fracpart *= 10;
- fracpart += ptr[0] - '0';
- }
- ptr++;
- len--;
- }
-
- fracpart = ((1 << 10) * fracpart + pwr/2) / pwr;
- if (fracpart >= (1 << 10)) {
- intpart++;
- fracpart &= (1 << 10) - 1;
- }
- }
-
- if (sign > 0) {
- /* If the result is larger than we can represent,
- * then clamp to the maximum value we can store. */
- if (intpart >= (1 << 21)) {
- intpart = (1 << 21) - 1;
- fracpart = (1 << 10) - 1;
- }
- } else {
- /* If the negated result is smaller than we can represent
- * then clamp to the minimum value we can store. */
- if (intpart >= (1 << 21)) {
- intpart = -(1 << 21);
- fracpart = 0;
- } else {
- intpart = -intpart;
- if (fracpart) {
- fracpart = (1 << 10) - fracpart;
- intpart--;
- }
- }
- }
-
- *value = (intpart << 10) | fracpart;
-
- *consumed = ptr - (const uint8_t *) data;
-
- return true;
-}
-
-/**
- * Parse a font \@size attribute
- *
- * \param size Data to parse (NUL-terminated)
- * \param val Pointer to location to receive enum value
- * \param len Pointer to location to receive length
- * \param unit Pointer to location to receive unit
- * \return True on success, false on failure
- */
-bool parse_font_size(const char *size, uint8_t *val,
- css_fixed *len, css_unit *unit)
-{
- static const uint8_t size_map[] = {
- CSS_FONT_SIZE_XX_SMALL,
- CSS_FONT_SIZE_SMALL,
- CSS_FONT_SIZE_MEDIUM,
- CSS_FONT_SIZE_LARGE,
- CSS_FONT_SIZE_X_LARGE,
- CSS_FONT_SIZE_XX_LARGE,
- CSS_FONT_SIZE_DIMENSION /* xxx-large (see below) */
- };
-
- const char *p = size;
- char mode;
- int value = 0;
-
- /* Skip whitespace */
- while (*p != '\0' && isWhitespace(*p))
- p++;
-
- mode = *p;
-
- /* Skip +/- */
- if (mode == '+' || mode == '-')
- p++;
-
- /* Need at least one digit */
- if (*p < '0' || *p > '9') {
- return false;
- }
-
- /* Consume digits, computing value */
- while ('0' <= *p && *p <= '9') {
- value = value * 10 + (*p - '0');
- p++;
- }
-
- /* Resolve relative sizes */
- if (mode == '+')
- value += 3;
- else if (mode == '-')
- value = 3 - value;
-
- /* Clamp to range [1,7] */
- if (value < 1)
- value = 1;
- else if (value > 7)
- value = 7;
-
- if (value == 7) {
- /* Manufacture xxx-large */
- *len = FDIV(FMUL(INTTOFIX(3), INTTOFIX(nsoption_int(font_size))),
- F_10);
- } else {
- /* Len is irrelevant */
- *len = 0;
- }
-
- *unit = CSS_UNIT_PT;
- *val = size_map[value - 1];
-
- return true;
-}
-
-/******************************************************************************
- * Utility functions *
- ******************************************************************************/
-
-/**
- * Determine if a given character is whitespace
- *
- * \param c Character to consider
- * \return true if character is whitespace, false otherwise
- */
-bool isWhitespace(char c)
-{
- return c == ' ' || c == '\t' || c == '\f' || c == '\r'
|| c == '\n';
-}
-
-/**
- * Determine if a given character is a valid hex digit
- *
- * \param c Character to consider
- * \return true if character is a valid hex digit, false otherwise
- */
-bool isHex(char c)
-{
- return ('0' <= c && c <= '9') ||
- ('A' <= (c & ~0x20) && (c & ~0x20) <= 'F');
-}
-
-/**
- * Convert a character representing a hex digit to the corresponding hex value
- *
- * \param c Character to convert
- * \return Hex value represented by character
- *
- * \note This function assumes an ASCII-compatible character set
- */
-uint8_t charToHex(char c)
-{
- /* 0-9 */
- c -= '0';
-
- /* A-F */
- if (c > 9)
- c -= 'A' - '9' - 1;
-
- /* a-f */
- if (c > 15)
- c -= 'a' - 'A';
-
- return c;
-}
-
diff --git a/css/select.h b/css/select.h
index 13b9e12..0e0be95 100644
--- a/css/select.h
+++ b/css/select.h
@@ -49,9 +49,9 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node *n,
css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
const css_computed_style *parent);
-css_error nscss_compute_font_size(void *pw, const css_hint *parent,
- css_hint *size);
-bool nscss_parse_colour(const char *data, css_color *result);
+css_error named_ancestor_node(void *pw, void *node,
+ const css_qname *qname, void **ancestor);
+css_error node_is_visited(void *pw, void *node, bool *match);
#endif
diff --git a/render/box_construct.c b/render/box_construct.c
index 2ad5eb2..8d98573 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -36,8 +36,9 @@
#include "utils/config.h"
#include "content/content_protected.h"
#include "css/css.h"
-#include "css/utils.h"
+#include "css/hints.h"
#include "css/select.h"
+#include "css/utils.h"
#include "utils/nsoption.h"
#include "utils/corestrings.h"
#include "utils/locale.h"
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=c1b6253891e9689cff9...
commit c1b6253891e9689cff9f20ba663506d78f6a7204
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Update to test shared computed styles version of libcss.
diff --git a/css/select.c b/css/select.c
index e88d3f6..85c32b5 100644
--- a/css/select.c
+++ b/css/select.c
@@ -290,7 +290,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node
*n,
error = css_computed_style_compose(ctx->parent_style,
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
nscss_compute_font_size, NULL,
- styles->styles[CSS_PSEUDO_ELEMENT_NONE]);
+ &(styles->styles[CSS_PSEUDO_ELEMENT_NONE]));
if (error != CSS_OK) {
css_select_results_destroy(styles);
return NULL;
@@ -317,7 +317,7 @@ css_select_results *nscss_get_style(nscss_select_ctx *ctx, dom_node
*n,
styles->styles[CSS_PSEUDO_ELEMENT_NONE],
styles->styles[pseudo_element],
nscss_compute_font_size, NULL,
- styles->styles[pseudo_element]);
+ &(styles->styles[pseudo_element]));
if (error != CSS_OK) {
/* TODO: perhaps this shouldn't be quite so
* catastrophic? */
@@ -371,7 +371,7 @@ css_computed_style *nscss_get_blank_style(nscss_select_ctx *ctx,
return NULL;
error = css_computed_style_compose(parent, partial,
- nscss_compute_font_size, NULL, partial);
+ nscss_compute_font_size, NULL, &partial);
if (error != CSS_OK) {
css_computed_style_destroy(partial);
return NULL;
-----------------------------------------------------------------------
Summary of changes:
amiga/Makefile.target | 2 +-
amiga/dist/NetSurf.guide | 62 +-
amiga/font.c | 27 +-
amiga/gui.c | 145 +++-
amiga/gui.h | 2 +-
amiga/hash/xxhash.c | 962 +++++++++++++++++++++++++++
amiga/hash/xxhash.h | 192 ++++++
amiga/menu.c | 3 +-
amiga/os3support.h | 1 +
amiga/resources/Themes/AISS/NetSurf.info | Bin 23720 -> 23778 bytes
amiga/resources/Themes/Default/NetSurf.info | Bin 14760 -> 14818 bytes
amiga/tree.c | 2 +-
javascript/duktape/Event.bnd | 5 +
javascript/duktape/dukky.c | 194 +++++-
test/js/event-onloadfrombody.html | 10 +
test/js/event-onloadfrombody2.html | 13 +
test/js/index.html | 1 +
utils/corestrings.c | 22 +
utils/corestrings.h | 9 +
19 files changed, 1589 insertions(+), 63 deletions(-)
create mode 100644 amiga/hash/xxhash.c
create mode 100644 amiga/hash/xxhash.h
create mode 100644 test/js/event-onloadfrombody.html
create mode 100644 test/js/event-onloadfrombody2.html
diff --git a/amiga/Makefile.target b/amiga/Makefile.target
index 29b3905..f422140 100644
--- a/amiga/Makefile.target
+++ b/amiga/Makefile.target
@@ -76,7 +76,7 @@ S_AMIGA := gui.c tree.c history.c hotlist.c schedule.c file.c \
datatypes.c dt_picture.c dt_anim.c dt_sound.c plugin_hack.c \
stringview/stringview.c stringview/urlhistory.c rtg.c \
agclass/amigaguide_class.c os3support.c font_bitmap.c \
- selectmenu.c
+ selectmenu.c hash/xxhash.c
S_AMIGA := $(addprefix amiga/,$(S_AMIGA))
# This is the final source build list
diff --git a/amiga/dist/NetSurf.guide b/amiga/dist/NetSurf.guide
index 5db267a..4c1d348 100755
--- a/amiga/dist/NetSurf.guide
+++ b/amiga/dist/NetSurf.guide
@@ -109,14 +109,23 @@ This section contains options for exporting to PDF. It is not
enabled in curren
@endnode
@node cli "Command line options"
-NetSurf URL/K,FORCE/S
+NetSurf URL/K,FORCE/S,NSOPTS/M
Where:
+URL = Address of page to open on startup
+FORCE = Force new instance of NetSurf to open (has some limitations, use for debugging
only)
+NSOPTS = Catches everything else and passes it to the NetSurf core command line parser
+@endnode
+
+@node tooltypes "ToolTypes"
+Supported tooltypes are:
-URL = Address of page to open on startup
-FORCE = Force new instance of NetSurf to open (has some limitations, use for debugging
only)
+@{b}USERSDIR@{ub}
+Location of the Users directory. This should contain the "Users" part of the
path, NetSurf will append the username. Defaults to PROGDIR:Users.
+The user directories contain user-specific preferences and cache data. Always locate
them on fast, non-volatile, writeable media.
-Note that there may be other generic options which can also be specified.
+@{b}USER@{ub}
+Current user. Defaults to the value of the USER env-var, or Default.
@endnode
@node options "Options file"
@@ -278,7 +287,7 @@ Items in the "Hotlist menu" folder node, up to a maximum
(currently) of 40 items
Items in folders within the Menu folder node will be converted to subitems in the menu.
-Folders more than one level down in the heirarchy will become menu items with no action.
Items deeper will not be included in the menu at all.
+Folders more than one level down in the heirarchy will become menu items with no action.
Items deeper will not be included in the menu at all (until we switch to using
menuclass).
Folders with no items in them will show up disabled in the menu. If they are named
"--" they will be displayed as separator bars.
@@ -336,7 +345,7 @@ The Installer script will set the MIMETYPE tooltype on basic relevant
default fi
This is a list of the keyboard shortcuts used in NetSurf
- RAmiga + R or F5 (reload the current page)
-- PageUp/Down (scroll up/down to one page)
+- PageUp/Down/Space (scroll up/down to one page)
- Home/End (go to top/bottom of the page)
- Left/Right/Up/Down (scroll the page)
- RAmiga + U (activate the URL bar)
@@ -345,26 +354,27 @@ This is a list of the keyboard shortcuts used in NetSurf
Keyboard shortcuts used in NetSurf menu
-- RAmiga + N (open a new window)
-- RAmiga + T (open a new tab)
-- RAmiga + O (open a local file)
-- RAmiga + S (save source page)
-- RAmiga + K (close current tab)
-- RAmiga + P (print a page)
-- RAmiga + ? (about NetSurf)
-- RAmiga + Q (quit NetSurf)
-- RAmiga + X (cut)
-- RAmiga + C (copy)
-- RAmiga + V (paste)
-- RAmiga + A (select all)
-- RAmiga + Z (clear selection)
-- RAmiga + F (find a string/text)
-- RAmiga + - (decrease font)
-- RAmiga + = (normal font)
-- RAmiga + + (increase font)
-- RAmiga + B (add link to bookmark)
-- RAmiga + H (show bookmarks)
-- RAmiga + E (execute script)
+- RAmiga + N (open a new window)
+- RAmiga + T (open a new tab)
+- RAmiga + O (open a local file)
+- RAmiga + S (save source page)
+- RAmiga + K (close current tab)
+- RAmiga + P (print a page)
+- RAmiga + ? (about NetSurf)
+- RAmiga + Q (quit NetSurf)
+- RAmiga + X (cut)
+- RAmiga + C (copy)
+- RAmiga + V (paste)
+- RAmiga + A (select all)
+- RAmiga + Z (undo)
+- RAmiga + Y (redo)
+- RAmiga + F (find a string/text)
+- RAmiga + - or F9 (decrease scale)
+- RAmiga + = or F8 (normal scale)
+- RAmiga + + or F10 (increase scale)
+- RAmiga + B (add link to bookmark)
+- RAmiga + H (show bookmarks)
+- RAmiga + E (execute script)
@endnode
diff --git a/amiga/font.c b/amiga/font.c
index 7569bb6..8848021 100644
--- a/amiga/font.c
+++ b/amiga/font.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 - 2013 Chris Young <chris(a)unsatisfactorysoftware.co.uk>
+ * Copyright 2008 - 2015 Chris Young <chris(a)unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf,
http://www.netsurf-browser.org/
*
@@ -52,6 +52,9 @@
#include "amiga/utf8.h"
#include "amiga/object.h"
#include "amiga/schedule.h"
+#ifdef __amigaos4__
+#include <amiga/hash/xxhash.h>
+#endif
#define NSA_UNICODE_FONT PLOT_FONT_FAMILY_COUNT
@@ -371,9 +374,11 @@ static inline bool amiga_nsfont_split(const plot_font_style_t
*fstyle,
static struct ami_font_node *ami_font_open(const char *font, bool critical)
{
struct ami_font_node *nodedata = NULL;
+ uint32 hash = 0;
#ifdef __amigaos4__
- nodedata = (struct ami_font_node *)FindSkipNode(ami_font_list, (APTR)font);
+ hash = XXH32(font, strlen(font), 0);
+ nodedata = (struct ami_font_node *)FindSkipNode(ami_font_list, (APTR)hash);
#else
struct nsObject *node = (struct nsObject *)FindIName((struct List *)ami_font_list,
font);
if(node) nodedata = node->objstruct;
@@ -384,10 +389,10 @@ static struct ami_font_node *ami_font_open(const char *font, bool
critical)
return nodedata;
}
- LOG("Font cache miss: %s", font);
+ LOG("Font cache miss: %s (%lx)", font, hash);
#ifdef __amigaos4__
- nodedata = (struct ami_font_node *)InsertSkipNode(ami_font_list, (APTR)font,
sizeof(struct ami_font_node));
+ nodedata = (struct ami_font_node *)InsertSkipNode(ami_font_list, (APTR)hash,
sizeof(struct ami_font_node));
#else
nodedata = AllocVecTagList(sizeof(struct ami_font_node), NULL);
#endif
@@ -916,7 +921,9 @@ void ami_font_savescanner(void)
#ifdef __amigaos4__
static LONG ami_font_cache_sort(struct Hook *hook, APTR key1, APTR key2)
{
- return stricmp(key1, key2);
+ if(key1 == key2) return 0;
+ if(key1 < key2) return -1;
+ return 1;
}
#endif
@@ -936,7 +943,7 @@ static void ami_font_cleanup(struct SkipList *skiplist)
SubTime(&curtime, &node->lastused);
if(curtime.Seconds > 300)
{
- LOG("Freeing %s not used for %ld seconds", node->skip_node.sn_Key,
curtime.Seconds);
+ LOG("Freeing font %lx not used for %ld seconds", node->skip_node.sn_Key,
curtime.Seconds);
ami_font_close(node);
RemoveSkipNode(skiplist, node->skip_node.sn_Key);
}
@@ -998,15 +1005,15 @@ void ami_init_fonts(void)
#ifdef __amigaos4__
static void ami_font_del_skiplist(struct SkipList *skiplist)
{
- struct SkipNode *node;
+ struct ami_font_node *node;
struct SkipNode *nnode;
- node = GetFirstSkipNode(skiplist);
+ node = (struct ami_font_node *)GetFirstSkipNode(skiplist);
if(node == NULL) return;
do {
- nnode = GetNextSkipNode(skiplist, node);
- ami_font_close((struct ami_font_node *)node);
+ nnode = GetNextSkipNode(skiplist, (struct SkipNode *)node);
+ ami_font_close(node);
} while((node = nnode));
diff --git a/amiga/gui.c b/amiga/gui.c
index a24942b..a3cd57b 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -31,6 +31,7 @@
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
+#include <proto/icon.h>
#include <proto/intuition.h>
#include <proto/keymap.h>
#include <proto/locale.h>
@@ -59,6 +60,7 @@
#include <proto/button.h>
#include <proto/chooser.h>
#include <proto/clicktab.h>
+#include <proto/label.h>
#include <proto/layout.h>
#include <proto/scroller.h>
#include <proto/space.h>
@@ -77,6 +79,7 @@
#include <gadgets/string.h>
#include <images/bevel.h>
#include <images/bitmap.h>
+#include <images/label.h>
#include <reaction/reaction_macros.h>
@@ -186,7 +189,9 @@ static struct Hook newprefs_hook;
static STRPTR temp_homepage_url = NULL;
static bool cli_force = false;
-static char *current_user;
+#define USERS_DIR "PROGDIR:Users"
+static char *users_dir = NULL;
+static char *current_user = NULL;
static char *current_user_dir;
static char *current_user_faviconcache;
@@ -650,11 +655,13 @@ static void ami_amiupdate(void)
char filename[1024];
BPTR amiupdatefh;
- DevNameFromLock(lock,(STRPTR)&filename,1024L,DN_FULLPATH);
+ DevNameFromLock(lock, (STRPTR)&filename, 1024L, DN_FULLPATH);
+
+ if((amiupdatefh = FOpen("ENVARC:AppPaths/NetSurf", MODE_NEWFILE, 0))) {
+ FPuts(amiupdatefh, (CONST_STRPTR)&filename);
+ FClose(amiupdatefh);
+ }
- amiupdatefh = FOpen("ENVARC:AppPaths/NetSurf",MODE_NEWFILE,0);
- FPuts(amiupdatefh,(CONST_STRPTR)&filename);
- FClose(amiupdatefh);
UnLock(lock);
}
}
@@ -851,6 +858,42 @@ static void ami_gui_commandline(int *argc, char **argv)
}
}
+static void ami_gui_read_tooltypes(struct WBArg *wbarg)
+{
+ struct DiskObject *dobj;
+ STRPTR *toolarray;
+ char *s;
+
+ if((*wbarg->wa_Name) && (dobj = GetDiskObject(wbarg->wa_Name))) {
+ toolarray = (STRPTR *)dobj->do_ToolTypes;
+
+ if((s = (char *)FindToolType(toolarray,"USERSDIR"))) users_dir =
ASPrintf("%s", s);
+ if((s = (char *)FindToolType(toolarray,"USER"))) current_user =
ASPrintf("%s", s);
+
+ FreeDiskObject(dobj);
+ }
+}
+
+static void ami_gui_read_all_tooltypes(int argc, char **argv)
+{
+ struct WBStartup *WBenchMsg;
+ struct WBArg *wbarg;
+ char i;
+ LONG olddir = -1;
+
+ if(argc == 0) { /* Started from WB */
+ WBenchMsg = (struct WBStartup *)argv;
+ for(i = 0, wbarg = WBenchMsg->sm_ArgList; i < WBenchMsg->sm_NumArgs;
i++,wbarg++) {
+ olddir =-1;
+ if((wbarg->wa_Lock) && (*wbarg->wa_Name))
+ olddir = SetCurrentDir(wbarg->wa_Lock);
+
+ ami_gui_read_tooltypes(wbarg);
+
+ if(olddir !=-1) SetCurrentDir(olddir);
+ }
+ }
+}
static void gui_init2(int argc, char** argv)
{
@@ -961,6 +1004,7 @@ static void gui_init2(int argc, char** argv)
temp_homepage_url = NULL;
}
}
+ /* this should be where we read tooltypes, but it's too late for that now */
}
}
@@ -1209,6 +1253,9 @@ int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie)
else nskey = NS_KEY_TAB;
break;
case RAWKEY_F5:
+ case RAWKEY_F8:
+ case RAWKEY_F9:
+ case RAWKEY_F10:
case RAWKEY_HELP:
// don't translate
nskey = keycode;
@@ -2299,6 +2346,7 @@ static void ami_handle_msg(void)
break;
case NS_KEY_PAGE_DOWN:
+ case ' ':
ami_gui_scroll_internal(gwin, 0, SCROLL_PAGE_DOWN);
break;
@@ -2330,10 +2378,23 @@ static void ami_handle_msg(void)
ami_gui_history(gwin, true);
break;
+ /* RawKeys. NB: These are passthrus in ami_key_to_nskey() */
case RAWKEY_F5: // reload
if(browser_window_reload_available(gwin->gw->bw))
browser_window_reload(gwin->gw->bw,false);
break;
+
+ case RAWKEY_F8: // scale 100%
+ ami_gui_set_scale(gwin->gw, 1.0);
+ break;
+
+ case RAWKEY_F9: // decrease scale
+ ami_gui_set_scale(gwin->gw, gwin->gw->scale - 0.1);
+ break;
+
+ case RAWKEY_F10: // increase scale
+ ami_gui_set_scale(gwin->gw, gwin->gw->scale + 0.1);
+ break;
case RAWKEY_HELP: // help
ami_help_open(AMI_HELP_GUI, scrn);
@@ -3019,15 +3080,44 @@ static bool ami_gui_hotlist_add(void *userdata, int level, int
item, const char
{
struct ami_gui_tb_userdata *tb_userdata = (struct ami_gui_tb_userdata *)userdata;
struct Node *speed_button_node;
+ char menu_icon[1024];
if(level != 1) return false;
if(item > AMI_GUI_TOOLBAR_MAX) return false;
if(is_folder == true) return false;
- tb_userdata->gw->hotlist_toolbar_lab[item] = ami_utf8_easy(title);
+ char *utf8title = ami_utf8_easy(title);
+ if(utf8title == NULL) return false;
+
+ char *iconname = ami_gui_get_cache_favicon_name(url, true);
+ if (iconname == NULL) iconname = ASPrintf("icons/content.png");
+ ami_locate_resource(menu_icon, iconname);
+
+ tb_userdata->gw->hotlist_toolbar_lab[item] = BitMapObj,
+ IA_Scalable, TRUE,
+ BITMAP_Screen, scrn,
+ BITMAP_SourceFile, menu_icon,
+ BITMAP_Masking, TRUE,
+ BitMapEnd;
+
+ /* \todo make this scale the bitmap to these dimensions */
+ SetAttrs(tb_userdata->gw->hotlist_toolbar_lab[item],
+ BITMAP_Width, 16,
+ BITMAP_Height, 16,
+ TAG_DONE);
+
+ Object *lab_item = LabelObj,
+ // LABEL_DrawInfo, dri,
+ LABEL_DisposeImage, TRUE,
+ LABEL_Image, tb_userdata->gw->hotlist_toolbar_lab[item],
+ LABEL_Text, " ",
+ LABEL_Text, utf8title,
+ LabelEnd;
+
+ free(utf8title);
speed_button_node = AllocSpeedButtonNode(item,
- SBNA_Text, tb_userdata->gw->hotlist_toolbar_lab[item],
+ SBNA_Image, lab_item,
SBNA_UserData, (void *)url,
TAG_DONE);
@@ -3115,7 +3205,7 @@ static void ami_gui_hotlist_toolbar_free(struct gui_window_2 *gwin,
struct List
for(i = 0; i < AMI_GUI_TOOLBAR_MAX; i++) {
if(gwin->hotlist_toolbar_lab[i]) {
- free(gwin->hotlist_toolbar_lab[i]);
+ DisposeObject(gwin->hotlist_toolbar_lab[i]);
gwin->hotlist_toolbar_lab[i] = NULL;
}
}
@@ -3331,6 +3421,7 @@ int ami_gui_count_windows(int window, int *tabs)
*/
void ami_gui_set_scale(struct gui_window *gw, float scale)
{
+ if(scale <= 0.0) return;
gw->scale = scale;
browser_window_set_scale(gw->bw, scale, true);
}
@@ -4201,7 +4292,7 @@ gui_window_create(struct browser_window *bw,
GA_ID, GID_STATUS,
GA_Left, scrn->WBorLeft + 2,
#ifdef __amigaos4__
- GA_RelBottom, -((2 + height + scrn->WBorBottom - scrn->RastPort.TxHeight)/2),
+ GA_RelBottom, scrn->WBorBottom - (height/2),
GA_BottomBorder, TRUE,
#else
GA_Top, g->shared->win->Height,
@@ -4220,9 +4311,9 @@ gui_window_create(struct browser_window *bw,
"frameiclass",
IA_Recessed, TRUE,
#endif
- IA_Top, 2 - (scrn->RastPort.TxHeight),
+ IA_Top, (int)(- ceil((scrn->WBorBottom + height) / 2)),
IA_Left, -4,
- IA_Height, 1 + height - scrn->WBorBottom,
+ IA_Height, 2 + height - scrn->WBorBottom,
IA_Label, NULL,
IA_InBorder, TRUE,
IA_Screen, scrn,
@@ -5376,10 +5467,36 @@ int main(int argc, char** argv)
return RETURN_FAIL;
}
- user = GetVar("user", temp, 1024, GVF_GLOBAL_ONLY);
- current_user = ASPrintf("%s", (user == -1) ? "Default" : temp);
+ ami_gui_read_all_tooltypes(argc, argv);
+
+ if(current_user == NULL) {
+ user = GetVar("user", temp, 1024, GVF_GLOBAL_ONLY);
+ current_user = ASPrintf("%s", (user == -1) ? "Default" : temp);
+ }
LOG("User: %s", current_user);
- current_user_dir = ASPrintf("PROGDIR:Users/%s", current_user);
+
+ if(users_dir == NULL) {
+ users_dir = ASPrintf("%s", USERS_DIR);
+ if(users_dir == NULL) {
+ ami_misc_fatal_error("Failed to allocate memory");
+ return RETURN_FAIL;
+ }
+ }
+
+ int len = strlen(current_user);
+ len += strlen(users_dir);
+ len += 2; /* for poss path sep and NULL term */
+
+ current_user_dir = AllocVecTags(len, NULL);
+ if(current_user_dir == NULL) {
+ ami_misc_fatal_error("Failed to allocate memory");
+ return RETURN_FAIL;
+ }
+
+ strlcpy(current_user_dir, users_dir, len);
+ AddPart(current_user_dir, current_user, len);
+ FreeVec(users_dir);
+ LOG("User dir: %s", current_user_dir);
if((lock = CreateDirTree(current_user_dir)))
UnLock(lock);
diff --git a/amiga/gui.h b/amiga/gui.h
index 6a01082..86dedcb 100644
--- a/amiga/gui.h
+++ b/amiga/gui.h
@@ -117,7 +117,7 @@ struct gui_window_2 {
UBYTE *menutype;
struct NewMenu *menu;
ULONG hotlist_items;
- char *hotlist_toolbar_lab[AMI_GUI_TOOLBAR_MAX];
+ Object *hotlist_toolbar_lab[AMI_GUI_TOOLBAR_MAX];
struct List hotlist_toolbar_list;
struct List *web_search_list;
Object *search_bm;
diff --git a/amiga/hash/xxhash.c b/amiga/hash/xxhash.c
new file mode 100644
index 0000000..d55a361
--- /dev/null
+++ b/amiga/hash/xxhash.c
@@ -0,0 +1,962 @@
+/*
+xxHash - Fast Hash algorithm
+Copyright (C) 2012-2015, Yann Collet
+
+BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php)
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You can contact the author at :
+- xxHash source repository :
https://github.com/Cyan4973/xxHash
+*/
+
+
+/**************************************
+* Tuning parameters
+**************************************/
+/* XXH_FORCE_MEMORY_ACCESS
+ * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and
portable.
+ * Unfortunately, on some target/compiler combinations, the generated assembly is
sub-optimal.
+ * The below switch allow to select different access method for improved performance.
+ * Method 0 (default) : use `memcpy()`. Safe and portable.
+ * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
+ * This method is safe if your compiler supports it, and *generally* as fast
or faster than `memcpy`.
+ * Method 2 : direct access. This method is portable but violate C standard.
+ * It can generate buggy code on targets which generate assembly depending on
alignment.
+ * But in some circumstances, it's the only known way to get the most
performance (ie GCC + ARMv6)
+ * See
http://stackoverflow.com/a/32095106/646947 for details.
+ * Prefer these methods in priority order (0 > 1 > 2)
+ */
+#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for
example */
+# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__)
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) ||
defined(__ARM_ARCH_6T2__) )
+# define XXH_FORCE_MEMORY_ACCESS 2
+# elif defined(__INTEL_COMPILER) || \
+ (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||
defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))
+# define XXH_FORCE_MEMORY_ACCESS 1
+# endif
+#endif
+
+/* XXH_ACCEPT_NULL_INPUT_POINTER :
+ * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory
access error, since it is a bad pointer.
+ * When this option is enabled, xxHash output for null input pointers will be the same as
a null-length input.
+ * By default, this option is disabled. To enable it, uncomment below define :
+ */
+/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
+
+/* XXH_FORCE_NATIVE_FORMAT :
+ * By default, xxHash library provides endian-independant Hash values, based on
little-endian convention.
+ * Results are therefore identical for little-endian and big-endian CPU.
+ * This comes at a performance cost for big-endian CPU, since some swapping is required
to emulate little-endian format.
+ * Should endian-independance be of no importance for your application, you may set the
#define below to 1,
+ * to improve speed for Big-endian CPU.
+ * This option has no impact on Little_Endian CPU.
+ */
+#define XXH_FORCE_NATIVE_FORMAT 1
+
+/* XXH_USELESS_ALIGN_BRANCH :
+ * This is a minor performance trick, only useful with lots of very small keys.
+ * It means : don't make a test between aligned/unaligned, because performance will
be the same.
+ * It saves one initial branch per hash.
+ */
+#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
+# define XXH_USELESS_ALIGN_BRANCH 1
+#endif
+
+
+/**************************************
+* Compiler Specific Options
+***************************************/
+#ifdef _MSC_VER /* Visual Studio */
+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is
constant */
+# define FORCE_INLINE static __forceinline
+#else
+# if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# ifdef __GNUC__
+# define FORCE_INLINE static inline __attribute__((always_inline))
+# else
+# define FORCE_INLINE static inline
+# endif
+# else
+# define FORCE_INLINE static
+# endif /* __STDC_VERSION__ */
+#endif
+
+
+/**************************************
+* Includes & Memory related functions
+***************************************/
+#include "xxhash.h"
+/* Modify the local functions below should you wish to use some other memory routines */
+/* for malloc(), free() */
+#include <stdlib.h>
+static void* XXH_malloc(size_t s) { return malloc(s); }
+static void XXH_free (void* p) { free(p); }
+/* for memcpy() */
+#include <string.h>
+static void* XXH_memcpy(void* dest, const void* src, size_t size) { return
memcpy(dest,src,size); }
+
+
+/**************************************
+* Basic Types
+***************************************/
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# include <stdint.h>
+ typedef uint8_t BYTE;
+ typedef uint16_t U16;
+ typedef uint32_t U32;
+ typedef int32_t S32;
+ typedef uint64_t U64;
+#else
+ typedef unsigned char BYTE;
+ typedef unsigned short U16;
+ typedef unsigned int U32;
+ typedef signed int S32;
+ typedef unsigned long long U64;
+#endif
+
+
+#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
+
+/* Force direct memory access. Only works on CPU which support unaligned memory access in
hardware */
+static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
+static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
+
+#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
+
+/* __pack instructions are safer, but compiler specific, hence potentially problematic
for some compilers */
+/* currently only defined for gcc and icc */
+typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign;
+
+static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
+static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
+
+#else
+
+/* portable and safe solution. Generally efficient.
+ * see :
http://stackoverflow.com/a/32095106/646947
+ */
+
+static U32 XXH_read32(const void* memPtr)
+{
+ U32 val;
+ memcpy(&val, memPtr, sizeof(val));
+ return val;
+}
+
+static U64 XXH_read64(const void* memPtr)
+{
+ U64 val;
+ memcpy(&val, memPtr, sizeof(val));
+ return val;
+}
+
+#endif // XXH_FORCE_DIRECT_MEMORY_ACCESS
+
+
+/******************************************
+* Compiler-specific Functions and Macros
+******************************************/
+#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+
+/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
+#if defined(_MSC_VER)
+# define XXH_rotl32(x,r) _rotl(x,r)
+# define XXH_rotl64(x,r) _rotl64(x,r)
+#else
+# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
+# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
+#endif
+
+#if defined(_MSC_VER) /* Visual Studio */
+# define XXH_swap32 _byteswap_ulong
+# define XXH_swap64 _byteswap_uint64
+#elif GCC_VERSION >= 403
+# define XXH_swap32 __builtin_bswap32
+# define XXH_swap64 __builtin_bswap64
+#else
+static U32 XXH_swap32 (U32 x)
+{
+ return ((x << 24) & 0xff000000 ) |
+ ((x << 8) & 0x00ff0000 ) |
+ ((x >> 8) & 0x0000ff00 ) |
+ ((x >> 24) & 0x000000ff );
+}
+static U64 XXH_swap64 (U64 x)
+{
+ return ((x << 56) & 0xff00000000000000ULL) |
+ ((x << 40) & 0x00ff000000000000ULL) |
+ ((x << 24) & 0x0000ff0000000000ULL) |
+ ((x << 8) & 0x000000ff00000000ULL) |
+ ((x >> 8) & 0x00000000ff000000ULL) |
+ ((x >> 24) & 0x0000000000ff0000ULL) |
+ ((x >> 40) & 0x000000000000ff00ULL) |
+ ((x >> 56) & 0x00000000000000ffULL);
+}
+#endif
+
+
+/***************************************
+* Architecture Macros
+***************************************/
+typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
+
+/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example one the compiler command
line */
+#ifndef XXH_CPU_LITTLE_ENDIAN
+ static const int one = 1;
+# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&one))
+#endif
+
+
+/*****************************
+* Memory reads
+*****************************/
+typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
+
+FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment
align)
+{
+ if (align==XXH_unaligned)
+ return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
+ else
+ return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const
U32*)ptr);
+}
+
+FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
+{
+ return XXH_readLE32_align(ptr, endian, XXH_unaligned);
+}
+
+FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment
align)
+{
+ if (align==XXH_unaligned)
+ return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
+ else
+ return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const
U64*)ptr);
+}
+
+FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
+{
+ return XXH_readLE64_align(ptr, endian, XXH_unaligned);
+}
+
+
+/***************************************
+* Macros
+***************************************/
+#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } /* use only
*after* variable declarations */
+
+
+/***************************************
+* Constants
+***************************************/
+#define PRIME32_1 2654435761U
+#define PRIME32_2 2246822519U
+#define PRIME32_3 3266489917U
+#define PRIME32_4 668265263U
+#define PRIME32_5 374761393U
+
+#define PRIME64_1 11400714785074694791ULL
+#define PRIME64_2 14029467366897019727ULL
+#define PRIME64_3 1609587929392839161ULL
+#define PRIME64_4 9650029242287828579ULL
+#define PRIME64_5 2870177450012600261ULL
+
+
+/*****************************
+* Simple Hash Functions
+*****************************/
+FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed,
XXH_endianess endian, XXH_alignment align)
+{
+ const BYTE* p = (const BYTE*)input;
+ const BYTE* bEnd = p + len;
+ U32 h32;
+#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
+
+#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+ if (p==NULL)
+ {
+ len=0;
+ bEnd=p=(const BYTE*)(size_t)16;
+ }
+#endif
+
+ if (len>=16)
+ {
+ const BYTE* const limit = bEnd - 16;
+ U32 v1 = seed + PRIME32_1 + PRIME32_2;
+ U32 v2 = seed + PRIME32_2;
+ U32 v3 = seed + 0;
+ U32 v4 = seed - PRIME32_1;
+
+ do
+ {
+ v1 += XXH_get32bits(p) * PRIME32_2;
+ v1 = XXH_rotl32(v1, 13);
+ v1 *= PRIME32_1;
+ p+=4;
+ v2 += XXH_get32bits(p) * PRIME32_2;
+ v2 = XXH_rotl32(v2, 13);
+ v2 *= PRIME32_1;
+ p+=4;
+ v3 += XXH_get32bits(p) * PRIME32_2;
+ v3 = XXH_rotl32(v3, 13);
+ v3 *= PRIME32_1;
+ p+=4;
+ v4 += XXH_get32bits(p) * PRIME32_2;
+ v4 = XXH_rotl32(v4, 13);
+ v4 *= PRIME32_1;
+ p+=4;
+ }
+ while (p<=limit);
+
+ h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4,
18);
+ }
+ else
+ {
+ h32 = seed + PRIME32_5;
+ }
+
+ h32 += (U32) len;
+
+ while (p+4<=bEnd)
+ {
+ h32 += XXH_get32bits(p) * PRIME32_3;
+ h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
+ p+=4;
+ }
+
+ while (p<bEnd)
+ {
+ h32 += (*p) * PRIME32_5;
+ h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
+ p++;
+ }
+
+ h32 ^= h32 >> 15;
+ h32 *= PRIME32_2;
+ h32 ^= h32 >> 13;
+ h32 *= PRIME32_3;
+ h32 ^= h32 >> 16;
+
+ return h32;
+}
+
+
+unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
+{
+#if 0
+ /* Simple version, good for code maintenance, but unfortunately slow for small inputs
*/
+ XXH32_state_t state;
+ XXH32_reset(&state, seed);
+ XXH32_update(&state, input, len);
+ return XXH32_digest(&state);
+#else
+ XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+
+# if !defined(XXH_USELESS_ALIGN_BRANCH)
+ if ((((size_t)input) & 3) == 0) /* Input is 4-bytes aligned, leverage the speed
benefit */
+ {
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
+ else
+ return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
+ }
+# endif
+
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
+ else
+ return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
+#endif
+}
+
+FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed,
XXH_endianess endian, XXH_alignment align)
+{
+ const BYTE* p = (const BYTE*)input;
+ const BYTE* bEnd = p + len;
+ U64 h64;
+#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
+
+#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+ if (p==NULL)
+ {
+ len=0;
+ bEnd=p=(const BYTE*)(size_t)32;
+ }
+#endif
+
+ if (len>=32)
+ {
+ const BYTE* const limit = bEnd - 32;
+ U64 v1 = seed + PRIME64_1 + PRIME64_2;
+ U64 v2 = seed + PRIME64_2;
+ U64 v3 = seed + 0;
+ U64 v4 = seed - PRIME64_1;
+
+ do
+ {
+ v1 += XXH_get64bits(p) * PRIME64_2;
+ p+=8;
+ v1 = XXH_rotl64(v1, 31);
+ v1 *= PRIME64_1;
+ v2 += XXH_get64bits(p) * PRIME64_2;
+ p+=8;
+ v2 = XXH_rotl64(v2, 31);
+ v2 *= PRIME64_1;
+ v3 += XXH_get64bits(p) * PRIME64_2;
+ p+=8;
+ v3 = XXH_rotl64(v3, 31);
+ v3 *= PRIME64_1;
+ v4 += XXH_get64bits(p) * PRIME64_2;
+ p+=8;
+ v4 = XXH_rotl64(v4, 31);
+ v4 *= PRIME64_1;
+ }
+ while (p<=limit);
+
+ h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4,
18);
+
+ v1 *= PRIME64_2;
+ v1 = XXH_rotl64(v1, 31);
+ v1 *= PRIME64_1;
+ h64 ^= v1;
+ h64 = h64 * PRIME64_1 + PRIME64_4;
+
+ v2 *= PRIME64_2;
+ v2 = XXH_rotl64(v2, 31);
+ v2 *= PRIME64_1;
+ h64 ^= v2;
+ h64 = h64 * PRIME64_1 + PRIME64_4;
+
+ v3 *= PRIME64_2;
+ v3 = XXH_rotl64(v3, 31);
+ v3 *= PRIME64_1;
+ h64 ^= v3;
+ h64 = h64 * PRIME64_1 + PRIME64_4;
+
+ v4 *= PRIME64_2;
+ v4 = XXH_rotl64(v4, 31);
+ v4 *= PRIME64_1;
+ h64 ^= v4;
+ h64 = h64 * PRIME64_1 + PRIME64_4;
+ }
+ else
+ {
+ h64 = seed + PRIME64_5;
+ }
+
+ h64 += (U64) len;
+
+ while (p+8<=bEnd)
+ {
+ U64 k1 = XXH_get64bits(p);
+ k1 *= PRIME64_2;
+ k1 = XXH_rotl64(k1,31);
+ k1 *= PRIME64_1;
+ h64 ^= k1;
+ h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
+ p+=8;
+ }
+
+ if (p+4<=bEnd)
+ {
+ h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
+ h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
+ p+=4;
+ }
+
+ while (p<bEnd)
+ {
+ h64 ^= (*p) * PRIME64_5;
+ h64 = XXH_rotl64(h64, 11) * PRIME64_1;
+ p++;
+ }
+
+ h64 ^= h64 >> 33;
+ h64 *= PRIME64_2;
+ h64 ^= h64 >> 29;
+ h64 *= PRIME64_3;
+ h64 ^= h64 >> 32;
+
+ return h64;
+}
+
+
+unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
+{
+#if 0
+ /* Simple version, good for code maintenance, but unfortunately slow for small inputs
*/
+ XXH64_state_t state;
+ XXH64_reset(&state, seed);
+ XXH64_update(&state, input, len);
+ return XXH64_digest(&state);
+#else
+ XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+
+# if !defined(XXH_USELESS_ALIGN_BRANCH)
+ if ((((size_t)input) & 7)==0) /* Input is aligned, let's leverage the speed
advantage */
+ {
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
+ else
+ return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
+ }
+# endif
+
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
+ else
+ return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
+#endif
+}
+
+/****************************************************
+* Advanced Hash Functions
+****************************************************/
+
+/*** Allocation ***/
+typedef struct
+{
+ U64 total_len;
+ U32 seed;
+ U32 v1;
+ U32 v2;
+ U32 v3;
+ U32 v4;
+ U32 mem32[4]; /* defined as U32 for alignment */
+ U32 memsize;
+} XXH_istate32_t;
+
+typedef struct
+{
+ U64 total_len;
+ U64 seed;
+ U64 v1;
+ U64 v2;
+ U64 v3;
+ U64 v4;
+ U64 mem64[4]; /* defined as U64 for alignment */
+ U32 memsize;
+} XXH_istate64_t;
+
+
+XXH32_state_t* XXH32_createState(void)
+{
+ XXH_STATIC_ASSERT(sizeof(XXH32_state_t) >= sizeof(XXH_istate32_t)); /* A
compilation error here means XXH32_state_t is not large enough */
+ return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
+}
+XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
+{
+ XXH_free(statePtr);
+ return XXH_OK;
+}
+
+XXH64_state_t* XXH64_createState(void)
+{
+ XXH_STATIC_ASSERT(sizeof(XXH64_state_t) >= sizeof(XXH_istate64_t)); /* A
compilation error here means XXH64_state_t is not large enough */
+ return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
+}
+XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
+{
+ XXH_free(statePtr);
+ return XXH_OK;
+}
+
+
+/*** Hash feed ***/
+
+XXH_errorcode XXH32_reset(XXH32_state_t* state_in, unsigned int seed)
+{
+ XXH_istate32_t* state = (XXH_istate32_t*) state_in;
+ state->seed = seed;
+ state->v1 = seed + PRIME32_1 + PRIME32_2;
+ state->v2 = seed + PRIME32_2;
+ state->v3 = seed + 0;
+ state->v4 = seed - PRIME32_1;
+ state->total_len = 0;
+ state->memsize = 0;
+ return XXH_OK;
+}
+
+XXH_errorcode XXH64_reset(XXH64_state_t* state_in, unsigned long long seed)
+{
+ XXH_istate64_t* state = (XXH_istate64_t*) state_in;
+ state->seed = seed;
+ state->v1 = seed + PRIME64_1 + PRIME64_2;
+ state->v2 = seed + PRIME64_2;
+ state->v3 = seed + 0;
+ state->v4 = seed - PRIME64_1;
+ state->total_len = 0;
+ state->memsize = 0;
+ return XXH_OK;
+}
+
+
+FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state_in, const void*
input, size_t len, XXH_endianess endian)
+{
+ XXH_istate32_t* state = (XXH_istate32_t *) state_in;
+ const BYTE* p = (const BYTE*)input;
+ const BYTE* const bEnd = p + len;
+
+#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+ if (input==NULL) return XXH_ERROR;
+#endif
+
+ state->total_len += len;
+
+ if (state->memsize + len < 16) /* fill in tmp buffer */
+ {
+ XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
+ state->memsize += (U32)len;
+ return XXH_OK;
+ }
+
+ if (state->memsize) /* some data left from previous update */
+ {
+ XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input,
16-state->memsize);
+ {
+ const U32* p32 = state->mem32;
+ state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
+ state->v1 = XXH_rotl32(state->v1, 13);
+ state->v1 *= PRIME32_1;
+ p32++;
+ state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
+ state->v2 = XXH_rotl32(state->v2, 13);
+ state->v2 *= PRIME32_1;
+ p32++;
+ state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
+ state->v3 = XXH_rotl32(state->v3, 13);
+ state->v3 *= PRIME32_1;
+ p32++;
+ state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
+ state->v4 = XXH_rotl32(state->v4, 13);
+ state->v4 *= PRIME32_1;
+ p32++;
+ }
+ p += 16-state->memsize;
+ state->memsize = 0;
+ }
+
+ if (p <= bEnd-16)
+ {
+ const BYTE* const limit = bEnd - 16;
+ U32 v1 = state->v1;
+ U32 v2 = state->v2;
+ U32 v3 = state->v3;
+ U32 v4 = state->v4;
+
+ do
+ {
+ v1 += XXH_readLE32(p, endian) * PRIME32_2;
+ v1 = XXH_rotl32(v1, 13);
+ v1 *= PRIME32_1;
+ p+=4;
+ v2 += XXH_readLE32(p, endian) * PRIME32_2;
+ v2 = XXH_rotl32(v2, 13);
+ v2 *= PRIME32_1;
+ p+=4;
+ v3 += XXH_readLE32(p, endian) * PRIME32_2;
+ v3 = XXH_rotl32(v3, 13);
+ v3 *= PRIME32_1;
+ p+=4;
+ v4 += XXH_readLE32(p, endian) * PRIME32_2;
+ v4 = XXH_rotl32(v4, 13);
+ v4 *= PRIME32_1;
+ p+=4;
+ }
+ while (p<=limit);
+
+ state->v1 = v1;
+ state->v2 = v2;
+ state->v3 = v3;
+ state->v4 = v4;
+ }
+
+ if (p < bEnd)
+ {
+ XXH_memcpy(state->mem32, p, bEnd-p);
+ state->memsize = (int)(bEnd-p);
+ }
+
+ return XXH_OK;
+}
+
+XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
+{
+ XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
+ else
+ return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
+}
+
+
+
+FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state_in, XXH_endianess
endian)
+{
+ const XXH_istate32_t* state = (const XXH_istate32_t*) state_in;
+ const BYTE * p = (const BYTE*)state->mem32;
+ const BYTE* bEnd = (const BYTE*)(state->mem32) + state->memsize;
+ U32 h32;
+
+ if (state->total_len >= 16)
+ {
+ h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) +
XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
+ }
+ else
+ {
+ h32 = state->seed + PRIME32_5;
+ }
+
+ h32 += (U32) state->total_len;
+
+ while (p+4<=bEnd)
+ {
+ h32 += XXH_readLE32(p, endian) * PRIME32_3;
+ h32 = XXH_rotl32(h32, 17) * PRIME32_4;
+ p+=4;
+ }
+
+ while (p<bEnd)
+ {
+ h32 += (*p) * PRIME32_5;
+ h32 = XXH_rotl32(h32, 11) * PRIME32_1;
+ p++;
+ }
+
+ h32 ^= h32 >> 15;
+ h32 *= PRIME32_2;
+ h32 ^= h32 >> 13;
+ h32 *= PRIME32_3;
+ h32 ^= h32 >> 16;
+
+ return h32;
+}
+
+
+unsigned int XXH32_digest (const XXH32_state_t* state_in)
+{
+ XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH32_digest_endian(state_in, XXH_littleEndian);
+ else
+ return XXH32_digest_endian(state_in, XXH_bigEndian);
+}
+
+
+FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state_in, const void*
input, size_t len, XXH_endianess endian)
+{
+ XXH_istate64_t * state = (XXH_istate64_t *) state_in;
+ const BYTE* p = (const BYTE*)input;
+ const BYTE* const bEnd = p + len;
+
+#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
+ if (input==NULL) return XXH_ERROR;
+#endif
+
+ state->total_len += len;
+
+ if (state->memsize + len < 32) /* fill in tmp buffer */
+ {
+ XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
+ state->memsize += (U32)len;
+ return XXH_OK;
+ }
+
+ if (state->memsize) /* some data left from previous update */
+ {
+ XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input,
32-state->memsize);
+ {
+ const U64* p64 = state->mem64;
+ state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
+ state->v1 = XXH_rotl64(state->v1, 31);
+ state->v1 *= PRIME64_1;
+ p64++;
+ state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
+ state->v2 = XXH_rotl64(state->v2, 31);
+ state->v2 *= PRIME64_1;
+ p64++;
+ state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
+ state->v3 = XXH_rotl64(state->v3, 31);
+ state->v3 *= PRIME64_1;
+ p64++;
+ state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
+ state->v4 = XXH_rotl64(state->v4, 31);
+ state->v4 *= PRIME64_1;
+ p64++;
+ }
+ p += 32-state->memsize;
+ state->memsize = 0;
+ }
+
+ if (p+32 <= bEnd)
+ {
+ const BYTE* const limit = bEnd - 32;
+ U64 v1 = state->v1;
+ U64 v2 = state->v2;
+ U64 v3 = state->v3;
+ U64 v4 = state->v4;
+
+ do
+ {
+ v1 += XXH_readLE64(p, endian) * PRIME64_2;
+ v1 = XXH_rotl64(v1, 31);
+ v1 *= PRIME64_1;
+ p+=8;
+ v2 += XXH_readLE64(p, endian) * PRIME64_2;
+ v2 = XXH_rotl64(v2, 31);
+ v2 *= PRIME64_1;
+ p+=8;
+ v3 += XXH_readLE64(p, endian) * PRIME64_2;
+ v3 = XXH_rotl64(v3, 31);
+ v3 *= PRIME64_1;
+ p+=8;
+ v4 += XXH_readLE64(p, endian) * PRIME64_2;
+ v4 = XXH_rotl64(v4, 31);
+ v4 *= PRIME64_1;
+ p+=8;
+ }
+ while (p<=limit);
+
+ state->v1 = v1;
+ state->v2 = v2;
+ state->v3 = v3;
+ state->v4 = v4;
+ }
+
+ if (p < bEnd)
+ {
+ XXH_memcpy(state->mem64, p, bEnd-p);
+ state->memsize = (int)(bEnd-p);
+ }
+
+ return XXH_OK;
+}
+
+XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
+{
+ XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
+ else
+ return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
+}
+
+
+
+FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state_in, XXH_endianess
endian)
+{
+ const XXH_istate64_t * state = (const XXH_istate64_t *) state_in;
+ const BYTE * p = (const BYTE*)state->mem64;
+ const BYTE* bEnd = (const BYTE*)state->mem64 + state->memsize;
+ U64 h64;
+
+ if (state->total_len >= 32)
+ {
+ U64 v1 = state->v1;
+ U64 v2 = state->v2;
+ U64 v3 = state->v3;
+ U64 v4 = state->v4;
+
+ h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4,
18);
+
+ v1 *= PRIME64_2;
+ v1 = XXH_rotl64(v1, 31);
+ v1 *= PRIME64_1;
+ h64 ^= v1;
+ h64 = h64*PRIME64_1 + PRIME64_4;
+
+ v2 *= PRIME64_2;
+ v2 = XXH_rotl64(v2, 31);
+ v2 *= PRIME64_1;
+ h64 ^= v2;
+ h64 = h64*PRIME64_1 + PRIME64_4;
+
+ v3 *= PRIME64_2;
+ v3 = XXH_rotl64(v3, 31);
+ v3 *= PRIME64_1;
+ h64 ^= v3;
+ h64 = h64*PRIME64_1 + PRIME64_4;
+
+ v4 *= PRIME64_2;
+ v4 = XXH_rotl64(v4, 31);
+ v4 *= PRIME64_1;
+ h64 ^= v4;
+ h64 = h64*PRIME64_1 + PRIME64_4;
+ }
+ else
+ {
+ h64 = state->seed + PRIME64_5;
+ }
+
+ h64 += (U64) state->total_len;
+
+ while (p+8<=bEnd)
+ {
+ U64 k1 = XXH_readLE64(p, endian);
+ k1 *= PRIME64_2;
+ k1 = XXH_rotl64(k1,31);
+ k1 *= PRIME64_1;
+ h64 ^= k1;
+ h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
+ p+=8;
+ }
+
+ if (p+4<=bEnd)
+ {
+ h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
+ h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
+ p+=4;
+ }
+
+ while (p<bEnd)
+ {
+ h64 ^= (*p) * PRIME64_5;
+ h64 = XXH_rotl64(h64, 11) * PRIME64_1;
+ p++;
+ }
+
+ h64 ^= h64 >> 33;
+ h64 *= PRIME64_2;
+ h64 ^= h64 >> 29;
+ h64 *= PRIME64_3;
+ h64 ^= h64 >> 32;
+
+ return h64;
+}
+
+
+unsigned long long XXH64_digest (const XXH64_state_t* state_in)
+{
+ XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
+
+ if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
+ return XXH64_digest_endian(state_in, XXH_littleEndian);
+ else
+ return XXH64_digest_endian(state_in, XXH_bigEndian);
+}
+
+
diff --git a/amiga/hash/xxhash.h b/amiga/hash/xxhash.h
new file mode 100644
index 0000000..c60aa61
--- /dev/null
+++ b/amiga/hash/xxhash.h
@@ -0,0 +1,192 @@
+/*
+ xxHash - Extremely Fast Hash algorithm
+ Header File
+ Copyright (C) 2012-2015, Yann Collet.
+
+ BSD 2-Clause License (
http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ You can contact the author at :
+ - xxHash source repository :
https://github.com/Cyan4973/xxHash
+*/
+
+/* Notice extracted from xxHash homepage :
+
+xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
+It also successfully passes all tests from the SMHasher suite.
+
+Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
+
+Name Speed Q.Score Author
+xxHash 5.4 GB/s 10
+CrapWow 3.2 GB/s 2 Andrew
+MumurHash 3a 2.7 GB/s 10 Austin Appleby
+SpookyHash 2.0 GB/s 10 Bob Jenkins
+SBox 1.4 GB/s 9 Bret Mulvey
+Lookup3 1.2 GB/s 9 Bob Jenkins
+SuperFastHash 1.2 GB/s 1 Paul Hsieh
+CityHash64 1.05 GB/s 10 Pike & Alakuijala
+FNV 0.55 GB/s 5 Fowler, Noll, Vo
+CRC32 0.43 GB/s 9
+MD5-32 0.33 GB/s 10 Ronald L. Rivest
+SHA1-32 0.28 GB/s 10
+
+Q.Score is a measure of quality of the hash function.
+It depends on successfully passing SMHasher test set.
+10 is a perfect score.
+
+A 64-bits version, named XXH64, is available since r35.
+It offers much better speed, but for 64-bits applications only.
+Name Speed on 64 bits Speed on 32 bits
+XXH64 13.8 GB/s 1.9 GB/s
+XXH32 6.8 GB/s 6.0 GB/s
+*/
+
+#pragma once
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+/*****************************
+* Definitions
+*****************************/
+#include <stddef.h> /* size_t */
+typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
+
+
+/*****************************
+* Namespace Emulation
+*****************************/
+/* Motivations :
+
+If you need to include xxHash into your library,
+but wish to avoid xxHash symbols to be present on your library interface
+in an effort to avoid potential name collision if another library also includes xxHash,
+
+you can use XXH_NAMESPACE, which will automatically prefix any symbol from xxHash
+with the value of XXH_NAMESPACE (so avoid to keep it NULL, and avoid numeric values).
+
+Note that no change is required within the calling program :
+it can still call xxHash functions using their regular name.
+They will be automatically translated by this header.
+*/
+#ifdef XXH_NAMESPACE
+# define XXH_CAT(A,B) A##B
+# define XXH_NAME2(A,B) XXH_CAT(A,B)
+# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
+# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
+# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
+# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
+# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
+# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
+# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
+# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
+# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
+# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
+# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
+# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
+#endif
+
+
+/*****************************
+* Simple Hash Functions
+*****************************/
+
+unsigned int XXH32 (const void* input, size_t length, unsigned seed);
+unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed);
+
+/*
+XXH32() :
+ Calculate the 32-bits hash of sequence "length" bytes stored at memory
address "input".
+ The memory between input & input+length must be valid (allocated and
read-accessible).
+ "seed" can be used to alter the result predictably.
+ This function successfully passes all SMHasher tests.
+ Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
+XXH64() :
+ Calculate the 64-bits hash of sequence of length "len" stored at memory
address "input".
+ Faster on 64-bits systems. Slower on 32-bits systems.
+*/
+
+
+
+/*****************************
+* Advanced Hash Functions
+*****************************/
+typedef struct { long long ll[ 6]; } XXH32_state_t;
+typedef struct { long long ll[11]; } XXH64_state_t;
+
+/*
+These structures allow static allocation of XXH states.
+States must then be initialized using XXHnn_reset() before first use.
+
+If you prefer dynamic allocation, please refer to functions below.
+*/
+
+XXH32_state_t* XXH32_createState(void);
+XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
+
+XXH64_state_t* XXH64_createState(void);
+XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
+
+/*
+These functions create and release memory for XXH state.
+States must then be initialized using XXHnn_reset() before first use.
+*/
+
+
+XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned seed);
+XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
+unsigned int XXH32_digest (const XXH32_state_t* statePtr);
+
+XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
+XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t
length);
+unsigned long long XXH64_digest (const XXH64_state_t* statePtr);
+
+/*
+These functions calculate the xxHash of an input provided in multiple smaller packets,
+as opposed to an input provided as a single block.
+
+XXH state space must first be allocated, using either static or dynamic method provided
above.
+
+Start a new hash by initializing state with a seed, using XXHnn_reset().
+
+Then, feed the hash state by calling XXHnn_update() as many times as necessary.
+Obviously, input must be valid, meaning allocated and read accessible.
+The function returns an error code, with 0 meaning OK, and any other value meaning there
is an error.
+
+Finally, you can produce a hash anytime, by using XXHnn_digest().
+This function returns the final nn-bits hash.
+You can nonetheless continue feeding the hash state with more input,
+and therefore get some new hashes, by calling again XXHnn_digest().
+
+When you are done, don't forget to free XXH state space, using typically
XXHnn_freeState().
+*/
+
+
+#if defined (__cplusplus)
+}
+#endif
diff --git a/amiga/menu.c b/amiga/menu.c
index 25345d0..6d885dc 100644
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -379,8 +379,7 @@ HOOKF(void, ami_menu_item_browser_scale_decrease, APTR, window, struct
IntuiMess
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
- if(gwin->gw->scale > 0.1)
- ami_gui_set_scale(gwin->gw, gwin->gw->scale - 0.1);
+ ami_gui_set_scale(gwin->gw, gwin->gw->scale - 0.1);
}
HOOKF(void, ami_menu_item_browser_scale_normal, APTR, window, struct IntuiMessage *)
diff --git a/amiga/os3support.h b/amiga/os3support.h
index 45a917a..dddedb7 100644
--- a/amiga/os3support.h
+++ b/amiga/os3support.h
@@ -144,6 +144,7 @@
#define FOpen(A,B,C) Open(A,B)
#define FClose(A) Close(A)
#define CreateDirTree(D) CreateDir(D) /*\todo This isn't quite right */
+#define SetCurrentDir(L) CurrentDir(L)
#define DevNameFromLock(A,B,C,D) NameFromLock(A,B,C)
/* Exec */
diff --git a/amiga/resources/Themes/AISS/NetSurf.info
b/amiga/resources/Themes/AISS/NetSurf.info
index b46db4a..7027575 100644
Binary files a/amiga/resources/Themes/AISS/NetSurf.info and
b/amiga/resources/Themes/AISS/NetSurf.info differ
diff --git a/amiga/resources/Themes/Default/NetSurf.info
b/amiga/resources/Themes/Default/NetSurf.info
index 8d90882..0e60172 100644
Binary files a/amiga/resources/Themes/Default/NetSurf.info and
b/amiga/resources/Themes/Default/NetSurf.info differ
diff --git a/amiga/tree.c b/amiga/tree.c
index 6f363e7..e4f7eb3 100644
--- a/amiga/tree.c
+++ b/amiga/tree.c
@@ -904,7 +904,7 @@ void ami_tree_close(struct treeview_window *twin)
ami_ssl_free(twin);
}
- if(twin->type == AMI_TREE_SSLCERT)
+ if(twin->type == AMI_TREE_HOTLIST)
ami_gui_hotlist_update_all();
}
diff --git a/javascript/duktape/Event.bnd b/javascript/duktape/Event.bnd
index 38e4640..a0bc3c3 100644
--- a/javascript/duktape/Event.bnd
+++ b/javascript/duktape/Event.bnd
@@ -19,6 +19,11 @@ init Event (struct dom_event *evt)
dom_event_ref(evt);
%}
+fini Event ()
+%{
+ dom_event_unref(priv->evt);
+%}
+
/* Note: many of these could be automatics once nsgenbind gets there. */
getter Event::type ()
diff --git a/javascript/duktape/dukky.c b/javascript/duktape/dukky.c
index b65e94b..f1f62d4 100644
--- a/javascript/duktape/dukky.c
+++ b/javascript/duktape/dukky.c
@@ -289,6 +289,41 @@ dukky_inject_not_ctr(duk_context *ctx, int idx, const char *name)
return;
}
+/* Duktape heap utility functions */
+
+/* We need to override the defaults because not all platforms are fully ANSI
+ * compatible. E.g. RISC OS gets upset if we malloc or realloc a zero byte
+ * block, as do debugging tools such as Electric Fence by Bruce Perens.
+ */
+
+static void *dukky_alloc_function(void *udata, duk_size_t size)
+{
+ if (size == 0)
+ return NULL;
+
+ return malloc(size);
+}
+
+static void *dukky_realloc_function(void *udata, void *ptr, duk_size_t size)
+{
+ if (ptr == NULL && size == 0)
+ return NULL;
+
+ if (size == 0) {
+ free(ptr);
+ return NULL;
+ }
+
+ return realloc(ptr, size);
+}
+
+static void dukky_free_function(void *udata, void *ptr)
+{
+ if (ptr != NULL)
+ free(ptr);
+}
+
+
/**************************************** js.h ******************************/
struct jscontext {
duk_context *ctx;
@@ -322,7 +357,12 @@ nserror js_newcontext(int timeout, jscallback *cb, void *cbctx,
*jsctx = NULL;
LOG("Creating new duktape javascript context");
if (ret == NULL) return NSERROR_NOMEM;
- ctx = ret->ctx = duk_create_heap_default();
+ ctx = ret->ctx = duk_create_heap(
+ dukky_alloc_function,
+ dukky_realloc_function,
+ dukky_free_function,
+ NULL,
+ NULL);
if (ret->ctx == NULL) { free(ret); return NSERROR_NOMEM; }
/* Create the prototype stuffs */
duk_push_global_object(ctx);
@@ -408,13 +448,6 @@ bool js_exec(jscontext *ctx, const char *txt, size_t txtlen)
return duk_get_boolean(CTX, 0);
}
-bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct
dom_node *target)
-{
- /* La La La */
- LOG("Oh dear, an event: %s", type);
- return true;
-}
-
/*** New style event handling ***/
static void dukky_push_event(duk_context *ctx, dom_event *evt)
@@ -457,6 +490,22 @@ static void dukky_push_handler_code_(duk_context *ctx, dom_string
*name,
dom_string *onname, *val;
dom_element *ele = (dom_element *)et;
dom_exception exc;
+ dom_node_type ntype;
+
+ /* Currently safe since libdom has no event targets which are not
+ * nodes. Reconsider this as and when we work out how to have
+ * window do stuff
+ */
+ exc = dom_node_get_node_type(et, &ntype);
+ if (exc != DOM_NO_ERR) {
+ duk_push_lstring(ctx, "", 0);
+ return;
+ }
+
+ if (ntype != DOM_ELEMENT_NODE) {
+ duk_push_lstring(ctx, "", 0);
+ return;
+ }
exc = dom_string_concat(corestring_dom_on, name, &onname);
if (exc != DOM_NO_ERR) {
@@ -494,6 +543,8 @@ bool dukky_get_current_value_of_event_handler(duk_context *ctx,
duk_pop_2(ctx);
/* ... node */
dukky_push_handler_code_(ctx, name, et);
+ /* ... node handlercode? */
+ /* TODO: If this is null, clean up and propagate */
/* ... node handlercode */
/** @todo This is entirely wrong, but it's hard to get right */
duk_push_string(ctx, "function (event) {");
@@ -668,6 +719,16 @@ void js_handle_new_element(jscontext *ctx, struct dom_element *node)
dom_ulong siz;
dom_attr *attr = NULL;
dom_string *key = NULL;
+ dom_string *nodename;
+ duk_bool_t is_body = false;
+
+ exc = dom_node_get_node_name(node, &nodename);
+ if (exc != DOM_NO_ERR) return;
+
+ if (nodename == corestring_dom_BODY)
+ is_body = true;
+
+ dom_string_unref(nodename);
exc = dom_node_get_attributes(node, &map);
if (exc != DOM_NO_ERR) return;
@@ -681,6 +742,19 @@ void js_handle_new_element(jscontext *ctx, struct dom_element *node)
if (exc != DOM_NO_ERR) goto out;
exc = dom_attr_get_name(attr, &key);
if (exc != DOM_NO_ERR) goto out;
+ if (is_body && (
+ key == corestring_dom_onblur ||
+ key == corestring_dom_onerror ||
+ key == corestring_dom_onfocus ||
+ key == corestring_dom_onload ||
+ key == corestring_dom_onresize ||
+ key == corestring_dom_onscroll)) {
+ /* This is a forwarded event, it doesn't matter,
+ * we should skip registering for it and later
+ * we will register it for Window itself
+ */
+ goto skip_register;
+ }
if (dom_string_length(key) > 2) {
/* Can be on* */
const uint8_t *data = (const uint8_t *)dom_string_data(key);
@@ -696,6 +770,7 @@ void js_handle_new_element(jscontext *ctx, struct dom_element *node)
}
}
}
+ skip_register:
dom_string_unref(key); key = NULL;
dom_node_unref(attr); attr = NULL;
}
@@ -723,3 +798,106 @@ void js_event_cleanup(jscontext *ctx, struct dom_event *evt)
duk_pop(CTX);
/* ... */
}
+
+bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct
dom_node *target)
+{
+ dom_exception exc;
+ dom_event *evt;
+ dom_event_target *body;
+
+ LOG("Event: %s (doc=%p, target=%p)", type, doc, target);
+
+ /** @todo Make this more generic, this only handles load and only
+ * targetting the window, so that we actually stand a chance of
+ * getting 3.4 out.
+ */
+
+ if (target != NULL)
+ /* Swallow non-Window-targetted events quietly */
+ return true;
+
+ if (strcmp(type, "load") != 0)
+ /* Swallow non-load events quietly */
+ return true;
+
+ /* Okay, we're processing load, targetted at Window, do the single
+ * thing which gets us there, which is to find the appropriate event
+ * handler and call it. If we have no event handler on Window then
+ * we divert to the body, and if there's no event handler there
+ * we swallow the event silently
+ */
+
+ exc = dom_event_create(&evt);
+ if (exc != DOM_NO_ERR) return true;
+ exc = dom_event_init(evt, corestring_dom_load, false, false);
+ if (exc != DOM_NO_ERR) {
+ dom_event_unref(evt);
+ return true;
+ }
+ /* ... */
+ duk_get_global_string(CTX, HANDLER_MAGIC);
+ /* ... handlers */
+ duk_push_lstring(CTX, "load", 4);
+ /* ... handlers "load" */
+ duk_get_prop(CTX, -2);
+ /* ... handlers handler? */
+ if (duk_is_undefined(CTX, -1)) {
+ /* No handler here, *try* and retrieve a handler from
+ * the body
+ */
+ duk_pop(CTX);
+ /* ... handlers */
+ exc = dom_html_document_get_body(doc, &body);
+ if (exc != DOM_NO_ERR) {
+ dom_event_unref(evt);
+ return true;
+ }
+ dukky_push_node(CTX, (struct dom_node *)body);
+ /* ... handlers bodynode */
+ if (dukky_get_current_value_of_event_handler(
+ CTX, corestring_dom_load, body) == false) {
+ /* ... handlers */
+ duk_pop(CTX);
+ return true;
+ }
+ /* ... handlers handler bodynode */
+ duk_pop(CTX);
+ }
+ /* ... handlers handler */
+ duk_insert(CTX, -2);
+ /* ... handler handlers */
+ duk_pop(CTX);
+ /* ... handler */
+ duk_push_global_object(CTX);
+ /* ... handler Window */
+ dukky_push_event(CTX, evt);
+ /* ... handler Window event */
+ if (duk_pcall_method(CTX, 1) != 0) {
+ /* Failed to run the handler */
+ /* ... err */
+ LOG("OH NOES! An error running a handler. Meh.");
+ duk_get_prop_string(CTX, -1, "name");
+ duk_get_prop_string(CTX, -2, "message");
+ duk_get_prop_string(CTX, -3, "fileName");
+ duk_get_prop_string(CTX, -4, "lineNumber");
+ duk_get_prop_string(CTX, -5, "stack");
+ /* ... err name message fileName lineNumber stack */
+ LOG("Uncaught error in JS: %s: %s", duk_safe_to_string(CTX, -5),
+ duk_safe_to_string(CTX, -4));
+ LOG(" was at: %s line %s", duk_safe_to_string(CTX, -3),
+ duk_safe_to_string(CTX, -2));
+ LOG(" Stack trace: %s", duk_safe_to_string(CTX, -1));
+
+ duk_pop_n(CTX, 6);
+ /* ... */
+ js_event_cleanup(ctx, evt);
+ dom_event_unref(evt);
+ return true;
+ }
+ /* ... result */
+ duk_pop(CTX);
+ /* ... */
+ js_event_cleanup(ctx, evt);
+ dom_event_unref(evt);
+ return true;
+}
diff --git a/test/js/event-onloadfrombody.html b/test/js/event-onloadfrombody.html
new file mode 100644
index 0000000..be491e6
--- /dev/null
+++ b/test/js/event-onloadfrombody.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>alert based onload (from body) example</title>
+
+</head>
+
+<body onload="alert('Running onload')">
+<h1>Just look at the log</h1>
+</body>
+</html>
diff --git a/test/js/event-onloadfrombody2.html b/test/js/event-onloadfrombody2.html
new file mode 100644
index 0000000..542e5ec
--- /dev/null
+++ b/test/js/event-onloadfrombody2.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>alert based onload (from body IDL attribute) example</title>
+
+</head>
+
+<body>
+ <h1>Just look at the log</h1>
+ <script type="text/javascript">
+ document.body.onload = function() { alert("onload event from IDL
attribute"); };
+ </script>
+</body>
+</html>
diff --git a/test/js/index.html b/test/js/index.html
index a1bc4c4..f5420ed 100644
--- a/test/js/index.html
+++ b/test/js/index.html
@@ -80,6 +80,7 @@
<h2>Dom events</h2>
<ul>
<li><a href="event-onload.html">window.onload</a></li>
+<li><a
href="event-onloadfrombody.html">body.onload</a></li>
<li><a
href="event-onclick.html">button.onclick</a></li>
</ul>
diff --git a/utils/corestrings.c b/utils/corestrings.c
index c263565..493dace 100644
--- a/utils/corestrings.c
+++ b/utils/corestrings.c
@@ -269,6 +269,12 @@ dom_string *corestring_dom_radio;
dom_string *corestring_dom_checkbox;
dom_string *corestring_dom_file;
dom_string *corestring_dom_on;
+dom_string *corestring_dom_onblur;
+dom_string *corestring_dom_onerror;
+dom_string *corestring_dom_onfocus;
+dom_string *corestring_dom_onload;
+dom_string *corestring_dom_onresize;
+dom_string *corestring_dom_onscroll;
dom_string *corestring_dom___ns_key_box_node_data;
dom_string *corestring_dom___ns_key_libcss_node_data;
dom_string *corestring_dom___ns_key_file_name_node_data;
@@ -544,7 +550,15 @@ void corestrings_fini(void)
CSS_DOM_STRING_UNREF(radio);
CSS_DOM_STRING_UNREF(checkbox);
CSS_DOM_STRING_UNREF(file);
+ /* DOM event prefix */
CSS_DOM_STRING_UNREF(on);
+ /* DOM events forwarded from body to window */
+ CSS_DOM_STRING_UNREF(onblur);
+ CSS_DOM_STRING_UNREF(onerror);
+ CSS_DOM_STRING_UNREF(onfocus);
+ CSS_DOM_STRING_UNREF(onload);
+ CSS_DOM_STRING_UNREF(onresize);
+ CSS_DOM_STRING_UNREF(onscroll);
/* DOM userdata keys, not really CSS */
CSS_DOM_STRING_UNREF(__ns_key_box_node_data);
CSS_DOM_STRING_UNREF(__ns_key_libcss_node_data);
@@ -863,7 +877,15 @@ nserror corestrings_init(void)
CSS_DOM_STRING_INTERN(radio);
CSS_DOM_STRING_INTERN(checkbox);
CSS_DOM_STRING_INTERN(file);
+ /* DOM event prefix */
CSS_DOM_STRING_INTERN(on);
+ /* DOM events forwarded from body to window */
+ CSS_DOM_STRING_INTERN(onblur);
+ CSS_DOM_STRING_INTERN(onerror);
+ CSS_DOM_STRING_INTERN(onfocus);
+ CSS_DOM_STRING_INTERN(onload);
+ CSS_DOM_STRING_INTERN(onresize);
+ CSS_DOM_STRING_INTERN(onscroll);
/* DOM userdata keys, not really CSS */
CSS_DOM_STRING_INTERN(__ns_key_box_node_data);
CSS_DOM_STRING_INTERN(__ns_key_libcss_node_data);
diff --git a/utils/corestrings.h b/utils/corestrings.h
index c72e8b0..4913e73 100644
--- a/utils/corestrings.h
+++ b/utils/corestrings.h
@@ -284,7 +284,16 @@ extern struct dom_string *corestring_dom_image;
extern struct dom_string *corestring_dom_radio;
extern struct dom_string *corestring_dom_checkbox;
extern struct dom_string *corestring_dom_file;
+/* Event prefix */
extern struct dom_string *corestring_dom_on;
+/* These are the event attributes which forward from body to window */
+extern struct dom_string *corestring_dom_onblur;
+extern struct dom_string *corestring_dom_onerror;
+extern struct dom_string *corestring_dom_onfocus;
+extern struct dom_string *corestring_dom_onload;
+extern struct dom_string *corestring_dom_onresize;
+extern struct dom_string *corestring_dom_onscroll;
+
/* DOM userdata keys */
extern struct dom_string *corestring_dom___ns_key_box_node_data;
extern struct dom_string *corestring_dom___ns_key_libcss_node_data;
--
NetSurf Browser