netsurf/render/html.c

1935 lines
50 KiB
C
Raw Normal View History

/*
* Copyright 2007 James Bursa <bursa@users.sourceforge.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/>.
*/
/** \file
* Content for text/html (implementation).
*/
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
#define _GNU_SOURCE /* for strndup() */
#include <assert.h>
#include <ctype.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "utils/config.h"
#include "content/content.h"
#include "content/fetch.h"
#include "content/fetchcache.h"
#include "desktop/browser.h"
#include "desktop/gui.h"
#include "desktop/options.h"
#include "image/bitmap.h"
#include "render/box.h"
#include "render/font.h"
#include "render/form.h"
#include "render/html.h"
#include "render/imagemap.h"
#include "render/layout.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/talloc.h"
#include "utils/url.h"
#include "utils/utils.h"
#define CHUNK 4096
/* Change these to 1 to cause a dump to stderr of the frameset or box
* when the trees have been built.
*/
#define ALWAYS_DUMP_FRAMESET 0
#define ALWAYS_DUMP_BOX 0
static void html_convert_css_callback(content_msg msg, struct content *css,
intptr_t p1, intptr_t p2, union content_msg_data data);
static bool html_meta_refresh(struct content *c, xmlNode *head);
static bool html_head(struct content *c, xmlNode *head);
static bool html_find_stylesheets(struct content *c, xmlNode *html);
static bool html_process_style_element(struct content *c, xmlNode *style);
static void html_object_callback(content_msg msg, struct content *object,
intptr_t p1, intptr_t p2, union content_msg_data data);
static void html_object_done(struct box *box, struct content *object,
bool background);
static void html_object_failed(struct box *box, struct content *content,
bool background);
static bool html_object_type_permitted(const content_type type,
const content_type *permitted_types);
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);
#endif
static const char empty_document[] =
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
" \"http://www.w3.org/TR/html4/strict.dtd\">"
"<html>"
"<head>"
"<title>Empty document</title>"
"</head>"
"<body>"
"<h1>Empty document</h1>"
"<p>The document sent by the server is empty.</p>"
"</body>"
"</html>";
/**
* Create a CONTENT_HTML.
*
* The content_html_data structure is initialized and the HTML parser is
* created.
*/
bool html_create(struct content *c, const char *params[])
{
unsigned int i;
struct content_html_data *html = &c->data.html;
union content_msg_data msg_data;
binding_error error;
html->parser_binding = NULL;
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
html->document = 0;
html->encoding = 0;
html->base_url = c->url;
html->base_target = NULL;
html->layout = 0;
html->background_colour = TRANSPARENT;
html->stylesheet_count = 0;
html->stylesheet_content = 0;
html->style = 0;
html->working_stylesheet = 0;
html->object_count = 0;
html->object = 0;
html->forms = 0;
html->imagemaps = 0;
html->bw = 0;
html->frameset = 0;
html->iframe = 0;
html->page = 0;
html->index = 0;
html->box = 0;
First merge of Adam Blokus' GSoC work from his branch 'branches/adamblokus/netsurf'. Merged revisions 4212-4552,4554-4709,4711-4724 via svnmerge from svn://svn.netsurf-browser.org/branches/adamblokus/netsurf ........ r4212 | adamblokus | 2008-05-26 19:42:31 +0200 (Mon, 26 May 2008) | 4 lines Pdf plotting skeleton pinned on Print Preview in GTK. Just creates a file and draws lines. ........ r4213 | adamblokus | 2008-05-27 00:11:03 +0200 (Tue, 27 May 2008) | 4 lines Pdf plotter - added drawing some graphic primitives. Still with limited functionality, but a snapshot of the currently viewed page can be made and resembles the original. ........ r4214 | adamblokus | 2008-05-27 11:43:31 +0200 (Tue, 27 May 2008) | 2 lines Corrected encoding name ........ r4215 | adamblokus | 2008-05-27 12:47:26 +0200 (Tue, 27 May 2008) | 3 lines Colours and polygons added. ........ r4217 | adamblokus | 2008-05-27 21:39:35 +0200 (Tue, 27 May 2008) | 6 lines Added rectangles, filled boxes and clipping. Taken into consideration joty's comments. Added a todo list for this part. Added some debug stuff and checking boundaries. ........ r4218 | adamblokus | 2008-05-28 12:37:30 +0200 (Wed, 28 May 2008) | 2 lines Added path ploting (not sure if valid argument order for bezier) and dashed/dotted line styles ........ r4221 | adamblokus | 2008-05-28 22:11:05 +0200 (Wed, 28 May 2008) | 3 lines Some more options in graphic primitives and normalizing some parameters. ........ r4235 | adamblokus | 2008-05-31 22:54:56 +0200 (Sat, 31 May 2008) | 4 lines Plotting changed as jmb suggested (is the least invasive one from the possible) Added dummy bitmap plotting - way of plotting an image is determined by its type. ........ r4251 | adamblokus | 2008-06-03 17:12:15 +0200 (Tue, 03 Jun 2008) | 3 lines Added plotting jpg and png images - quite a lot to improve in this code, but it seems to work ;) ........ r4263 | adamblokus | 2008-06-05 14:20:32 +0200 (Thu, 05 Jun 2008) | 3 lines Added hadling images other than png and jpeg - with transparency. ........ r4267 | adamblokus | 2008-06-06 15:36:34 +0200 (Fri, 06 Jun 2008) | 5 lines Added handling NULL-returns from all mallocs. Added plot_bitmap_tile handling. Changed code style a little. ........ r4327 | adamblokus | 2008-06-12 17:46:34 +0200 (Thu, 12 Jun 2008) | 5 lines Added a first prototype of the paged-output organization. Still not sure about naming, file locations etc. Works with the same pdf plotting as before. ........ r4328 | adamblokus | 2008-06-13 13:52:15 +0200 (Fri, 13 Jun 2008) | 4 lines Added primitive width adjustment and outputing the whole website in multiple pages. ........ r4336 | joty | 2008-06-15 15:06:57 +0200 (Sun, 15 Jun 2008) | 1 line Fix RISC OS build failure (change r4235 wasn't complete). ........ r4337 | joty | 2008-06-15 18:15:32 +0200 (Sun, 15 Jun 2008) | 16 lines This enables "Export PDF" in RISC OS build: - Docs/Doxyfile(PREDEFINED): Added WITH_PDF_EXPORT - Makefile.sources(S_PDF): Add to RISC OS target as well. - utils/config.h: Define WITH_PDF_EXPORT which controls if we want to have PDF export functionality or not. - riscos/save_pdf.c,riscos/save_pdf.h(save_as_pdf): Use PDF print API made by Adam Blokus to write a PDF file under RISC OS. - riscos/save.c: Call save_as_pdf added. - riscos/menus.c: Add 'Export->PDF' menu entry. - riscos/menus.h(menu_action): Added BROWSER_EXPORT_PDF. - desktop/gui.h(gui_save_type): Added GUI_SAVE_PDF. - desktop/print.c(print_run): Added return value. - Makefile(CCACHE): Moved closed to the place where CC is set for the first time. (LDFLAGS): Centralised adding all non-pkgconfig libraries and added Haru + PNG libs. ........ r4343 | adamblokus | 2008-06-16 01:08:52 +0200 (Mon, 16 Jun 2008) | 3 lines Added margins and page size adjustment. ........ r4412 | adamblokus | 2008-06-21 20:22:07 +0200 (Sat, 21 Jun 2008) | 4 lines Added 'fuzzy' margins on page bottom. Disabled direct png embedding, because it is too unstable in Haru now. ........ r4421 | adamblokus | 2008-06-22 18:52:28 +0200 (Sun, 22 Jun 2008) | 2 lines Added "Save as.." dialog and Export->PDF menu entry. Print preview still works with default path. ........ r4437 | adamblokus | 2008-06-25 02:44:46 +0200 (Wed, 25 Jun 2008) | 4 lines Added skeleton of applying loose layout. Minor code cleaning-up. ........ r4492 | adamblokus | 2008-07-02 09:02:42 +0200 (Wed, 02 Jul 2008) | 5 lines Implemented the elementar ideas of the loose layout. Added scaling in the printing routine. Added some basic demonstrations. ........ r4493 | adamblokus | 2008-07-02 09:05:55 +0200 (Wed, 02 Jul 2008) | 3 lines Cleaned up the loosing code - commited to much of leftover rubbish code. ........ r4507 | adamblokus | 2008-07-04 14:25:48 +0200 (Fri, 04 Jul 2008) | 4 lines Added duplicating box tree and current content - window flickering during printing solved. Minor error checking after new HPDF_Image_AddSMask call. ........ r4515 | adamblokus | 2008-07-06 22:28:16 +0200 (Sun, 06 Jul 2008) | 2 lines Changes in loosen layout (image resizing). ........ r4517 | adamblokus | 2008-07-06 22:38:23 +0200 (Sun, 06 Jul 2008) | 2 lines Added pdf font handling and rendering functions with the use of Haru functions. ........ r4555 | adamblokus | 2008-07-10 00:59:05 +0200 (Thu, 10 Jul 2008) | 2 lines Added a very basic and still buggy GTK print implementation. ........ r4565 | adamblokus | 2008-07-10 14:50:16 +0200 (Thu, 10 Jul 2008) | 2 lines Added gtk printing one more time - I have forgotten to add the main file. ........ r4566 | adamblokus | 2008-07-10 14:57:02 +0200 (Thu, 10 Jul 2008) | 2 lines removed error with comment ........ r4569 | adamblokus | 2008-07-10 15:52:55 +0200 (Thu, 10 Jul 2008) | 5 lines Major style improvements - added a lot of doxygen comments, followed tlsa's style guide. Added some more error checking, too. ........ r4575 | adamblokus | 2008-07-10 18:48:26 +0200 (Thu, 10 Jul 2008) | 2 lines Cleaned up the code. ........ r4687 | adamblokus | 2008-07-17 14:17:19 +0200 (Thu, 17 Jul 2008) | 2 lines Changed everything according to jmb's review plus some minor bug fixes to gtk_print. ........ r4688 | adamblokus | 2008-07-17 17:16:34 +0200 (Thu, 17 Jul 2008) | 2 lines Solved the netsurf.glade clash from r4421. ........ r4693 | adamblokus | 2008-07-18 18:11:51 +0200 (Fri, 18 Jul 2008) | 2 lines Fixed bug with wrong number of pages in gtk printing. ........ r4695 | adamblokus | 2008-07-18 19:59:24 +0200 (Fri, 18 Jul 2008) | 3 lines - fixed uncommented line from the previous commit - fixed bug with scale bigger than 1.0 (incorretly clipped page) ........ r4696 | adamblokus | 2008-07-18 23:28:00 +0200 (Fri, 18 Jul 2008) | 2 lines Fixed bug in gtk_print_font_paint (and nsfont_paint). ........ r4697 | adamblokus | 2008-07-18 23:35:38 +0200 (Fri, 18 Jul 2008) | 2 lines Bug fix in nsfont_paint. ........ r4711 | adamblokus | 2008-07-19 22:44:15 +0200 (Sat, 19 Jul 2008) | 2 lines Added gtk_selection files. ........ r4712 | adamblokus | 2008-07-20 11:15:06 +0200 (Sun, 20 Jul 2008) | 2 lines Addam missing glade files. ........ r4713 | joty | 2008-07-20 17:13:10 +0200 (Sun, 20 Jul 2008) | 1 line Follow change r4517 for RISC OS and BeOS platforms : Added pdf font handling and rendering functions with the use of Haru functions. ........ r4714 | joty | 2008-07-20 18:19:50 +0200 (Sun, 20 Jul 2008) | 1 line Declare haru_nsfont iso define an instance for each C source including the font_haru.h header. This fixes breakage of PDF export on RISC OS. ........ r4724 | adamblokus | 2008-07-23 03:30:08 +0200 (Wed, 23 Jul 2008) | 6 lines Applied changes according to joty's review. Added checking the dimensions of a plotted image to pdf plotter. Commented out jpg embedding (it seems to cause some problems I'll bring it back when I figure out what's wrong) . Added back some files removed by mistake. ........ svn path=/trunk/netsurf/; revision=4741
2008-07-26 20:01:59 +04:00
html->font_func = &nsfont;
for (i = 0; params[i]; i += 2) {
if (strcasecmp(params[i], "charset") == 0) {
html->encoding = talloc_strdup(c, params[i + 1]);
if (!html->encoding) {
error = BINDING_NOMEM;
goto error;
}
html->encoding_source = ENCODING_SOURCE_HEADER;
break;
}
}
/* Create the parser binding */
error = binding_create_tree(c, html->encoding, &html->parser_binding);
if (error == BINDING_BADENCODING && html->encoding != NULL) {
/* Ok, we don't support the declared encoding. Bailing out
* isn't exactly user-friendly, so fall back to autodetect */
talloc_free(html->encoding);
html->encoding = NULL;
error = binding_create_tree(c, html->encoding,
&html->parser_binding);
}
if (error != BINDING_OK)
goto error;
return true;
error:
if (error == BINDING_BADENCODING) {
LOG(("Bad encoding: %s", html->encoding ? html->encoding : ""));
msg_data.error = messages_get("ParsingFail");
} else
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/**
* Process data for CONTENT_HTML.
*
* The data is parsed in chunks of size CHUNK, multitasking in between.
*/
bool html_process_data(struct content *c, char *data, unsigned int size)
{
unsigned long x;
binding_error err;
const char *encoding;
for (x = 0; x + CHUNK <= size; x += CHUNK) {
err = binding_parse_chunk(c->data.html.parser_binding,
(uint8_t *) data + x, CHUNK);
if (err == BINDING_ENCODINGCHANGE) {
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
goto encoding_change;
}
gui_multitask();
}
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
err = binding_parse_chunk(c->data.html.parser_binding,
(uint8_t *) data + x, (size - x));
if (err == BINDING_ENCODINGCHANGE) {
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
goto encoding_change;
}
return true;
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
encoding_change:
/* Retrieve new encoding */
encoding = binding_get_encoding(
c->data.html.parser_binding,
&c->data.html.encoding_source);
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
if (c->data.html.encoding != NULL)
talloc_free(c->data.html.encoding);
c->data.html.encoding = talloc_strdup(c, encoding);
if (c->data.html.encoding == NULL) {
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
union content_msg_data msg_data;
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* Destroy binding */
binding_destroy_tree(c->data.html.parser_binding);
/* Create new binding, using the new encoding */
err = binding_create_tree(c, c->data.html.encoding,
&c->data.html.parser_binding);
if (err == BINDING_BADENCODING) {
/* Ok, we don't support the declared encoding. Bailing out
* isn't exactly user-friendly, so fall back to Windows-1252 */
talloc_free(c->data.html.encoding);
c->data.html.encoding = talloc_strdup(c, "Windows-1252");
if (c->data.html.encoding == NULL) {
union content_msg_data msg_data;
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
err = binding_create_tree(c, c->data.html.encoding,
&c->data.html.parser_binding);
}
if (err != BINDING_OK) {
union content_msg_data msg_data;
if (err == BINDING_BADENCODING) {
LOG(("Bad encoding: %s", c->data.html.encoding
? c->data.html.encoding : ""));
msg_data.error = messages_get("ParsingFail");
} else
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* Recurse to reprocess all that data. This is safe because
* the encoding is now specified at parser-start which means
* it cannot be changed again. */
return html_process_data(c, c->source_data, c->source_size);
}
/**
* Convert a CONTENT_HTML for display.
*
* The following steps are carried out in order:
*
* - parsing to an XML tree is completed
* - stylesheets are fetched
* - the XML tree is converted to a box tree and object fetches are started
* - the box tree is laid out
*
* On exit, the content status will be either CONTENT_STATUS_DONE if the
* document is completely loaded or CONTENT_STATUS_READY if objects are still
* being fetched.
*/
bool html_convert(struct content *c, int width, int height)
{
xmlNode *html, *head;
union content_msg_data msg_data;
unsigned int time_before, time_taken;
#ifdef WITH_HUBBUB
struct form *f;
#endif
/* finish parsing */
if (c->source_size == 0) {
binding_error err;
/* Destroy current binding */
binding_destroy_tree(c->data.html.parser_binding);
/* Also, any existing encoding information,
* as it's not guaranteed to match the error page.
*/
talloc_free(c->data.html.encoding);
c->data.html.encoding = NULL;
/* Create new binding, using default charset */
err = binding_create_tree(c, NULL,
&c->data.html.parser_binding);
if (err != BINDING_OK) {
union content_msg_data msg_data;
if (err == BINDING_BADENCODING) {
LOG(("Bad encoding: %s", c->data.html.encoding
? c->data.html.encoding : ""));
msg_data.error = messages_get("ParsingFail");
} else
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* Process the error page */
if (html_process_data(c, (char *) empty_document,
SLEN(empty_document)) == false)
return false;
}
Merged revisions 4859-5013,5016-5018 via svnmerge from svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub ........ r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong. ........ r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines Fix segfault caused by mismatched struct layout expectations. Fix warnings, too. ........ r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap. ........ r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines Remove deugging printf()s, add Aliases file, add script { display: none; } block. ........ r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines Fix a segfault bug. ........ r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines Add gtk/res/Aliases as a symlink to the one in !NS/Resources ........ r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines Fix symlink. ........ r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines Make multiple parallel parser instances work correctly. ........ r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line Don't display contents of STYLE. ........ r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines Fix reparent_children to actually work Make get_parent_node pay attention to the element_only flag Fixup node referencing when appending a text child Make clone_node clone attributes and namespace information in the non-deep case ........ r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines Fix debug target ........ r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines Use talloc to allocate space for Hubbub. ........ r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines Stub out the encoding change callback so NS-hubbub compiles again. ........ r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines Tell Hubbub the encoding that HTTP gives us, if we have one. ........ r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on. ........ r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines Fix (I hope) a 64-bit compiler warning. ........ r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.) ........ r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb) ........ r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines Pedantic typo fix. Make Hubbub YES when building for RISC OS. Make Hubbub AUTO when building for GTK Ignore the presence of Hubbub on other platforms. Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016) Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO) ........ svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
binding_parse_completed(c->data.html.parser_binding);
c->data.html.document =
binding_get_document(c->data.html.parser_binding);
/*xmlDebugDumpDocument(stderr, c->data.html.document);*/
if (!c->data.html.document) {
LOG(("Parsing failed"));
msg_data.error = messages_get("ParsingFail");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
if (c->data.html.encoding == NULL) {
const char *encoding = binding_get_encoding(
c->data.html.parser_binding,
&c->data.html.encoding_source);
c->data.html.encoding = talloc_strdup(c, encoding);
if (c->data.html.encoding == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
}
/* locate html and head elements */
html = xmlDocGetRootElement(c->data.html.document);
if (html == 0 || strcmp((const char *) html->name, "html") != 0) {
LOG(("html element not found"));
msg_data.error = messages_get("ParsingFail");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
for (head = html->children;
head != 0 && head->type != XML_ELEMENT_NODE;
head = head->next)
;
if (head && strcmp((const char *) head->name, "head") != 0) {
head = 0;
LOG(("head element not found"));
}
if (head) {
if (!html_head(c, head)) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* handle meta refresh */
if (!html_meta_refresh(c, head))
return false;
}
/* get stylesheets */
if (!html_find_stylesheets(c, html))
return false;
#ifdef WITH_HUBBUB
/* 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) {
char *action;
url_func_result res;
/* Make all actions absolute */
res = url_join(f->action, c->data.html.base_url, &action);
if (res != URL_FUNC_OK) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
free(f->action);
f->action = action;
/* Ensure each form has a document encoding */
if (f->document_charset == NULL) {
f->document_charset = strdup(c->data.html.encoding);
if (f->document_charset == NULL) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR,
msg_data);
return false;
}
}
}
#endif
/* convert xml tree to box tree */
LOG(("XML to box"));
content_set_status(c, messages_get("Processing"));
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
if (!xml_to_box(html, c)) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
#if ALWAYS_DUMP_BOX
box_dump(c->data.html.layout->children, 0);
#endif
#if ALWAYS_DUMP_FRAMESET
if (c->data.html.frameset)
html_dump_frameset(c->data.html.frameset, 0);
#endif
/* extract image maps - can't do this sensibly in xml_to_box */
if (!imagemap_extract(html, c)) {
LOG(("imagemap extraction failed"));
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/*imagemap_dump(c);*/
/* layout the box tree */
html_set_status(c, messages_get("Formatting"));
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
LOG(("Layout document"));
time_before = wallclock();
html_reformat(c, width, height);
time_taken = wallclock() - time_before;
LOG(("Layout took %dcs", time_taken));
c->reformat_time = wallclock() +
((time_taken < option_min_reflow_period ?
option_min_reflow_period : time_taken * 1.25));
LOG(("Scheduling relayout no sooner than %dcs",
c->reformat_time - wallclock()));
/*box_dump(c->data.html.layout->children, 0);*/
/* Destroy the parser binding */
binding_destroy_tree(c->data.html.parser_binding);
c->data.html.parser_binding = NULL;
if (c->active == 0)
c->status = CONTENT_STATUS_DONE;
else
c->status = CONTENT_STATUS_READY;
html_set_status(c, "");
return true;
}
/**
* Process elements in <head>.
*
* \param c content structure
* \param head xml node of head element
* \return true on success, false on memory exhaustion
*
* The title and base href are extracted if present.
*/
bool html_head(struct content *c, xmlNode *head)
{
xmlNode *node;
xmlChar *s;
c->title = 0;
for (node = head->children; node != 0; node = node->next) {
if (node->type != XML_ELEMENT_NODE)
continue;
LOG(("Node: %s", node->name));
if (!c->title && strcmp((const char *) node->name,
"title") == 0) {
xmlChar *title = xmlNodeGetContent(node);
char *title2;
if (!title)
return false;
title2 = squash_whitespace((const char *) title);
xmlFree(title);
if (!title2)
return false;
c->title = talloc_strdup(c, title2);
free(title2);
if (!c->title)
return false;
} else if (strcmp((const char *) node->name, "base") == 0) {
char *href = (char *) xmlGetProp(node,
(const xmlChar *) "href");
if (href) {
char *url;
url_func_result res;
res = url_normalize(href, &url);
if (res == URL_FUNC_OK) {
c->data.html.base_url =
talloc_strdup(c, url);
free(url);
}
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")) ||
('a' <= s[0] && s[0] <= 'z') ||
('A' <= s[0] && s[0] <= 'Z')) { /* [6.16] */
c->data.html.base_target =
talloc_strdup(c,
(const char *) s);
if (!c->data.html.base_target) {
xmlFree(s);
return false;
}
}
xmlFree(s);
}
}
}
return true;
}
/**
* Search for meta refresh
*
* http://wp.netscape.com/assist/net_sites/pushpull.html
*
* \param c content structure
* \param head xml node of head element
* \return true on success, false otherwise (error reported)
*/
bool html_meta_refresh(struct content *c, xmlNode *head)
{
xmlNode *n;
xmlChar *equiv, *content;
union content_msg_data msg_data;
char *url, *end, *refresh = NULL, quote = 0;
url_func_result res;
for (n = head == 0 ? 0 : head->children; n; n = n->next) {
if (n->type != XML_ELEMENT_NODE)
continue;
/* Recurse into noscript elements */
if (strcmp((const char *) n->name, "noscript") == 0) {
if (!html_meta_refresh(c, n)) {
/* Some error occurred */
return false;
} else if (c->refresh) {
/* Meta refresh found - stop */
return true;
}
}
if (strcmp((const char *) n->name, "meta")) {
continue;
}
equiv = xmlGetProp(n, (const xmlChar *) "http-equiv");
if (!equiv)
continue;
if (strcasecmp((const char *) equiv, "refresh")) {
xmlFree(equiv);
continue;
}
xmlFree(equiv);
content = xmlGetProp(n, (const xmlChar *) "content");
if (!content)
continue;
end = (char *) content + strlen((const char *) content);
/* content := *LWS intpart fracpart? *LWS [';' *LWS *1url *LWS]
* intpart := 1*DIGIT
* fracpart := 1*('.' | DIGIT)
* url := "url" *LWS '=' *LWS (url-nq | url-sq | url-dq)
* url-nq := *urlchar
* url-sq := "'" *(urlchar | '"') "'"
* url-dq := '"' *(urlchar | "'") '"'
* urlchar := [#x9#x21#x23-#x26#x28-#x7E] | nonascii
* nonascii := [#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
*/
/* *LWS intpart */
msg_data.delay = (int)strtol((char *) content, &url, 10);
/* a very small delay and self-referencing URL can cause a loop
* that grinds machines to a halt. To prevent this we set a
* minimum refresh delay of 1s. */
if (msg_data.delay < 1)
msg_data.delay = 1;
/* fracpart? (ignored, as delay is integer only) */
while (url < end && (('0' <= *url && *url <= '9') ||
*url == '.')) {
url++;
}
/* *LWS */
while (url < end && isspace(*url)) {
url++;
}
/* ';' */
if (url < end && *url == ';')
url++;
/* *LWS */
while (url < end && isspace(*url)) {
url++;
}
if (url == end) {
/* Just delay specified, so refresh current page */
xmlFree(content);
c->refresh = talloc_strdup(c, c->url);
if (!c->refresh) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c,
CONTENT_MSG_ERROR, msg_data);
return false;
}
content_broadcast(c, CONTENT_MSG_REFRESH, msg_data);
break;
}
/* "url" */
if (url <= end - 3) {
if (strncasecmp(url, "url", 3) == 0) {
url += 3;
} else {
/* Unexpected input, ignore this header */
continue;
}
} else {
/* Insufficient input, ignore this header */
continue;
}
/* *LWS */
while (url < end && isspace(*url)) {
url++;
}
/* '=' */
if (url < end) {
if (*url == '=') {
url++;
} else {
/* Unexpected input, ignore this header */
continue;
}
} else {
/* Insufficient input, ignore this header */
continue;
}
/* *LWS */
while (url < end && isspace(*url)) {
url++;
}
/* '"' or "'" */
if (url < end && (*url == '"' || *url == '\'')) {
quote = *url;
url++;
}
/* Start of URL */
refresh = url;
if (quote != 0) {
/* url-sq | url-dq */
while (url < end && *url != quote)
url++;
} else {
/* url-nq */
while (url < end && !isspace(*url))
url++;
}
/* '"' or "'" or *LWS (we don't care) */
if (url < end)
*url = '\0';
res = url_join(refresh, c->data.html.base_url, &refresh);
xmlFree(content);
if (res == URL_FUNC_NOMEM) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
} else if (res == URL_FUNC_FAILED) {
/* This isn't fatal so carry on looking */
continue;
}
c->refresh = talloc_strdup(c, refresh);
free(refresh);
if (!c->refresh) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
content_broadcast(c, CONTENT_MSG_REFRESH, msg_data);
}
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
* \return true on success, false if an error occurred
*/
bool html_find_stylesheets(struct content *c, xmlNode *html)
{
xmlNode *node;
char *rel, *type, *media, *href, *url, *url2;
unsigned int i = STYLESHEET_START;
unsigned int last_active = 0;
union content_msg_data msg_data;
url_func_result res;
struct content **stylesheet_content;
/* stylesheet 0 is the base style sheet,
* stylesheet 1 is the adblocking stylesheet,
* stylesheet 2 is any <style> elements */
c->data.html.stylesheet_content = talloc_array(c, struct content *,
STYLESHEET_START);
if (!c->data.html.stylesheet_content)
goto no_memory;
c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = 0;
c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0;
c->data.html.stylesheet_count = STYLESHEET_START;
c->active = 0;
c->data.html.stylesheet_content[STYLESHEET_BASE] = fetchcache(
default_stylesheet_url,
html_convert_css_callback, (intptr_t) c,
STYLESHEET_BASE, c->width, c->height,
true, 0, 0, false, false);
if (!c->data.html.stylesheet_content[STYLESHEET_BASE])
goto no_memory;
c->active++;
fetchcache_go(c->data.html.stylesheet_content[STYLESHEET_BASE],
c->url, html_convert_css_callback, (intptr_t) c,
STYLESHEET_BASE, c->width, c->height,
0, 0, false, 0);
if (option_block_ads) {
c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] =
fetchcache(adblock_stylesheet_url,
html_convert_css_callback, (intptr_t) c,
STYLESHEET_ADBLOCK, c->width,
c->height, true, 0, 0, false, false);
if (!c->data.html.stylesheet_content[STYLESHEET_ADBLOCK])
goto no_memory;
c->active++;
fetchcache_go(c->data.html.
stylesheet_content[STYLESHEET_ADBLOCK],
c->url, html_convert_css_callback,
(intptr_t) c, STYLESHEET_ADBLOCK, c->width,
c->height, 0, 0, false, 0);
}
node = html;
/* depth-first search the tree for link elements */
while (node) {
if (node->children) { /* 1. children */
node = node->children;
} else if (node->next) { /* 2. siblings */
node = node->next;
} else { /* 3. 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 'stylesheet'> */
if ((rel = (char *) xmlGetProp(node,
(const xmlChar *) "rel")) == NULL)
continue;
if (strcasestr(rel, "stylesheet") == 0) {
xmlFree(rel);
continue;
} else if (strcasestr(rel, "alternate")) {
/* Ignore alternate stylesheets */
xmlFree(rel);
continue;
}
xmlFree(rel);
/* type='text/css' or not present */
if ((type = (char *) xmlGetProp(node,
(const xmlChar *) "type")) != NULL) {
if (strcmp(type, "text/css") != 0) {
xmlFree(type);
continue;
}
xmlFree(type);
}
/* media contains 'screen' or 'all' or not present */
if ((media = (char *) xmlGetProp(node,
(const xmlChar *) "media")) != NULL) {
if (strcasestr(media, "screen") == 0 &&
strcasestr(media, "all") == 0) {
xmlFree(media);
continue;
}
xmlFree(media);
}
/* href='...' */
if ((href = (char *) xmlGetProp(node,
(const xmlChar *) "href")) == NULL)
continue;
/* TODO: only the first preferred stylesheets (ie.
* those with a title attribute) should be loaded
* (see HTML4 14.3) */
res = url_join(href, c->data.html.base_url, &url);
xmlFree(href);
if (res != URL_FUNC_OK)
continue;
LOG(("linked stylesheet %i '%s'", i, url));
res = url_normalize(url, &url2);
if (res != URL_FUNC_OK) {
if (res == URL_FUNC_NOMEM)
goto no_memory;
continue;
}
free(url);
/* start fetch */
stylesheet_content = talloc_realloc(c,
c->data.html.stylesheet_content,
struct content *, i + 1);
if (!stylesheet_content) {
free(url2);
goto no_memory;
}
c->data.html.stylesheet_content = stylesheet_content;
c->data.html.stylesheet_content[i] = fetchcache(url2,
html_convert_css_callback,
(intptr_t) c, i, c->width, c->height,
true, 0, 0, false, false);
free(url2);
if (!c->data.html.stylesheet_content[i])
goto no_memory;
c->active++;
fetchcache_go(c->data.html.stylesheet_content[i],
c->url,
html_convert_css_callback,
(intptr_t) c, i, c->width, c->height,
0, 0, false, c->url);
i++;
} else if (strcmp((const char *) node->name, "style") == 0) {
if (!html_process_style_element(c, node))
return false;
}
}
c->data.html.stylesheet_count = i;
if (c->data.html.stylesheet_content[STYLESHEET_STYLE] != 0) {
if (css_convert(c->data.html.
stylesheet_content[STYLESHEET_STYLE], c->width,
c->height)) {
if (!content_add_user(c->data.html.
stylesheet_content[STYLESHEET_STYLE],
html_convert_css_callback,
(intptr_t) c, STYLESHEET_STYLE)) {
/* no memory */
c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0;
goto no_memory;
}
} else {
/* conversion failed */
c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0;
}
}
/* complete the fetches */
while (c->active != 0) {
if (c->active != last_active) {
html_set_status(c, "");
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
last_active = c->active;
}
fetch_poll();
gui_multitask();
}
/* check that the base stylesheet loaded; layout fails without it */
if (!c->data.html.stylesheet_content[STYLESHEET_BASE]) {
msg_data.error = "Base stylesheet failed to load";
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
assert(c->data.html.stylesheet_content[STYLESHEET_BASE]);
css_set_origin(c->data.html.stylesheet_content[STYLESHEET_BASE],
CSS_ORIGIN_UA);
/* any of our other stylesheet pointers could be NULL at this point if
* the CSS file(s) failed to load/fetch */
if (c->data.html.stylesheet_content[STYLESHEET_ADBLOCK])
css_set_origin(c->data.html.stylesheet_content[
STYLESHEET_ADBLOCK], CSS_ORIGIN_UA);
if (c->data.html.stylesheet_content[STYLESHEET_STYLE])
css_set_origin(c->data.html.stylesheet_content[
STYLESHEET_STYLE], CSS_ORIGIN_AUTHOR);
for (i = STYLESHEET_START; i != c->data.html.stylesheet_count; i++)
if (c->data.html.stylesheet_content[i])
css_set_origin(c->data.html.stylesheet_content[i],
CSS_ORIGIN_AUTHOR);
c->data.html.working_stylesheet = css_make_working_stylesheet(
c->data.html.stylesheet_content,
c->data.html.stylesheet_count);
if (!c->data.html.working_stylesheet)
goto no_memory;
return true;
no_memory:
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/**
* Process an inline stylesheet in the document.
*
* \param c content structure
* \param style xml node of style element
* \return true on success, false if an error occurred
*/
bool html_process_style_element(struct content *c, xmlNode *style)
{
xmlNode *child;
char *type, *media, *data;
union content_msg_data msg_data;
/* type='text/css', or not present (invalid but common) */
if ((type = (char *) xmlGetProp(style, (const xmlChar *) "type"))) {
if (strcmp(type, "text/css") != 0) {
xmlFree(type);
return true;
}
xmlFree(type);
}
/* media contains 'screen' or 'all' or not present */
if ((media = (char *) xmlGetProp(style, (const xmlChar *) "media"))) {
if (strcasestr(media, "screen") == 0 &&
strcasestr(media, "all") == 0) {
xmlFree(media);
return true;
}
xmlFree(media);
}
/* create stylesheet */
if (c->data.html.stylesheet_content[STYLESHEET_STYLE] == 0) {
const char *params[] = { 0 };
c->data.html.stylesheet_content[STYLESHEET_STYLE] =
content_create(c->data.html.base_url);
if (!c->data.html.stylesheet_content[STYLESHEET_STYLE])
goto no_memory;
if (!content_set_type(c->data.html.
stylesheet_content[STYLESHEET_STYLE],
CONTENT_CSS, "text/css", params))
/** \todo not necessarily caused by
* memory exhaustion */
goto no_memory;
}
/* can't just use xmlNodeGetContent(style), because that won't
* give the content of comments which may be used to 'hide'
* the content */
for (child = style->children; child != 0; child = child->next) {
data = (char *) xmlNodeGetContent(child);
if (!content_process_data(c->data.html.
stylesheet_content[STYLESHEET_STYLE],
data, strlen(data))) {
xmlFree(data);
/** \todo not necessarily caused by
* memory exhaustion */
goto no_memory;
}
xmlFree(data);
}
return true;
no_memory:
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/**
* Callback for fetchcache() for linked stylesheets.
*/
void html_convert_css_callback(content_msg msg, struct content *css,
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 stylesheet is really CSS */
if (css->type != CONTENT_CSS) {
c->data.html.stylesheet_content[i] = 0;
c->active--;
LOG(("%s is not CSS", css->url));
content_add_error(c, "NotCSS", 0);
html_set_status(c, messages_get("NotCSS"));
content_broadcast(c, CONTENT_MSG_STATUS, data);
content_remove_user(css,
html_convert_css_callback,
(intptr_t) c, i);
if (!css->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(css->fetch);
css->fetch = 0;
css->status = CONTENT_STATUS_ERROR;
}
}
break;
case CONTENT_MSG_READY:
break;
case CONTENT_MSG_DONE:
LOG(("got stylesheet '%s'", css->url));
c->active--;
break;
case CONTENT_MSG_LAUNCH:
/* Fall through */
case CONTENT_MSG_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
* in error is still in use by us before invalidating
* the pointer */
if (c->data.html.stylesheet_content[i] == css) {
c->data.html.stylesheet_content[i] = 0;
c->active--;
content_add_error(c, "?", 0);
}
break;
case CONTENT_MSG_STATUS:
html_set_status(c, css->status_message);
content_broadcast(c, CONTENT_MSG_STATUS, data);
break;
case CONTENT_MSG_NEWPTR:
c->data.html.stylesheet_content[i] = css;
break;
case CONTENT_MSG_AUTH:
c->data.html.stylesheet_content[i] = 0;
c->active--;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_SSL:
c->data.html.stylesheet_content[i] = 0;
c->active--;
content_add_error(c, "?", 0);
break;
default:
assert(0);
}
}
/**
* Start a fetch for an object required by a page.
*
* \param c content of type CONTENT_HTML
* \param url URL of object to fetch (copied)
* \param box box that will contain the object
* \param permitted_types array of types, terminated by CONTENT_UNKNOWN,
* or 0 if all types except OTHER and UNKNOWN acceptable
* \param available_width estimate of width of object
* \param available_height estimate of height of object
* \param background this is a background image
* \return true on success, false on memory exhaustion
*/
bool html_fetch_object(struct content *c, char *url, struct box *box,
const content_type *permitted_types,
int available_width, int available_height,
bool background)
{
unsigned int i = c->data.html.object_count;
struct content_html_object *object;
struct content *c_fetch;
char *url2;
url_func_result res;
/* Normalize the URL */
res = url_normalize(url, &url2);
if (res != URL_FUNC_OK) {
LOG(("failed to normalize url '%s'", url));
return res != URL_FUNC_NOMEM;
}
/* initialise fetch */
c_fetch = fetchcache(url2, html_object_callback,
(intptr_t) c, i, available_width, available_height,
true, 0, 0, false, false);
/* No longer need normalized url */
free(url2);
if (!c_fetch)
return false;
/* add to object list */
object = talloc_realloc(c, c->data.html.object,
struct content_html_object, i + 1);
if (!object) {
content_remove_user(c_fetch, html_object_callback,
(intptr_t) c, i);
return false;
}
c->data.html.object = object;
c->data.html.object[i].box = box;
c->data.html.object[i].permitted_types = permitted_types;
c->data.html.object[i].background = background;
c->data.html.object[i].content = c_fetch;
c->data.html.object_count++;
c->active++;
/* start fetch */
fetchcache_go(c_fetch, c->url,
html_object_callback, (intptr_t) c, i,
available_width, available_height,
0, 0, false, c->url);
return true;
}
/**
* Start a fetch for an object required by a page, replacing an existing object.
*
* \param c content of type CONTENT_HTML
* \param i index of object to replace in c->data.html.object
* \param url URL of object to fetch (copied)
* \param post_urlenc url encoded post data, or 0 if none
* \param post_multipart multipart post data, or 0 if none
* \return true on success, false on memory exhaustion
*/
bool html_replace_object(struct content *c, unsigned int i, char *url,
char *post_urlenc,
struct form_successful_control *post_multipart)
{
struct content *c_fetch;
struct content *page;
char *url2;
url_func_result res;
assert(c->type == CONTENT_HTML);
if (c->data.html.object[i].content) {
/* remove existing object */
if (c->data.html.object[i].content->status !=
CONTENT_STATUS_DONE)
c->active--;
content_remove_user(c->data.html.object[i].content,
html_object_callback, (intptr_t) c, i);
c->data.html.object[i].content = 0;
c->data.html.object[i].box->object = 0;
}
res = url_normalize(url, &url2);
if (res != URL_FUNC_OK)
return res != URL_FUNC_NOMEM;
/* initialise fetch */
c_fetch = fetchcache(url2, html_object_callback,
(intptr_t) c, i,
c->data.html.object[i].box->width,
c->data.html.object[i].box->height,
false, post_urlenc, post_multipart, false, false);
free(url2);
if (!c_fetch)
return false;
c->data.html.object[i].content = c_fetch;
for (page = c; page; page = page->data.html.page) {
assert(page->type == CONTENT_HTML);
page->active++;
page->status = CONTENT_STATUS_READY;
}
/* start fetch */
fetchcache_go(c_fetch, c->url,
html_object_callback, (intptr_t) c, i,
c->data.html.object[i].box->width,
c->data.html.object[i].box->height,
post_urlenc, post_multipart, false, c->url);
return true;
}
/**
* Callback for fetchcache() for objects.
*/
void html_object_callback(content_msg msg, struct content *object,
intptr_t p1, intptr_t p2, union content_msg_data data)
{
struct content *c = (struct content *) p1;
unsigned int i = p2;
int x, y;
struct box *box = c->data.html.object[i].box;
switch (msg) {
case CONTENT_MSG_LOADING:
/* check if the type is acceptable for this object */
if (html_object_type_permitted(object->type,
c->data.html.object[i].permitted_types)) {
if (c->data.html.bw)
content_open(object,
c->data.html.bw, c,
i, box,
box->object_params);
break;
}
/* not acceptable */
c->data.html.object[i].content = 0;
c->active--;
content_add_error(c, "?", 0);
html_set_status(c, messages_get("BadObject"));
content_broadcast(c, CONTENT_MSG_STATUS, data);
content_remove_user(object, html_object_callback,
(intptr_t) c, i);
if (!object->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(object->fetch);
object->fetch = 0;
object->status = CONTENT_STATUS_ERROR;
}
html_object_failed(box, c,
c->data.html.object[i].background);
break;
case CONTENT_MSG_READY:
if (object->type == CONTENT_HTML) {
html_object_done(box, object,
c->data.html.object[i].background);
if (c->status == CONTENT_STATUS_READY ||
c->status ==
CONTENT_STATUS_DONE)
content_reformat(c,
c->available_width,
c->height);
}
break;
case CONTENT_MSG_DONE:
html_object_done(box, object,
c->data.html.object[i].background);
c->active--;
break;
case CONTENT_MSG_LAUNCH:
/* Fall through */
case CONTENT_MSG_ERROR:
/* The object 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.object[i].content == object) {
c->data.html.object[i].content = 0;
c->active--;
content_add_error(c, "?", 0);
html_set_status(c, data.error);
content_broadcast(c, CONTENT_MSG_STATUS,
data);
html_object_failed(box, c,
c->data.html.object[i].background);
}
break;
case CONTENT_MSG_STATUS:
html_set_status(c, object->status_message);
/* content_broadcast(c, CONTENT_MSG_STATUS, 0); */
break;
case CONTENT_MSG_REFORMAT:
break;
case CONTENT_MSG_REDRAW:
if (!box_visible(box))
break;
box_coords(box, &x, &y);
if (object == data.redraw.object) {
data.redraw.x = data.redraw.x *
box->width / object->width;
data.redraw.y = data.redraw.y *
box->height / object->height;
data.redraw.width = data.redraw.width *
box->width / object->width;
data.redraw.height = data.redraw.height *
box->height / object->height;
data.redraw.object_width = box->width;
data.redraw.object_height = box->height;
}
data.redraw.x += x + box->padding[LEFT];
data.redraw.y += y + box->padding[TOP];
data.redraw.object_x += x + box->padding[LEFT];
data.redraw.object_y += y + box->padding[TOP];
content_broadcast(c, CONTENT_MSG_REDRAW, data);
break;
case CONTENT_MSG_NEWPTR:
c->data.html.object[i].content = object;
break;
case CONTENT_MSG_AUTH:
c->data.html.object[i].content = 0;
c->active--;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_SSL:
c->data.html.object[i].content = 0;
c->active--;
content_add_error(c, "?", 0);
break;
case CONTENT_MSG_REFRESH:
if (object->type == CONTENT_HTML)
/* only for HTML objects */
schedule(data.delay * 100,
html_object_refresh, object);
break;
default:
assert(0);
}
if (c->status == CONTENT_STATUS_READY && c->active == 0 &&
(msg == CONTENT_MSG_LOADING ||
msg == CONTENT_MSG_DONE ||
msg == CONTENT_MSG_ERROR ||
msg == CONTENT_MSG_AUTH)) {
/* all objects have arrived */
content_reformat(c, c->available_width, c->height);
html_set_status(c, "");
content_set_done(c);
}
/* If 1) the configuration option to reflow pages while objects are
* fetched is set
* 2) an object is newly fetched & converted,
* 3) the object's parent HTML is ready for reformat,
* 4) the time since the previous reformat is more than the
* configured minimum time between reformats
* then reformat the page to display newly fetched objects */
else if (option_incremental_reflow && msg == CONTENT_MSG_DONE &&
(c->status == CONTENT_STATUS_READY ||
c->status == CONTENT_STATUS_DONE) &&
(wallclock() > c->reformat_time)) {
unsigned int time_before = wallclock(), time_taken;
content_reformat(c, c->available_width, c->height);
time_taken = wallclock() - time_before;
c->reformat_time = wallclock() +
((time_taken < option_min_reflow_period ?
option_min_reflow_period : time_taken * 1.25));
}
if (c->status == CONTENT_STATUS_READY)
html_set_status(c, "");
}
/**
* Update a box whose content has completed rendering.
*/
void html_object_done(struct box *box, struct content *object,
bool background)
{
struct box *b;
if (background) {
box->background = object;
return;
}
box->object = object;
/* invalidate parent min, max widths */
for (b = box; b; b = b->parent)
b->max_width = UNKNOWN_MAX_WIDTH;
/* delete any clones of this box */
while (box->next && box->next->clone) {
/* box_free_box(box->next); */
box->next = box->next->next;
}
}
/**
* Handle object fetching or loading failure.
*
* \param box box containing object which failed to load
* \param content document of type CONTENT_HTML
* \param background the object was the background image for the box
*
* Any fallback content for the object is made visible.
*/
void html_object_failed(struct box *box, struct content *content,
bool background)
{
struct box *b, *ic;
if (background)
return;
if (!box->fallback)
return;
/* make fallback boxes into children or siblings, as appropriate */
if (box->type != BOX_INLINE) {
/* easy case: fallbacks become children */
assert(box->type == BOX_BLOCK ||
box->type == BOX_TABLE_CELL ||
box->type == BOX_INLINE_BLOCK);
box->children = box->fallback;
box->last = box->children;
while (box->last->next)
box->last = box->last->next;
box->fallback = 0;
box_normalise_block(box, content);
} else {
assert(box->parent->type == BOX_INLINE_CONTAINER);
if (box->fallback->type == BOX_INLINE_CONTAINER &&
!box->fallback->next) {
/* the fallback is a single inline container: splice
* it into this inline container */
for (b = box->fallback->children; b; b = b->next)
b->parent = box->parent;
box->fallback->last->next = box->next;
if (!box->next)
box->parent->last = box->fallback->last;
box->next = box->fallback->children;
box->next->prev = box;
box->fallback = 0;
} else {
if (box->next) {
/* split this inline container into two inline
* containers */
ic = box_create(0, 0, 0, 0, 0, content);
if (!ic) {
union content_msg_data msg_data;
msg_data.error =
messages_get("NoMemory");
content_broadcast(content,
CONTENT_MSG_ERROR,
msg_data);
return;
}
ic->type = BOX_INLINE_CONTAINER;
box_insert_sibling(box->parent, ic);
ic->children = box->next;
ic->last = box->parent->last;
ic->children->prev = 0;
box->next = 0;
box->parent->last = box;
for (b = ic->children; b; b = b->next)
b->parent = ic;
}
/* insert the fallback after the parent */
for (b = box->fallback; b->next; b = b->next)
b->parent = box->parent->parent;
b->parent = box->parent->parent;
/* [b is the last fallback box] */
b->next = box->parent->next;
if (b->next)
b->next->prev = b;
box->parent->next = box->fallback;
box->fallback->prev = box->parent;
box->fallback = 0;
box_normalise_block(box->parent->parent, content);
}
}
/* invalidate parent min, max widths */
for (b = box->parent; b; b = b->parent)
b->max_width = UNKNOWN_MAX_WIDTH;
box->width = UNKNOWN_WIDTH;
}
/**
* Check if a type is in a list.
*
* \param type the content_type to search for
* \param permitted_types array of types, terminated by CONTENT_UNKNOWN,
* or 0 if all types except OTHER and UNKNOWN acceptable
* \return the type is in the list or acceptable
*/
bool html_object_type_permitted(const content_type type,
const content_type *permitted_types)
{
if (permitted_types) {
for (; *permitted_types != CONTENT_UNKNOWN; permitted_types++)
if (*permitted_types == type)
return true;
} else if (type < CONTENT_OTHER) {
return true;
}
return false;
}
/**
* schedule() callback for object refresh
*/
void html_object_refresh(void *p)
{
struct content *c = (struct content *)p;
assert(c->type == CONTENT_HTML);
/* Ignore if refresh URL has gone
* (may happen if fetch errored) */
if (!c->refresh)
return;
c->fresh = false;
if (!html_replace_object(c->data.html.page, c->data.html.index,
c->refresh, 0, 0)) {
/** \todo handle memory exhaustion */
}
}
/**
* Stop loading a CONTENT_HTML in state READY.
*/
void html_stop(struct content *c)
{
unsigned int i;
struct content *object;
assert(c->status == CONTENT_STATUS_READY);
for (i = 0; i != c->data.html.object_count; i++) {
object = c->data.html.object[i].content;
if (!object)
continue;
if (object->status == CONTENT_STATUS_DONE)
; /* already loaded: do nothing */
else if (object->status == CONTENT_STATUS_READY)
content_stop(object, html_object_callback,
(intptr_t) c, i);
else {
content_remove_user(c->data.html.object[i].content,
html_object_callback, (intptr_t) c, i);
c->data.html.object[i].content = 0;
}
}
c->status = CONTENT_STATUS_DONE;
}
/**
* Reformat a CONTENT_HTML to a new width.
*/
void html_reformat(struct content *c, int width, int height)
{
struct box *layout;
layout_document(c, width, height);
layout = c->data.html.layout;
/* width and height are at least margin box of document */
c->width = layout->x + layout->padding[LEFT] + layout->width +
layout->padding[RIGHT] + layout->border[RIGHT] +
layout->margin[RIGHT];
c->height = layout->y + layout->padding[TOP] + layout->height +
layout->padding[BOTTOM] + layout->border[BOTTOM] +
layout->margin[BOTTOM];
/* if boxes overflow right or bottom edge, expand to contain it */
if (c->width < layout->x + layout->descendant_x1)
c->width = layout->x + layout->descendant_x1;
if (c->height < layout->y + layout->descendant_y1)
c->height = layout->y + layout->descendant_y1;
}
/**
* Destroy a CONTENT_HTML and free all resources it owns.
*/
void html_destroy(struct content *c)
{
unsigned int i;
struct form *f, *g;
LOG(("content %p", c));
/* Destroy forms */
for (f = c->data.html.forms; f != NULL; f = g) {
g = f->prev;
form_free(f);
}
imagemap_destroy(c);
if (c->bitmap) {
bitmap_destroy(c->bitmap);
c->bitmap = NULL;
}
if (c->data.html.parser_binding)
binding_destroy_tree(c->data.html.parser_binding);
if (c->data.html.document)
xmlFreeDoc(c->data.html.document);
/* Free base target */
if (c->data.html.base_target) {
talloc_free(c->data.html.base_target);
c->data.html.base_target = NULL;
}
/* Free frameset */
if (c->data.html.frameset) {
html_destroy_frameset(c->data.html.frameset);
talloc_free(c->data.html.frameset);
c->data.html.frameset = NULL;
}
/* Free iframes */
if (c->data.html.iframe) {
html_destroy_iframe(c->data.html.iframe);
c->data.html.iframe = NULL;
}
/* Free stylesheets */
if (c->data.html.stylesheet_count) {
for (i = 0; i != c->data.html.stylesheet_count; i++) {
if (c->data.html.stylesheet_content[i])
content_remove_user(c->data.html.
stylesheet_content[i],
html_convert_css_callback,
(intptr_t) c, i);
}
}
talloc_free(c->data.html.working_stylesheet);
/*if (c->data.html.style)
css_free_style(c->data.html.style);*/
/* Free objects */
for (i = 0; i != c->data.html.object_count; i++) {
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)
schedule_remove(html_object_refresh,
c->data.html.object[i].content);
}
}
}
void html_destroy_frameset(struct content_html_frames *frameset) {
int i;
if (frameset->name) {
talloc_free(frameset->name);
frameset->name = NULL;
}
if (frameset->url) {
talloc_free(frameset->url);
frameset->url = NULL;
}
if (frameset->children) {
for (i = 0; i < (frameset->rows * frameset->cols); i++) {
if (frameset->children[i].name) {
talloc_free(frameset->children[i].name);
frameset->children[i].name = NULL;
}
if (frameset->children[i].url) {
talloc_free(frameset->children[i].url);
frameset->children[i].url = NULL;
}
if (frameset->children[i].children)
html_destroy_frameset(&frameset->children[i]);
}
talloc_free(frameset->children);
frameset->children = NULL;
}
}
void html_destroy_iframe(struct content_html_iframe *iframe) {
struct content_html_iframe *next;
next = iframe;
while ((iframe = next) != NULL) {
next = iframe->next;
if (iframe->name)
talloc_free(iframe->name);
if (iframe->url)
talloc_free(iframe->url);
talloc_free(iframe);
}
}
/**
* Set the content status.
*/
void html_set_status(struct content *c, const char *extra)
{
unsigned int stylesheets = 0, objects = 0;
if (c->data.html.object_count == 0)
stylesheets = c->data.html.stylesheet_count - c->active;
else {
stylesheets = c->data.html.stylesheet_count;
objects = c->data.html.object_count - c->active;
}
content_set_status(c, "%u/%u %s %u/%u %s %s",
stylesheets, c->data.html.stylesheet_count,
messages_get((c->data.html.stylesheet_count == 1) ?
"styl" : "styls"),
objects, c->data.html.object_count,
messages_get((c->data.html.object_count == 1) ?
"obj" : "objs"),
extra);
}
/**
* Handle a window containing a CONTENT_HTML being opened.
*/
void html_open(struct content *c, struct browser_window *bw,
struct content *page, unsigned int index, struct box *box,
struct object_params *params)
{
unsigned int i;
c->data.html.bw = bw;
c->data.html.page = page;
c->data.html.index = index;
c->data.html.box = box;
for (i = 0; i != c->data.html.object_count; i++) {
if (c->data.html.object[i].content == 0)
continue;
if (c->data.html.object[i].content->type == CONTENT_UNKNOWN)
continue;
content_open(c->data.html.object[i].content,
bw, c, i,
c->data.html.object[i].box,
c->data.html.object[i].box->object_params);
}
}
/**
* Handle a window containing a CONTENT_HTML being closed.
*/
void html_close(struct content *c)
{
unsigned int i;
c->data.html.bw = 0;
schedule_remove(html_object_refresh, c);
for (i = 0; i != c->data.html.object_count; i++) {
if (c->data.html.object[i].content == 0)
continue;
if (c->data.html.object[i].content->type == CONTENT_UNKNOWN)
continue;
content_close(c->data.html.object[i].content);
}
}
#if ALWAYS_DUMP_FRAMESET
/**
* Print a frameset tree to stderr.
*/
void html_dump_frameset(struct content_html_frames *frame,
unsigned int depth)
{
unsigned int i;
int row, col, index;
const char *unit[] = {"px", "%", "*"};
const char *scrolling[] = {"auto", "yes", "no"};
assert(frame);
fprintf(stderr, "%p ", frame);
fprintf(stderr, "(%i %i) ", frame->rows, frame->cols);
fprintf(stderr, "w%g%s ", frame->width.value, unit[frame->width.unit]);
fprintf(stderr, "h%g%s ", frame->height.value,unit[frame->height.unit]);
fprintf(stderr, "(margin w%i h%i) ",
frame->margin_width, frame->margin_height);
if (frame->name)
fprintf(stderr, "'%s' ", frame->name);
if (frame->url)
fprintf(stderr, "<%s> ", frame->url);
if (frame->no_resize)
fprintf(stderr, "noresize ");
fprintf(stderr, "(scrolling %s) ", scrolling[frame->scrolling]);
if (frame->border)
fprintf(stderr, "border %x ",
(unsigned int) frame->border_colour);
fprintf(stderr, "\n");
if (frame->children) {
for (row = 0; row != frame->rows; row++) {
for (col = 0; col != frame->cols; col++) {
for (i = 0; i != depth; i++)
fprintf(stderr, " ");
fprintf(stderr, "(%i %i): ", row, col);
index = (row * frame->cols) + col;
html_dump_frameset(&frame->children[index],
depth + 1);
}
}
}
}
#endif