From 09b1ede5a3fe5c37e34fe1c13780536f30297806 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Tue, 15 Apr 2003 17:53:00 +0000 Subject: [PATCH] [project @ 2003-04-15 17:53:00 by bursa] Inline images and related. svn path=/import/netsurf/; revision=125 --- !NetSurf/Resources/CSS,f79 | 1 + !NetSurf/Resources/intro,faf | 4 +- content/cache.c | 4 +- content/content.c | 13 ++- content/content.h | 18 ++- content/fetch.c | 6 +- css/css.c | 5 +- desktop/browser.c | 15 ++- desktop/browser.h | 5 +- render/box.c | 192 ++++++++++++++++---------------- render/box.h | 18 +-- render/html.c | 205 +++++++++++++++++++++++++++-------- render/html.h | 3 +- render/layout.c | 36 +++--- riscos/gui.c | 54 +++++++-- 15 files changed, 378 insertions(+), 201 deletions(-) diff --git a/!NetSurf/Resources/CSS,f79 b/!NetSurf/Resources/CSS,f79 index 55400d14d..7115b9588 100644 --- a/!NetSurf/Resources/CSS,f79 +++ b/!NetSurf/Resources/CSS,f79 @@ -36,3 +36,4 @@ td { text-align: left; } hr { background-color: #000; height: 1px; } center { text-align: center; } +small { font-size: smaller; } diff --git a/!NetSurf/Resources/intro,faf b/!NetSurf/Resources/intro,faf index e79aff807..deb57bfb2 100644 --- a/!NetSurf/Resources/intro,faf +++ b/!NetSurf/Resources/intro,faf @@ -37,7 +37,7 @@ fetching
@@ -60,7 +60,7 @@ spotted.

NetSurf currently uses the following libraries:

- + diff --git a/content/cache.c b/content/cache.c index f9dd4e4f5..bf0f46511 100644 --- a/content/cache.c +++ b/content/cache.c @@ -1,5 +1,5 @@ /** - * $Id: cache.c,v 1.2 2003/03/04 11:59:35 bursa Exp $ + * $Id: cache.c,v 1.3 2003/04/15 17:53:00 bursa Exp $ */ #include @@ -108,7 +108,7 @@ struct content * cache_get(const char * const url) void cache_put(struct content * content) { struct cache_entry * e; - LOG(("content %p, url '%s'", content, content->url)); + LOG(("content %p, url '%s', size %lu", content, content->url, content->size)); current_size += content->size; /* clear old data from the usused_list until the size drops below max_size */ diff --git a/content/content.c b/content/content.c index 439c0fba2..5a9e2956b 100644 --- a/content/content.c +++ b/content/content.c @@ -1,5 +1,5 @@ /** - * $Id: content.c,v 1.6 2003/04/06 18:09:34 bursa Exp $ + * $Id: content.c,v 1.7 2003/04/15 17:53:00 bursa Exp $ */ #include @@ -75,6 +75,7 @@ struct content * content_create(content_type type, char *url) c->status = CONTENT_LOADING; c->size = sizeof(struct content); c->status_callback = 0; + strcpy(c->status_message, "Loading"); handler_map[type].create(c); return c; } @@ -102,9 +103,11 @@ int content_convert(struct content *c, unsigned long width, unsigned long height assert(c != 0); assert(c->type < CONTENT_OTHER); assert(c->status == CONTENT_LOADING); + c->available_width = width; if (handler_map[c->type].convert(c, width, height)) return 1; - c->status = CONTENT_READY; + if (c->status == CONTENT_LOADING) + c->status = CONTENT_DONE; return 0; } @@ -118,7 +121,8 @@ void content_revive(struct content *c, unsigned long width, unsigned long height { assert(c != 0); assert(c->type < CONTENT_OTHER); - assert(c->status == CONTENT_READY); + assert(c->status == CONTENT_DONE); + c->available_width = width; handler_map[c->type].revive(c, width, height); } @@ -131,7 +135,8 @@ void content_reformat(struct content *c, unsigned long width, unsigned long heig { assert(c != 0); assert(c->type < CONTENT_OTHER); - assert(c->status == CONTENT_READY); + assert(c->status != CONTENT_LOADING); + c->available_width = width; handler_map[c->type].reformat(c, width, height); } diff --git a/content/content.h b/content/content.h index ce7f05248..462d58b69 100644 --- a/content/content.h +++ b/content/content.h @@ -1,5 +1,5 @@ /** - * $Id: content.h,v 1.8 2003/04/13 12:50:10 bursa Exp $ + * $Id: content.h,v 1.9 2003/04/15 17:53:00 bursa Exp $ */ #ifndef _NETSURF_DESKTOP_CONTENT_H_ @@ -49,8 +49,15 @@ struct content { char *url; content_type type; - enum {CONTENT_LOADING, CONTENT_READY} status; + enum { + CONTENT_LOADING, /* content is being fetched or converted + and is not safe to display */ + CONTENT_PENDING, /* some parts of content still being + loaded, but can be displayed */ + CONTENT_DONE /* all finished */ + } status; unsigned long width, height; + unsigned long available_width; union { @@ -69,6 +76,12 @@ struct content } text_selection; struct font_set* fonts; struct page_elements elements; + unsigned int object_count; /* images etc. */ + struct { + char *url; + struct content *content; + struct box *box; + } *object; } html; struct @@ -94,6 +107,7 @@ struct content int error; void (*status_callback)(void *p, const char *status); void *status_p; + char status_message[80]; }; diff --git a/content/fetch.c b/content/fetch.c index d1c3f0e07..642010fb3 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -1,5 +1,5 @@ /** - * $Id: fetch.c,v 1.4 2003/04/09 21:57:09 bursa Exp $ + * $Id: fetch.c,v 1.5 2003/04/15 17:53:00 bursa Exp $ */ #include @@ -191,8 +191,10 @@ void fetch_poll(void) LOG(("CURLMSG_DONE, result %i", curl_msg->data.result)); /* inform the caller that the fetch is done */ - if (curl_msg->data.result == CURLE_OK) + if (curl_msg->data.result == CURLE_OK && f->had_headers) f->callback(FETCH_FINISHED, f->p, 0, 0); + else if (curl_msg->data.result == CURLE_OK) + f->callback(FETCH_ERROR, f->p, "No data received", 0); else if (curl_msg->data.result != CURLE_WRITE_ERROR) f->callback(FETCH_ERROR, f->p, f->error_buffer, 0); diff --git a/css/css.c b/css/css.c index d348ad0f3..70e992e15 100644 --- a/css/css.c +++ b/css/css.c @@ -1,5 +1,5 @@ /** - * $Id: css.c,v 1.6 2003/04/09 21:57:09 bursa Exp $ + * $Id: css.c,v 1.7 2003/04/15 17:53:00 bursa Exp $ */ #include @@ -61,7 +61,7 @@ const struct css_style css_empty_style = { { CSS_FONT_SIZE_INHERIT, { { 1, CSS_UNIT_EM } } }, CSS_FONT_WEIGHT_INHERIT, CSS_FONT_STYLE_INHERIT, - { CSS_HEIGHT_AUTO, { 1, CSS_UNIT_EM } }, + { CSS_HEIGHT_INHERIT, { 1, CSS_UNIT_EM } }, { CSS_LINE_HEIGHT_INHERIT, { 1.2 } }, CSS_TEXT_ALIGN_INHERIT, { CSS_WIDTH_INHERIT, { { 1, CSS_UNIT_EM } } } @@ -131,6 +131,7 @@ int css_convert(struct content *c, unsigned int width, unsigned int height) /* complete fetch of any imported stylesheets */ while (c->active != 0) { + LOG(("importing %i from '%s'", c->active, c->url)); fetch_poll(); gui_multitask(); } diff --git a/desktop/browser.c b/desktop/browser.c index fff407822..32c9bc659 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -1,5 +1,5 @@ /** - * $Id: browser.c,v 1.33 2003/04/12 12:38:32 andrew Exp $ + * $Id: browser.c,v 1.34 2003/04/15 17:53:00 bursa Exp $ */ #include "netsurf/content/cache.h" @@ -19,8 +19,6 @@ #include static void browser_window_start_throbber(struct browser_window* bw); -static void browser_window_stop_throbber(struct browser_window* bw); -static void browser_window_reformat(struct browser_window* bw); static void browser_window_text_selection(struct browser_window* bw, unsigned long click_x, unsigned long click_y, int click_type); static void browser_window_clear_text_selection(struct browser_window* bw); @@ -214,6 +212,7 @@ void browser_window_open_location_historical(struct browser_window* bw, const ch assert(bw != 0 && url != 0); browser_window_set_status(bw, "Opening page..."); + browser_window_start_throbber(bw); bw->time0 = clock(); fetchcache(url, 0, browser_window_callback, bw, gui_window_get_width(bw->window), 0, @@ -276,9 +275,13 @@ void browser_window_callback(fetchcache_msg msg, struct content *c, bw->current_content = c; browser_window_reformat(bw); gui_window_set_redraw_safety(bw->window, previous_safety); - sprintf(status, "Page complete (%gs)", ((float) (clock() - bw->time0)) / CLOCKS_PER_SEC); - browser_window_set_status(bw, status); - browser_window_stop_throbber(bw); + if (bw->current_content->status == CONTENT_DONE) { + sprintf(status, "Page complete (%gs)", ((float) (clock() - bw->time0)) / CLOCKS_PER_SEC); + browser_window_set_status(bw, status); + browser_window_stop_throbber(bw); + } else { + browser_window_set_status(bw, bw->current_content->status_message); + } } break; diff --git a/desktop/browser.h b/desktop/browser.h index 299b17f73..11eba93c8 100644 --- a/desktop/browser.h +++ b/desktop/browser.h @@ -1,5 +1,5 @@ /** - * $Id: browser.h,v 1.11 2003/03/04 11:59:35 bursa Exp $ + * $Id: browser.h,v 1.12 2003/04/15 17:53:00 bursa Exp $ */ #ifndef _NETSURF_DESKTOP_BROWSER_H_ @@ -111,4 +111,7 @@ int box_position_distance(struct box_position* x, struct box_position* y); void gui_redraw_gadget(struct browser_window* bw, struct gui_gadget* g); +void browser_window_stop_throbber(struct browser_window* bw); +void browser_window_reformat(struct browser_window* bw); + #endif diff --git a/render/box.c b/render/box.c index f99715659..04550a6ec 100644 --- a/render/box.c +++ b/render/box.c @@ -1,5 +1,5 @@ /** - * $Id: box.c,v 1.41 2003/04/13 12:50:10 bursa Exp $ + * $Id: box.c,v 1.42 2003/04/15 17:53:00 bursa Exp $ */ #include @@ -9,6 +9,7 @@ #include #include "libxml/HTMLparser.h" #include "libutf-8/utf-8.h" +#include "netsurf/content/fetchcache.h" #include "netsurf/css/css.h" #include "netsurf/riscos/font.h" #include "netsurf/render/box.h" @@ -21,14 +22,19 @@ * internal functions */ +struct fetch_data { + struct content *c; + unsigned int i; +}; + static void box_add_child(struct box * parent, struct box * child); static struct box * box_create(box_type type, struct css_style * style, char *href); -static struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, - struct content ** stylesheet, unsigned int stylesheet_count, +static struct box * convert_xml_to_box(xmlNode * n, struct content *c, + struct css_style * parent_style, struct css_selector ** selector, unsigned int depth, struct box * parent, struct box * inline_container, - char *href, struct font_set *fonts, + char *href, struct gui_gadget* current_select, struct formoption* current_option, struct gui_gadget* current_textarea, struct form* current_form, struct page_elements* elements); @@ -42,7 +48,8 @@ static void box_normalise_table_row(struct box *row); static void box_normalise_inline_container(struct box *cont); static void gadget_free(struct gui_gadget* g); static void box_free_box(struct box *box); -static struct box* box_image(xmlNode * n, struct css_style* style, char* href); +static struct box* box_image(xmlNode *n, struct content *content, + struct css_style *style, char *href); static struct box* box_textarea(xmlNode* n, struct css_style* style, struct form* current_form); static struct box* box_select(xmlNode * n, struct css_style* style, struct form* current_form); static struct formoption* box_option(xmlNode* n, struct css_style* style, struct gui_gadget* current_select); @@ -99,49 +106,64 @@ struct box * box_create(box_type type, struct css_style * style, box->col = 0; box->font = 0; box->gadget = 0; - box->img = 0; + box->object = 0; return box; } +/** + * make a box tree with style data from an xml tree + */ + +void xml_to_box(xmlNode *n, struct content *c) +{ + struct css_selector* selector = xcalloc(1, sizeof(struct css_selector)); + + LOG(("node %p", n)); + assert(c->type == CONTENT_HTML); + + c->data.html.layout = xcalloc(1, sizeof(struct box)); + c->data.html.layout->type = BOX_BLOCK; + + c->data.html.style = xcalloc(1, sizeof(struct css_style)); + memcpy(c->data.html.style, &css_base_style, sizeof(struct css_style)); + c->data.html.fonts = font_new_set(); + + c->data.html.object_count = 0; + c->data.html.object = xcalloc(0, sizeof(*c->data.html.object)); + + convert_xml_to_box(n, c, c->data.html.style, + &selector, 0, c->data.html.layout, 0, 0, 0, 0, + 0, 0, &c->data.html.elements); + LOG(("normalising")); + box_normalise_block(c->data.html.layout->children); +} + + /** * make a box tree with style data from an xml tree * * arguments: * n xml tree + * content content structure * parent_style style at this point in xml tree - * stylesheet stylesheet to use * selector element selector hierachy to this point * depth depth in xml tree * parent parent in box tree * inline_container current inline container box, or 0 + * href current link, or 0 + * current_* forms state + * elements forms structure * * returns: * updated current inline container */ -void xml_to_box(xmlNode * n, struct css_style * parent_style, - struct content ** stylesheet, unsigned int stylesheet_count, +struct box * convert_xml_to_box(xmlNode * n, struct content *content, + struct css_style * parent_style, struct css_selector ** selector, unsigned int depth, struct box * parent, struct box * inline_container, - char *href, struct font_set *fonts, - struct gui_gadget* current_select, struct formoption* current_option, - struct gui_gadget* current_textarea, struct form* current_form, - struct page_elements* elements) -{ - LOG(("node %p", n)); - convert_xml_to_box(n, parent_style, stylesheet, stylesheet_count, - selector, depth, parent, inline_container, href, fonts, current_select, current_option, - current_textarea, current_form, elements); - LOG(("normalising")); - box_normalise_block(parent->children); -} - -struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, - struct content ** stylesheet, unsigned int stylesheet_count, - struct css_selector ** selector, unsigned int depth, - struct box * parent, struct box * inline_container, - char *href, struct font_set *fonts, + char *href, struct gui_gadget* current_select, struct formoption* current_option, struct gui_gadget* current_textarea, struct form* current_form, struct page_elements* elements) @@ -152,10 +174,9 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, xmlNode * c; char * s; char * text = 0; - xmlChar *s2; - assert(n != 0 && parent_style != 0 && stylesheet != 0 && selector != 0 && - parent != 0 && fonts != 0); + assert(n != 0 && content != 0 && parent_style != 0 && selector != 0 && + parent != 0); LOG(("depth %i, node %p, node type %i", depth, n, n->type)); gui_multitask(); @@ -168,13 +189,18 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, (*selector)[depth].class = s; /* TODO: free this later */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "id"))) (*selector)[depth].id = s; - style = box_get_style(stylesheet, stylesheet_count, parent_style, n, + style = box_get_style(content->data.html.stylesheet_content, + content->data.html.stylesheet_count, parent_style, n, *selector, depth + 1); LOG(("display: %s", css_display_name[style->display])); if (style->display == CSS_DISPLAY_NONE) { free(style); return inline_container; } + /* floats are treated as blocks */ + if (style->float_ == CSS_FLOAT_LEFT || style->float_ == CSS_FLOAT_RIGHT) + if (style->display == CSS_DISPLAY_INLINE) + style->display = CSS_DISPLAY_BLOCK; /* special elements */ if (strcmp((const char *) n->name, "a") == 0) { @@ -187,21 +213,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, add_form_element(elements, form); } else if (strcmp((const char *) n->name, "img") == 0) { - LOG(("image")); - /*box = box_image(n, style, href); - add_img_element(elements, box->img);*/ - /*if (style->display == CSS_DISPLAY_INLINE) { - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "alt"))) { - text = squash_tolat1(s); - xfree(s); - } - }*/ - /* TODO: block images, start fetch */ - if ((s2 = xmlGetProp(n, (const xmlChar *) "alt"))) { - xmlNode *alt = xmlNewText(s2); - free(s2); - xmlAddChild(n, alt); - } + box = box_image(n, content, style, href); } else if (strcmp((const char *) n->name, "textarea") == 0) { char * content = xmlNodeGetContent(n); @@ -243,6 +255,8 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, text = squash_tolat1(n->content); } + content->size += sizeof(struct box) + sizeof(struct css_style); + if (text != 0) { if (text[0] == ' ' && text[1] == 0) { if (inline_container != 0) { @@ -286,7 +300,7 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, box->space = 0; } box->text = text; - box->font = font_open(fonts, box->style); + box->font = font_open(content->data.html.fonts, box->style); } else if (style->float_ == CSS_FLOAT_LEFT || style->float_ == CSS_FLOAT_RIGHT) { LOG(("float")); @@ -313,10 +327,9 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, box_add_child(parent, box); inline_container_c = 0; for (c = n->children; c != 0; c = c->next) - inline_container_c = convert_xml_to_box(c, style, - stylesheet, stylesheet_count, + inline_container_c = convert_xml_to_box(c, content, style, selector, depth + 1, box, inline_container_c, - href, fonts, current_select, current_option, + href, current_select, current_option, current_textarea, current_form, elements); if (style->float_ == CSS_FLOAT_NONE) /* continue in this inline container if this is a float */ @@ -326,19 +339,18 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, assert(box == 0); /* special inline elements have already been added to the inline container above */ for (c = n->children; c != 0; c = c->next) - inline_container = convert_xml_to_box(c, style, - stylesheet, stylesheet_count, + inline_container = convert_xml_to_box(c, content, style, selector, depth + 1, parent, inline_container, - href, fonts, current_select, current_option, + href, current_select, current_option, current_textarea, current_form, elements); break; case CSS_DISPLAY_TABLE: box = box_create(BOX_TABLE, style, href); box_add_child(parent, box); for (c = n->children; c != 0; c = c->next) - convert_xml_to_box(c, style, stylesheet, stylesheet_count, + convert_xml_to_box(c, content, style, selector, depth + 1, box, 0, - href, fonts, current_select, current_option, + href, current_select, current_option, current_textarea, current_form, elements); inline_container = 0; break; @@ -349,10 +361,9 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, box_add_child(parent, box); inline_container_c = 0; for (c = n->children; c != 0; c = c->next) - inline_container_c = convert_xml_to_box(c, style, - stylesheet, stylesheet_count, + inline_container_c = convert_xml_to_box(c, content, style, selector, depth + 1, box, inline_container_c, - href, fonts, current_select, current_option, + href, current_select, current_option, current_textarea, current_form, elements); inline_container = 0; break; @@ -360,9 +371,9 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, box = box_create(BOX_TABLE_ROW, style, href); box_add_child(parent, box); for (c = n->children; c != 0; c = c->next) - convert_xml_to_box(c, style, stylesheet, stylesheet_count, + convert_xml_to_box(c, content, style, selector, depth + 1, box, 0, - href, fonts, current_select, current_option, + href, current_select, current_option, current_textarea, current_form, elements); inline_container = 0; break; @@ -376,10 +387,9 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style, box_add_child(parent, box); inline_container_c = 0; for (c = n->children; c != 0; c = c->next) - inline_container_c = convert_xml_to_box(c, style, - stylesheet, stylesheet_count, + inline_container_c = convert_xml_to_box(c, content, style, selector, depth + 1, box, inline_container_c, - href, fonts, current_select, current_option, + href, current_select, current_option, current_textarea, current_form, elements); inline_container = 0; break; @@ -972,11 +982,6 @@ void box_free_box(struct box *box) free(box->gadget); } - if (box->img != 0) - { - free(box->img); - } - if (box->text != 0) free(box->text); /* only free href if we're the top most user */ @@ -989,40 +994,45 @@ void box_free_box(struct box *box) } } -struct box* box_image(xmlNode * n, struct css_style* style, char* href) + +/** + * add an image to the box tree + */ + +struct box* box_image(xmlNode *n, struct content *content, + struct css_style *style, char *href) { - struct box* box = 0; - char* s; + struct box *box; + char *s, *url; + xmlChar *s2; + struct fetch_data *fetch_data; + /* box type is decided by caller, BOX_INLINE is just a default */ box = box_create(BOX_INLINE, style, href); - box->img = xcalloc(1, sizeof(struct img)); - box->text = 0; - box->length = 0; - box->font = 0; + /* handle alt text */ + /*if ((s2 = xmlGetProp(n, (const xmlChar *) "alt"))) { + box->text = squash_tolat1(s2); + box->length = strlen(box->text); + box->font = font_open(content->data.html.fonts, style); + free(s2); + }*/ - if (style->width.width == CSS_WIDTH_AUTO) { - /* should find the real image width */ - style->width.width = CSS_WIDTH_LENGTH; - style->width.value.length.unit = CSS_UNIT_PX; - style->width.value.length.value = 24; - } + /* img without src is an error */ + if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) + return box; - if (style->height.height == CSS_HEIGHT_AUTO) { - /* should find the real image height */ - style->height.height = CSS_HEIGHT_LENGTH; - style->height.length.unit = CSS_UNIT_PX; - style->height.length.value = 24; - } + url = url_join(s, content->url); + LOG(("image '%s'", url)); + free(s); - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "alt"))) - { - box->img->alt = s; - } + /* start fetch */ + html_fetch_image(content, url, box); return box; } + struct box* box_textarea(xmlNode* n, struct css_style* style, struct form* current_form) { struct box* box = 0; diff --git a/render/box.h b/render/box.h index b4972b6d0..5adb69554 100644 --- a/render/box.h +++ b/render/box.h @@ -1,5 +1,5 @@ /** - * $Id: box.h,v 1.23 2003/04/10 21:44:45 bursa Exp $ + * $Id: box.h,v 1.24 2003/04/15 17:53:00 bursa Exp $ */ #ifndef _NETSURF_RENDER_BOX_H_ @@ -74,11 +74,6 @@ struct gui_gadget { } data; }; -struct img { - char* alt; - char* src; -}; - struct box { box_type type; struct css_style * style; @@ -99,7 +94,7 @@ struct box { struct column *col; struct font_data *font; struct gui_gadget* gadget; - struct img* img; + struct content* object; /* usually an image */ }; struct form @@ -132,14 +127,7 @@ struct page_elements * interface */ -void xml_to_box(xmlNode * n, struct css_style * parent_style, - struct content ** stylesheet, unsigned int stylesheet_count, - struct css_selector ** selector, unsigned int depth, - struct box * parent, struct box * inline_container, - char *href, struct font_set *fonts, - struct gui_gadget* current_select, struct formoption* current_option, - struct gui_gadget* current_textarea, struct form* current_form, - struct page_elements* elements); +void xml_to_box(xmlNode *n, struct content *c); void box_dump(struct box * box, unsigned int depth); void box_free(struct box *box); diff --git a/render/html.c b/render/html.c index 9b38b7378..0c60acdb5 100644 --- a/render/html.c +++ b/render/html.c @@ -1,5 +1,5 @@ /** - * $Id: html.c,v 1.14 2003/04/13 12:50:10 bursa Exp $ + * $Id: html.c,v 1.15 2003/04/15 17:53:00 bursa Exp $ */ #include @@ -25,6 +25,8 @@ static void html_convert_css_callback(fetchcache_msg msg, struct content *css, void *p, const char *error); static void html_title(struct content *c, xmlNode *head); static void html_find_stylesheets(struct content *c, xmlNode *head); +static void html_image_callback(fetchcache_msg msg, struct content *image, + void *p, const char *error); void html_create(struct content *c) @@ -51,10 +53,7 @@ void html_process_data(struct content *c, char *data, unsigned long size) int html_convert(struct content *c, unsigned int width, unsigned int height) { - struct css_selector* selector = xcalloc(1, sizeof(struct css_selector)); - struct fetch_data *fetch_data; unsigned int i; - char status[80]; xmlDoc *document; xmlNode *html, *head; @@ -91,39 +90,11 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) html_title(c, head); /* get stylesheets */ - c->error = 0; - c->active = 0; - html_find_stylesheets(c, head); - while (c->active != 0) { - if (c->status_callback != 0) { - sprintf(status, "Loading %u stylesheets", c->active); - c->status_callback(c->status_p, status); - } - fetch_poll(); - gui_multitask(); - } - - if (c->error) { - c->status_callback(c->status_p, "Warning: some stylesheets failed to load"); - } - - LOG(("Copying base style")); - c->data.html.style = xcalloc(1, sizeof(struct css_style)); - memcpy(c->data.html.style, &css_base_style, sizeof(struct css_style)); - - LOG(("Creating box")); - c->data.html.layout = xcalloc(1, sizeof(struct box)); - c->data.html.layout->type = BOX_BLOCK; - - c->data.html.fonts = font_new_set(); - + /* convert xml tree to box tree */ LOG(("XML to box")); - xml_to_box(html, c->data.html.style, - c->data.html.stylesheet_content, c->data.html.stylesheet_count, - &selector, 0, c->data.html.layout, 0, 0, c->data.html.fonts, - 0, 0, 0, 0, &c->data.html.elements); + xml_to_box(html, c); /*box_dump(c->data.html.layout->children, 0);*/ /* XML tree and stylesheets not required past this point */ @@ -137,6 +108,7 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) cache_free(c->data.html.stylesheet_content[i]); xfree(c->data.html.stylesheet_content); + /* layout the box tree */ c->status_callback(c->status_p, "Formatting document"); LOG(("Layout document")); layout_document(c->data.html.layout->children, width); @@ -144,6 +116,9 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) c->width = c->data.html.layout->children->width; c->height = c->data.html.layout->children->height; + + if (c->active != 0) + c->status = CONTENT_PENDING; return 0; } @@ -200,8 +175,9 @@ void html_title(struct content *c, xmlNode *head) void html_find_stylesheets(struct content *c, xmlNode *head) { - xmlNode *node; + xmlNode *node, *node2; char *rel, *type, *media, *href, *data, *url; + char status[80]; unsigned int i = 2; struct fetch_data *fetch_data; @@ -210,6 +186,9 @@ void html_find_stylesheets(struct content *c, xmlNode *head) c->data.html.stylesheet_content[1] = 0; c->data.html.stylesheet_count = 2; + c->error = 0; + c->active = 0; + fetch_data = xcalloc(1, sizeof(*fetch_data)); fetch_data->c = c; fetch_data->i = 0; @@ -218,10 +197,7 @@ void html_find_stylesheets(struct content *c, xmlNode *head) html_convert_css_callback, fetch_data, c->width, c->height, 1 << CONTENT_CSS); - if (head == 0) - return; - - for (node = head->children; node != 0; node = node->next) { + for (node = head == 0 ? 0 : head->children; node != 0; node = node->next) { if (strcmp(node->name, "link") == 0) { /* rel='stylesheet' */ if (!(rel = (char *) xmlGetProp(node, (const xmlChar *) "rel"))) @@ -294,11 +270,16 @@ void html_find_stylesheets(struct content *c, xmlNode *head) /* create stylesheet */ LOG(("style element")); if (c->data.html.stylesheet_content[1] == 0) - c->data.html.stylesheet_content[1] = content_create(CONTENT_CSS, ""); + c->data.html.stylesheet_content[1] = content_create(CONTENT_CSS, c->url); - data = xmlNodeGetContent(node); - content_process_data(c->data.html.stylesheet_content[1], data, strlen(data)); - free(data); + /* can't just use xmlNodeGetContent(node), because that won't give + * the content of comments which may be used to 'hide' the content */ + for (node2 = node->children; node2 != 0; node2 = node2->next) { + data = xmlNodeGetContent(node2); + content_process_data(c->data.html.stylesheet_content[1], + data, strlen(data)); + free(data); + } } } @@ -306,15 +287,142 @@ void html_find_stylesheets(struct content *c, xmlNode *head) if (c->data.html.stylesheet_content[1] != 0) content_convert(c->data.html.stylesheet_content[1], c->width, c->height); + + /* complete the fetches */ + while (c->active != 0) { + if (c->status_callback != 0) { + sprintf(status, "Loading %u stylesheets", c->active); + c->status_callback(c->status_p, status); + } + fetch_poll(); + gui_multitask(); + } + + if (c->error) { + c->status_callback(c->status_p, "Warning: some stylesheets failed to load"); + } +} + + +void html_fetch_image(struct content *c, char *url, struct box *box) +{ + struct fetch_data *fetch_data; + + /* add to object list */ + c->data.html.object = xrealloc(c->data.html.object, + (c->data.html.object_count + 1) * + sizeof(*c->data.html.object)); + c->data.html.object[c->data.html.object_count].url = url; + c->data.html.object[c->data.html.object_count].content = 0; + c->data.html.object[c->data.html.object_count].box = box; + + /* start fetch */ + fetch_data = xcalloc(1, sizeof(*fetch_data)); + fetch_data->c = c; + fetch_data->i = c->data.html.object_count; + c->data.html.object_count++; + c->active++; + fetchcache(url, c->url, + html_image_callback, + fetch_data, 0, 0, 1 << CONTENT_JPEG); +} + + +void html_image_callback(fetchcache_msg msg, struct content *image, + void *p, const char *error) +{ + struct fetch_data *data = p; + struct content *c = data->c; + unsigned int i = data->i; + struct box *box = c->data.html.object[i].box; + switch (msg) { + case FETCHCACHE_OK: + LOG(("got image '%s'", image->url)); + box->object = image; + c->data.html.object[i].content = image; + /* set dimensions to object dimensions if auto */ + if (box->style->width.width == CSS_WIDTH_AUTO) { + box->style->width.width = CSS_WIDTH_LENGTH; + box->style->width.value.length.unit = CSS_UNIT_PX; + box->style->width.value.length.value = image->width; + box->min_width = box->max_width = image->width; + /* invalidate parent min, max widths */ + if (box->parent->max_width != UNKNOWN_MAX_WIDTH) { + struct box *b = box->parent; + if (b->min_width < image->width) + b->min_width = image->width; + if (b->max_width < image->width) + b->max_width = image->width; + for (b = b->parent; + b != 0 && b->max_width != UNKNOWN_MAX_WIDTH; + b = b->parent) + b->max_width = UNKNOWN_MAX_WIDTH; + } + } + if (box->style->height.height == CSS_HEIGHT_AUTO) { + box->style->height.height = CSS_HEIGHT_LENGTH; + box->style->height.length.unit = CSS_UNIT_PX; + box->style->height.length.value = image->height; + } + /* remove alt text */ + if (box->text != 0) { + free(box->text); + box->text = 0; + box->length = 0; + } + /*if (box->children != 0) { + box_free(box->children); + box->children = 0; + }*/ + /* TODO: recalculate min, max width */ + /* drop through */ + case FETCHCACHE_BADTYPE: + case FETCHCACHE_ERROR: + if (c->active == 1 && c->status == CONTENT_PENDING) { + /* all images have arrived */ + content_reformat(c, c->available_width, 0); + } + c->active--; + if (c->active == 0) + sprintf(c->status_message, "Document done"); + else + sprintf(c->status_message, "Loading %i images", c->active); + free(data); + break; + case FETCHCACHE_STATUS: + /* TODO: need to add a way of sending status to the + * owning window */ + break; + default: + assert(0); + } } void html_revive(struct content *c, unsigned int width, unsigned int height) { - /* TODO: reload images and fix any pointers to them */ + unsigned int i; + struct fetch_data *fetch_data; + + /* reload images and fix pointers */ + for (i = 0; i != c->data.html.object_count; i++) { + if (c->data.html.object[i].content != 0) { + fetch_data = xcalloc(1, sizeof(*fetch_data)); + fetch_data->c = c; + fetch_data->i = i; + c->active++; + fetchcache(c->data.html.object[i].url, c->url, + html_image_callback, + fetch_data, 0, 0, 1 << CONTENT_JPEG); + } + } + layout_document(c->data.html.layout->children, width); c->width = c->data.html.layout->children->width; c->height = c->data.html.layout->children->height; + + if (c->active != 0) + c->status = CONTENT_PENDING; } @@ -328,6 +436,7 @@ void html_reformat(struct content *c, unsigned int width, unsigned int height) void html_destroy(struct content *c) { + unsigned int i; LOG(("content %p", c)); if (c->data.html.layout != 0) @@ -336,4 +445,12 @@ void html_destroy(struct content *c) font_free_set(c->data.html.fonts); if (c->title != 0) xfree(c->title); + + for (i = 0; i != c->data.html.object_count; i++) { + if (c->data.html.object[i].content != 0) + cache_free(c->data.html.object[i].content); + free(c->data.html.object[i].url); + } + free(c->data.html.object); } + diff --git a/render/html.h b/render/html.h index 1dd9e3a51..a22d04112 100644 --- a/render/html.h +++ b/render/html.h @@ -1,5 +1,5 @@ /** - * $Id: html.h,v 1.1 2003/02/09 12:58:15 bursa Exp $ + * $Id: html.h,v 1.2 2003/04/15 17:53:00 bursa Exp $ */ #ifndef _NETSURF_RENDER_HTML_H_ @@ -13,5 +13,6 @@ int html_convert(struct content *c, unsigned int width, unsigned int height); void html_revive(struct content *c, unsigned int width, unsigned int height); void html_reformat(struct content *c, unsigned int width, unsigned int height); void html_destroy(struct content *c); +void html_fetch_image(struct content *c, char *url, struct box *box); #endif diff --git a/render/layout.c b/render/layout.c index 7b1e40ba4..f2b950840 100644 --- a/render/layout.c +++ b/render/layout.c @@ -1,5 +1,5 @@ /** - * $Id: layout.c,v 1.39 2003/04/13 12:50:10 bursa Exp $ + * $Id: layout.c,v 1.40 2003/04/15 17:53:00 bursa Exp $ */ #include @@ -77,8 +77,12 @@ signed long len(struct css_length * length, struct css_style * style) void layout_document(struct box * doc, unsigned long width) { + struct box *box; doc->float_children = 0; layout_node(doc, width, doc, 0, 0); + for (box = doc->float_children; box != 0; box = box->next) + if (doc->height < box->y + box->height) + doc->height = box->y + box->height; } @@ -159,6 +163,7 @@ int gadget_height(struct gui_gadget* gadget) } return 0; } + /** * layout_block -- position block and recursively layout children * @@ -353,11 +358,10 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long h = line_height(b->style ? b->style : b->parent->parent->style); else if (b->gadget != 0) h = gadget_height(b->gadget); - else { - assert(b->style != 0); - assert(b->style->height.height == CSS_HEIGHT_LENGTH); + else if (b->style != 0 && b->style->height.height == CSS_HEIGHT_LENGTH) h = len(&b->style->height.length, b->style); - } + else + h = 0; b->height = h; if (h > height) height = h; @@ -367,17 +371,12 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long b->width = font_width(b->font, b->text, b->length); else if (b->gadget != 0) b->width = gadget_width(b->gadget); - else { - assert(b->style != 0); - assert(b->style->width.width == CSS_WIDTH_LENGTH || - b->style->width.width == CSS_WIDTH_PERCENT); - if (b->style->width.width == CSS_WIDTH_LENGTH) - b->width = len(&b->style->width.value.length, - b->style); - else - b->width = width * b->style->width.value.percent - / 100; - } + else if (b->style != 0 && b->style->width.width == CSS_WIDTH_LENGTH) + b->width = len(&b->style->width.value.length, b->style); + else if (b->style != 0 && b->style->width.width == CSS_WIDTH_PERCENT) + b->width = width * b->style->width.value.percent / 100; + else + b->width = 0; } if (b->text != 0) @@ -417,10 +416,9 @@ struct box * layout_line(struct box * first, unsigned long width, unsigned long /* either a float with no width specified (contravenes standard) * or we don't know the width for some reason, eg. image not loaded */ calculate_widths(b); - w = width / 2; - if (d->max_width < w) + if (d->max_width < width) w = d->max_width; - else if (w < d->min_width) + else w = d->min_width; } layout_node(d, w, d, 0, 0); diff --git a/riscos/gui.c b/riscos/gui.c index 9ed95d2a2..b69c4a542 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -1,5 +1,5 @@ /** - * $Id: gui.c,v 1.25 2003/04/11 21:06:51 bursa Exp $ + * $Id: gui.c,v 1.26 2003/04/15 17:53:00 bursa Exp $ */ #include "netsurf/riscos/font.h" @@ -326,7 +326,8 @@ gui_window* create_gui_browser_window(struct browser_window* bw) window.flags = wimp_WINDOW_MOVEABLE | wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_VSCROLL | - wimp_WINDOW_SIZE_ICON | wimp_WINDOW_TOGGLE_ICON; + wimp_WINDOW_HSCROLL | wimp_WINDOW_SIZE_ICON | wimp_WINDOW_TOGGLE_ICON | + wimp_WINDOW_IGNORE_XEXTENT; window.title_fg = wimp_COLOUR_BLACK; window.title_bg = wimp_COLOUR_LIGHT_GREY; window.work_fg = wimp_COLOUR_LIGHT_GREY; @@ -578,12 +579,20 @@ void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, current_background_color = box->style->background_color; } - if (box->img != 0) + if (box->object != 0) + { + if (box->object->type == CONTENT_JPEG) { + xjpeg_plot_scaled((jpeg_image *) box->object->data.jpeg.data, + (int) x + (int) box->x * 2, (int) y - (int) box->y * 2 - (int) box->height * 2, + 0, (int) box->object->data.jpeg.length, jpeg_SCALE_DITHERED); + } + } +/* if (box->img != 0) { colourtrans_set_gcol(os_COLOUR_LIGHT_GREY, 0, os_ACTION_OVERWRITE, 0); os_plot(os_MOVE_TO, (int) x + (int) box->x * 2, (int) y - (int) box->y * 2); os_plot(os_PLOT_RECTANGLE | os_PLOT_BY, (int) box->width * 2, - (int) box->height * 2); - } + }*/ else if (box->gadget != 0) { wimp_icon icon; @@ -855,7 +864,7 @@ void ro_gui_window_redraw(gui_window* g, wimp_draw* redraw) xjpeg_plot_scaled((jpeg_image *) c->data.jpeg.data, (int) redraw->box.x0 - (int) redraw->xscroll, (int) redraw->box.y1 - (int) redraw->yscroll - (int) c->height * 2, - 0, (int) c->data.jpeg.length, 0); + 0, (int) c->data.jpeg.length, jpeg_SCALE_DITHERED); break; default: @@ -905,7 +914,7 @@ void gui_window_set_extent(gui_window* g, unsigned long width, unsigned long hei extent.y0 = ro_y_units(height); if (extent.y0 > -960) extent.y0 = -960; - extent.x1 = 8192; //ro_x_units(width); + extent.x1 = ro_x_units(width); if ((g->data.browser.bw->flags & browser_TOOLBAR) != 0) { extent.y1 = ro_theme_toolbar_height(current_theme); @@ -972,10 +981,19 @@ fprintf(stderr, "Set URL '%s'\n", msg->data.set_url.url); void ro_gui_window_open(gui_window* g, wimp_open* open) { - wimp_open_window(open); - if (g->type == GUI_BROWSER_WINDOW) { + if (g->data.browser.bw->current_content != 0) { + if (g->data.browser.bw->current_content->width + < browser_x_units(open->visible.x1 - open->visible.x0)) + gui_window_set_extent(g, browser_x_units(open->visible.x1 - open->visible.x0), + g->data.browser.bw->current_content->height); + else + gui_window_set_extent(g, g->data.browser.bw->current_content->width, + g->data.browser.bw->current_content->height); + } + wimp_open_window(open); + if ((g->data.browser.bw->flags & browser_TOOLBAR) != 0) { wimp_outline outline; @@ -1011,6 +1029,8 @@ void ro_gui_window_open(gui_window* g, wimp_open* open) } } + } else { + wimp_open_window(open); } } @@ -1024,7 +1044,7 @@ void ro_gui_icon_bar_click(wimp_pointer* pointer) { struct browser_window* bw; bw = create_browser_window(browser_TITLE | browser_TOOLBAR - | browser_SCROLL_X_NONE | browser_SCROLL_Y_ALWAYS, 640, 480); + | browser_SCROLL_X_ALWAYS | browser_SCROLL_Y_ALWAYS, 640, 480); gui_window_show(bw->window); browser_window_open_location(bw, HOME_URL); wimp_set_caret_position(bw->window->data.browser.toolbar, @@ -1077,6 +1097,19 @@ void ro_gui_throb(void) { if (g->type == GUI_BROWSER_WINDOW) { + if (g->data.browser.bw->current_content->status == CONTENT_PENDING) { + /* images still loading */ + gui_window_set_status(g, g->data.browser.bw->current_content->status_message); + if (g->data.browser.bw->current_content->active == 0) { + /* any image fetches have finished */ + browser_window_reformat(g->data.browser.bw); + browser_window_stop_throbber(g->data.browser.bw); + /* TODO: move this elsewhere: can't just move it to the image loader, + * because then this if would be triggered when an old content is + * present */ + g->data.browser.bw->current_content->status = CONTENT_DONE; + } + } if ((g->data.browser.bw->flags & browser_TOOLBAR) != 0) { if (g->data.browser.bw->throbbing != 0) @@ -1281,7 +1314,7 @@ void ro_gui_w_click(wimp_pointer* pointer) { struct browser_window* bw; bw = create_browser_window(browser_TITLE | browser_TOOLBAR - | browser_SCROLL_X_NONE | browser_SCROLL_Y_ALWAYS, 640, 480); + | browser_SCROLL_X_ALWAYS | browser_SCROLL_Y_ALWAYS, 640, 480); gui_window_show(bw->window); browser_window_open_location(bw, "http://sourceforge.net/projects/netsurf/"); wimp_set_caret_position(bw->window->data.browser.toolbar, ro_theme_icon(current_theme, THEME_TOOLBAR, "TOOLBAR_URL"), @@ -1904,6 +1937,7 @@ void gui_poll(void) switch (event) { case wimp_NULL_REASON_CODE : + ro_gui_throb(); if (over_window != NULL || current_drag.type == draginfo_BROWSER_TEXT_SELECTION) {
libxml(XML and HTML parser)
(XML and HTML parser)
libcurl (HTTP, etc.)
OSLib