Precis:

This is the first issued review of Mark Benjamin's branch which implements
favicon support for the browser core and the GTK frontend.


Added files


Index: render/favicon.c
===================================================================
--- /dev/null   2008-11-24 10:09:14.252162000 +0000
+++ render/favicon.c    2009-04-28 16:01:49.412080078 +0100
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2007 James Bursa <[email protected]>
+ * Copyright 2009 Mark Benjamin <[email protected]>
+ *
+ * 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 *html_get_icon_ref(struct content *c, xmlNode *html);
+static void html_favicon_callback(content_msg msg, struct content *icon,
+               intptr_t p1, intptr_t p2, union content_msg_data data);
+static unsigned long hash(char *str);
+
+unsigned long 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 *html_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(hash(rel)) {
+                       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(hash(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(hash(suf)) {
+                               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 html_get_icon(struct content *c, xmlNode *html)
+{
+       union content_msg_data msg_data;
+       char *url = html_get_icon_ref(c, html);
+       struct content *favcontent = NULL;
+       if (url != NULL)                
+               favcontent = fetchcache(url, html_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, html_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 html_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)) {
+                               
+                               /* may need call to content_open() */
+                               
+                       } 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,
+                                               html_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
===================================================================
--- /dev/null   2008-11-24 10:09:14.252162000 +0000
+++ render/favicon.h    2009-04-28 16:01:49.412080078 +0100
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2007 James Bursa <[email protected]>
+ * Copyright 2009 Mark Benjamin <[email protected]>
+ *
+ * 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__
+
+bool html_get_icon(struct content *c, xmlNode *html);
+
+#endif


Changed files


 !NetSurf/Resources/en/Messages |    1 
 Makefile.sources               |    2 
 amiga/gui.c                    |    4 +
 beos/beos_scaffolding.cpp      |    4 +
 desktop/browser.c              |   17 ++++++
 desktop/gui.h                  |    1 
 desktop/print.c                |    2 
 framebuffer/fb_gui.c           |    4 +
 gtk/dialogs/gtk_options.c      |   41 +++++++++-----
 gtk/dialogs/gtk_source.c       |   36 +++++++++++++
 gtk/gtk_bitmap.c               |    7 +-
 gtk/gtk_scaffolding.c          |   99 ++++++++++++++++++++++++++++++++++-
 gtk/gtk_scaffolding.h          |   44 +--------------
 gtk/gtk_tabs.c                 |    2 
 gtk/options.h                  |    7 +-
 gtk/res/netsurf.glade          |  113 ++++++++++++++++++++++++-----------------
 gtk/res/options.glade          |   60 +++++++++++++++++++++
 image/ico.c                    |    9 +++
 image/ico.h                    |    2 
 render/html.c                  |   60 +++++++++++++--------
 render/html.h                  |    3 +
 riscos/window.c                |    3 +
 22 files changed, 386 insertions(+), 135 deletions(-)


Index: render/html.c
===================================================================
--- render/html.c       (revision 7353)
+++ render/html.c       (working copy)
@@ -36,7 +36,11 @@
 #include "desktop/gui.h"
 #include "desktop/options.h"
 #include "image/bitmap.h"
+#include "image/png.h"
+#include "image/gif.h"
+#include "image/ico.h"
 #include "render/box.h"
+#include "render/favicon.h"
 #include "render/font.h"
 #include "render/form.h"
 #include "render/html.h"
@@ -73,7 +77,6 @@ static bool html_object_type_permitted(c
 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 +164,7 @@ bool html_create(struct content *c, cons
 
 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 +286,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
  *
@@ -399,6 +403,9 @@ bool html_convert(struct content *c, int
        if (!html_find_stylesheets(c, html))
                return false;
 
+       /* get icon */
+       html_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 +541,20 @@ bool html_head(struct content *c, xmlNod
                                }
                                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 +625,8 @@ bool html_meta_refresh(struct content *c
 
                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 +769,13 @@ bool html_meta_refresh(struct content *c
        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 +854,7 @@ bool html_find_stylesheets(struct conten
 
                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 +882,8 @@ bool html_find_stylesheets(struct conten
                        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 +958,8 @@ bool html_find_stylesheets(struct conten
                                        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 +1139,8 @@ void html_convert_css_callback(content_m
                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 +1685,8 @@ void html_stop(struct content *c)
                                        (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 +1792,10 @@ void html_destroy(struct content *c)
                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       (revision 7353)
+++ render/html.h       (working copy)
@@ -128,6 +128,8 @@ struct content_html_data {
        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 @@ void html_open(struct content *c, struct
                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: image/ico.c
===================================================================
--- image/ico.c (revision 7353)
+++ image/ico.c (working copy)
@@ -114,6 +114,15 @@ bool nsico_redraw(struct content *c, int
                        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 (revision 7353)
+++ image/ico.h (working copy)
@@ -47,7 +47,7 @@ bool nsico_redraw_tiled(struct content *
                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        (revision 7353)
+++ framebuffer/fb_gui.c        (working copy)
@@ -1000,6 +1000,10 @@ void gui_window_stop_throbber(struct gui
 
 }
 
+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       (revision 7353)
+++ gtk/options.h       (working copy)
@@ -34,6 +34,7 @@ extern int option_history_age;
 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 @@ bool option_disable_plugins = false; \
 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 @@ bool option_new_blank = false;
 { "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    (revision 7353)
+++ gtk/gtk_bitmap.c    (working copy)
@@ -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 @@ struct bitmap {
   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       (revision 7353)
+++ gtk/gtk_scaffolding.c       (working copy)
@@ -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 @@ struct menu_events {
        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 @@ nsgtk_scaffolding *nsgtk_new_scaffolding
        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 @@ nsgtk_scaffolding *nsgtk_new_scaffolding
        /* 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 @@ void gui_window_stop_throbber(struct gui
 
        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 @@ GtkNotebook* nsgtk_scaffolding_get_noteb
        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 @@ void nsgtk_scaffolding_set_top_level (st
                } 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       (revision 7353)
+++ gtk/gtk_scaffolding.h       (working copy)
@@ -26,52 +26,16 @@
 
 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);
-
-GtkNotebook* nsgtk_scaffolding_get_notebook (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);
 
 void nsgtk_scaffolding_set_top_level (struct gui_window *gw);
 
Index: gtk/gtk_tabs.c
===================================================================
--- gtk/gtk_tabs.c      (revision 7353)
+++ gtk/gtk_tabs.c      (working copy)
@@ -81,7 +81,7 @@ void nsgtk_tab_add(struct gui_window *wi
        }
        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   (revision 7353)
+++ gtk/dialogs/gtk_options.c   (working copy)
@@ -97,6 +97,8 @@ DECLARE(checkRequestOverwrite);
 DECLARE(fileChooserDownloads);
 DECLARE(checkFocusNew);
 DECLARE(checkNewBlank);
+DECLARE(sourceButtonTab);
+static GtkWidget *sourceButtonWindow;
 
 DECLARE(spinMarginTop);
 DECLARE(spinMarginBottom);
@@ -133,6 +135,12 @@ GtkDialog* nsgtk_options_init(struct bro
                                "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();
        
@@ -187,6 +195,7 @@ GtkDialog* nsgtk_options_init(struct bro
        
        CONNECT(checkFocusNew, "toggled");
        CONNECT(checkNewBlank, "toggled");
+       CONNECT(sourceButtonTab, "toggled");
        
        CONNECT(spinMarginTop, "value-changed");
        CONNECT(spinMarginBottom, "value-changed");
@@ -388,6 +397,7 @@ void nsgtk_options_load(void) 
        
        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);
@@ -647,26 +657,26 @@ COMBO_CHANGED(comboButtonType, option_bu
        while (current) {
                switch(option_button_type) {
                case 1:
-                       
gtk_toolbar_set_style(GTK_TOOLBAR(current->scaffold->tool_bar),
-                                             GTK_TOOLBAR_ICONS);
-                       
gtk_toolbar_set_icon_size(GTK_TOOLBAR(current->scaffold->tool_bar),
-                                                 GTK_ICON_SIZE_SMALL_TOOLBAR);
+                       gtk_toolbar_set_style(nsgtk_scaffolding_get_toolbar(
+                               current), GTK_TOOLBAR_ICONS);
+                       gtk_toolbar_set_icon_size(nsgtk_scaffolding_get_toolbar(
+                                       current), GTK_ICON_SIZE_SMALL_TOOLBAR);
                        break;
                case 2:
-                       
gtk_toolbar_set_style(GTK_TOOLBAR(current->scaffold->tool_bar),
-                                             GTK_TOOLBAR_ICONS);
-                       
gtk_toolbar_set_icon_size(GTK_TOOLBAR(current->scaffold->tool_bar),
-                                                 GTK_ICON_SIZE_LARGE_TOOLBAR);
+                       gtk_toolbar_set_style(nsgtk_scaffolding_get_toolbar(
+                                       current), GTK_TOOLBAR_ICONS);
+                       gtk_toolbar_set_icon_size(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_BOTH);
-                       
gtk_toolbar_set_icon_size(GTK_TOOLBAR(current->scaffold->tool_bar),
-                                                 GTK_ICON_SIZE_LARGE_TOOLBAR);
+                       gtk_toolbar_set_style(nsgtk_scaffolding_get_toolbar(
+                                       current), GTK_TOOLBAR_BOTH);
+                       gtk_toolbar_set_icon_size(nsgtk_scaffolding_get_toolbar(
+                                       current), GTK_ICON_SIZE_LARGE_TOOLBAR);
                        break;
                case 4:
-                       
gtk_toolbar_set_style(GTK_TOOLBAR(current->scaffold->tool_bar),
-                                             GTK_TOOLBAR_TEXT);
+                       gtk_toolbar_set_style(nsgtk_scaffolding_get_toolbar(
+                                       current), GTK_TOOLBAR_TEXT);
                default:
                        break;
                }
@@ -696,6 +706,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)
 END_HANDLER
 
Index: gtk/dialogs/gtk_source.c
===================================================================
--- gtk/dialogs/gtk_source.c    (revision 7353)
+++ gtk/dialogs/gtk_source.c    (working copy)
@@ -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 gchar *glade_Location;
 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,6 +106,10 @@ MENUEVENT(source_about),
 
 void nsgtk_source_dialog_init(GtkWindow *parent, struct browser_window *bw)
 {              
+       if (option_source_tab) {
+               nsgtk_source_tab_init(parent, bw);
+               return;
+       }
        if (bw->current_content->type == CONTENT_HTML) {
                glade_Location = g_strconcat(res_dir_location, "source.glade", 
                                NULL);
@@ -208,6 +215,35 @@ void nsgtk_source_dialog_init(GtkWindow 
        }
 }
 
+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);
+       struct browser_window *newbw = browser_window_create(g_strconcat(
+                       "file://", filename, NULL), bw, NULL, false, true);
+       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       (revision 7353)
+++ gtk/res/netsurf.glade       (working copy)
@@ -790,7 +790,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 +802,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 +811,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 +820,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 +829,7 @@
                 <property name="stock_id">gtk-refresh</property>
               </widget>
               <packing>
-                <property name="homogeneous">True</property>
+                <property name="expand">False</property>
               </packing>
             </child>
             <child>
@@ -838,7 +838,22 @@
                 <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>
@@ -852,6 +867,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 +883,10 @@
                   </widget>
                 </child>
               </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">False</property>
+              </packing>
             </child>
           </widget>
           <packing>
@@ -956,106 +979,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       (revision 7353)
+++ gtk/res/options.glade       (working copy)
@@ -1742,6 +1742,66 @@ Text only</property>
                   </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">&lt;b&gt;View Source&lt;/b&gt;</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      (revision 7353)
+++ !NetSurf/Resources/en/Messages      (working copy)
@@ -607,6 +607,7 @@ Done:Document done
 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: beos/beos_scaffolding.cpp
===================================================================
--- beos/beos_scaffolding.cpp   (revision 7353)
+++ beos/beos_scaffolding.cpp   (working copy)
@@ -2312,6 +2312,10 @@ void gui_window_stop_throbber(struct gui
        g->top_view->UnlockLooper();
 }
 
+void gui_window_set_icon(struct gui_window *g, struct content *icon)
+{
+}
+
 #warning XXX
 #if 0 /* GTK */
 gboolean nsbeos_scaffolding_is_busy(nsbeos_scaffolding *scaffold)
Index: Makefile.sources
===================================================================
--- Makefile.sources    (revision 7353)
+++ Makefile.sources    (working copy)
@@ -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     (revision 7353)
+++ riscos/window.c     (working copy)
@@ -1092,6 +1092,9 @@ void gui_window_stop_throbber(struct gui
        }
 }
 
+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   (revision 7353)
+++ desktop/browser.c   (working copy)
@@ -85,6 +85,7 @@ static bool browser_window_check_throbbe
 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 @@ void browser_window_callback(content_msg
                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 @@ bool browser_window_check_throbber(struc
        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       (revision 7353)
+++ desktop/gui.h       (working copy)
@@ -88,6 +88,7 @@ void gui_window_hide_pointer(struct gui_
 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     (revision 7353)
+++ desktop/print.c     (working copy)
@@ -197,7 +197,7 @@ struct content *print_init(struct conten
 }
 
 /**
- * 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
Index: amiga/gui.c
===================================================================
--- amiga/gui.c (revision 7353)
+++ amiga/gui.c (working copy)
@@ -2658,6 +2658,10 @@ void gui_window_stop_throbber(struct gui
        g->shared->throbber_frame = 0;
 }
 
+void gui_window_set_icon(struct gui_window *g, struct content *icon)
+{
+}
+
 void ami_update_throbber(struct gui_window_2 *g,bool redraw)
 {
        struct IBox *bbox;


Conflicted files




Removed files



Reply via email to