Experimental new frames code.

svn path=/trunk/netsurf/; revision=2906
This commit is contained in:
Richard Wilson 2006-09-02 15:52:41 +00:00
parent b51f807fe3
commit 74fa727509
31 changed files with 2318 additions and 806 deletions

Binary file not shown.

Binary file not shown.

View File

@ -363,6 +363,11 @@ Encoding1:detected
Encoding2:from <meta>
EncodingUnk:Unknown
# Misc
#
Selecting:Selecting
FrameDrag:Resizing frames
# Errors
# ======
@ -809,9 +814,10 @@ HelpContentConfig:\Tcontent configuration \w
HelpContentConfig2:This indicates whether NetSurf will atempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
HelpContentConfig5:\Sreset the Content options back to their default values.
HelpContentConfig6:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
HelpContentConfig7:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
HelpContentConfig8:\Sreset the Content options back to their default values.
HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpFontConfig:\font configuration \w
HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.

Binary file not shown.

View File

@ -363,6 +363,11 @@ Encoding1:detected
Encoding2:from <meta>
EncodingUnk:Unknown
# Misc
#
Selecting:Selecting
FrameDrag:Resizing frames
# Errors
# ======
@ -809,9 +814,10 @@ HelpContentConfig:\Tcontent configuration \w
HelpContentConfig2:This indicates whether NetSurf will attempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
HelpContentConfig5:\Sreset the Content options back to their default values.
HelpContentConfig6:\Sclose this \w without saving changes.|M\Areturn the content options to the last saved configuration.
HelpContentConfig7:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
HelpContentConfig8:\Sreset the Content options back to their default values.
HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the content options to the last saved configuration.
HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpFontConfig:\Tfont configuration \w
HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.

Binary file not shown.

View File

@ -363,6 +363,11 @@ Encoding1:détecté
Encoding2:de <meta>
EncodingUnk:Inconnu
# Misc
#
Selecting:Selecting
FrameDrag:Resizing frames
# Errors
# ======
@ -806,12 +811,13 @@ HelpConnectConfig28:\Sfermer cette fenêtre sans sauvegarder les changements.|M\
HelpConnectConfig29:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
HelpContentConfig:\Tla fenêtre de configuration du Contenu
HelpContentConfig2:Ceci indique si Netsurf doit essayer de bloquer les pubs sur les pages web.|MEn de rares circonstances, cette option peut également bloquer du contenu valide.
HelpContentConfig2:Ceci indique si Netsurf doit essayer de bloquer les pubs sur les pages web.|MEn de rares circonstances, cette option peut également bloquer du contenu valide.
HelpContentConfig3:Ceci indique si Netsurf doit empêcher les sites web d'ouvrir automatiquement de nouvelles fenêtres sur votre Bureau.
HelpContentConfig4:Ceci indique si Netsurf doit autoriser les plug-ins externes à manipuler des types de contenu supplémentaires, comme le Flash.
HelpContentConfig5:\Srevenir aux valeurs par défaut des options du Contenu.
HelpContentConfig6:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Contenu précédemment sauvegardées.
HelpContentConfig7:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
HelpContentConfig8:\Srevenir aux valeurs par défaut des options du Contenu.
HelpContentConfig9:\Sfermer cette fenêtre sans sauver les changements|M\Arevenir aux options de Contenu précédemment sauvegardées.
HelpContentConfig10:\Ssauver ces réglages et fermer la fenêtre.|M\Asauver ces réglages sans fermer la fenêtre.
HelpFontConfig:\Tla fenêtre de configuration de Fontes
HelpFontConfig3:\Tla fonte sans-sérif actuellement sélectionnée.|MNetsurf utilisera cette fonte à chaque fois qu'une page web spécifiera une police sans-sérif.

Binary file not shown.

View File

@ -363,6 +363,11 @@ Encoding1:detected
Encoding2:from <meta>
EncodingUnk:Unknown
# Misc
#
Selecting:Selecting
FrameDrag:Resizing frames
# Errors
# ======
@ -809,9 +814,10 @@ HelpContentConfig:\Tcontent configuration \w
HelpContentConfig2:This indicates whether NetSurf will atempt to block advertisements on web pages|MIn rare circumstances, this option may cause valid content to be blocked too.
HelpContentConfig3:This indicates whether NetSurf will stop web sites from automatically opening new windows on your desktop.
HelpContentConfig4:This indicates whether NetSurf will allow external plug-ins to handle additional types of content, such as Flash.
HelpContentConfig5:\Sreset the Content options back to their default values.
HelpContentConfig6:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
HelpContentConfig7:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpContentConfig7:This indicates whether NetSurf will allow links to open in new windows.
HelpContentConfig8:\Sreset the Content options back to their default values.
HelpContentConfig9:\Sclose this \w without saving changes.|M\Areturn the cache options to the last saved configuration.
HelpContentConfig10:\Ssave these settings and close the \w.|M\Asave these settings without closing the \w.
HelpFontConfig:\font configuration \w
HelpFontConfig3:\Tcurrently selected sans-serif font.|MNetSurf will use this font wherever a web page specifies a sans-serif typeface.

Binary file not shown.

View File

