Hi,
As I've now updated the branch to avoid conflicts, here is the diff file
representing all the files I've adjusted in the favs branch
so modulo the fact that as I now know I should make one branch for every
work area rather than generally tidying up code in a feature branch /
continuing a patch as in the view source in new tab case, hopefully it's
closer to what you would be looking for now
I've wrapped the diff file at 81 in thunderbird [including the +/-] I
hope it presents correctly
Best
Mark
http://www.halloit.com
Key ID 046B65CF
Index: render/html.c
===================================================================
--- render/html.c (.../trunk/netsurf) (revision 7376)
+++ render/html.c (.../branches/MarkieB/favs) (revision 7376)
@@ -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"
@@ -73,7 +74,6 @@
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);
@@ -161,7 +161,7 @@
error:
if (error == BINDING_BADENCODING) {
- LOG(("Bad encoding: %s", html->encoding ? html->encoding :
""));
+ LOG(("Bad encoding: %s", html->encoding ? html->encoding
:""));
msg_data.error = messages_get("ParsingFail");
} else
msg_data.error = messages_get("NoMemory");
@@ -283,6 +283,7 @@
*
* - 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
*
@@ -399,6 +400,9 @@
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) {
@@ -534,17 +538,20 @@
}
xmlFree(href);
}
- /* don't use the central values to ease freeing later on */
- if ((s = xmlGetProp(node, (const xmlChar *) "target"))) {
- if ((!strcasecmp((const char *) s, "_blank")) ||
- (!strcasecmp((const char *) s,
- "_top")) ||
- (!strcasecmp((const char *) s,
- "_parent")) ||
- (!strcasecmp((const char *) s,
- "_self")) ||
+ /* don't use the central values to ease freeing later
+ * on */
+ if ((s = xmlGetProp(node, (const xmlChar *)
+ "target"))) {
+ if ((!strcasecmp((const char *) s, "_blank"))
+ ||(!strcasecmp((const char *)
+ s, "_top")) || (!strcasecmp(
+ (const char *) s, "_parent"))
+ || (!strcasecmp((const char *)
+ s, "_self")) ||
('a' <= s[0] && s[0] <= 'z') ||
- ('A' <= s[0] && s[0] <= 'Z')) { /* [6.16] */
+ ('A' <= s[0] && s[0] <= 'Z')
+ ) {
+ /* [6.16] */
c->data.html.base_target =
talloc_strdup(c,
(const char *) s);
@@ -615,7 +622,8 @@
end = (char *) content + strlen((const char *) content);
- /* content := *LWS intpart fracpart? *LWS [';' *LWS *1url *LWS]
+ /* content := *LWS intpart fracpart? *LWS [';' *LWS *1url
+ * *LWS]
* intpart := 1*DIGIT
* fracpart := 1*('.' | DIGIT)
* url := "url" *LWS '=' *LWS (url-nq | url-sq | url-dq)
@@ -758,14 +766,13 @@
return true;
}
-
/**
* Process inline stylesheets and fetch linked stylesheets.
*
* 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
*/
@@ -844,7 +851,7 @@
if (strcmp((const char *) node->name, "link") == 0) {
- /* rel=<space separated list, including 'stylesheet'> */
+ /* rel=<space separated list, including 'stylesheet'>*/
if ((rel = (char *) xmlGetProp(node,
(const xmlChar *) "rel")) == NULL)
continue;
@@ -872,7 +879,8 @@
if ((media = (char *) xmlGetProp(node,
(const xmlChar *) "media")) != NULL) {
if (strcasestr(media, "screen") == 0 &&
- strcasestr(media, "all") == 0) {
+ strcasestr(media, "all")
+ == 0) {
xmlFree(media);
continue;
}
@@ -947,7 +955,8 @@
html_convert_css_callback,
(intptr_t) c, STYLESHEET_STYLE)) {
/* no memory */
- c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0;
+ c->data.html.stylesheet_content[
+ STYLESHEET_STYLE] = 0;
goto no_memory;
}
} else {
@@ -1127,7 +1136,8 @@
case CONTENT_MSG_LAUNCH:
/* Fall through */
case CONTENT_MSG_ERROR:
- LOG(("stylesheet %s failed: %s", css->url, data.error));
+ LOG(("stylesheet %s failed: %s", css->url,
+ data.error));
/* The stylesheet we were fetching may have been
* redirected, in that case, the object pointers
* will differ, so ensure that the object that's
@@ -1672,7 +1682,8 @@
(intptr_t) c, i);
else {
content_remove_user(c->data.html.object[i].content,
- html_object_callback, (intptr_t) c, i);
+ html_object_callback, (intptr_t) c,
+ i);
c->data.html.object[i].content = 0;
}
}
@@ -1778,8 +1789,10 @@
LOG(("object %i %p", i, c->data.html.object[i].content));
if (c->data.html.object[i].content) {
content_remove_user(c->data.html.object[i].content,
- html_object_callback, (intptr_t) c, i);
- if (c->data.html.object[i].content->type == CONTENT_HTML)
+ html_object_callback, (intptr_t) c,
+ i);
+ if (c->data.html.object[i].content->type ==
+ CONTENT_HTML)
schedule_remove(html_object_refresh,
c->data.html.object[i].content);
}
Index: render/html.h
===================================================================
--- render/html.h (.../trunk/netsurf) (revision 7376)
+++ render/html.h (.../branches/MarkieB/favs) (revision 7376)
@@ -128,6 +128,8 @@
colour background_colour; /**< Document background colour. */
const struct font_functions *font_func;
+ struct content *favicon;
+
/** Number of entries in stylesheet_content. */
unsigned int stylesheet_count;
/** Stylesheets. Each may be 0. */
@@ -184,6 +186,7 @@
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,
Index: render/favicon.c
===================================================================
--- render/favicon.c (.../trunk/netsurf) (revision 0)
+++ render/favicon.c (.../branches/MarkieB/favs) (revision 7376)
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2007 James Bursa <bursa(a)users.sourceforge.net>
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin(a)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);
+static unsigned long favicon_hash(char *str);
+
+unsigned long favicon_hash(char *str)
+{
+ if (str == NULL)
+ return 0;
+ unsigned long hash = 5381;
+ int c;
+ while ((c = (unsigned char) *str++))
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+ return hash;
+}
+
+/**
+ * retrieve 1 url reference to 1 favicon
+ * \param html xml node of html element
+ * \return pointer to url; NULL for no icon
+ */
+char *favicon_get_icon_ref(struct content *c, xmlNode *html)
+{
+ xmlNode *node;
+ char *rel, *type, *href, *url, *suf, *url2;
+ url2 = NULL;
+ url_func_result res;
+ int score, hiscore;
+ hiscore = 0;
+ /* hashed values - saves calculating them afresh every time */
+ #define HHICON 0x7c98572e
+ /* icon */
+ #define HHSHORTCUTICON 0xfcbccdca
+ /* shortcut icon */
+ #define HHAPPLETOUCHICON 0x024c6ddd
+ /* apple-touch-icon */
+ #define HHIMAGEPNG 0x7382417c
+ /* image/png */
+ #define HHIMAGEGIF 0x73821a8d
+ /* image/gif */
+ #define HHIMAGEVNDMICROSOFTICON 0xdae02bba
+ /* image.vnd.microsoft.icon */
+ #define HHIMAGEJPEG 0xe3c72f5d
+ /* image/jpeg */
+ #define HHIMAGEJPG 0x73822838
+ /* image/jpg */
+ #define HHIMAGEICO 0x73822252
+ /* image/ico */
+ #define HHIMAGEICON 0xe3c66d00
+ /* image/icon */
+ #define HHIMAGEXICON 0x0e3e78e5
+ /* image/x-icon */
+ #define HHTEXTICO 0x17e966a2
+ /* text/icon */
+ #define HHAPPLICATIONICO 0x087b6fb4
+ /*application/icon*/
+ #define HHSUFICO 0x0b887ec0
+ /* ico */
+ #define HHSUFPNG 0x0b889dea
+ /* png */
+ #define HHSUFGIF 0x0b8876fb
+ /* gif */
+ #define HHSUFJPG 0x0b888486
+ /* jpg */
+ #define HHSUFJPEG 0x7c99198b
+ /* jpeg */
+
+ union content_msg_data msg_data;
+
+ node = html;
+ while (node) {
+ score = 0;
+ suf = NULL;
+ 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"));
+ switch(favicon_hash(rel)) {
+ /* give points for rel attributes, kind of arbitrary
+ * in an attempt to test how closely standards are
+ * being respected; the reason apple-touch-icon scores
+ * less is that the appearance of such is really
+ * specific to the iphone style */
+ case HHICON:
+ LOG(("icon"));
+ score = 3;
+ break;
+ case HHSHORTCUTICON:
+ LOG(("shortcut icon"));
+ score = 5;
+ break;
+ case HHAPPLETOUCHICON:
+ LOG(("apple-touch-icon"));
+ score = 1;
+ break;
+ }
+ xmlFree(rel);
+ /* current implementation scores candidates according
+ * to how closely they seem to adhere to standards,
+ * scoring system may be modified in the future */
+ if ((type = (char *) xmlGetProp(node,
+ (const xmlChar *) "type")) != NULL) {
+ switch(favicon_hash(type)) {
+ /* here we score highest for "image/type"
+ * mime types, lower scores for "type/ico"
+ * mime types, no score for no type */
+ case HHIMAGEPNG:
+ score += 5;
+ break;
+ case HHIMAGEGIF:
+ score += 5;
+ break;
+ case HHIMAGEVNDMICROSOFTICON:
+ score += 5;
+ break;
+ case HHIMAGEJPEG:
+ score += 5;
+ break;
+ case HHIMAGEJPG:
+ score += 5;
+ break;
+ case HHIMAGEICO:
+ score += 5;
+ break;
+ case HHIMAGEICON:
+ score += 5;
+ break;
+ case HHIMAGEXICON:
+ score += 5;
+ break;
+ case HHTEXTICO:
+ score += 2;
+ break;
+ case HHAPPLICATIONICO:
+ score += 1;
+ break;
+ }
+ xmlFree(type);
+ }
+ if ((href = (char *) xmlGetProp(node,
+ (const xmlChar *) "href")) == NULL)
+ continue;
+ suf = strrchr(href, '.');
+ if (suf != NULL) {
+ suf ++;
+ switch(favicon_hash(suf)) {
+ /* here the largest bonus points of all
+ * attributes, notably for .ico, .png, .gif
+ * as the standards support; less for .jpg */
+ case HHSUFICO:
+ score += 10;
+ break;
+ case HHSUFPNG:
+ score += 10;
+ break;
+ case HHSUFGIF:
+ score += 10;
+ break;
+ case HHSUFJPG:
+ score += 7;
+ break;
+ case HHSUFJPEG:
+ score += 7;
+ break;
+ }
+ }
+ if (score > hiscore) {
+ res = url_join(href, c->data.html.base_url,
+ &url);
+ xmlFree(href);
+ if (res != URL_FUNC_OK)
+ continue;
+
+ LOG(("best favicon so far '%s'", url));
+ res = url_normalize(url, &url2);
+ if (res != URL_FUNC_OK) {
+ url2 = NULL;
+ if (res == URL_FUNC_NOMEM)
+ goto no_memory;
+ continue;
+ }
+ hiscore = score;
+ free(url);
+ }
+ }
+ }
+ if (url2 == NULL) {
+ struct url_components comp;
+ if (url_get_components(c->data.html.base_url, &comp) !=
+ URL_FUNC_OK)
+ return NULL;
+ if (url_normalize(comp.authority,
+ &url) != URL_FUNC_OK)
+ return NULL;
+ url_destroy_components(&comp);
+ if (url_join("/favicon.ico", url, &url2) != URL_FUNC_OK)
+ return NULL;
+ free(url);
+ }
+ LOG(("Best 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)
+{
+ union content_msg_data msg_data;
+ char *url = favicon_get_icon_ref(c, html);
+ struct content *favcontent = NULL;
+ if (url != NULL)
+ 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->url);
+
+ if (!c->data.html.favicon) {
+ msg_data.error = "Favicon failed to load";
+ return false;
+ }
+ 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)) {
+
+ } else {
+ 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;
+
+ default:
+ assert(0);
+ }
+}
Index: render/favicon.h
===================================================================
--- render/favicon.h (.../trunk/netsurf) (revision 0)
+++ render/favicon.h (.../branches/MarkieB/favs) (revision 7376)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin(a)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_
+
+typedef enum {
+ HHICON = 0x7c98572e,
+ /* icon */
+ HHSHORTCUTICON = 0xfcbccdca,
+ /* shortcut icon */
+ HHAPPLETOUCHICON = 0x024c6ddd,
+ /* apple-touch-icon */
+ HHIMAGEPNG = 0x7382417c,
+ /* image/png */
+ HHIMAGEGIF = 0x73821a8d,
+ /* image/gif */
+ HHIMAGEVNDMICROSOFTICON = 0xdae02bba,
+ /* image.vnd.microsoft.icon */
+ HHIMAGEJPEG = 0xe3c72f5d,
+ /* image/jpeg */
+ HHIMAGEJPG = 0x73822838,
+ /* image/jpg */
+ HHIMAGEICO = 0x73822252,
+ /* image/ico */
+ HHIMAGEICON = 0xe3c66d00,
+ /* image/icon */
+ HHIMAGEXICON = 0x0e3e78e5,
+ /* image/x-icon */
+ HHTEXTICO = 0x17e966a2,
+ /* text/icon */
+ HHAPPLICATIONICO = 0x087b6fb4,
+ /* application/icon */
+ HHSUFICO = 0x0b887ec0,
+ /* ico */
+ HHSUFPNG = 0x0b889dea,
+ /* png */
+ HHSUFGIF = 0x0b8876fb,
+ /* gif */
+ HHSUFJPG = 0x0b888486,
+ /* jpg */
+ HHSUFJPEG = 0x7c99198b
+ /* jpeg */
+} favicon_string_hash;
+
+bool favicon_get_icon(struct content *c, xmlNode *html);
+
+#endif
Index: image/ico.c
===================================================================
--- image/ico.c (.../trunk/netsurf) (revision 7376)
+++ image/ico.c (.../branches/MarkieB/favs) (revision 7376)
@@ -114,6 +114,15 @@
background_colour, c);
}
+bool nsico_set_bitmap_from_size(struct content *c, int width, int height)
+{
+ struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
+ if (!bmp->decoded)
+ if (bmp_decode(bmp) != BMP_OK)
+ return false;
+ c->bitmap = bmp->bitmap;
+ return true;
+}
bool nsico_redraw_tiled(struct content *c, int x, int y,
int width, int height,
Index: image/ico.h
===================================================================
--- image/ico.h (.../trunk/netsurf) (revision 7376)
+++ image/ico.h (.../branches/MarkieB/favs) (revision 7376)
@@ -47,7 +47,7 @@
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
float scale, colour background_colour,
bool repeat_x, bool repeat_y);
-
+bool nsico_set_bitmap_from_size(struct content *c, int width, int height);
#endif /* WITH_BMP */
#endif
Index: framebuffer/fb_gui.c
===================================================================
--- framebuffer/fb_gui.c (.../trunk/netsurf) (revision 7376)
+++ framebuffer/fb_gui.c (.../branches/MarkieB/favs) (revision 7376)
@@ -1000,6 +1000,10 @@
}
+void gui_window_set_icon(struct gui_window *g, struct content *icon)
+{
+}
+
void gui_window_place_caret(struct gui_window *g, int x, int y, int height)
{
}
Index: gtk/options.h
===================================================================
--- gtk/options.h (.../trunk/netsurf) (revision 7376)
+++ gtk/options.h (.../branches/MarkieB/favs) (revision 7376)
@@ -34,6 +34,7 @@
extern bool option_hover_urls;
extern bool option_focus_new;
extern bool option_new_blank;
+extern bool option_source_tab;
#define EXTRA_OPTION_DEFINE \
bool option_render_resample = false; \
@@ -48,7 +49,8 @@
int option_history_age = 0; \
bool option_hover_urls = false; \
bool option_focus_new = false; \
-bool option_new_blank = false;
+bool option_new_blank = false; \
+bool option_source_tab = false;
#define EXTRA_OPTION_TABLE \
{ "render_resample", OPTION_BOOL, &option_render_resample }, \
@@ -63,6 +65,7 @@
{ "history_age", OPTION_INTEGER, &option_history_age}, \
{ "hover_urls", OPTION_BOOL, &option_hover_urls}, \
{ "focus_new", OPTION_BOOL, &option_focus_new}, \
-{ "new_blank", OPTION_BOOL, &option_new_blank}
+{ "new_blank", OPTION_BOOL, &option_new_blank}, \
+{ "source_tab", OPTION_BOOL, &option_source_tab}
#endif
Index: gtk/gtk_bitmap.c
===================================================================
--- gtk/gtk_bitmap.c (.../trunk/netsurf) (revision 7376)
+++ gtk/gtk_bitmap.c (.../branches/MarkieB/favs) (revision 7376)
@@ -34,6 +34,9 @@
#include "utils/log.h"
+#define MIN_PRETILE_WIDTH 256
+#define MIN_PRETILE_HEIGHT 256
+
struct bitmap {
GdkPixbuf *primary;
GdkPixbuf *pretile_x;
@@ -41,10 +44,6 @@
GdkPixbuf *pretile_xy;
};
-#define MIN_PRETILE_WIDTH 256
-#define MIN_PRETILE_HEIGHT 256
-
-
/**
* Create a bitmap.
*
Index: gtk/gtk_scaffolding.c
===================================================================
--- gtk/gtk_scaffolding.c (.../trunk/netsurf) (revision 7376)
+++ gtk/gtk_scaffolding.c (.../branches/MarkieB/favs) (revision 7376)
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
#include <libxml/debugXML.h>
#include "content/content.h"
#include "desktop/browser.h"
@@ -37,6 +38,7 @@
#endif
#include "desktop/selection.h"
#include "desktop/textinput.h"
+#include "gtk/gtk_bitmap.h"
#include "gtk/gtk_completion.h"
#include "gtk/dialogs/gtk_options.h"
#include "gtk/dialogs/gtk_about.h"
@@ -52,6 +54,7 @@
#include "gtk/gtk_throbber.h"
#include "gtk/gtk_window.h"
#include "gtk/options.h"
+#include "image/ico.h"
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
@@ -77,6 +80,44 @@
GCallback handler;
};
+struct gtk_scaffolding {
+ GtkWindow *window;
+ GtkNotebook *notebook;
+ GtkEntry *url_bar;
+ GtkEntryCompletion *url_bar_completion;
+ GtkStatusbar *status_bar;
+ GtkMenuItem *edit_menu;
+ GtkMenuItem *tabs_menu;
+ GtkToolbar *tool_bar;
+ GtkToolButton *back_button;
+ GtkToolButton *history_button;
+ GtkToolButton *forward_button;
+ GtkToolButton *stop_button;
+ GtkToolButton *reload_button;
+ GtkToolItem *toolFav;
+ GtkMenuBar *menu_bar;
+ GtkMenuItem *back_menu;
+ GtkMenuItem *forward_menu;
+ GtkMenuItem *stop_menu;
+ GtkMenuItem *reload_menu;
+ GtkImage *throbber;
+ GtkPaned *status_pane;
+
+ GladeXML *xml;
+
+ GladeXML *popup_xml;
+ GtkMenu *popup_menu;
+
+ struct gtk_history_window *history_window;
+ GtkDialog *preferences_dialog;
+
+ int throb_frame;
+ struct gui_window *top_level;
+ int being_destroyed;
+
+ bool fullscreen;
+};
+
static int open_windows = 0; /**< current number of open browsers */
static struct gtk_scaffolding *current_model; /**< current window for model
dialogue use */
@@ -1238,6 +1279,7 @@
g->forward_menu = GTK_MENU_ITEM(GET_WIDGET("forward"));
g->stop_menu = GTK_MENU_ITEM(GET_WIDGET("stop"));
g->reload_menu = GTK_MENU_ITEM(GET_WIDGET("reload"));
+ g->toolFav = GTK_TOOL_ITEM(GET_WIDGET("toolFav"));
g->throbber = GTK_IMAGE(GET_WIDGET("throbber"));
g->preferences_dialog = NULL;
@@ -1378,8 +1420,10 @@
/* connect history window signals to their handlers */
CONNECT(g->history_window->drawing_area, "expose_event",
nsgtk_history_expose_event, g->history_window);
-// CONNECT(g->history_window->drawing_area, "motion_notify_event",
-// nsgtk_history_motion_notify_event, g->history_window);
+ /*
+ CONNECT(g->history_window->drawing_area, "motion_notify_event",
+ nsgtk_history_motion_notify_event, g->history_window);
+ */
CONNECT(g->history_window->drawing_area, "button_press_event",
nsgtk_history_button_press_event, g->history_window);
CONNECT(g->history_window->window, "delete_event",
@@ -1546,6 +1590,40 @@
gtk_image_set_from_pixbuf(g->throbber, nsgtk_throbber->framedata[0]);
}
+/**
+ * set favicon
+ */
+void gui_window_set_icon(struct gui_window *_g, struct content *icon)
+{
+ struct gtk_scaffolding *g = nsgtk_get_scaffold(_g);
+ GtkWidget *currenticon = gtk_bin_get_child(GTK_BIN(g->toolFav));
+ GtkImage *iconImage = NULL;
+ if (currenticon != NULL) {
+ gtk_container_remove(GTK_CONTAINER(g->toolFav),
+ currenticon);
+ }
+ if ((icon != NULL) && (icon->type == CONTENT_ICO)) {
+ nsico_set_bitmap_from_size(icon, 20, 20);
+ }
+ if ((icon != NULL) && (icon->bitmap != NULL)) {
+ GdkPixbuf *pb = gtk_bitmap_get_primary(icon->bitmap);
+ if ((pb != NULL) && (gdk_pixbuf_get_width(pb) > 0) &&
+ (gdk_pixbuf_get_height(pb) > 0)) {
+ pb = gdk_pixbuf_scale_simple(pb, 20, 20,
+ GDK_INTERP_HYPER);
+ iconImage = GTK_IMAGE(
+ gtk_image_new_from_pixbuf(pb));
+ } else {
+ iconImage = NULL;
+ }
+ }
+ if (iconImage == NULL)
+ iconImage = GTK_IMAGE(gtk_image_new_from_file(g_strconcat(
+ res_dir_location, "netsurf-16x16.xpm", NULL)));
+ gtk_container_add(GTK_CONTAINER(g->toolFav), GTK_WIDGET(
+ iconImage));
+ gtk_widget_show_all(GTK_WIDGET(g->toolFav));
+}
gboolean nsgtk_scaffolding_is_busy(struct gtk_scaffolding *scaffold)
{
@@ -1563,14 +1641,24 @@
return g->scaffold->notebook;
}
+GtkEntry *nsgtk_scaffolding_get_urlbar(struct gui_window *g)
+{
+ return g->scaffold->url_bar;
+}
+
+GtkToolbar *nsgtk_scaffolding_get_toolbar(struct gui_window *g)
+{
+ return g->scaffold->tool_bar;
+}
+
+
void nsgtk_scaffolding_set_top_level (struct gui_window *gw)
{
gw->scaffold->top_level = gw;
-
/* Synchronise the history (will also update the URL bar) */
nsgtk_window_update_back_forward(gw->scaffold);
- /* Ensure the window's title bar is updated */
+ /* Ensure the window's title bar as well as favicon are updated */
if (gw->bw != NULL && gw->bw->current_content != NULL) {
if (gw->bw->current_content->title != NULL) {
gui_window_set_title(gw,
@@ -1578,6 +1666,9 @@
} else {
gui_window_set_title(gw, gw->bw->current_content->url);
}
+ if (gw->bw->current_content->type == CONTENT_HTML)
+ gui_window_set_icon(gw, gw->bw->current_content->
+ data.html.favicon);
}
}
Index: gtk/gtk_scaffolding.h
===================================================================
--- gtk/gtk_scaffolding.h (.../trunk/netsurf) (revision 7376)
+++ gtk/gtk_scaffolding.h (.../branches/MarkieB/favs) (revision 7376)
@@ -26,55 +26,19 @@
typedef struct gtk_scaffolding nsgtk_scaffolding;
-struct gtk_scaffolding {
- GtkWindow *window;
- GtkNotebook *notebook;
- GtkEntry *url_bar;
- GtkEntryCompletion *url_bar_completion;
- GtkStatusbar *status_bar;
- GtkMenuItem *edit_menu;
- GtkMenuItem *tabs_menu;
- GtkToolbar *tool_bar;
- GtkToolButton *back_button;
- GtkToolButton *history_button;
- GtkToolButton *forward_button;
- GtkToolButton *stop_button;
- GtkToolButton *reload_button;
- GtkMenuBar *menu_bar;
- GtkMenuItem *back_menu;
- GtkMenuItem *forward_menu;
- GtkMenuItem *stop_menu;
- GtkMenuItem *reload_menu;
- GtkImage *throbber;
- GtkPaned *status_pane;
-
- GladeXML *xml;
-
- GladeXML *popup_xml;
- GtkMenu *popup_menu;
-
- struct gtk_history_window *history_window;
- GtkDialog *preferences_dialog;
-
- int throb_frame;
- struct gui_window *top_level;
- int being_destroyed;
-
- bool fullscreen;
-};
-
GtkWindow *nsgtk_get_window_for_scaffold(struct gtk_scaffolding *g);
nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel);
gboolean nsgtk_scaffolding_is_busy(nsgtk_scaffolding *scaffold);
-GtkWindow* nsgtk_scaffolding_get_window (struct gui_window *g);
+GtkWindow *nsgtk_scaffolding_get_window(struct gui_window *g);
+GtkNotebook *nsgtk_scaffolding_get_notebook(struct gui_window *g);
+GtkEntry *nsgtk_scaffolding_get_urlbar(struct gui_window *g);
+GtkToolbar *nsgtk_scaffolding_get_toolbar(struct gui_window *g);
-GtkNotebook* nsgtk_scaffolding_get_notebook (struct gui_window *g);
+void nsgtk_scaffolding_set_top_level(struct gui_window *gw);
-void nsgtk_scaffolding_set_top_level (struct gui_window *gw);
-
void nsgtk_scaffolding_destroy(nsgtk_scaffolding *scaffold);
void nsgtk_scaffolding_popup_menu(struct gtk_scaffolding *g, gdouble x,
Index: gtk/gtk_tabs.c
===================================================================
--- gtk/gtk_tabs.c (.../trunk/netsurf) (revision 7376)
+++ gtk/gtk_tabs.c (.../branches/MarkieB/favs) (revision 7376)
@@ -81,7 +81,7 @@
}
if (background)
gtk_notebook_set_current_page(GTK_NOTEBOOK(tabs), remember);
- gtk_widget_grab_focus(GTK_WIDGET(window->scaffold->url_bar));
+ gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_get_urlbar(window)));
}
void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child,
Index: gtk/dialogs/gtk_options.c
===================================================================
--- gtk/dialogs/gtk_options.c (.../trunk/netsurf) (revision 7376)
+++ gtk/dialogs/gtk_options.c (.../branches/MarkieB/favs) (revision 7376)
@@ -97,6 +97,8 @@
DECLARE(fileChooserDownloads);
DECLARE(checkFocusNew);
DECLARE(checkNewBlank);
+DECLARE(sourceButtonTab);
+static GtkWidget *sourceButtonWindow;
DECLARE(spinMarginTop);
DECLARE(spinMarginBottom);
@@ -133,7 +135,13 @@
wndPreferences = GTK_DIALOG(glade_xml_get_widget(gladeFile,
"dlgPreferences"));
gtk_window_set_transient_for (GTK_WINDOW(wndPreferences), parent);
-
+
+ FIND_WIDGET(sourceButtonTab);
+ FIND_WIDGET(sourceButtonWindow);
+ GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(
+ sourceButtonWindow));
+ gtk_radio_button_set_group(GTK_RADIO_BUTTON(sourceButtonTab), group);
+
/* set the widgets to reflect the current options */
nsgtk_options_load();
@@ -188,6 +196,7 @@
CONNECT(checkFocusNew, "toggled");
CONNECT(checkNewBlank, "toggled");
+ CONNECT(sourceButtonTab, "toggled");
CONNECT(spinMarginTop, "value-changed");
CONNECT(spinMarginBottom, "value-changed");
@@ -200,7 +209,7 @@
CONNECT(checkCompressPDF, "toggled");
CONNECT(checkPasswordPDF, "toggled");
CONNECT(setDefaultExportOptions, "clicked");
-
+
g_signal_connect(G_OBJECT(wndPreferences), "response",
G_CALLBACK (dialog_response_handler), NULL);
@@ -312,7 +321,6 @@
gtk_box_pack_start(GTK_BOX(combolanguagevbox),
comboLanguage, FALSE, FALSE, 0);
gtk_widget_show(comboLanguage);
-
SET_ENTRY(entryHomePageURL,
option_homepage_url ? option_homepage_url : "");
SET_BUTTON(setCurrentPage);
@@ -380,6 +388,7 @@
SET_CHECK(checkFocusNew, option_focus_new);
SET_CHECK(checkNewBlank, option_new_blank);
+ SET_CHECK(sourceButtonTab, option_source_tab);
SET_SPIN(spinMarginTop, option_margin_top);
SET_SPIN(spinMarginBottom, option_margin_bottom);
@@ -649,32 +658,32 @@
switch(option_button_type) {
case 0:
gtk_toolbar_set_style(
- GTK_TOOLBAR(current->scaffold->tool_bar),
- GTK_TOOLBAR_ICONS);
+ nsgtk_scaffolding_get_toolbar(current),
+ GTK_TOOLBAR_ICONS);
gtk_toolbar_set_icon_size(
- GTK_TOOLBAR(current->scaffold->tool_bar),
- GTK_ICON_SIZE_SMALL_TOOLBAR);
+ nsgtk_scaffolding_get_toolbar(current),
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
break;
case 1:
gtk_toolbar_set_style(
- GTK_TOOLBAR(current->scaffold->tool_bar),
- GTK_TOOLBAR_ICONS);
+ nsgtk_scaffolding_get_toolbar(current),
+ GTK_TOOLBAR_ICONS);
gtk_toolbar_set_icon_size(
- GTK_TOOLBAR(current->scaffold->tool_bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
+ nsgtk_scaffolding_get_toolbar(current),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
break;
case 2:
gtk_toolbar_set_style(
- GTK_TOOLBAR(current->scaffold->tool_bar),
- GTK_TOOLBAR_BOTH);
+ nsgtk_scaffolding_get_toolbar(current),
+ GTK_TOOLBAR_BOTH);
gtk_toolbar_set_icon_size(
- GTK_TOOLBAR(current->scaffold->tool_bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
+ nsgtk_scaffolding_get_toolbar(current),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
break;
case 3:
gtk_toolbar_set_style(
- GTK_TOOLBAR(current->scaffold->tool_bar),
- GTK_TOOLBAR_TEXT);
+ nsgtk_scaffolding_get_toolbar(current),
+ GTK_TOOLBAR_TEXT);
default:
break;
}
@@ -702,6 +711,9 @@
END_HANDLER
CHECK_CHANGED(checkNewBlank, option_new_blank)
+END_HANDLER
+
+CHECK_CHANGED(sourceButtonTab, option_source_tab)
END_HANDLER
SPIN_CHANGED(spinMarginTop, option_margin_top)
Index: gtk/dialogs/gtk_source.c
===================================================================
--- gtk/dialogs/gtk_source.c (.../trunk/netsurf) (revision 7376)
+++ gtk/dialogs/gtk_source.c (.../branches/MarkieB/favs) (revision 7376)
@@ -28,8 +28,10 @@
#include "gtk/gtk_gui.h"
#include "gtk/gtk_print.h"
#include "gtk/gtk_selection.h"
+#include "gtk/options.h"
#include "desktop/netsurf.h"
#include "desktop/print.h"
+#include "desktop/options.h"
#include "utils/messages.h"
#include "utils/url.h"
#include "utils/utils.h"
@@ -61,6 +63,7 @@
static struct nsgtk_source_window *nsgtk_source_list = 0;
static char source_zoomlevel = 10;
+void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw);
static void nsgtk_attach_source_menu_handlers(GladeXML *xml, gpointer g);
static gboolean nsgtk_source_delete_event(GtkWindow *window, gpointer g);
static gboolean nsgtk_source_destroy_event(GtkWindow *window, gpointer g);
@@ -103,111 +106,149 @@
void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
{
- if (bw->current_content->type == CONTENT_HTML) {
- glade_Location = g_strconcat(res_dir_location, "source.glade",
- NULL);
- glade_File = glade_xml_new(glade_Location, NULL, NULL);
- if (glade_File == NULL) {
- LOG(("error loading glade tree"));
- }
+ if (bw->current_content->type != CONTENT_HTML)
+ return;
+
+ if (option_source_tab) {
+ nsgtk_source_tab_init(parent, bw);
+ return;
+ }
+
+ glade_Location = g_strconcat(res_dir_location, "source.glade",
+ NULL);
+ glade_File = glade_xml_new(glade_Location, NULL, NULL);
+ if (glade_File == NULL) {
+ LOG(("error loading glade tree"));
+ }
+ g_free(glade_Location);
- char *data = NULL;
+ char *data = NULL;
- utf8_convert_ret r = utf8_from_enc(
- bw->current_content->source_data,
- bw->current_content->data.html.encoding,
- bw->current_content->source_size,
- &data);
- if (r == UTF8_CONVERT_NOMEM) {
- warn_user("NoMemory",0);
- return;
- } else if (r == UTF8_CONVERT_BADENC) {
- warn_user("EncNotRec",0);
- return;
- }
+ utf8_convert_ret r = utf8_from_enc(
+ bw->current_content->source_data,
+ bw->current_content->data.html.encoding,
+ bw->current_content->source_size,
+ &data);
+ if (r == UTF8_CONVERT_NOMEM) {
+ warn_user("NoMemory",0);
+ return;
+ } else if (r == UTF8_CONVERT_BADENC) {
+ warn_user("EncNotRec",0);
+ return;
+ }
- GtkWindow *wndSource = GTK_WINDOW(glade_xml_get_widget(
- glade_File, "wndSource"));
- GtkWidget *cutbutton = glade_xml_get_widget(
- glade_File, "source_cut");
- GtkWidget *pastebutton = glade_xml_get_widget(
- glade_File, "source_paste");
- GtkWidget *deletebutton = glade_xml_get_widget(
- glade_File, "source_delete");
- GtkWidget *printbutton = glade_xml_get_widget(
- glade_File, "source_print");
- gtk_widget_set_sensitive(cutbutton, FALSE);
- gtk_widget_set_sensitive(pastebutton, FALSE);
- gtk_widget_set_sensitive(deletebutton, FALSE);
- /* for now */
- gtk_widget_set_sensitive(printbutton, FALSE);
-
- struct nsgtk_source_window *thiswindow =
- malloc(sizeof(struct nsgtk_source_window));
- if (thiswindow == NULL) {
- free(data);
- warn_user("NoMemory", 0);
- return;
- }
+ GtkWindow *wndSource = GTK_WINDOW(glade_xml_get_widget(
+ glade_File, "wndSource"));
+ GtkWidget *cutbutton = glade_xml_get_widget(
+ glade_File, "source_cut");
+ GtkWidget *pastebutton = glade_xml_get_widget(
+ glade_File, "source_paste");
+ GtkWidget *deletebutton = glade_xml_get_widget(
+ glade_File, "source_delete");
+ GtkWidget *printbutton = glade_xml_get_widget(
+ glade_File, "source_print");
+ gtk_widget_set_sensitive(cutbutton, FALSE);
+ gtk_widget_set_sensitive(pastebutton, FALSE);
+ gtk_widget_set_sensitive(deletebutton, FALSE);
+ /* for now */
+ gtk_widget_set_sensitive(printbutton, FALSE);
+
+ struct nsgtk_source_window *thiswindow =
+ malloc(sizeof(struct nsgtk_source_window));
+ if (thiswindow == NULL) {
+ free(data);
+ warn_user("NoMemory", 0);
+ return;
+ }
- thiswindow->url = strdup(bw->current_content->url);
- if (thiswindow->url == NULL) {
- free(thiswindow);
- free(data);
- warn_user("NoMemory", 0);
- return;
- }
+ thiswindow->url = strdup(bw->current_content->url);
+ if (thiswindow->url == NULL) {
+ free(thiswindow);
+ free(data);
+ warn_user("NoMemory", 0);
+ return;
+ }
- thiswindow->data = data;
-
- thiswindow->sourcewindow = wndSource;
- thiswindow->bw = bw;
+ thiswindow->data = data;
- char *title = malloc(strlen(bw->current_content->url)
- + SLEN("Source of ") + 1);
- if (title == NULL) {
- free(thiswindow->url);
- free(thiswindow);
- free(data);
- warn_user("NoMemory", 0);
- return;
- }
- sprintf(title, "Source of %s", bw->current_content->url);
+ thiswindow->sourcewindow = wndSource;
+ thiswindow->bw = bw;
- thiswindow->next = nsgtk_source_list;
- thiswindow->prev = NULL;
- if (nsgtk_source_list != NULL)
- nsgtk_source_list->prev = thiswindow;
- nsgtk_source_list = thiswindow;
-
- nsgtk_attach_source_menu_handlers(glade_File, thiswindow);
+ char *title = malloc(strlen(bw->current_content->url)
+ + SLEN("Source of ") + 1);
+ if (title == NULL) {
+ free(thiswindow->url);
+ free(thiswindow);
+ free(data);
+ warn_user("NoMemory", 0);
+ return;
+ }
+ sprintf(title, "Source of %s", bw->current_content->url);
+
+ thiswindow->next = nsgtk_source_list;
+ thiswindow->prev = NULL;
+ if (nsgtk_source_list != NULL)
+ nsgtk_source_list->prev = thiswindow;
+ nsgtk_source_list = thiswindow;
- gtk_window_set_title(wndSource, title);
+ nsgtk_attach_source_menu_handlers(glade_File, thiswindow);
- g_signal_connect(G_OBJECT(wndSource), "destroy",
- G_CALLBACK(nsgtk_source_destroy_event),
- thiswindow);
- g_signal_connect(G_OBJECT(wndSource), "delete-event",
- G_CALLBACK(nsgtk_source_delete_event),
- thiswindow);
+ gtk_window_set_title(wndSource, title);
+
+ g_signal_connect(G_OBJECT(wndSource), "destroy",
+ G_CALLBACK(nsgtk_source_destroy_event),
+ thiswindow);
+ g_signal_connect(G_OBJECT(wndSource), "delete-event",
+ G_CALLBACK(nsgtk_source_delete_event),
+ thiswindow);
+
+ GtkTextView *sourceview = GTK_TEXT_VIEW(
+ glade_xml_get_widget(glade_File,
+ "source_view"));
+ PangoFontDescription *fontdesc =
+ pango_font_description_from_string("Monospace 8");
+
+ thiswindow->gv = sourceview;
+ gtk_widget_modify_font(GTK_WIDGET(sourceview), fontdesc);
+ GtkTextBuffer *tb = gtk_text_view_get_buffer(sourceview);
+ gtk_text_buffer_set_text(tb, thiswindow->data, -1);
- GtkTextView *sourceview = GTK_TEXT_VIEW(
- glade_xml_get_widget(glade_File,
- "source_view"));
- PangoFontDescription *fontdesc =
- pango_font_description_from_string("Monospace 8");
+ gtk_widget_show(GTK_WIDGET(wndSource));
- thiswindow->gv = sourceview;
- gtk_widget_modify_font(GTK_WIDGET(sourceview), fontdesc);
- GtkTextBuffer *tb = gtk_text_view_get_buffer(sourceview);
- gtk_text_buffer_set_text(tb, thiswindow->data, -1);
-
- gtk_widget_show(GTK_WIDGET(wndSource));
+ free(title);
+}
- free(title);
+void nsgtk_source_tab_init(GtkWindow *parent, struct browser_window *bw)
+{
+ char *ndata = 0;
+ utf8_convert_ret r = utf8_from_enc(
+ bw->current_content->source_data,
+ bw->current_content->data.html.encoding,
+ bw->current_content->source_size,
+ &ndata);
+ if (r == UTF8_CONVERT_NOMEM) {
+ warn_user("NoMemory",0);
+ return;
+ } else if (r == UTF8_CONVERT_BADENC) {
+ warn_user("EncNotRec",0);
+ return;
}
+ gchar *filename;
+ gint handle = g_file_open_tmp("nsgtksourceXXXXXX", &filename, NULL);
+ close (handle); /* in case it was binary mode */
+ FILE *f = fopen(filename, "w");
+ fprintf(f, "%s", ndata);
+ fclose(f);
+ filename = g_strconcat("file://", filename, NULL);
+ struct browser_window *newbw = browser_window_create(filename, bw,
+ NULL, false, true);
+ g_free(filename);
+ if (newbw->current_content)
+ newbw->current_content->title = g_strconcat("source of ",
+ bw->current_content->url , NULL);
}
+
void nsgtk_attach_source_menu_handlers(GladeXML *xml, gpointer g)
{
struct menu_events *event = source_menu_events;
Index: gtk/res/netsurf.glade
===================================================================
--- gtk/res/netsurf.glade (.../trunk/netsurf) (revision 7376)
+++ gtk/res/netsurf.glade (.../branches/MarkieB/favs) (revision 7376)
@@ -422,6 +422,7 @@
<property name="visible">True</property>
<property name="label"
translatable="yes">View S_ource</property>
<property
name="use_underline">True</property>
+ <accelerator key="F8" modifiers=""
signal="activate"/>
<child internal-child="image">
<widget class="GtkImage"
id="menu-item-image28">
<property
name="visible">True</property>
@@ -790,7 +791,7 @@
<property name="stock_id">gtk-go-back</property>
</widget>
<packing>
- <property name="homogeneous">True</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
@@ -802,7 +803,7 @@
<property
name="icon">arrow_down_8x32.png</property>
</widget>
<packing>
- <property name="homogeneous">True</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
@@ -811,7 +812,7 @@
<property
name="stock_id">gtk-go-forward</property>
</widget>
<packing>
- <property name="homogeneous">True</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
@@ -820,7 +821,7 @@
<property name="stock_id">gtk-stop</property>
</widget>
<packing>
- <property name="homogeneous">True</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
@@ -829,7 +830,7 @@
<property name="stock_id">gtk-refresh</property>
</widget>
<packing>
- <property name="homogeneous">True</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
@@ -838,10 +839,25 @@
<property name="stock_id">gtk-home</property>
</widget>
<packing>
- <property name="homogeneous">True</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
+ <widget class="GtkToolItem" id="toolFav">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkImage" id="FavIcon">
+ <property name="visible">True</property>
+ <property
name="pixbuf">netsurf-16x16.xpm</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
<widget class="GtkToolItem" id="toolURLBar">
<property name="visible">True</property>
<child>
@@ -852,6 +868,10 @@
</widget>
</child>
</widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
</child>
<child>
<widget class="GtkToolItem" id="toolthrobber">
@@ -864,6 +884,10 @@
</widget>
</child>
</widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
</child>
</widget>
<packing>
@@ -956,106 +980,106 @@
<property name="column_spacing">11</property>
<property name="row_spacing">10</property>
<child>
- <widget class="GtkLabel"
id="labelLoginHost">
+ <widget class="GtkEntry"
id="entryLoginUser">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label"
translatable="yes">moo.yoo.com</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="text"
translatable="yes">sesame</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="x_options"></property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label57">
+ <widget class="GtkEntry"
id="entryLoginPass">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label"
translatable="yes">Password</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property
name="activates_default">True</property>
+ <property name="text"
translatable="yes">opensesame</property>
</widget>
<packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
- <property name="x_options"></property>
+ <property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label56">
+ <widget class="GtkLabel"
id="labelLoginRealm">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label"
translatable="yes">Username</property>
+ <property name="label"
translatable="yes">my sekr3t area</property>
</widget>
<packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label54">
+ <widget class="GtkLabel" id="label55">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label"
translatable="yes">Host</property>
+ <property name="label"
translatable="yes">Realm</property>
</widget>
<packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="label55">
+ <widget class="GtkLabel" id="label54">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label"
translatable="yes">Realm</property>
+ <property name="label"
translatable="yes">Host</property>
</widget>
<packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
- <widget class="GtkLabel"
id="labelLoginRealm">
+ <widget class="GtkLabel" id="label56">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label"
translatable="yes">my sekr3t area</property>
+ <property name="label"
translatable="yes">Username</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
<property name="x_options"></property>
</packing>
</child>
<child>
- <widget class="GtkEntry"
id="entryLoginPass">
+ <widget class="GtkLabel" id="label57">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="visibility">False</property>
- <property
name="activates_default">True</property>
- <property name="text"
translatable="yes">opensesame</property>
+ <property name="xalign">0</property>
+ <property name="label"
translatable="yes">Password</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
- <property name="y_options"></property>
+ <property name="x_options"></property>
</packing>
</child>
<child>
- <widget class="GtkEntry"
id="entryLoginUser">
+ <widget class="GtkLabel"
id="labelLoginHost">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="text"
translatable="yes">sesame</property>
+ <property name="xalign">0</property>
+ <property name="label"
translatable="yes">moo.yoo.com</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"></property>
+ <property name="x_options"></property>
</packing>
</child>
</widget>
Index: gtk/res/options.glade
===================================================================
--- gtk/res/options.glade (.../trunk/netsurf) (revision 7376)
+++ gtk/res/options.glade (.../branches/MarkieB/favs) (revision 7376)
@@ -1742,6 +1742,66 @@
</packing>
</child>
<child>
+ <widget class="GtkFrame" id="frame9">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property
name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment"
id="alignment9">
+ <property name="visible">True</property>
+ <property
name="left_padding">12</property>
+ <child>
+ <widget class="GtkHBox" id="hbox9">
+ <property
name="visible">True</property>
+ <child>
+ <widget class="GtkRadioButton"
id="sourceButtonWindow">
+ <property
name="visible">True</property>
+ <property
name="can_focus">True</property>
+ <property name="label"
translatable="yes">in own window </property>
+ <property
name="response_id">0</property>
+ <property
name="active">True</property>
+ <property
name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property
name="expand">False</property>
+ <property
name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton"
id="sourceButtonTab">
+ <property
name="visible">True</property>
+ <property
name="can_focus">True</property>
+ <property name="label"
translatable="yes">in new tab</property>
+ <property
name="response_id">0</property>
+ <property
name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property
name="expand">False</property>
+ <property
name="fill">False</property>
+ <property
name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label22">
+ <property name="visible">True</property>
+ <property name="label"
translatable="yes"><b>View
Source</b></property>
+ <property
name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property
name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
<placeholder/>
</child>
</widget>
Index: !NetSurf/Resources/en/Messages
===================================================================
--- !NetSurf/Resources/en/Messages (.../trunk/netsurf) (revision 7376)
+++ !NetSurf/Resources/en/Messages (.../branches/MarkieB/favs) (revision 7376)
@@ -607,6 +607,7 @@
BadRedirect:Bad redirect URL
FetchFailed:Unable to fetch document
NotCSS:Warning: stylesheet is not CSS
+NotFavIco:Favicon not supported
BadObject:Warning: bad object type
ObjError:Error loading object: %s
ParsingFail:Parsing the document failed.
Index: Makefile.sources
===================================================================
--- Makefile.sources (.../trunk/netsurf) (revision 7376)
+++ Makefile.sources (.../branches/MarkieB/favs) (revision 7376)
@@ -8,7 +8,7 @@
S_CONTENT := content.c fetch.c fetchcache.c urldb.c \
fetchers/fetch_curl.c fetchers/fetch_data.c
S_CSS := css.c css_enum.c parser.c ruleset.c scanner.c
-S_RENDER := box.c box_construct.c box_normalise.c directory.c \
+S_RENDER := box.c box_construct.c box_normalise.c directory.c favicon.c \
form.c html.c html_redraw.c hubbub_binding.c imagemap.c \
layout.c list.c loosen.c table.c textplain.c
S_UTILS := base64.c filename.c hashtable.c locale.c messages.c talloc.c \
Index: riscos/window.c
===================================================================
--- riscos/window.c (.../trunk/netsurf) (revision 7376)
+++ riscos/window.c (.../branches/MarkieB/favs) (revision 7376)
@@ -1092,6 +1092,9 @@
}
}
+void gui_window_set_icon(struct gui_window *g, struct content *icon)
+{
+}
/**
* Place the caret in a browser window.
Index: desktop/browser.c
===================================================================
--- desktop/browser.c (.../trunk/netsurf) (revision 7376)
+++ desktop/browser.c (.../branches/MarkieB/favs) (revision 7376)
@@ -85,6 +85,7 @@
static void browser_window_convert_to_download(struct browser_window *bw);
static void browser_window_start_throbber(struct browser_window *bw);
static void browser_window_stop_throbber(struct browser_window *bw);
+static void browser_window_set_icon(struct browser_window *bw);
static void browser_window_set_status(struct browser_window *bw,
const char *text);
static void browser_window_set_pointer(struct gui_window *g,
@@ -491,6 +492,7 @@
browser_window_update(bw, false);
browser_window_set_status(bw, c->status_message);
browser_window_stop_throbber(bw);
+ browser_window_set_icon(bw);
history_update(bw->history, c);
hotlist_visited(c);
free(bw->referer);
@@ -763,6 +765,21 @@
return false;
}
+/**
+ * when ready, set icon at top level
+ * \param bw browser_window
+ * current implementation ignores lower-levels' link rels completely
+ */
+void browser_window_set_icon(struct browser_window *bw)
+{
+ while (bw->parent)
+ bw = bw->parent;
+ if ((bw->current_content != NULL) && (bw->current_content->type ==
CONTENT_HTML))
+ gui_window_set_icon(bw->window,
+ bw->current_content->data.html.favicon);
+ else
+ gui_window_set_icon(bw->window, NULL);
+}
/**
* Redraw browser window, set extent to content, and update title.
Index: desktop/gui.h
===================================================================
--- desktop/gui.h (.../trunk/netsurf) (revision 7376)
+++ desktop/gui.h (.../branches/MarkieB/favs) (revision 7376)
@@ -88,6 +88,7 @@
void gui_window_set_url(struct gui_window *g, const char *url);
void gui_window_start_throbber(struct gui_window *g);
void gui_window_stop_throbber(struct gui_window *g);
+void gui_window_set_icon(struct gui_window *g, struct content *icon);
void gui_window_place_caret(struct gui_window *g, int x, int y, int height);
void gui_window_remove_caret(struct gui_window *g);
void gui_window_new_content(struct gui_window *g);
Index: desktop/print.c
===================================================================
--- desktop/print.c (.../trunk/netsurf) (revision 7376)
+++ desktop/print.c (.../branches/MarkieB/favs) (revision 7376)
@@ -197,7 +197,7 @@
}
/**
- * The content is resized to fit page width. In case it is to wide, it is
+ * The content is resized to fit page width. In case it is too wide, it is
* loosened.
*
* \param content The content to be printed