summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/favicon.c232
-rw-r--r--render/favicon.h27
-rw-r--r--render/html.c8
-rw-r--r--render/html.h3
-rw-r--r--render/html_redraw.c9
-rw-r--r--render/layout.c2
-rw-r--r--render/textplain.c12
7 files changed, 283 insertions, 10 deletions
diff --git a/render/favicon.c b/render/favicon.c
new file mode 100644
index 000000000..fdf6e25f1
--- /dev/null
+++ b/render/favicon.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2007 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * 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 "content/fetch.h"
+#include "content/fetchcache.h"
+#include "render/favicon.h"
+#include "render/html.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/talloc.h"
+#include "utils/url.h"
+#include "utils/utils.h"
+
+static char *favicon_get_icon_ref(struct content *c, xmlNode *html);
+static void favicon_callback(content_msg msg, struct content *icon,
+ intptr_t p1, intptr_t p2, union content_msg_data data);
+
+/**
+ * retrieve 1 url reference to 1 favicon
+ * \param html xml node of html element
+ * \return pointer to url; NULL for no icon; caller owns returned pointer
+ */
+char *favicon_get_icon_ref(struct content *c, xmlNode *html)
+{
+ xmlNode *node;
+ char *rel, *href, *url, *url2;
+ url2 = NULL;
+ url_func_result res;
+
+ union content_msg_data msg_data;
+
+ node = html;
+ while (node) {
+ if (node->children) { /* children */
+ node = node->children;
+ } else if (node->next) { /* siblings */
+ node = node->next;
+ } else { /* ancestor siblings */
+ while (node && !node->next)
+ node = node->parent;
+ if (!node)
+ break;
+ node = node->next;
+ }
+ assert(node);
+
+ if (node->type != XML_ELEMENT_NODE)
+ continue;
+ if (strcmp((const char *) node->name, "link") == 0) {
+ /* rel=<space separated list, including 'icon'> */
+ if ((rel = (char *) xmlGetProp(node,
+ (const xmlChar *) "rel")) == NULL)
+ continue;
+ if (strcasestr(rel, "icon") == 0) {
+ xmlFree(rel);
+ continue;
+ }
+ LOG(("icon node found"));
+ if (strcasecmp(rel, "apple-touch-icon") == 0) {
+ xmlFree(rel);
+ continue;
+ }
+ xmlFree(rel);
+ if (( href = (char *) xmlGetProp(node,
+ (const xmlChar *) "href")) == NULL)
+ continue;
+ res = url_join(href, c->data.html.base_url,
+ &url);
+ xmlFree(href);
+ if (res != URL_FUNC_OK)
+ continue;
+ LOG(("most recent favicon '%s'", url));
+ if (url2 != NULL) {
+ free(url2);
+ url2 = NULL;
+ }
+ res = url_normalize(url, &url2);
+ if (res != URL_FUNC_OK) {
+ url2 = NULL;
+ if (res == URL_FUNC_NOMEM)
+ goto no_memory;
+ continue;
+ }
+ free(url);
+
+ }
+ }
+ if (url2 == NULL) {
+ if (url_join("/favicon.ico", c->data.html.base_url, &url2)
+ != URL_FUNC_OK)
+ return NULL;
+ }
+ LOG(("favicon %s", url2));
+ return url2;
+no_memory:
+ msg_data.error = messages_get("NoMemory");
+ /* content_broadcast(c, CONTENT_MSG_ERROR, msg_data); */
+ return false;
+}
+
+/**
+ * retrieve 1 favicon
+ * \param c content structure
+ * \param html xml node of html element
+ * \return true for success, false for error
+ */
+
+bool favicon_get_icon(struct content *c, xmlNode *html)
+{
+ char *url = favicon_get_icon_ref(c, html);
+ struct content *favcontent = NULL;
+ if (url == NULL)
+ return false;
+
+ favcontent = fetchcache(url, favicon_callback, (intptr_t) c, 0,
+ c->width, c->height, true, 0, 0, false, false);
+ free(url);
+ if (favcontent == NULL)
+ return false;
+
+ c->data.html.favicon = favcontent;
+
+ fetchcache_go(favcontent, c->url, favicon_callback, (intptr_t) c, 0,
+ c->width, c->height, 0, 0, false, c);
+
+ return true;
+}
+
+/**
+ * Callback for fetchcache() for linked favicon
+ */
+
+void favicon_callback(content_msg msg, struct content *icon,
+ intptr_t p1, intptr_t p2, union content_msg_data data)
+{
+ struct content *c = (struct content *) p1;
+ unsigned int i = p2;
+ switch (msg) {
+ case CONTENT_MSG_LOADING:
+ /* check that the favicon is really a correct image type */
+ if (!((icon->type == CONTENT_ICO) ||
+ (icon->type == CONTENT_PNG) ||
+ (icon->type == CONTENT_GIF))) {
+ c->data.html.favicon = 0;
+ LOG(("%s is not a favicon", icon->url));
+ content_add_error(c, "NotFavIco", 0);
+ html_set_status(c, messages_get("NotFavIco"));
+ content_broadcast(c, CONTENT_MSG_STATUS, data);
+ content_remove_user(icon,
+ favicon_callback,
+ (intptr_t) c, i);
+ if (!icon->user_list->next) {
+ /* we were the only user and we don't want this
+ * content, so stop it fetching and mark it as
+ * having an error so it gets removed from the
+ * cache next time content_clean() gets called
+ */
+ fetch_abort(icon->fetch);
+ icon->fetch = 0;
+ icon->status = CONTENT_STATUS_ERROR;
+ }
+ }
+ break;
+
+ case CONTENT_MSG_READY:
+ break;
+
+ case CONTENT_MSG_DONE:
+ LOG(("got favicon '%s'", icon->url));
+ break;
+
+ case CONTENT_MSG_LAUNCH:
+ /* Fall through */
+ case CONTENT_MSG_ERROR:
+ LOG(("favicon %s failed: %s", icon->url, data.error));
+ /* The favicon we were fetching may have been
+ * redirected, in that case, the object pointers
+ * will differ, so ensure that the object that's
+ * in error is still in use by us before invalidating
+ * the pointer */
+ if (c->data.html.favicon == icon) {
+ c->data.html.favicon = 0;
+ content_add_error(c, "?", 0);
+ }
+ break;
+
+ case CONTENT_MSG_STATUS:
+ html_set_status(c, icon->status_message);
+ content_broadcast(c, CONTENT_MSG_STATUS, data);
+ break;
+
+ case CONTENT_MSG_NEWPTR:
+ c->data.html.favicon = icon;
+ break;
+
+ case CONTENT_MSG_AUTH:
+ c->data.html.favicon = 0;
+ content_add_error(c, "?", 0);
+ break;
+
+ case CONTENT_MSG_SSL:
+ c->data.html.favicon = 0;
+ content_add_error(c, "?", 0);
+ break;
+ case CONTENT_MSG_REDRAW:
+ /* currently no support for favicon animations */
+ case CONTENT_MSG_REFRESH:
+ break;
+ case CONTENT_MSG_REFORMAT:
+ /* would be unusual :) */
+ break;
+ default:
+ assert(0);
+ }
+}
diff --git a/render/favicon.h b/render/favicon.h
new file mode 100644
index 000000000..30030101a
--- /dev/null
+++ b/render/favicon.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ *
+ * 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_RENDER_FAVICON_H_
+#define _NETSURF_RENDER_FAVICON_H_
+
+#include <libxml/tree.h>
+#include "content/content.h"
+
+bool favicon_get_icon(struct content *c, xmlNode *html);
+
+#endif
diff --git a/render/html.c b/render/html.c
index 241d61350..8592ad6e2 100644
--- a/render/html.c
+++ b/render/html.c
@@ -37,6 +37,7 @@
#include "desktop/options.h"
#include "image/bitmap.h"
#include "render/box.h"
+#include "render/favicon.h"
#include "render/font.h"
#include "render/form.h"
#include "render/html.h"
@@ -74,7 +75,6 @@ static bool html_object_type_permitted(const content_type type,
static void html_object_refresh(void *p);
static void html_destroy_frameset(struct content_html_frames *frameset);
static void html_destroy_iframe(struct content_html_iframe *iframe);
-static void html_set_status(struct content *c, const char *extra);
#if ALWAYS_DUMP_FRAMESET
static void html_dump_frameset(struct content_html_frames *frame,
unsigned int depth);
@@ -307,6 +307,7 @@ encoding_change:
*
* - parsing to an XML tree is completed
* - stylesheets are fetched
+ * - favicon is retrieved
* - the XML tree is converted to a box tree and object fetches are started
* - the box tree is laid out
*
@@ -424,6 +425,9 @@ bool html_convert(struct content *c, int width, int height)
if (!html_find_stylesheets(c, html))
return false;
+ /* get icon */
+ favicon_get_icon(c, html);
+
/* Retrieve forms from parser */
c->data.html.forms = binding_get_forms(c->data.html.parser_binding);
for (f = c->data.html.forms; f != NULL; f = f->prev) {
@@ -792,7 +796,7 @@ bool html_meta_refresh(struct content *c, xmlNode *head)
* Uses STYLE and LINK elements inside and outside HEAD
*
* \param c content structure
- * \param head xml node of html element
+ * \param html xml node of html element
* \return true on success, false if an error occurred
*/
diff --git a/render/html.h b/render/html.h
index e18c33a2c..51abba3ba 100644
--- a/render/html.h
+++ b/render/html.h
@@ -133,6 +133,8 @@ struct content_html_data {
colour background_colour; /**< Document background colour. */
const struct font_functions *font_func;
+ struct content *favicon; /**< the favicon for the page */
+
/** Number of entries in stylesheet_content. */
unsigned int stylesheet_count;
/** Stylesheets. Each may be 0. */
@@ -189,6 +191,7 @@ void html_open(struct content *c, struct browser_window *bw,
struct content *page, unsigned int index, struct box *box,
struct object_params *params);
void html_close(struct content *c);
+void html_set_status(struct content *c, const char *extra);
/* in render/html_redraw.c */
bool html_redraw(struct content *c, int x, int y,
diff --git a/render/html_redraw.c b/render/html_redraw.c
index becf99fe4..2a5154035 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -41,6 +41,7 @@
#include "desktop/textinput.h"
#include "desktop/options.h"
#include "desktop/print.h"
+#include "desktop/search.h"
#include "desktop/scroll.h"
#include "image/bitmap.h"
#include "render/box.h"
@@ -880,12 +881,14 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
}
/* what about the current search operation, if any? */
- if (!highlighted && search_current_window ==
- current_redraw_browser->window &&
+ if (!highlighted && (current_redraw_browser->search_context
+ != NULL) &&
gui_search_term_highlighted(
current_redraw_browser->window,
offset, offset + len,
- &start_idx, &end_idx)) {
+ &start_idx, &end_idx,
+ current_redraw_browser->
+ search_context)) {
highlighted = true;
}
diff --git a/render/layout.c b/render/layout.c
index c83753195..3463210bc 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -4435,7 +4435,7 @@ void layout_calculate_descendant_bboxes(struct box *box)
{
struct box *child;
- if (box->width == UNKNOWN_WIDTH || box->height == AUTO /*||
+ if ((box->width == UNKNOWN_WIDTH) || (box->height == AUTO) /*||
box->width < 0 || box->height < 0*/) {
LOG(("%p has bad width or height", box));
/*while (box->parent)
diff --git a/render/textplain.c b/render/textplain.c
index 05d2fbe33..07f37610c 100644
--- a/render/textplain.c
+++ b/render/textplain.c
@@ -34,6 +34,7 @@
#include "desktop/gui.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
+#include "desktop/search.h"
#include "desktop/selection.h"
#include "render/box.h"
#include "render/font.h"
@@ -437,11 +438,14 @@ bool textplain_redraw(struct content *c, int x, int y,
highlighted = true;
}
- if (!highlighted && search_current_window == bw->window) {
+ if (!highlighted && (bw->search_context
+ != NULL)) {
unsigned start_idx, end_idx;
- if (gui_search_term_highlighted(bw->window,
- tab_ofst, tab_ofst + 1,
- &start_idx, &end_idx))
+ if (gui_search_term_highlighted(
+ bw->window,
+ tab_ofst, tab_ofst + 1,
+ &start_idx, &end_idx,
+ bw->search_context))
highlighted = true;
}