@ -816,7 +816,6 @@ void content_destroy(struct content *c)
if (c->type < HANDLER_MAP_COUNT && handler_map[c->type].destroy)
handler_map[c->type].destroy(c);
talloc_free(c);
}
@ -855,6 +854,7 @@ void content_quit(void)
while (content_list && progress) {
progress = false;
for (c = content_list; c; c = next) {
assert(c->next != c);
next = c->next;
if (c->user_list->next &&

View File

@ -81,6 +81,7 @@
#include <curl/curl.h>
#include "netsurf/image/bitmap.h"
#include "netsurf/content/content.h"
#include "netsurf/content/urldb.h"
#include "netsurf/desktop/cookies.h"
#include "netsurf/desktop/options.h"
@ -89,6 +90,7 @@
#include "netsurf/riscos/bitmap.h"
#endif
#include "netsurf/utils/log.h"
#include "netsurf/utils/filename.h"
#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
@ -117,6 +119,10 @@ struct auth_data {
* username:password */
};
struct cache_internal_data {
char filename[12]; /**< Cached filename, or first byte 0 for none */
};
struct url_internal_data {
char *title; /**< Resource title */
unsigned int visits; /**< Visit count */
@ -135,6 +141,7 @@ struct path_data {
struct bitmap *thumb; /**< Thumbnail image of resource */
struct url_internal_data urld; /**< URL data for resource */
struct cache_internal_data cache; /**< Cache data for resource */
struct auth_data auth; /**< Authentication data for resource */
struct cookie_internal_data *cookies; /**< Cookies associated with resource */
@ -3361,6 +3368,60 @@ void urldb_save_cookie_paths(FILE *fp, struct path_data *parent)
}
/**
* Sets the content data associated with a particular URL
*
* \param url the URL to associate content with
* \param content the content to associate
* \return true on success, false otherwise
*/
bool urldb_set_cache_data(const char *url, const struct content *content) {
struct path_data *p;
char *filename;
assert(url && content);
p = urldb_find_url(url);
if (!p)
return false;
/* new filename needed */
if (p->cache.filename[0] == 0) {
filename = filename_request();
if (!filename)
return false;
sprintf(p->cache.filename, filename);
}
/* todo: save content, set cache data etc */
return true;
}
/**
* Gets a file:// URL for the cached data associated with a URL
*
* \param url the URL to get the associated content for
* \return a local URL allocated on heap, or NULL
*/
char *urldb_get_cache_data(const char *url) {
struct path_data *p;
assert(url);
p = urldb_find_url(url);
if (!p)
return NULL;
/* no file cache */
if (p->cache.filename[0] == 0)
return NULL;
/* todo: handle cache expiry etc */
return filename_as_url(p->cache.filename);
}
#ifdef TEST_URLDB
int option_expire_url = 0;

View File

@ -14,6 +14,7 @@
#include <stdbool.h>
#include <time.h>
#include "netsurf/content/content.h"
#include "netsurf/content/content_type.h"
typedef enum {
@ -100,4 +101,8 @@ void urldb_delete_cookie(const char *domain, const char *path, const char *name)
void urldb_load_cookies(const char *filename);
void urldb_save_cookies(const char *filename);
/* Cache */
bool urldb_set_cache_data(const char *url, const struct content *content);
char *urldb_get_cache_data(const char *url);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <time.h>
#include "netsurf/render/html.h"
struct box;
struct content;
@ -38,6 +39,8 @@ typedef bool (*browser_paste_callback)(struct browser_window *bw,
typedef void (*browser_move_callback)(struct browser_window *bw,
void *p);
/** Browser window data. */
struct browser_window {
/** Page currently displayed, or 0. Must have status READY or DONE. */
@ -84,20 +87,26 @@ struct browser_window {
DRAGGING_HSCROLL,
DRAGGING_SELECTION,
DRAGGING_PAGE_SCROLL,
DRAGGING_2DSCROLL
DRAGGING_2DSCROLL,
DRAGGING_FRAME
} drag_type;
/** Box currently being scrolled, or 0. */
struct box *scrolling_box;
/** Mouse position at start of current scroll drag. */
int scrolling_start_x;
int scrolling_start_y;
int drag_start_x;
int drag_start_y;
/** Scroll offsets at start of current scroll draw. */
int scrolling_start_scroll_x;
int scrolling_start_scroll_y;
int drag_start_scroll_x;
int drag_start_scroll_y;
/** Well dimensions for current scroll drag. */
int scrolling_well_width;
int scrolling_well_height;
int drag_well_width;
int drag_well_height;
/** Frame resize directions for current frame resize drag. */
unsigned int drag_resize_left : 1;
unsigned int drag_resize_right : 1;
unsigned int drag_resize_up : 1;
unsigned int drag_resize_down : 1;
/** Referer for current fetch, or 0. */
char *referer;
@ -107,6 +116,50 @@ struct browser_window {
/** Refresh interval (-1 if undefined) */
int refresh_interval;
/** Window dimensions */
int x0;
int y0;
int x1;
int y1;
/** Window characteristics */
enum {
BROWSER_WINDOW_NORMAL,
BROWSER_WINDOW_IFRAME,
BROWSER_WINDOW_FRAME,
BROWSER_WINDOW_FRAMESET,
} browser_window_type;
/** frameset characteristics */
int rows;
int cols;
/** frame dimensions */
struct frame_dimension frame_width;
struct frame_dimension frame_height;
int margin_width;
int margin_height;
/** frame name for targetting */
char *name;
/** frame characteristics */
bool no_resize;
frame_scrolling scrolling;
bool border;
colour border_colour;
/** iframe parent box */
struct box *box;
/** [cols * rows] children */
struct browser_window *children;
struct browser_window *parent;
/** [iframe_count] iframes */
int iframe_count;
struct browser_window *iframes;
};
@ -129,6 +182,7 @@ extern struct browser_window *current_redraw_browser;
struct browser_window * browser_window_create(const char *url,
struct browser_window *clone, char *referer, bool history_add);
struct browser_window * browser_window_owner(struct browser_window *bw);
void browser_window_go(struct browser_window *bw, const char *url,
char *referer, bool history_add);
void browser_window_go_post(struct browser_window *bw, const char *url,
@ -139,6 +193,12 @@ void browser_window_stop(struct browser_window *bw);
void browser_window_reload(struct browser_window *bw, bool all);
void browser_window_destroy(struct browser_window *bw);
void browser_window_update(struct browser_window *bw, bool scroll_to_top);
void browser_window_create_iframes(struct browser_window *bw,
struct content_html_iframe *iframe);
void browser_window_recalculate_iframes(struct browser_window *bw);
void browser_window_create_frameset(struct browser_window *bw,
struct content_html_frames *frameset);
void browser_window_recalculate_frameset(struct browser_window *bw);
void browser_window_mouse_click(struct browser_window *bw,
browser_mouse_state mouse, int x, int y);

View File

@ -65,9 +65,12 @@ bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy);
void gui_window_set_scroll(struct gui_window *g, int sx, int sy);
void gui_window_scroll_visible(struct gui_window *g, int x0, int y0,
int x1, int y1);
void gui_window_position_frame(struct gui_window *g, int x0, int y0,
int x1, int y1);
void gui_window_get_dimensions(struct gui_window *g, int *width, int *height);
int gui_window_get_width(struct gui_window *g);
int gui_window_get_height(struct gui_window *g);
void gui_window_set_extent(struct gui_window *g, int width, int height);
void gui_window_update_extent(struct gui_window *g);
void gui_window_set_status(struct gui_window *g, const char *text);
void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape);
void gui_window_hide_pointer(struct gui_window *g);
@ -81,6 +84,7 @@ bool gui_window_scroll_start(struct gui_window *g);
bool gui_window_box_scroll_start(struct gui_window *g,
int x0, int y0, int x1, int y1);
void gui_window_save_as_link(struct gui_window *g, struct content *c);
bool gui_window_frame_resize_start(struct gui_window *g);
struct gui_download_window *gui_download_window_create(const char *url,
const char *mime_type, struct fetch *fetch,

View File

@ -33,12 +33,15 @@
#define RIGHT_MARGIN 50
#define BOTTOM_MARGIN 30
/** A node in the history tree. */
struct history_entry {
struct history_page {
char *url; /**< Page URL. */
char *frag_id; /** Fragment identifier */
char *title; /**< Page title. */
};
/** A node in the history tree. */
struct history_entry {
struct history_page page;
struct history_entry *back; /**< Parent. */
struct history_entry *next; /**< Next sibling. */
struct history_entry *forward; /**< First child. */
@ -153,16 +156,16 @@ struct history_entry *history_clone_entry(struct history *history,
if (!new_entry)
return 0;
memcpy(new_entry, entry, sizeof *entry);
new_entry->url = strdup(entry->url);
if (entry->frag_id)
new_entry->frag_id = strdup(entry->frag_id);
new_entry->title = strdup(entry->title);
if (((entry->url) && (!new_entry->url)) ||
((entry->title) && (!new_entry->title)) ||
((entry->frag_id) && (!new_entry->frag_id))) {
free(new_entry->url);
free(new_entry->title);
free(new_entry->frag_id);
new_entry->page.url = strdup(entry->page.url);
if (entry->page.frag_id)
new_entry->page.frag_id = strdup(entry->page.frag_id);
new_entry->page.title = strdup(entry->page.title);
if (((entry->page.url) && (!new_entry->page.url)) ||
((entry->page.title) && (!new_entry->page.title)) ||
((entry->page.frag_id) && (!new_entry->page.frag_id))) {
free(new_entry->page.url);
free(new_entry->page.title);
free(new_entry->page.frag_id);
free(new_entry);
return 0;
}
@ -230,9 +233,9 @@ void history_add(struct history *history, struct content *content,
return;
}
entry->url = url;
entry->frag_id = frag_id ? strdup(frag_id) : 0;
entry->title = title;
entry->page.url = url;
entry->page.frag_id = frag_id ? strdup(frag_id) : 0;
entry->page.title = title;
entry->back = history->current;
entry->next = 0;
entry->forward = entry->forward_pref = entry->forward_last = 0;
@ -282,12 +285,12 @@ void history_update(struct history *history, struct content *content)
if (!history || !history->current || !history->current->bitmap)
return;
if (history->current->title)
free(history->current->title);
if (history->current->page.title)
free(history->current->page.title);
if (content->title)
history->current->title = strdup(content->title);
history->current->page.title = strdup(content->title);
else
history->current->title = 0;
history->current->page.title = 0;
thumbnail_create(content, history->current->bitmap, 0);
}
@ -318,10 +321,10 @@ void history_free_entry(struct history_entry *entry)
return;
history_free_entry(entry->forward);
history_free_entry(entry->next);
free(entry->url);
if (entry->frag_id)
free(entry->frag_id);
free(entry->title);
free(entry->page.url);
if (entry->page.frag_id)
free(entry->page.frag_id);
free(entry->page.title);
free(entry);
}
@ -397,16 +400,17 @@ void history_go(struct browser_window *bw, struct history *history,
char *url;
struct history_entry *current;
if (entry->frag_id) {
url = malloc(strlen(entry->url) + strlen(entry->frag_id) + 5);
if (entry->page.frag_id) {
url = malloc(strlen(entry->page.url) +
strlen(entry->page.frag_id) + 5);
if (!url) {
warn_user("NoMemory", 0);
return;
}
sprintf(url, "%s#%s", entry->url, entry->frag_id);
sprintf(url, "%s#%s", entry->page.url, entry->page.frag_id);
}
else
url = entry->url;
url = entry->page.url;
if (new_window) {
current = history->current;
@ -418,7 +422,7 @@ void history_go(struct browser_window *bw, struct history *history,
browser_window_go(bw, url, 0, false);
}
if (entry->frag_id)
if (entry->page.frag_id)
free(url);
}
@ -552,19 +556,19 @@ bool history_redraw_entry(struct history *history,
struct history_entry *child;
colour c = entry == history->current ? 0x0000ff : 0x333333;
int tailsize = 5;
if (!plot.bitmap(entry->x, entry->y, WIDTH, HEIGHT, entry->bitmap,
0xffffff))
if (!plot.bitmap(entry->x, entry->y, WIDTH, HEIGHT,
entry->bitmap, 0xffffff))
return false;
if (!plot.rectangle(entry->x - 1, entry->y - 1, WIDTH + 1, HEIGHT + 1,
entry == history->current ? 2 : 1, c, false, false))
return false;
if (!nsfont_position_in_string(&css_base_style, entry->title,
strlen(entry->title), WIDTH, &char_offset, &actual_x))
if (!nsfont_position_in_string(&css_base_style, entry->page.title,
strlen(entry->page.title), WIDTH, &char_offset, &actual_x))
return false;
if (!plot.text(entry->x, entry->y + HEIGHT + 12, &css_base_style,
entry->title, char_offset, 0xffffff, c))
entry->page.title, char_offset, 0xffffff, c))
return false;
for (child = entry->forward; child; child = child->next) {
@ -635,7 +639,7 @@ const char *history_position_url(struct history *history, int x, int y)
if (!entry)
return 0;
return entry->url;
return entry->page.url;
}

View File

@ -102,10 +102,15 @@ void netsurf_poll(void)
void netsurf_exit(void)
{
LOG(("Closing GUI"));
gui_quit();
LOG(("Closing content"));
content_quit();
LOG(("Closing fetches"));
fetch_quit();
LOG(("Closing utf8"));
utf8_finalise();
LOG(("Exited successfully"));
}

View File

@ -124,7 +124,8 @@ int option_max_fetchers_per_host = 2;
* is this plus option_max_fetchers.
*/
int option_max_cached_fetch_handles = 6;
/** Whether to use knockout rendering */
/** Whether to allow target="_blank" */
bool option_target_blank = true;
EXTRA_OPTION_DEFINE
@ -174,6 +175,8 @@ struct {
OPTION_INTEGER, &option_max_fetchers_per_host },
{ "max_cached_fetch_handles",
OPTION_INTEGER, &option_max_cached_fetch_handles },
{ "target_blank",
OPTION_BOOL, &option_target_blank },
EXTRA_OPTION_TABLE
};

View File

@ -57,6 +57,7 @@ extern char *option_ca_bundle;
extern char *option_cookie_file;
extern char *option_cookie_jar;
extern char *option_homepage_url;
extern bool option_target_blank;
extern bool option_url_suggestion;
extern int option_window_x;
extern int option_window_y;

View File

@ -253,6 +253,7 @@ struct object_param {
extern const char *TARGET_SELF;
extern const char *TARGET_PARENT;
extern const char *TARGET_TOP;
extern const char *TARGET_BLANK;
#define UNKNOWN_WIDTH INT_MAX

View File

@ -1,10 +1,11 @@
/*
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
* http://www.opensource.org/licenses/gpl-license
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
* Copyright 2005 John M Bell <jmb202@ecs.soton.ac.uk>
* Copyright 2006 Richard Wilson <info@tinct.net>
*/
/** \file
@ -22,6 +23,7 @@
#include "netsurf/utils/config.h"
#include "netsurf/content/content.h"
#include "netsurf/css/css.h"
#include "netsurf/desktop/browser.h"
#include "netsurf/desktop/options.h"
#include "netsurf/render/box.h"
#include "netsurf/render/form.h"
@ -37,13 +39,6 @@
#include "netsurf/utils/utils.h"
/** MultiLength, as defined by HTML 4.01. */
struct box_multi_length {
enum { LENGTH_PX, LENGTH_PERCENT, LENGTH_RELATIVE } type;
float value;
};
static const content_type image_types[] = {
#ifdef WITH_JPEG
CONTENT_JPEG,
@ -77,6 +72,7 @@ static const content_type image_types[] = {
const char *TARGET_SELF = "_self";
const char *TARGET_PARENT = "_parent";
const char *TARGET_TOP = "_top";
const char *TARGET_BLANK = "_blank";
static bool convert_xml_to_box(xmlNode *n, struct content *content,
@ -114,6 +110,8 @@ static bool box_input(BOX_SPECIAL_PARAMS);
static bool box_input_text(BOX_SPECIAL_PARAMS, bool password);
static bool box_button(BOX_SPECIAL_PARAMS);
static bool box_frameset(BOX_SPECIAL_PARAMS);
static bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
struct content *content);
static bool box_select_add_option(struct form_control *control, xmlNode *n);
static bool box_object(BOX_SPECIAL_PARAMS);
static bool box_embed(BOX_SPECIAL_PARAMS);
@ -122,13 +120,13 @@ static bool box_pre(BOX_SPECIAL_PARAMS);
static bool box_iframe(BOX_SPECIAL_PARAMS);
static bool box_get_attribute(xmlNode *n, const char *attribute,
void *context, char **value);
static struct box_multi_length *box_parse_multi_lengths(const char *s,
unsigned int *count, void *context);
static struct frame_dimension *box_parse_multi_lengths(const char *s,
unsigned int *count);
/* element_table must be sorted by name */
struct element_entry {
char name[10]; /* element type */
char name[10]; /* element type */
bool (*convert)(BOX_SPECIAL_PARAMS);
};
static const struct element_entry element_table[] = {
@ -228,17 +226,17 @@ static const box_type box_map[] = {
/**
* Recursively construct a box tree from an xml tree and stylesheets.
*
* \param n fragment of xml tree
* \param content content of type CONTENT_HTML that is being processed
* \param n fragment of xml tree
* \param content content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
* \param parent parent in box tree
* \param parent parent in box tree
* \param inline_container current inline container box, or 0, updated to
* new current inline container on exit
* new current inline container on exit
* \param containing_block current containing block for absolutes, as defined
* by CSS 2.1 10.1 4
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
* by CSS 2.1 10.1 4
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
* \return true on success, false on memory exhaustion
*/
@ -266,17 +264,17 @@ bool convert_xml_to_box(xmlNode *n, struct content *content,
/**
* Construct the box tree for an XML element.
*
* \param n XML node of type XML_ELEMENT_NODE
* \param content content of type CONTENT_HTML that is being processed
* \param n XML node of type XML_ELEMENT_NODE
* \param content content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
* \param parent parent in box tree
* \param parent parent in box tree
* \param inline_container current inline container box, or 0, updated to
* new current inline container on exit
* new current inline container on exit
* \param containing_block current containing block for absolutes, as defined
* by CSS 2.1 10.1 4
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
* by CSS 2.1 10.1 4
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
* \return true on success, false on memory exhaustion
*/
@ -471,8 +469,8 @@ bool box_construct_element(xmlNode *n, struct content *content,
xmlFree(s);
}
if (strcmp((const char *) n->name, "table") == 0) {
border_color = 0x888888; /* default colour */
if ((s = (char *) xmlGetProp(n,
border_color = 0x888888; /* default colour */
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "cellpadding"))) {
char *endp;
long value = strtol(s, &endp, 10);
@ -481,7 +479,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
box_set_cellpadding(box, value);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(n,
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "bordercolor"))) {
unsigned int r, g, b;
if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
@ -490,7 +488,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
border_color = named_colour(s);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(n,
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "border"))) {
int value = atoi(s);
if (!strrchr(s, '%') && 0 < value) /* % not implemented */
@ -501,7 +499,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
/* transfer <tr height="n"> down to the <td> elements */
if (strcmp((const char *) n->name, "tr") == 0) {
if ((s = (char *) xmlGetProp(n,
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "height"))) {
float value = atof(s);
if (value < 0 || strlen(s) == 0) {
@ -515,12 +513,12 @@ bool box_construct_element(xmlNode *n, struct content *content,
struct box *child;
float current;
for (child = box->children; child; child = child->next) {
if (child->type == BOX_TABLE_CELL) {
current = css_len2px(
&child->style->height.length,
child->style);
value = (value > current) ?
value : current;
if (child->type == BOX_TABLE_CELL) {
current = css_len2px(
&child->style->height.length,
child->style);
value = (value > current) ?
value : current;
child->style->height.height =
CSS_HEIGHT_LENGTH;
child->style->height.length.unit =
@ -538,7 +536,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
if (style->background_image.type == CSS_BACKGROUND_IMAGE_URI) {
if (!html_fetch_object(content, style->background_image.uri,
box, image_types, content->available_width,
1000, true, 0))
1000, true))
return false;
}
@ -549,15 +547,15 @@ bool box_construct_element(xmlNode *n, struct content *content,
/**
* Construct the box tree for an XML text node.
*
* \param n XML node of type XML_TEXT_NODE
* \param content content of type CONTENT_HTML that is being processed
* \param n XML node of type XML_TEXT_NODE
* \param content content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
* \param parent parent in box tree
* \param parent parent in box tree
* \param inline_container current inline container box, or 0, updated to
* new current inline container on exit
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
* new current inline container on exit
* \param href current link URL, or 0 if not in a link
* \param target current link target, or 0 if none
* \param title current title, or 0 if none
* \return true on success, false on memory exhaustion
*/
@ -726,9 +724,9 @@ bool box_construct_text(xmlNode *n, struct content *content,
/**
* Get the style for an element.
*
* \param c content of type CONTENT_HTML that is being processed
* \param c content of type CONTENT_HTML that is being processed
* \param parent_style style at this point in xml tree
* \param n node in xml tree
* \param n node in xml tree
* \return the new style, or 0 on memory exhaustion
*
* The style is collected from three sources:
@ -985,7 +983,7 @@ struct css_style * box_get_style(struct content *c,
* by CSS 2.1 9.7.
*
* \param style style to update
* \param root this is the root element
* \param root this is the root element
*/
void box_solve_display(struct css_style *style, bool root)
@ -1016,7 +1014,7 @@ void box_solve_display(struct css_style *style, bool root)
/**
* Set the cellpadding on a table.
*
* \param box box to set cellpadding on
* \param box box to set cellpadding on
* \param value padding in pixels
*
* The descendants of the box are searched for table cells, and the padding is
@ -1046,7 +1044,7 @@ void box_set_cellpadding(struct box *box, int value)
break;
default:
break;
}
}
}
}
@ -1054,7 +1052,7 @@ void box_set_cellpadding(struct box *box, int value)
/**
* Set the borders on a table.
*
* \param box box to set cellpadding on
* \param box box to set cellpadding on
* \param value border in pixels
*
* The descendants of the box are searched for table cells, and the border is
@ -1067,8 +1065,8 @@ void box_set_table_border(struct box *box, int value, colour color)
if (box->type == BOX_TABLE) {
for (unsigned int i = 0; i != 4; i++) {
if (box->style->border[i].style ==
CSS_BORDER_STYLE_NONE) {
if (box->style->border[i].style ==
CSS_BORDER_STYLE_NONE) {
box->style->border[i].color = color;
box->style->border[i].width.width =
CSS_BORDER_WIDTH_LENGTH;
@ -1092,8 +1090,8 @@ void box_set_table_border(struct box *box, int value, colour color)
break;
case BOX_TABLE_CELL:
for (unsigned int i = 0; i != 4; i++) {
if (child->style->border[i].style ==
CSS_BORDER_STYLE_NONE) {
if (child->style->border[i].style ==
CSS_BORDER_STYLE_NONE) {
child->style->border[i].color = color;
child->style->border[i].width.width =
CSS_BORDER_WIDTH_LENGTH;
@ -1108,7 +1106,7 @@ void box_set_table_border(struct box *box, int value, colour color)
break;
default:
break;
}
}
}
}
@ -1116,9 +1114,9 @@ void box_set_table_border(struct box *box, int value, colour color)
/**
* Apply the CSS text-transform property to given text for its ASCII chars.
*
* \param s string to transform
* \param s string to transform
* \param len length of s
* \param tt transform type
* \param tt transform type
*/
void box_text_transform(char *s, unsigned int len,
@ -1231,11 +1229,13 @@ bool box_a(BOX_SPECIAL_PARAMS)
/* target frame [16.3] */
if ((s = xmlGetProp(n, (const xmlChar *) "target"))) {
if (!strcmp(s, "_blank") || !strcmp(s, "_top"))
if (!strcasecmp(s, "_blank"))
box->target = TARGET_BLANK;
else if (!strcasecmp(s, "_top"))
box->target = TARGET_TOP;
else if (!strcmp(s, "_parent"))
else if (!strcasecmp(s, "_parent"))
box->target = TARGET_PARENT;
else if (!strcmp(s, "_self"))
else if (!strcasecmp(s, "_self"))
/* the default may have been overridden by a
* <base target=...>, so this is different to 0 */
box->target = TARGET_SELF;
@ -1246,7 +1246,7 @@ bool box_a(BOX_SPECIAL_PARAMS)
xmlFree(s);
return false;
}
}
}
xmlFree(s);
}
@ -1294,7 +1294,7 @@ bool box_image(BOX_SPECIAL_PARAMS)
/* start fetch */
ok = html_fetch_object(content, url, box, image_types,
content->available_width, 1000, false, 0);
content->available_width, 1000, false);
free(url);
return ok;
}
@ -1406,7 +1406,7 @@ bool box_object(BOX_SPECIAL_PARAMS)
/* start fetch (MIME type is ok or not specified) */
if (!html_fetch_object(content, params->data, box, 0,
content->available_width, 1000, false, 0))
content->available_width, 1000, false))
return false;
/* convert children and place into fallback */
@ -1563,96 +1563,117 @@ no_memory:
bool box_frameset(BOX_SPECIAL_PARAMS)
{
unsigned int row, col;
unsigned int rows = 1, cols = 1;
int object_width, object_height;
char *s, *s1, *url, *name;
struct box *row_box;
struct box *cell_box;
struct box *frameset_box;
struct css_style *style = box->style;
struct css_style *row_style;
struct css_style *cell_style;
struct box_multi_length *row_height = 0, *col_width = 0;
xmlNode *c;
url_func_result res;
bool ok;
box->type = BOX_TABLE;
if (content->data.html.frameset) {
LOG(("Error: multiple framesets in document."));
return false;
}
content->data.html.frameset = talloc_zero(content, struct content_html_frames);
if (!content->data.html.frameset)
return false;
ok = box_create_frameset(content->data.html.frameset, n, content);
if (ok)
box->style->display = CSS_DISPLAY_NONE;
if (convert_children)
*convert_children = false;
return ok;
}
bool box_create_frameset(struct content_html_frames *f, xmlNode *n,
struct content *content) {
unsigned int row, col, index, i;
unsigned int rows = 1, cols = 1;
char *s, *url;
struct frame_dimension *row_height = 0, *col_width = 0;
xmlNode *c;
struct content_html_frames *frame;
bool default_border = true;
colour default_border_colour = 0x000000;
/* parse rows and columns */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "rows"))) {
row_height = box_parse_multi_lengths(s, &rows, content);
row_height = box_parse_multi_lengths(s, &rows);
xmlFree(s);
if (!row_height)
return false;
} else {
row_height = calloc(1, sizeof(struct frame_dimension));
if (!row_height)
return false;
row_height->value = 100;
row_height->unit = FRAME_DIMENSION_PERCENT;
}
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "cols"))) {
col_width = box_parse_multi_lengths(s, &cols, content);
col_width = box_parse_multi_lengths(s, &cols);
xmlFree(s);
if (!col_width)
return false;
}
LOG(("rows %u, cols %u", rows, cols));
box->min_width = 1;
box->max_width = 10000;
box->col = talloc_array(content, struct column, cols);
if (!box->col)
return false;
if (col_width) {
for (col = 0; col != cols; col++) {
if (col_width[col].type == LENGTH_PX) {
box->col[col].type = COLUMN_WIDTH_FIXED;
box->col[col].width = col_width[col].value;
} else if (col_width[col].type == LENGTH_PERCENT) {
box->col[col].type = COLUMN_WIDTH_PERCENT;
box->col[col].width = col_width[col].value;
} else {
box->col[col].type = COLUMN_WIDTH_RELATIVE;
box->col[col].width = col_width[col].value;
}
box->col[col].min = 1;
box->col[col].max = 10000;
}
} else {
box->col[0].type = COLUMN_WIDTH_RELATIVE;
box->col[0].width = 1;
box->col[0].min = 1;
box->col[0].max = 10000;
col_width = calloc(1, sizeof(struct frame_dimension));
if (!col_width)
return false;
col_width->value = 100;
col_width->unit = FRAME_DIMENSION_PERCENT;
}
/* create the frameset table */
/* common extension: border="0|1" to control all children */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "border"))) {
if ((s[0] == '0') && (s[1] == '\0'))
default_border = false;
xmlFree(s);
}
/* common extension: frameborder="yes|no" to control all children */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "frameborder"))) {
if (!strcasecmp(s, "no"))
default_border = false;
xmlFree(s);
}
/* common extension: bordercolor="#RRGGBB|<named colour>" to control all children */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bordercolor"))) {
unsigned int r, g, b;
if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
default_border_colour = (b << 16) | (g << 8) | r;
else if (s[0] != '#')
default_border_colour = named_colour(s);
xmlFree(s);
}
/* update frameset and create default children */
f->cols = cols;
f->rows = rows;
f->scrolling = SCROLLING_NO;
f->children = talloc_array(content, struct content_html_frames, (rows * cols));
for (row = 0; row < rows; row++) {
for (col = 0; col < cols; col++) {
index = (row * cols) + col;
frame = &f->children[index];
frame->cols = 0;
frame->rows = 0;
frame->width = col_width[col];
frame->height = row_height[row];
frame->margin_width = -1;
frame->margin_height = -1;
frame->name = NULL;
frame->url = NULL;
frame->no_resize = false;
frame->scrolling = SCROLLING_AUTO;
frame->border = default_border;
frame->border_colour = default_border_colour;
frame->children = NULL;
}
}
free(col_width);
free(row_height);
/* create the frameset windows */
c = n->children;
for (row = 0; c && row != rows; row++) {
row_style = talloc_memdup(content, style, sizeof *style);
if (!row_style)
return false;
object_height = 1000; /** \todo get available height */
/* if (row_height) {
row_style->height.height = CSS_HEIGHT_LENGTH;
row_style->height.length.unit = CSS_UNIT_PX;
if (row_height[row].type == LENGTH_PERCENT)
row_style->height.length.value = 1000 *
row_height[row].value / 100;
else if (row_height[row].type == LENGTH_RELATIVE)
row_style->height.length.value = 100 *
row_height[row].value;
else
row_style->height.length.value =
row_height[row].value;
object_height = row_style->height.length.value;
}*/
row_box = box_create(row_style, 0, 0, 0, 0, content);
if (!row_box)
return false;
row_box->type = BOX_TABLE_ROW;
box_add_child(box, row_box);
for (col = 0; c && col != cols; col++) {
for (row = 0; c && row < rows; row++) {
for (col = 0; c && col < cols; col++) {
while (c && !(c->type == XML_ELEMENT_NODE && (
strcmp((const char *) c->name, "frame") == 0 ||
strcmp((const char *) c->name, "frameset") == 0
@ -1661,83 +1682,91 @@ bool box_frameset(BOX_SPECIAL_PARAMS)
if (!c)
break;
/* estimate frame width */
object_width = content->available_width;
if (col_width && col_width[col].type == LENGTH_PX)
object_width = col_width[col].value;
cell_style = talloc_memdup(content, style,
sizeof *style);
if (!cell_style)
return false;
cell_style->overflow = CSS_OVERFLOW_AUTO;
cell_box = box_create(cell_style, 0, 0, 0, 0, content);
if (!cell_box)
return false;
cell_box->type = BOX_TABLE_CELL;
box_add_child(row_box, cell_box);
/* get current frame */
index = (row * cols) + col;
frame = &f->children[index];
/* nest framesets */
if (strcmp((const char *) c->name, "frameset") == 0) {
LOG(("frameset"));
frameset_box = box_create(cell_style, 0, 0, 0,
0, content);
if (!frameset_box)
frame->border = 0;
if (!box_create_frameset(frame, c, content))
return false;
if (!box_frameset(c, content, frameset_box, 0))
return false;
box_add_child(cell_box, frameset_box);
c = c->next;
continue;
}
/* get frame URL */
if (!(s = (char *) xmlGetProp(c,
(const xmlChar *) "src"))) {
c = c->next;
continue;
}
s1 = strip(s);
res = url_join(s1, content->data.html.base_url, &url);
if (!box_extract_link(s, content->data.html.base_url, &url)) {
xmlFree(s);
c = c->next;
continue;
}
xmlFree(s);
/* if url is equivalent to the parent's url,
* we've got infinite inclusion. stop it here.
* also bail if url_join failed.
*/
if (res != URL_FUNC_OK || strcasecmp(url,
content->data.html.base_url) == 0) {
LOG(("url_join failed"));
if (!url) {
c = c->next;
continue;
}
name = xmlGetProp(c, (const xmlChar *) "name");
/* don't include ourself */
if (strcmp(content->data.html.base_url, url) == 0) {
free(url);
c = c->next;
continue;
}
LOG(("frame, url '%s', name '%s'", url, name));
/* fill in specified values */
frame->url = talloc_strdup(content, url);
if ((s = (char *) xmlGetProp(c,
(const xmlChar *) "name"))) {
frame->name = talloc_strdup(content, s);
xmlFree(s);
}
frame->no_resize = xmlHasProp(c,
(const xmlChar *) "noresize");
if ((s = (char *) xmlGetProp(c,
(const xmlChar *) "frameborder"))) {
i = atoi(s);
frame->border = (i != 0);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(c,
(const xmlChar *) "scrolling"))) {
if (!strcasecmp(s, "yes"))
frame->scrolling = SCROLLING_YES;
else if (!strcasecmp(s, "no"))
frame->scrolling = SCROLLING_NO;
xmlFree(s);
}
if ((s = (char *) xmlGetProp(c,
(const xmlChar *) "marginwidth"))) {
frame->margin_width = atoi(s);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(c,
(const xmlChar *) "marginheight"))) {
frame->margin_width = atoi(s);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(c, (const xmlChar *) "bordercolor"))) {
unsigned int r, g, b;
if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
frame->border_colour = (b << 16) | (g << 8) | r;
else if (s[0] != '#')
frame->border_colour = named_colour(s);
xmlFree(s);
}
if (!html_fetch_object(content, url,
cell_box, 0,
object_width, object_height, false,
name))
return false;
/* release temporary memory */
free(url);
if (name)
xmlFree(name);
c = c->next;
}
}
talloc_free(row_height);
talloc_free(col_width);
style->width.width = CSS_WIDTH_PERCENT;
style->width.value.percent = 100;
if (convert_children)
*convert_children = false;
return true;
}
@ -1748,33 +1777,93 @@ bool box_frameset(BOX_SPECIAL_PARAMS)
bool box_iframe(BOX_SPECIAL_PARAMS)
{
bool ok;
char *url;
xmlChar *src;
char *url, *s;
struct content_html_iframe *iframe;
int i;
/* get frame URL */
if (!(src = xmlGetProp(n, (const xmlChar *) "src")))
if (!(s = (char *) xmlGetProp(n,
(const xmlChar *) "src")))
return true;
if (!box_extract_link((char *) src, content->data.html.base_url, &url))
if (!box_extract_link(s, content->data.html.base_url, &url)) {
xmlFree(s);
return false;
}
xmlFree(s);
if (!url)
return true;
/* Don't include ourself */
/* don't include ourself */
if (strcmp(content->data.html.base_url, url) == 0) {
free(url);
return true;
}
/* start fetch */
ok = html_fetch_object(content, url, box, 0,
content->available_width, 0, false, 0);
/* create a new iframe */
iframe = talloc(content, struct content_html_iframe);
if (!iframe) {
free(url);
return false;
}
iframe->box = box;
iframe->margin_width = -1;
iframe->margin_height = -1;
iframe->name = NULL;
iframe->url = talloc_strdup(content, url);
iframe->scrolling = SCROLLING_AUTO;
iframe->border = true;
iframe->next = content->data.html.iframe;
content->data.html.iframe = iframe;
/* fill in specified values */
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "name"))) {
iframe->name = talloc_strdup(content, s);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "frameborder"))) {
i = atoi(s);
iframe->border = (i != 0);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "bordercolor"))) {
unsigned int r, g, b;
if (s[0] == '#' && sscanf(s + 1, "%2x%2x%2x", &r, &g, &b) == 3)
iframe->border_colour = (b << 16) | (g << 8) | r;
else if (s[0] != '#')
iframe->border_colour = named_colour(s);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "scrolling"))) {
if (!strcasecmp(s, "yes"))
iframe->scrolling = SCROLLING_YES;
else if (!strcasecmp(s, "no"))
iframe->scrolling = SCROLLING_NO;
xmlFree(s);
}
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "marginwidth"))) {
iframe->margin_width = atoi(s);
xmlFree(s);
}
if ((s = (char *) xmlGetProp(n,
(const xmlChar *) "marginheight"))) {
iframe->margin_width = atoi(s);
xmlFree(s);
}
/* release temporary memory */
free(url);
*convert_children = false;
/* box */
box->type = BOX_INLINE_BLOCK;
assert(box->style);
return ok;
if (convert_children)
*convert_children = false;
return true;
}
@ -1976,12 +2065,12 @@ bool box_input(BOX_SPECIAL_PARAMS)
if (!html_fetch_object(content, url,
box, image_types,
content->available_width,
1000, false, 0)) {
1000, false)) {
free(url);
goto no_memory;
}
}
free(url);
}
}
free(url);
}
} else {
@ -2244,7 +2333,7 @@ no_memory:
* Add an option to a form select control (helper function for box_select()).
*
* \param control select containing the option
* \param n xml element node for <option>
* \param n xml element node for <option>
* \return true on success, false on memory exhaustion
*/
@ -2432,7 +2521,7 @@ bool box_embed(BOX_SPECIAL_PARAMS)
/* start fetch */
return html_fetch_object(content, params->data, box, 0,
content->available_width, 1000, false, 0);
content->available_width, 1000, false);
}
/**
@ -2443,7 +2532,7 @@ bool box_embed(BOX_SPECIAL_PARAMS)
/**
* Get the value of an XML element's attribute.
*
* \param n xmlNode, of type XML_ELEMENT_NODE
* \param n xmlNode, of type XML_ELEMENT_NODE
* \param attribute name of attribute
* \param context talloc context for result buffer
* \param value updated to value, if the attribute is present
@ -2471,8 +2560,8 @@ bool box_get_attribute(xmlNode *n, const char *attribute,
* Extract a URL from a relative link, handling junk like whitespace and
* attempting to read a real URL from "javascript:" links.
*
* \param rel relative URL taken from page
* \param base base for relative URLs
* \param rel relative URL taken from page
* \param base base for relative URLs
* \param result updated to target URL on heap, unchanged if extract failed
* \return true on success, false on memory exhaustion
*/
@ -2537,24 +2626,23 @@ bool box_extract_link(const char *rel, const char *base, char **result)
/**
* Parse a multi-length-list, as defined by HTML 4.01.
*
* \param s string to parse
* \param s string to parse
* \param count updated to number of entries
* \param context talloc context block
* \return array of struct box_multi_length, or 0 on memory exhaustion
*/
struct box_multi_length *box_parse_multi_lengths(const char *s,
unsigned int *count, void *context)
struct frame_dimension *box_parse_multi_lengths(const char *s,
unsigned int *count)
{
char *end;
unsigned int i, n;
struct box_multi_length *length;
struct frame_dimension *length;
for (i = 0, n = 1; s[i]; i++)
if (s[i] == ',')
n++;
length = talloc_array(context, struct box_multi_length, n);
length = calloc(n, sizeof(struct frame_dimension));
if (!length)
return NULL;
@ -2566,9 +2654,15 @@ struct box_multi_length *box_parse_multi_lengths(const char *s,
length[i].value = 1;
s = end;
switch (*s) {
case '%': length[i].type = LENGTH_PERCENT; break;
case '*': length[i].type = LENGTH_RELATIVE; break;
default: length[i].type = LENGTH_PX; break;
case '%':
length[i].unit = FRAME_DIMENSION_PERCENT;
break;
case '*':
length[i].unit = FRAME_DIMENSION_RELATIVE;
break;
default:
length[i].unit = FRAME_DIMENSION_PIXELS;
break;
}
while (*s && *s != ',')
s++;

View File

@ -53,8 +53,8 @@ static void html_object_failed(struct box *box, struct content *content,
static bool html_object_type_permitted(const content_type type,
const content_type *permitted_types);
static void html_object_refresh(void *p);
static bool html_find_frame(struct content *c, const char *frame,
struct content **page, unsigned int *i);
static void html_destroy_frameset(struct content_html_frames *frameset);
static void html_destroy_iframe(struct content_html_iframe *iframe);
/**
@ -75,6 +75,7 @@ bool html_create(struct content *c, const char *params[])
html->encoding = 0;
html->getenc = true;
html->base_url = c->url;
html->base_target = NULL;
html->layout = 0;
html->background_colour = TRANSPARENT;
html->stylesheet_count = 0;
@ -86,6 +87,8 @@ bool html_create(struct content *c, const char *params[])
html->forms = 0;
html->imagemaps = 0;
html->bw = 0;
html->frameset = 0;
html->iframe = 0;
html->page = 0;
html->index = 0;
html->box = 0;
@ -494,6 +497,7 @@ bool html_meta_refresh(struct content *c, xmlNode *head)
bool html_head(struct content *c, xmlNode *head)
{
xmlNode *node;
xmlChar *s;
c->title = 0;
@ -528,6 +532,21 @@ bool html_head(struct content *c, xmlNode *head)
}
xmlFree(href);
}
/* don't use the central values to ease freeing later on */
if ((s = xmlGetProp(node, (const xmlChar *) "target"))) {
if ((!strcasecmp(s, "_blank")) || (!strcasecmp(s, "_top")) ||
(!strcasecmp(s, "_parent")) ||
(!strcasecmp(s, "_self")) ||
('a' <= s[0] && s[0] <= 'z') ||
('A' <= s[0] && s[0] <= 'Z')) { /* [6.16] */
c->data.html.base_target = talloc_strdup(c, s);
if (!c->data.html.base_target) {
xmlFree(s);
return false;
}
}
xmlFree(s);
}
}
}
return true;
@ -903,7 +922,7 @@ void html_convert_css_callback(content_msg msg, struct content *css,
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, char *frame)
bool background)
{
unsigned int i = c->data.html.object_count;
struct content_html_object *object;
@ -935,9 +954,6 @@ bool html_fetch_object(struct content *c, char *url, struct 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[i].frame = 0;
if (frame)
c->data.html.object[i].frame = talloc_strdup(c, frame);
c->data.html.object_count++;
c->active++;
@ -1388,6 +1404,7 @@ void html_stop(struct content *c)
void html_reformat(struct content *c, int width, int height)
{
struct box *doc;
layout_document(c, width, height);
doc = c->data.html.layout;
@ -1396,6 +1413,11 @@ void html_reformat(struct content *c, int width, int height)
c->height = doc->descendant_y1 +
doc->margin[TOP] + doc->margin[BOTTOM];
if ((c->data.html.frameset) && (c->data.html.bw))
browser_window_recalculate_frameset(c->data.html.bw);
if ((c->data.html.iframe) && (c->data.html.bw))
browser_window_recalculate_iframes(c->data.html.bw);
}
@ -1418,6 +1440,25 @@ void html_destroy(struct content *c)
if (c->data.html.parser)
htmlFreeParserCtxt(c->data.html.parser);
/* 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++) {
@ -1430,7 +1471,7 @@ void html_destroy(struct content *c)
}
talloc_free(c->data.html.working_stylesheet);
/*if (c->data.html.style)
css_free_style(c->data.html.style);*/
@ -1447,6 +1488,48 @@ void html_destroy(struct content *c)
}
}
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);
}
}
/**
* Handle a window containing a CONTENT_HTML being opened.
@ -1471,6 +1554,11 @@ void html_open(struct content *c, struct browser_window *bw,
c->data.html.object[i].box,
c->data.html.object[i].box->object_params);
}
if (c->data.html.frameset)
browser_window_create_frameset(bw, c->data.html.frameset);
if (c->data.html.iframe)
browser_window_create_iframes(bw, c->data.html.iframe);
}
@ -1491,87 +1579,3 @@ void html_close(struct content *c)
content_close(c->data.html.object[i].content);
}
}
/**
* Find the target frame for a link.
*
* \param c content containing the link, of type CONTENT_HTML
* \param target target frame
* \retval page updated to content containing target object, or 0 if the
* target should replace the top-level content
* \retval i updated to index of target object in page->data.html.object
*/
void html_find_target(struct content *c, const char *target,
struct content **page, unsigned int *i)
{
*page = 0;
assert(c->type == CONTENT_HTML);
if (!target) {
/** \todo get target from <base target=...> */
*page = c->data.html.page;
*i = c->data.html.index;
return;
}
if (target == TARGET_SELF) {
*page = c->data.html.page;
*i = c->data.html.index;
return;
} else if (target == TARGET_PARENT) {
if (c->data.html.page && c->data.html.page->data.html.page) {
*page = c->data.html.page->data.html.page;
*i = c->data.html.page->data.html.index;
}
return;
} else if (target == TARGET_TOP) {
return;
}
/* recursively search for a frame named target, starting with the
* top-level content in the frameset */
while (c->data.html.page)
c = c->data.html.page;
html_find_frame(c, target, page, i);
}
/**
* Recursively search a frameset for a frame.
*
* \param c frameset page, of type CONTENT_HTML
* \param frame name of frame
* \retval page updated to content containing the frame, if true returned
* \retval i updated to index of target frame in page->data.html.object
* \return true iff the frame was found
*/
bool html_find_frame(struct content *c, const char *frame,
struct content **page, unsigned int *i)
{
unsigned int j;
assert(c->type == CONTENT_HTML);
for (j = 0; j != c->data.html.object_count; j++) {
if (c->data.html.object[j].frame &&
!strcmp(c->data.html.object[j].frame, frame)) {
*page = c;
*i = j;
return true;
}
if (c->data.html.object[j].content &&
c->data.html.object[j].content->type ==
CONTENT_HTML) {
if (html_find_frame(c->data.html.object[j].content,
frame, page, i))
return true;
}
}
return false;
}

