diff options
author | Vincent Sanders <vince@netsurf-browser.org> | 2018-05-10 11:34:26 +0100 |
---|---|---|
committer | Vincent Sanders <vince@kyllikki.org> | 2018-05-10 13:37:02 +0100 |
commit | 2a03ea30490892ac52b3da325ab78e1aa888f83e (patch) | |
tree | d041e4a2aab3b224ad41612d47ea2119895e27ac /render/imagemap.c | |
parent | 1b892391d7859398c212b9fda5b532308fa6e8fd (diff) | |
download | netsurf-2a03ea30490892ac52b3da325ab78e1aa888f83e.tar.gz netsurf-2a03ea30490892ac52b3da325ab78e1aa888f83e.tar.bz2 |
move html and text content handlers where they belong
Diffstat (limited to 'render/imagemap.c')
-rw-r--r-- | render/imagemap.c | 801 |
1 files changed, 0 insertions, 801 deletions
diff --git a/render/imagemap.c b/render/imagemap.c deleted file mode 100644 index 0d3b42a1b..000000000 --- a/render/imagemap.c +++ /dev/null @@ -1,801 +0,0 @@ -/* - * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk> - * - * 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/>. - */ - -/* - * Much of this shamelessly copied from utils/messages.c - */ - -#include <assert.h> -#include <stdbool.h> -#include <string.h> -#include <strings.h> - -#include <dom/dom.h> - -#include "utils/log.h" -#include "utils/corestrings.h" -#include "content/content_protected.h" -#include "content/hlcache.h" - -#include "render/box.h" -#include "render/html_internal.h" -#include "render/imagemap.h" - -#define HASH_SIZE 31 /* fixed size hash table */ - -typedef enum { - IMAGEMAP_DEFAULT, - IMAGEMAP_RECT, - IMAGEMAP_CIRCLE, - IMAGEMAP_POLY -} imagemap_entry_type; - -struct mapentry { - imagemap_entry_type type; /**< type of shape */ - nsurl *url; /**< absolute url to go to */ - char *target; /**< target frame (if any) */ - union { - struct { - int x; /**< x coordinate of centre */ - int y; /**< y coordinate of center */ - int r; /**< radius of circle */ - } circle; - struct { - int x0; /**< left hand edge */ - int y0; /**< top edge */ - int x1; /**< right hand edge */ - int y1; /**< bottom edge */ - } rect; - struct { - int num; /**< number of points */ - float *xcoords; /**< x coordinates */ - float *ycoords; /**< y coordinates */ - } poly; - } bounds; - struct mapentry *next; /**< next entry in list */ -}; - -struct imagemap { - char *key; /**< key for this entry */ - struct mapentry *list; /**< pointer to linked list of entries */ - struct imagemap *next; /**< next entry in this hash chain */ -}; - -/** - * Create hashtable of imagemaps - * - * \param c The containing content - * \return true on success, false otherwise - */ -static bool imagemap_create(html_content *c) -{ - assert(c != NULL); - - if (c->imagemaps == NULL) { - c->imagemaps = calloc(HASH_SIZE, sizeof(struct imagemap *)); - if (c->imagemaps == NULL) { - return false; - } - } - - return true; -} - -/** - * Hash function. - * - * \param key The key to hash. - * \return The hashed value. - */ -static unsigned int imagemap_hash(const char *key) -{ - unsigned int z = 0; - - if (key == 0) return 0; - - for (; *key != 0; key++) { - z += *key & 0x1f; - } - - return (z % (HASH_SIZE - 1)) + 1; -} - -/** - * Add an imagemap to the hashtable, creating it if it doesn't exist - * - * \param c The containing content - * \param key The name of the imagemap - * \param list List of map regions - * \return true on succes, false otherwise - */ -static bool -imagemap_add(html_content *c, dom_string *key, struct mapentry *list) -{ - struct imagemap *map; - unsigned int slot; - - assert(c != NULL); - assert(key != NULL); - assert(list != NULL); - - if (imagemap_create(c) == false) - return false; - - map = calloc(1, sizeof(*map)); - if (map == NULL) - return false; - - /* \todo Stop relying on NULL termination of dom_string */ - map->key = strdup(dom_string_data(key)); - if (map->key == NULL) { - free(map); - return false; - } - - map->list = list; - - slot = imagemap_hash(map->key); - - map->next = c->imagemaps[slot]; - c->imagemaps[slot] = map; - - return true; -} - -/** - * Free list of imagemap entries - * - * \param list Pointer to head of list - */ -static void imagemap_freelist(struct mapentry *list) -{ - struct mapentry *entry, *prev; - - assert(list != NULL); - - entry = list; - - while (entry != NULL) { - prev = entry; - - nsurl_unref(entry->url); - - if (entry->target) - free(entry->target); - - if (entry->type == IMAGEMAP_POLY) { - free(entry->bounds.poly.xcoords); - free(entry->bounds.poly.ycoords); - } - - entry = entry->next; - free(prev); - } -} - -/** - * Destroy hashtable of imagemaps - * - * \param c The containing content - */ -void imagemap_destroy(html_content *c) -{ - unsigned int i; - - assert(c != NULL); - - /* no imagemaps -> return */ - if (c->imagemaps == NULL) - return; - - for (i = 0; i != HASH_SIZE; i++) { - struct imagemap *map, *next; - - map = c->imagemaps[i]; - while (map != NULL) { - next = map->next; - imagemap_freelist(map->list); - free(map->key); - free(map); - map = next; - } - } - - free(c->imagemaps); -} - -/** - * Dump imagemap data to the log - * - * \param c The containing content - */ -void imagemap_dump(html_content *c) -{ - unsigned int i; - - int j; - - assert(c != NULL); - - if (c->imagemaps == NULL) - return; - - for (i = 0; i != HASH_SIZE; i++) { - struct imagemap *map; - struct mapentry *entry; - - map = c->imagemaps[i]; - while (map != NULL) { - NSLOG(netsurf, INFO, "Imagemap: %s", map->key); - - for (entry = map->list; entry; entry = entry->next) { - switch (entry->type) { - case IMAGEMAP_DEFAULT: - NSLOG(netsurf, INFO, "\tDefault: %s", - nsurl_access(entry->url)); - break; - case IMAGEMAP_RECT: - NSLOG(netsurf, INFO, - "\tRectangle: %s: [(%d,%d),(%d,%d)]", - nsurl_access(entry->url), - entry->bounds.rect.x0, - entry->bounds.rect.y0, - entry->bounds.rect.x1, - entry->bounds.rect.y1); - break; - case IMAGEMAP_CIRCLE: - NSLOG(netsurf, INFO, - "\tCircle: %s: [(%d,%d),%d]", - nsurl_access(entry->url), - entry->bounds.circle.x, - entry->bounds.circle.y, - entry->bounds.circle.r); - break; - case IMAGEMAP_POLY: - NSLOG(netsurf, INFO, - "\tPolygon: %s:", - nsurl_access(entry->url)); - for (j = 0; j != entry->bounds.poly.num; - j++) { - fprintf(stderr, "(%d,%d) ", - (int)entry->bounds.poly.xcoords[j], - (int)entry->bounds.poly.ycoords[j]); - } - fprintf(stderr,"\n"); - break; - } - } - map = map->next; - } - } -} - -/** - * Adds an imagemap entry to the list - * - * \param c The html content that the imagemap belongs to - * \param n The xmlNode representing the entry to add - * \param base_url Base URL for resolving relative URLs - * \param entry Pointer to list of entries - * \param tagtype The type of tag - * \return false on memory exhaustion, true otherwise - */ -static bool -imagemap_addtolist(const struct html_content *c, dom_node *n, nsurl *base_url, - struct mapentry **entry, dom_string *tagtype) -{ - dom_exception exc; - dom_string *href = NULL, *target = NULL, *shape = NULL; - dom_string *coords = NULL; - struct mapentry *new_map, *temp; - bool ret = true; - - if (dom_string_caseless_isequal(tagtype, corestring_dom_area)) { - bool nohref = false; - exc = dom_element_has_attribute(n, - corestring_dom_nohref, &nohref); - if ((exc != DOM_NO_ERR) || nohref) - /* Skip <area nohref="anything" /> */ - goto ok_out; - } - - exc = dom_element_get_attribute(n, corestring_dom_href, &href); - if (exc != DOM_NO_ERR || href == NULL) { - /* No href="" attribute, skip this element */ - goto ok_out; - } - - exc = dom_element_get_attribute(n, corestring_dom_target, &target); - if (exc != DOM_NO_ERR) { - goto ok_out; - } - - exc = dom_element_get_attribute(n, corestring_dom_shape, &shape); - if (exc != DOM_NO_ERR) { - goto ok_out; - } - - /* If there's no shape, we default to rectangles */ - if (shape == NULL) - shape = dom_string_ref(corestring_dom_rect); - - if (!dom_string_caseless_lwc_isequal(shape, corestring_lwc_default)) { - /* If not 'default' and there's no 'coords' give up */ - exc = dom_element_get_attribute(n, corestring_dom_coords, - &coords); - if (exc != DOM_NO_ERR || coords == NULL) { - goto ok_out; - } - } - - new_map = calloc(1, sizeof(*new_map)); - if (new_map == NULL) { - goto bad_out; - } - - if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_rect) || - dom_string_caseless_lwc_isequal(shape, corestring_lwc_rectangle)) - new_map->type = IMAGEMAP_RECT; - else if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_circle)) - new_map->type = IMAGEMAP_CIRCLE; - else if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_poly) || - dom_string_caseless_lwc_isequal(shape, corestring_lwc_polygon)) - new_map->type = IMAGEMAP_POLY; - else if (dom_string_caseless_lwc_isequal(shape, corestring_lwc_default)) - new_map->type = IMAGEMAP_DEFAULT; - else - goto bad_out; - - if (box_extract_link(c, href, base_url, &new_map->url) == false) - goto bad_out; - - if (new_map->url == NULL) { - /* non-fatal error -> ignore this */ - goto ok_free_map_out; - } - - if (target != NULL) { - /* Copy target into the map */ - new_map->target = malloc(dom_string_byte_length(target) + 1); - if (new_map->target == NULL) - goto bad_out; - /* Safe, but relies on dom_strings being NULL terminated */ - /* \todo Do this better */ - strcpy(new_map->target, dom_string_data(target)); - } - - if (new_map->type != IMAGEMAP_DEFAULT) { - int x, y; - float *xcoords, *ycoords; - /* coordinates are a comma-separated list of values */ - char *val = strtok((char *)dom_string_data(coords), ","); - int num = 1; - - switch (new_map->type) { - case IMAGEMAP_RECT: - /* (left, top, right, bottom) */ - while (val != NULL && num <= 4) { - switch (num) { - case 1: - new_map->bounds.rect.x0 = atoi(val); - break; - case 2: - new_map->bounds.rect.y0 = atoi(val); - break; - case 3: - new_map->bounds.rect.x1 = atoi(val); - break; - case 4: - new_map->bounds.rect.y1 = atoi(val); - break; - } - - num++; - val = strtok(NULL, ","); - } - break; - case IMAGEMAP_CIRCLE: - /* (x, y, radius ) */ - while (val != NULL && num <= 3) { - switch (num) { - case 1: - new_map->bounds.circle.x = atoi(val); - break; - case 2: - new_map->bounds.circle.y = atoi(val); - break; - case 3: - new_map->bounds.circle.r = atoi(val); - break; - } - - num++; - val = strtok(NULL, ","); - } - break; - case IMAGEMAP_POLY: - new_map->bounds.poly.xcoords = NULL; - new_map->bounds.poly.ycoords = NULL; - - while (val != NULL) { - x = atoi(val); - - val = strtok(NULL, ","); - if (val == NULL) - break; - - y = atoi(val); - - xcoords = realloc(new_map->bounds.poly.xcoords, - num * sizeof(float)); - if (xcoords == NULL) { - goto bad_out; - } - new_map->bounds.poly.xcoords = xcoords; - - ycoords = realloc(new_map->bounds.poly.ycoords, - num * sizeof(float)); - if (ycoords == NULL) { - goto bad_out; - } - new_map->bounds.poly.ycoords = ycoords; - - new_map->bounds.poly.xcoords[num - 1] = x; - new_map->bounds.poly.ycoords[num - 1] = y; - - num++; - val = strtok(NULL, ","); - } - - new_map->bounds.poly.num = num - 1; - - break; - default: - break; - } - } - - new_map->next = NULL; - - if (*entry) { - /* add to END of list */ - for (temp = (*entry); temp->next != NULL; temp = temp->next) - ; - temp->next = new_map; - } else { - (*entry) = new_map; - } - - /* All good, linked in, let's clean up */ - goto ok_out; - -bad_out: - ret = false; -ok_free_map_out: - if (new_map != NULL) { - if (new_map->url != NULL) - nsurl_unref(new_map->url); - if (new_map->type == IMAGEMAP_POLY && - new_map->bounds.poly.ycoords != NULL) - free(new_map->bounds.poly.ycoords); - if (new_map->type == IMAGEMAP_POLY && - new_map->bounds.poly.xcoords != NULL) - free(new_map->bounds.poly.xcoords); - if (new_map->target != NULL) - free(new_map->target); - - free(new_map); - } -ok_out: - if (href != NULL) - dom_string_unref(href); - if (target != NULL) - dom_string_unref(target); - if (shape != NULL) - dom_string_unref(shape); - if (coords != NULL) - dom_string_unref(coords); - - return ret; -} - -/** - * Extract an imagemap from html source - * - * \param node XML node containing map - * \param c Content containing document - * \param entry List of map entries - * \param tname The sub-tags to consider on this pass - * \return false on memory exhaustion, true otherwise - */ -static bool -imagemap_extract_map_entries(dom_node *node, html_content *c, - struct mapentry **entry, dom_string *tname) -{ - dom_nodelist *nlist; - dom_exception exc; - unsigned long ent; - uint32_t tag_count; - - exc = dom_element_get_elements_by_tag_name(node, tname, &nlist); - if (exc != DOM_NO_ERR) { - return false; - } - - exc = dom_nodelist_get_length(nlist, &tag_count); - if (exc != DOM_NO_ERR) { - dom_nodelist_unref(nlist); - return false; - } - - for (ent = 0; ent < tag_count; ++ent) { - dom_node *subnode; - - exc = dom_nodelist_item(nlist, ent, &subnode); - if (exc != DOM_NO_ERR) { - dom_nodelist_unref(nlist); - return false; - } - if (imagemap_addtolist(c, subnode, c->base_url, - entry, tname) == false) { - dom_node_unref(subnode); - dom_nodelist_unref(nlist); - return false; - } - dom_node_unref(subnode); - } - - dom_nodelist_unref(nlist); - - return true; -} - -/** - * Extract an imagemap from html source - * - * \param node XML node containing map - * \param c Content containing document - * \param entry List of map entries - * \return false on memory exhaustion, true otherwise - */ -static bool imagemap_extract_map(dom_node *node, html_content *c, - struct mapentry **entry) -{ - if (imagemap_extract_map_entries(node, c, entry, - corestring_dom_area) == false) - return false; - return imagemap_extract_map_entries(node, c, entry, - corestring_dom_a); -} - -/** - * Extract all imagemaps from a document tree - * - * \param c The content to extract imagemaps from. - * \return false on memory exhaustion, true otherwise - */ -nserror -imagemap_extract(html_content *c) -{ - dom_nodelist *nlist; - dom_exception exc; - unsigned long mapnr; - uint32_t maybe_maps; - nserror ret = NSERROR_OK; - - exc = dom_document_get_elements_by_tag_name(c->document, - corestring_dom_map, - &nlist); - if (exc != DOM_NO_ERR) { - return NSERROR_DOM; - } - - exc = dom_nodelist_get_length(nlist, &maybe_maps); - if (exc != DOM_NO_ERR) { - ret = NSERROR_DOM; - goto out_nlist; - } - - for (mapnr = 0; mapnr < maybe_maps; ++mapnr) { - dom_node *node; - dom_string *name; - exc = dom_nodelist_item(nlist, mapnr, &node); - if (exc != DOM_NO_ERR) { - ret = NSERROR_DOM; - goto out_nlist; - } - - exc = dom_element_get_attribute(node, corestring_dom_id, - &name); - if (exc != DOM_NO_ERR) { - dom_node_unref(node); - ret = NSERROR_DOM; - goto out_nlist; - } - - if (name == NULL) { - exc = dom_element_get_attribute(node, - corestring_dom_name, - &name); - if (exc != DOM_NO_ERR) { - dom_node_unref(node); - ret = NSERROR_DOM; - goto out_nlist; - } - } - - if (name != NULL) { - struct mapentry *entry = NULL; - if (imagemap_extract_map(node, c, &entry) == false) { - if (entry != NULL) { - imagemap_freelist(entry); - } - - dom_string_unref(name); - dom_node_unref(node); - ret = NSERROR_NOMEM; /** @todo check this */ - goto out_nlist; - } - - /* imagemap_extract_map may not extract anything, - * so entry can still be NULL here. This isn't an - * error as it just means that we've encountered - * an incorrectly defined <map>...</map> block - */ - if ((entry != NULL) && - (imagemap_add(c, name, entry) == false)) { - imagemap_freelist(entry); - - dom_string_unref(name); - dom_node_unref(node); - ret = NSERROR_NOMEM; /** @todo check this */ - goto out_nlist; - } - } - - dom_string_unref(name); - dom_node_unref(node); - } - -out_nlist: - - dom_nodelist_unref(nlist); - - return ret; -} - -/** - * Test if a point lies within an arbitrary polygon - * Modified from comp.graphics.algorithms FAQ 2.03 - * - * \param num Number of vertices - * \param xpt Array of x coordinates - * \param ypt Array of y coordinates - * \param x Left hand edge of containing box - * \param y Top edge of containing box - * \param click_x X coordinate of click - * \param click_y Y coordinate of click - * \return 1 if point is in polygon, 0 if outside. 0 or 1 if on boundary - */ -static int -imagemap_point_in_poly(int num, float *xpt, float *ypt, unsigned long x, - unsigned long y, unsigned long click_x, unsigned long click_y) -{ - int i, j, c = 0; - - assert(xpt != NULL); - assert(ypt != NULL); - - for (i = 0, j = num - 1; i < num; j = i++) { - if ((((ypt[i] + y <= click_y) && (click_y < ypt[j] + y)) || - ((ypt[j] + y <= click_y) && (click_y < ypt[i] + y))) && - (click_x < (xpt[j] - xpt[i]) * - (click_y - (ypt[i] + y)) / (ypt[j] - ypt[i]) + xpt[i] + x)) - c = !c; - } - - return c; -} - -/** - * Retrieve url associated with imagemap entry - * - * \param c The containing content - * \param key The map name to search for - * \param x The left edge of the containing box - * \param y The top edge of the containing box - * \param click_x The horizontal location of the click - * \param click_y The vertical location of the click - * \param target Pointer to location to receive target pointer (if any) - * \return The url associated with this area, or NULL if not found - */ -nsurl *imagemap_get(struct html_content *c, const char *key, - unsigned long x, unsigned long y, - unsigned long click_x, unsigned long click_y, - const char **target) -{ - unsigned int slot = 0; - struct imagemap *map; - struct mapentry *entry; - unsigned long cx, cy; - - assert(c != NULL); - - if (key == NULL) - return NULL; - - if (c->imagemaps == NULL) - return NULL; - - slot = imagemap_hash(key); - - for (map = c->imagemaps[slot]; map != NULL; map = map->next) { - if (map->key != NULL && strcasecmp(map->key, key) == 0) - break; - } - - if (map == NULL || map->list == NULL) - return NULL; - - for (entry = map->list; entry; entry = entry->next) { - switch (entry->type) { - case IMAGEMAP_DEFAULT: - /* just return the URL. no checks required */ - if (target) - *target = entry->target; - return entry->url; - break; - case IMAGEMAP_RECT: - if (click_x >= x + entry->bounds.rect.x0 && - click_x <= x + entry->bounds.rect.x1 && - click_y >= y + entry->bounds.rect.y0 && - click_y <= y + entry->bounds.rect.y1) { - if (target) - *target = entry->target; - return entry->url; - } - break; - case IMAGEMAP_CIRCLE: - cx = x + entry->bounds.circle.x - click_x; - cy = y + entry->bounds.circle.y - click_y; - if ((cx * cx + cy * cy) <= - (unsigned long) (entry->bounds.circle.r * - entry->bounds.circle.r)) { - if (target) - *target = entry->target; - return entry->url; - } - break; - case IMAGEMAP_POLY: - if (imagemap_point_in_poly(entry->bounds.poly.num, - entry->bounds.poly.xcoords, - entry->bounds.poly.ycoords, x, y, - click_x, click_y)) { - if (target) - *target = entry->target; - return entry->url; - } - break; - } - } - - if (target) - *target = NULL; - - return NULL; -} |