View File

@ -37,6 +37,22 @@ struct plotters;
extern char *default_stylesheet_url;
extern char *adblock_stylesheet_url;
struct frame_dimension {
float value;
enum {
FRAME_DIMENSION_PIXELS, /* '100', '200' */
FRAME_DIMENSION_PERCENT, /* '5%', '20%' */
FRAME_DIMENSION_RELATIVE /* '*', '2*' */
} unit;
};
typedef enum {
SCROLLING_AUTO,
SCROLLING_YES,
SCROLLING_NO
} frame_scrolling;
/** An object (<img>, <object>, etc.) in a CONTENT_HTML document. */
struct content_html_object {
char *url; /**< URL of this object. */
@ -46,7 +62,44 @@ struct content_html_object {
* CONTENT_UNKNOWN, or 0 if any type is acceptable. */
const content_type *permitted_types;
bool background; /**< This object is a background image. */
char *frame; /**< Name of frame, or 0 if not a frame. */
};
/** Frame tree (<frameset>, <frame>) */
struct content_html_frames {
int cols; /** number of columns in frameset */
int rows; /** number of rows in frameset */
struct frame_dimension width; /** frame width */
struct frame_dimension height; /** frame width */
int margin_width; /** frame margin width */
int margin_height; /** frame margin height */
char *name; /** frame name (for targetting) */
char *url; /** frame url */
bool no_resize; /** frame is not resizable */
frame_scrolling scrolling; /** scrolling characteristics */
bool border; /** frame has a border */
colour border_colour; /** frame border colour */
struct content_html_frames *children; /** [cols * rows] children */
};
/** Inline frame list (<iframe>) */
struct content_html_iframe {
struct box *box;
int margin_width; /** frame margin width */
int margin_height; /** frame margin height */
char *name; /** frame name (for targetting) */
char *url; /** frame url */
frame_scrolling scrolling; /** scrolling characteristics */
bool border; /** frame has a border */
colour border_colour; /** frame border colour */
struct content_html_iframe *next;
};
/** Data specific to CONTENT_HTML. */
@ -63,6 +116,7 @@ struct content_html_data {
* wasn't specified in the Content-Type header. */
char *base_url; /**< Base URL (may be a copy of content->url). */
char *base_target; /**< Base target */
struct box *layout; /**< Box tree, or 0. */
colour background_colour; /**< Document background colour. */
@ -87,6 +141,12 @@ struct content_html_data {
/** Browser window containing this document, or 0 if not open. */
struct browser_window *bw;
/** Frameset information */
struct content_html_frames *frameset;
/** Inline frame information */
struct content_html_iframe *iframe;
/** Content of type CONTENT_HTML containing this, or 0 if not an object
* within a page. */
struct content *page;
@ -108,7 +168,7 @@ void html_destroy(struct content *c);
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, char *frame);
bool background);
bool html_replace_object(struct content *c, unsigned int i, char *url,
char *post_urlenc,
struct form_successful_control *post_multipart);
@ -117,8 +177,6 @@ void html_open(struct content *c, struct browser_window *bw,
struct content *page, unsigned int index, struct box *box,
struct object_params *params);
void html_close(struct content *c);
void html_find_target(struct content *c, const char *target,
struct content **page, unsigned int *i);
/* in render/html_redraw.c */
bool html_redraw(struct content *c, int x, int y,

View File

@ -20,9 +20,10 @@
#define CONTENT_BLOCK_ADVERTISEMENTS 2
#define CONTENT_BLOCK_POPUPS 3
#define CONTENT_NO_PLUGINS 4
#define CONTENT_DEFAULT_BUTTON 5
#define CONTENT_CANCEL_BUTTON 6
#define CONTENT_OK_BUTTON 7
#define CONTENT_TARGET_BLANK 7
#define CONTENT_DEFAULT_BUTTON 8
#define CONTENT_CANCEL_BUTTON 9
#define CONTENT_OK_BUTTON 10
static void ro_gui_options_content_default(wimp_pointer *pointer);
static bool ro_gui_options_content_ok(wimp_w w);
@ -35,11 +36,14 @@ bool ro_gui_options_content_initialise(wimp_w w) {
option_block_popups);
ro_gui_set_icon_selected_state(w, CONTENT_NO_PLUGINS,
option_no_plugins);
ro_gui_set_icon_selected_state(w, CONTENT_TARGET_BLANK,
option_target_blank);
/* initialise all functions for a newly created window */
ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_ADVERTISEMENTS);
ro_gui_wimp_event_register_checkbox(w, CONTENT_BLOCK_POPUPS);
ro_gui_wimp_event_register_checkbox(w, CONTENT_NO_PLUGINS);
ro_gui_wimp_event_register_checkbox(w, CONTENT_TARGET_BLANK);
ro_gui_wimp_event_register_button(w, CONTENT_DEFAULT_BUTTON,
ro_gui_options_content_default);
ro_gui_wimp_event_register_cancel(w, CONTENT_CANCEL_BUTTON);
@ -59,6 +63,8 @@ void ro_gui_options_content_default(wimp_pointer *pointer) {
false);
ro_gui_set_icon_selected_state(pointer->w, CONTENT_NO_PLUGINS,
false);
ro_gui_set_icon_selected_state(pointer->w, CONTENT_TARGET_BLANK,
true);
}
bool ro_gui_options_content_ok(wimp_w w) {
@ -68,6 +74,8 @@ bool ro_gui_options_content_ok(wimp_w w) {
CONTENT_BLOCK_POPUPS);
option_no_plugins = ro_gui_get_icon_selected_state(w,
CONTENT_NO_PLUGINS);
option_target_blank = ro_gui_get_icon_selected_state(w,
CONTENT_TARGET_BLANK);
ro_gui_save_options();
return true;

View File

@ -156,7 +156,7 @@ static bool gui_track = false;
/** Handle of window which the pointer is over. */
static wimp_w gui_track_wimp_w;
/** Browser window which the pointer is over, or 0 if none. */
static struct gui_window *gui_track_gui_window;
struct gui_window *gui_track_gui_window;
/** Some windows have been resized, and should be reformatted. */
bool gui_reformat_pending = false;
@ -727,10 +727,6 @@ void gui_init2(int argc, char** argv)
option_language);
}
#ifdef WITH_KIOSK_BROWSING
open_window = true;
#endif
if (open_window)
browser_window_create(url, NULL, 0, true);
@ -754,7 +750,7 @@ void gui_quit(void)
rufl_quit();
free(gui_sprites);
xwimp_close_down(task_handle);
free(default_stylesheet_url);
free(default_stylesheet_url);
free(adblock_stylesheet_url);
xhourglass_off();
}
@ -1008,6 +1004,7 @@ void ro_gui_null_reason_code(void)
case GUI_DRAG_SELECTION:
case GUI_DRAG_SCROLL:
case GUI_DRAG_FRAME:
assert(gui_track_gui_window);
ro_gui_window_mouse_at(gui_track_gui_window, &pointer);
break;
@ -1168,6 +1165,7 @@ void ro_gui_pointer_leaving_window(wimp_leaving *leaving)
case GUI_DRAG_SELECTION:
case GUI_DRAG_SCROLL:
case GUI_DRAG_SAVE:
case GUI_DRAG_FRAME:
/* ignore Pointer_Leaving_Window event that the Wimp mysteriously
issues when a Wimp_DragBox drag operation is started */
break;
@ -1186,10 +1184,20 @@ void ro_gui_pointer_leaving_window(wimp_leaving *leaving)
void ro_gui_pointer_entering_window(wimp_entering *entering)
{
gui_track_wimp_w = entering->w;
gui_track_gui_window = ro_gui_window_lookup(entering->w);
gui_track = gui_track_gui_window || gui_track_wimp_w == history_window ||
gui_track_wimp_w == dialog_url_complete;
switch (gui_current_drag_type) {
case GUI_DRAG_SELECTION:
case GUI_DRAG_SCROLL:
case GUI_DRAG_SAVE:
case GUI_DRAG_FRAME:
/* ignore entering new windows/frames */
break;
default:
gui_track_wimp_w = entering->w;
gui_track_gui_window = ro_gui_window_lookup(entering->w);
gui_track = gui_track_gui_window || gui_track_wimp_w == history_window ||
gui_track_wimp_w == dialog_url_complete;
break;
}
}
@ -1284,6 +1292,10 @@ void ro_gui_drag_end(wimp_dragged *drag)
ro_gui_theme_toolbar_editor_drag_end(drag);
break;
case GUI_DRAG_FRAME:
ro_gui_window_frame_resize_end(gui_track_gui_window, drag);
break;
default:
assert(gui_current_drag_type == GUI_DRAG_NONE);
break;
@ -1500,6 +1512,8 @@ void ro_msg_dataload(wimp_message *message)
g = ro_gui_window_lookup(message->data.data_xfer.w);
if (g) {
while (g->bw->parent)
g = g->bw->parent->window;
if (ro_gui_window_dataload(g, message))
return;
}

View File

@ -42,6 +42,7 @@ extern wimp_w dialog_info, dialog_saveas, dialog_zoom, dialog_pageinfo,
dialog_objinfo, dialog_tooltip, dialog_warning, dialog_openurl,
dialog_debug, dialog_folder, dialog_entry, dialog_url_complete,
dialog_search, dialog_print, dialog_theme_install;
extern struct gui_window *gui_track_gui_window;
extern wimp_w current_menu_window;
extern bool current_menu_open;
extern wimp_menu *font_menu; /* font.c */
@ -58,7 +59,7 @@ extern struct tree *hotlist_tree, *global_history_tree, *cookies_tree;
typedef enum { GUI_DRAG_NONE, GUI_DRAG_SELECTION, GUI_DRAG_DOWNLOAD_SAVE,
GUI_DRAG_SAVE, GUI_DRAG_SCROLL, GUI_DRAG_STATUS_RESIZE,
GUI_DRAG_TREE_SELECT, GUI_DRAG_TREE_MOVE,
GUI_DRAG_TOOLBAR_CONFIG } gui_drag_type;
GUI_DRAG_TOOLBAR_CONFIG, GUI_DRAG_FRAME } gui_drag_type;
extern gui_drag_type gui_current_drag_type;
@ -88,6 +89,8 @@ struct gui_window {
int throbtime; /**< Time of last throbber frame. */
int iconise_icon; /**< ID number of icon when window is iconised */
char validation[12]; /**< Validation string for colours */
/** Options. */
struct {
@ -164,6 +167,7 @@ browser_mouse_state ro_gui_mouse_click_state(wimp_mouse_state buttons);
bool ro_gui_shift_pressed(void);
bool ro_gui_ctrl_pressed(void);
void ro_gui_window_scroll_end(struct gui_window *g, wimp_dragged *drag);
void ro_gui_window_frame_resize_end(struct gui_window *g, wimp_dragged *drag);
void ro_gui_window_set_scale(struct gui_window *g, float scale);
void ro_gui_window_iconise(struct gui_window *g,
wimp_full_message_window_info *wi);

View File

@ -1375,6 +1375,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) {
int xeig, yeig;
os_coord pixel = {1, 1};
int top, bottom, right;
bool parent_hscroll;
/* calculate 1px in OS units */
ro_convert_pixels_to_os_units(&pixel, (os_mode)-1);
@ -1411,7 +1412,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) {
warn_user("WimpError", error->errmess);
return false;
}
parent_hscroll = state.flags & wimp_WINDOW_HSCROLL;
height = state.visible.y1 - state.visible.y0 + 2;
/* We can't obscure the height of the scroll bar as we
@ -1677,7 +1678,7 @@ bool ro_gui_theme_process_toolbar(struct toolbar *toolbar, int width) {
/* Open or close the window
*/
if (!toolbar->display_status) {
if ((!toolbar->display_status) || (!parent_hscroll)) {
if (state.flags & wimp_WINDOW_OPEN)
xwimp_close_window(toolbar->status_handle);
} else {

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,7 @@
#include <sys/stat.h>
#include "netsurf/utils/filename.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/url.h"
#include "netsurf/utils/utils.h"
#define FULL_WORD (unsigned int)4294967295
@ -422,3 +423,26 @@ static struct directory *filename_create_directory(const char *prefix) {
return new_dir;
}
/**
* Converts a filename into a local URL
*
* \param filename the filename to convert
* \return a local URL allocated on heap, or NULL on failure.
*/
char *filename_as_url(const char *filename) {
char *temp, *url;
int length;
length = strlen(TEMP_FILENAME_PREFIX) + strlen(filename) + 2;
temp = malloc(length);
if (!temp) {
LOG(("No memory for malloc()"));
return NULL;
}
sprintf(temp, "%s/%s", TEMP_FILENAME_PREFIX, filename);
url = path_to_url(temp);
free(temp);
return url;
}

View File

@ -21,5 +21,6 @@ bool filename_claim(const char *filename);
void filename_release(const char *filename);
bool filename_initialise(void);
void filename_flush(void);
char *filename_as_url(const char *filename);
#endif